7 use Scalar::Util 'blessed';
10 our $VERSION = '0.70';
11 $VERSION = eval $VERSION;
12 our $AUTHORITY = 'cpan:STEVAN';
20 get_all_attribute_values
21 resolve_metatrait_alias
22 resolve_metaclass_alias
27 Sub::Exporter::setup_exporter({
29 groups => { all => \@exports }
32 ## some utils for the utils ...
36 return Class::MOP::get_metaclass_by_name(blessed($_[0]) || $_[0]);
42 my ($class_or_obj, $role) = @_;
44 my $meta = find_meta($class_or_obj);
46 return unless defined $meta;
47 return unless $meta->can('does_role');
48 return 1 if $meta->does_role($role);
52 sub search_class_by_role {
53 my ($class_or_obj, $role_name) = @_;
55 my $meta = find_meta($class_or_obj);
57 return unless defined $meta;
59 foreach my $class ($meta->class_precedence_list) {
61 my $_meta = find_meta($class);
63 next unless defined $_meta;
65 foreach my $role (@{ $_meta->roles || [] }) {
66 return $class if $role->name eq $role_name;
74 my $applicant = shift;
76 Moose->throw_error("Must specify at least one role to apply to $applicant") unless @_;
78 my $roles = Data::OptList::mkopt( [@_] );
80 my $meta = ( blessed $applicant ? $applicant : find_meta($applicant) );
82 foreach my $role_spec (@$roles) {
83 Class::MOP::load_class( $role_spec->[0] );
86 ( $_->[0]->can('meta') && $_->[0]->meta->isa('Moose::Meta::Role') )
87 || Moose->throw_error("You can only consume roles, "
89 . " is not a Moose role")
92 if ( scalar @$roles == 1 ) {
93 my ( $role, $params ) = @{ $roles->[0] };
94 $role->meta->apply( $meta, ( defined $params ? %$params : () ) );
97 Moose::Meta::Role->combine( @$roles )->apply($meta);
101 # instance deconstruction ...
103 sub get_all_attribute_values {
104 my ($class, $instance) = @_;
106 map { $_->name => $_->get_value($instance) }
107 grep { $_->has_value($instance) }
108 $class->compute_all_applicable_attributes
112 sub get_all_init_args {
113 my ($class, $instance) = @_;
115 map { $_->init_arg => $_->get_value($instance) }
116 grep { $_->has_value($instance) }
117 grep { defined($_->init_arg) }
118 $class->compute_all_applicable_attributes
122 sub resolve_metatrait_alias {
123 return resolve_metaclass_alias( @_, trait => 1 );
129 sub resolve_metaclass_alias {
130 my ( $type, $metaclass_name, %options ) = @_;
132 my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
133 return $cache{$cache_key}{$metaclass_name}
134 if $cache{$cache_key}{$metaclass_name};
136 my $possible_full_name
140 . ( $options{trait} ? "Trait::" : "" )
143 my $loaded_class = Class::MOP::load_first_existing_class(
148 return $cache{$cache_key}{$metaclass_name}
149 = $loaded_class->can('register_implementation')
150 ? $loaded_class->register_implementation
155 sub add_method_modifier {
156 my ( $class_or_obj, $modifier_name, $args ) = @_;
157 my $meta = find_meta($class_or_obj);
158 my $code = pop @{$args};
159 my $add_modifier_method = 'add_' . $modifier_name . '_method_modifier';
160 if ( my $method_modifier_type = ref( @{$args}[0] ) ) {
161 if ( $method_modifier_type eq 'Regexp' ) {
162 my @all_methods = $meta->get_all_methods;
164 = grep { $_->name =~ @{$args}[0] } @all_methods;
165 $meta->$add_modifier_method( $_->name, $code )
166 for @matched_methods;
170 $meta->$add_modifier_method( $_, $code ) for @{$args};
177 return $items[0] if @items == 1;
178 return "$items[0] and $items[1]" if @items == 2;
180 my $tail = pop @items;
181 my $list = join ', ', @items;
182 $list .= ', and ' . $tail;
195 Moose::Util - Utilities for working with Moose classes
199 use Moose::Util qw/find_meta does_role search_class_by_role/;
201 my $meta = find_meta($object) || die "No metaclass found";
203 if (does_role($object, $role)) {
204 print "The object can do $role!\n";
207 my $class = search_class_by_role($object, 'FooRole');
208 print "Nearest class with 'FooRole' is $class\n";
212 This is a set of utility functions to help working with Moose classes, and
213 is used internally by Moose itself. The goal is to provide useful functions
214 that for both Moose users and Moose extenders (MooseX:: authors).
216 This is a relatively new addition to the Moose tool chest, so ideas,
217 suggestions and contributions to this collection are most welcome.
218 See the L<TODO> section below for a list of ideas for possible functions
221 =head1 EXPORTED FUNCTIONS
225 =item B<find_meta ($class_or_obj)>
227 This will attempt to locate a metaclass for the given C<$class_or_obj>
230 =item B<does_role ($class_or_obj, $role_name)>
232 Returns true if C<$class_or_obj> can do the role C<$role_name>.
234 =item B<search_class_by_role ($class_or_obj, $role_name)>
236 Returns first class in precedence list that consumed C<$role_name>.
238 =item B<apply_all_roles ($applicant, @roles)>
240 Given an C<$applicant> (which can somehow be turned into either a
241 metaclass or a metarole) and a list of C<@roles> this will do the
242 right thing to apply the C<@roles> to the C<$applicant>. This is
243 actually used internally by both L<Moose> and L<Moose::Role>, and the
244 C<@roles> will be preprocessed through L<Data::OptList::mkopt>
245 to allow for the additional arguments to be passed.
247 =item B<get_all_attribute_values($meta, $instance)>
249 Returns the values of the C<$instance>'s fields keyed by the attribute names.
251 =item B<get_all_init_args($meta, $instance)>
253 Returns a hash reference where the keys are all the attributes' C<init_arg>s
254 and the values are the instance's fields. Attributes without an C<init_arg>
257 =item B<resolve_metaclass_alias($category, $name, %options)>
259 =item B<resolve_metatrait_alias($category, $name, %options)>
261 Resolve a short name like in e.g.
267 to a full class name.
269 =item B<add_method_modifier ($class_or_obj, $modifier_name, $args)>
271 =item B<english_list(@items)>
273 Given a list of scalars, turns them into a proper list in English
274 ("one and two", "one, two, three, and four"). This is used to help us
275 make nicer error messages.
281 Here is a list of possible functions to write
285 =item discovering original method from modified method
287 =item search for origin class of a method or attribute
293 All complex software has bugs lurking in it, and this module is no
294 exception. If you find a bug please either email me, or add the bug
299 Anders Nor Berle E<lt>debolaz@gmail.comE<gt>
301 B<with contributions from:>
303 Robert (phaylon) Sedlacek
307 =head1 COPYRIGHT AND LICENSE
309 Copyright 2007-2009 by Infinity Interactive, Inc.
311 L<http://www.iinteractive.com>
313 This library is free software; you can redistribute it and/or modify
314 it under the same terms as Perl itself.