method_modifiers_are_arrays
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Class;
3
4use strict;
5use warnings;
6
6ba6d68c 7use Carp 'confess';
a7d0cd00 8use Scalar::Util 'weaken', 'blessed';
a15dff8d 9
78cd1d3b 10our $VERSION = '0.04';
bc1e29b5 11
c0e30cf5 12use base 'Class::MOP::Class';
13
598340d5 14__PACKAGE__->meta->add_attribute('roles' => (
ef333f17 15 reader => 'roles',
16 default => sub { [] }
17));
18
19sub add_role {
20 my ($self, $role) = @_;
21 (blessed($role) && $role->isa('Moose::Meta::Role'))
22 || confess "Roles must be instances of Moose::Meta::Role";
23 push @{$self->roles} => $role;
24}
25
26sub does_role {
27 my ($self, $role_name) = @_;
28 (defined $role_name)
29 || confess "You must supply a role name to look for";
30 foreach my $role (@{$self->roles}) {
31 return 1 if $role->name eq $role_name;
32 }
33 return 0;
34}
35
a15dff8d 36sub construct_instance {
37 my ($class, %params) = @_;
e522431d 38 my $instance = $params{'__INSTANCE__'} || {};
a15dff8d 39 foreach my $attr ($class->compute_all_applicable_attributes()) {
40 my $init_arg = $attr->init_arg();
41 # try to fetch the init arg from the %params ...
42 my $val;
ca01a97b 43 if (exists $params{$init_arg}) {
44 $val = $params{$init_arg};
45 }
46 else {
47 # skip it if it's lazy
48 next if $attr->is_lazy;
49 # and die if it is required
50 confess "Attribute (" . $attr->name . ") is required"
51 if $attr->is_required
52 }
a15dff8d 53 # if nothing was in the %params, we can use the
54 # attribute's default value (if it has one)
8339fae2 55 if (!defined $val && $attr->has_default) {
56 $val = $attr->default($instance);
57 }
00867c44 58 if (defined $val) {
00867c44 59 if ($attr->has_type_constraint) {
34a66aa3 60 if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
a27aa600 61 $val = $attr->type_constraint->coercion->coerce($val);
7415b2cb 62 }
a27aa600 63 (defined($attr->type_constraint->check($val)))
66811d63 64 || confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";
00867c44 65 }
a15dff8d 66 }
67 $instance->{$attr->name} = $val;
6ba6d68c 68 if (defined $val && $attr->is_weak_ref) {
69 weaken($instance->{$attr->name});
70 }
a15dff8d 71 }
72 return $instance;
73}
74
a7d0cd00 75sub has_method {
76 my ($self, $method_name) = @_;
77 (defined $method_name && $method_name)
78 || confess "You must define a method name";
79
80 my $sub_name = ($self->name . '::' . $method_name);
81
82 no strict 'refs';
83 return 0 if !defined(&{$sub_name});
84 my $method = \&{$sub_name};
85
86 return 1 if blessed($method) && $method->isa('Moose::Meta::Role::Method');
87 return $self->SUPER::has_method($method_name);
88}
89
90
78cd1d3b 91sub add_override_method_modifier {
92 my ($self, $name, $method, $_super_package) = @_;
93 # need this for roles ...
94 $_super_package ||= $self->name;
95 my $super = $self->find_next_method_by_name($name);
96 (defined $super)
97 || confess "You cannot override '$name' because it has no super method";
05d9eaf6 98 $self->add_method($name => bless sub {
78cd1d3b 99 my @args = @_;
100 no strict 'refs';
101 no warnings 'redefine';
102 local *{$_super_package . '::super'} = sub { $super->(@args) };
103 return $method->(@args);
05d9eaf6 104 } => 'Moose::Meta::Method::Overriden');
78cd1d3b 105}
106
107sub add_augment_method_modifier {
05d9eaf6 108 my ($self, $name, $method) = @_;
78cd1d3b 109 my $super = $self->find_next_method_by_name($name);
110 (defined $super)
05d9eaf6 111 || confess "You cannot augment '$name' because it has no super method";
112 my $_super_package = $super->package_name;
113 # BUT!,... if this is an overriden method ....
114 if ($super->isa('Moose::Meta::Method::Overriden')) {
115 # we need to be sure that we actually
116 # find the next method, which is not
117 # an 'override' method, the reason is
118 # that an 'override' method will not
119 # be the one calling inner()
120 my $real_super = $self->_find_next_method_by_name_which_is_not_overridden($name);
121 $_super_package = $real_super->package_name;
122 }
78cd1d3b 123 $self->add_method($name => sub {
124 my @args = @_;
125 no strict 'refs';
126 no warnings 'redefine';
05d9eaf6 127 local *{$_super_package . '::inner'} = sub { $method->(@args) };
78cd1d3b 128 return $super->(@args);
129 });
130}
131
05d9eaf6 132sub _find_next_method_by_name_which_is_not_overridden {
133 my ($self, $name) = @_;
134 my @methods = $self->find_all_methods_by_name($name);
135 foreach my $method (@methods) {
136 return $method->{code}
137 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overriden');
138 }
139 return undef;
140}
141
142package Moose::Meta::Method::Overriden;
143
144use strict;
145use warnings;
146
147our $VERSION = '0.01';
148
149use base 'Class::MOP::Method';
150
c0e30cf5 1511;
152
153__END__
154
155=pod
156
157=head1 NAME
158
e522431d 159Moose::Meta::Class - The Moose metaclass
c0e30cf5 160
c0e30cf5 161=head1 DESCRIPTION
162
e522431d 163This is a subclass of L<Class::MOP::Class> with Moose specific
164extensions.
165
6ba6d68c 166For the most part, the only time you will ever encounter an
167instance of this class is if you are doing some serious deep
168introspection. To really understand this class, you need to refer
169to the L<Class::MOP::Class> documentation.
170
c0e30cf5 171=head1 METHODS
172
173=over 4
174
a15dff8d 175=item B<construct_instance>
176
6ba6d68c 177This provides some Moose specific extensions to this method, you
178almost never call this method directly unless you really know what
179you are doing.
180
181This method makes sure to handle the moose weak-ref, type-constraint
182and type coercion features.
ef1d5f4b 183
e9ec68d6 184=item B<has_method ($name)>
185
186This accomidates Moose::Meta::Role::Method instances, which are
187aliased, instead of added, but still need to be counted as valid
188methods.
189
78cd1d3b 190=item B<add_override_method_modifier ($name, $method)>
191
192=item B<add_augment_method_modifier ($name, $method)>
193
ef333f17 194=item B<roles>
195
196=item B<add_role ($role)>
197
198=item B<does_role ($role_name)>
199
c0e30cf5 200=back
201
202=head1 BUGS
203
204All complex software has bugs lurking in it, and this module is no
205exception. If you find a bug please either email me, or add the bug
206to cpan-RT.
207
c0e30cf5 208=head1 AUTHOR
209
210Stevan Little E<lt>stevan@iinteractive.comE<gt>
211
212=head1 COPYRIGHT AND LICENSE
213
214Copyright 2006 by Infinity Interactive, Inc.
215
216L<http://www.iinteractive.com>
217
218This library is free software; you can redistribute it and/or modify
219it under the same terms as Perl itself.
220
221=cut