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