doc updates
[gitmo/Moose.git] / lib / Moose / Util.pm
CommitLineData
9a641848 1package Moose::Util;
2
9a641848 3use strict;
4use warnings;
5
7125b244 6use Sub::Exporter;
d7d8a8c7 7use Scalar::Util 'blessed';
8use Carp 'confess';
7125b244 9use Class::MOP ();
9a641848 10
9c10b5ad 11our $VERSION = '0.04';
7125b244 12our $AUTHORITY = 'cpan:STEVAN';
9a641848 13
7125b244 14my @exports = qw[
6532ca5a 15 find_meta
16 does_role
7125b244 17 search_class_by_role
d7d8a8c7 18 apply_all_roles
ab76842e 19 get_all_init_args
20 get_all_attribute_values
7125b244 21];
9a641848 22
7125b244 23Sub::Exporter::setup_exporter({
24 exports => \@exports,
11065d1f 25 groups => { all => \@exports }
7125b244 26});
27
28## some utils for the utils ...
29
6532ca5a 30sub find_meta {
7125b244 31 return unless $_[0];
d7d8a8c7 32 return Class::MOP::get_metaclass_by_name(blessed($_[0]) || $_[0]);
7125b244 33}
9a641848 34
7125b244 35## the functions ...
adf82331 36
7125b244 37sub does_role {
38 my ($class_or_obj, $role) = @_;
adf82331 39
6532ca5a 40 my $meta = find_meta($class_or_obj);
7125b244 41
42 return unless defined $meta;
adf82331 43
7125b244 44 return 1 if $meta->does_role($role);
45 return;
9a641848 46}
47
1631b53f 48sub search_class_by_role {
7125b244 49 my ($class_or_obj, $role_name) = @_;
50
6532ca5a 51 my $meta = find_meta($class_or_obj);
7125b244 52
53 return unless defined $meta;
54
55 foreach my $class ($meta->class_precedence_list) {
56
6532ca5a 57 my $_meta = find_meta($class);
1631b53f 58
7125b244 59 next unless defined $_meta;
60
61 foreach my $role (@{ $_meta->roles || [] }) {
1631b53f 62 return $class if $role->name eq $role_name;
63 }
64 }
65
7125b244 66 return;
1631b53f 67}
68
d7d8a8c7 69sub apply_all_roles {
70 my $applicant = shift;
71
72 confess "Must specify at least one role to apply to $applicant" unless @_;
73
74 my $roles = Data::OptList::mkopt([ @_ ]);
75
76 #use Data::Dumper;
77 #warn Dumper $roles;
78
d9bb6c63 79 my $meta = (blessed $applicant ? $applicant : find_meta($applicant));
d7d8a8c7 80
9c10b5ad 81 foreach my $role_spec (@$roles) {
82 Class::MOP::load_class($role_spec->[0]);
83 }
d7d8a8c7 84
85 ($_->[0]->can('meta') && $_->[0]->meta->isa('Moose::Meta::Role'))
86 || confess "You can only consume roles, " . $_->[0] . " is not a Moose role"
87 foreach @$roles;
88
89 if (scalar @$roles == 1) {
90 my ($role, $params) = @{$roles->[0]};
91 $role->meta->apply($meta, (defined $params ? %$params : ()));
92 }
93 else {
94 Moose::Meta::Role->combine(
95 @$roles
96 )->apply($meta);
97 }
98}
99
ab76842e 100# instance deconstruction ...
101
102sub get_all_attribute_values {
103 my ($class, $instance) = @_;
104 return +{
105 map { $_->name => $_->get_value($instance) }
106 grep { $_->has_value($instance) }
107 $class->compute_all_applicable_attributes
108 };
109}
110
111sub get_all_init_args {
112 my ($class, $instance) = @_;
113 return +{
114 map { $_->init_arg => $_->get_value($instance) }
115 grep { $_->has_value($instance) }
116 grep { defined($_->init_arg) }
117 $class->compute_all_applicable_attributes
118 };
119}
120
d9bb6c63 121
9a641848 1221;
123
124__END__
125
126=pod
127
128=head1 NAME
129
7125b244 130Moose::Util - Utilities for working with Moose classes
9a641848 131
132=head1 SYNOPSIS
133
6532ca5a 134 use Moose::Util qw/find_meta does_role search_class_by_role/;
135
136 my $meta = find_meta($object) || die "No metaclass found";
9a641848 137
adf82331 138 if (does_role($object, $role)) {
139 print "The object can do $role!\n";
9a641848 140 }
141
1631b53f 142 my $class = search_class_by_role($object, 'FooRole');
143 print "Nearest class with 'FooRole' is $class\n";
144
7125b244 145=head1 DESCRIPTION
146
004222dc 147This is a set of utility functions to help working with Moose classes, and
148is used internally by Moose itself. The goal is to provide useful functions
149that for both Moose users and Moose extenders (MooseX:: authors).
150
151This is a relatively new addition to the Moose toolchest, so ideas,
152suggestions and contributions to this collection are most welcome.
153See the L<TODO> section below for a list of ideas for possible functions
154to write.
7125b244 155
156=head1 EXPORTED FUNCTIONS
9a641848 157
158=over 4
159
6532ca5a 160=item B<find_meta ($class_or_obj)>
161
162This will attempt to locate a metaclass for the given C<$class_or_obj>
163and return it.
164
7125b244 165=item B<does_role ($class_or_obj, $role_name)>
166
167Returns true if C<$class_or_obj> can do the role C<$role_name>.
168
169=item B<search_class_by_role ($class_or_obj, $role_name)>
170
171Returns first class in precedence list that consumed C<$role_name>.
172
d7d8a8c7 173=item B<apply_all_roles ($applicant, @roles)>
174
175Given an C<$applicant> (which can somehow be turned into either a
176metaclass or a metarole) and a list of C<@roles> this will do the
177right thing to apply the C<@roles> to the C<$applicant>. This is
3bb22459 178actually used internally by both L<Moose> and L<Moose::Role>, and the
179C<@roles> will be pre-processed through L<Data::OptList::mkopt>
180to allow for the additional arguments to be passed.
d7d8a8c7 181
ab76842e 182=item B<get_all_attribute_values($meta, $instance)>
183
184Returns the values of the C<$instance>'s fields keyed by the attribute names.
185
186=item B<get_all_init_args($meta, $instance)>
187
188Returns a hash reference where the keys are all the attributes' C<init_arg>s
189and the values are the instance's fields. Attributes without an C<init_arg>
190will be skipped.
191
7125b244 192=back
9a641848 193
7125b244 194=head1 TODO
9a641848 195
7125b244 196Here is a list of possible functions to write
9a641848 197
7125b244 198=over 4
1631b53f 199
7125b244 200=item discovering original method from modified method
1631b53f 201
7125b244 202=item search for origin class of a method or attribute
1631b53f 203
9a641848 204=back
205
206=head1 BUGS
207
208All complex software has bugs lurking in it, and this module is no
209exception. If you find a bug please either email me, or add the bug
210to cpan-RT.
211
212=head1 AUTHOR
213
214Anders Nor Berle E<lt>debolaz@gmail.comE<gt>
215
7125b244 216B<with contributions from:>
217
218Robert (phaylon) Sedlacek
219
220Stevan Little
221
9a641848 222=head1 COPYRIGHT AND LICENSE
223
778db3ac 224Copyright 2007-2008 by Infinity Interactive, Inc.
9a641848 225
226L<http://www.iinteractive.com>
227
228This library is free software; you can redistribute it and/or modify
229it under the same terms as Perl itself.
230
231=cut
232