X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FUtil.pm;h=d4c0d93495760bd331f901791c51be87ddbec498;hb=70a69dd18fb75bd1ada6e8067ea1a3e50d1546d0;hp=3637df1bc02fb10660a9e121c5e74ddb86ec5478;hpb=baf46b9edc7dc3665c7eaf9d1684b157efb09e1a;p=gitmo%2FMoose.git diff --git a/lib/Moose/Util.pm b/lib/Moose/Util.pm index 3637df1..d4c0d93 100644 --- a/lib/Moose/Util.pm +++ b/lib/Moose/Util.pm @@ -3,18 +3,20 @@ package Moose::Util; use strict; use warnings; +use Data::OptList; use Sub::Exporter; use Scalar::Util 'blessed'; use Class::MOP 0.60; -our $VERSION = '0.72_01'; +our $VERSION = '0.83'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; my @exports = qw[ - find_meta + find_meta does_role - search_class_by_role + search_class_by_role + ensure_all_roles apply_all_roles get_all_init_args get_all_attribute_values @@ -31,10 +33,7 @@ Sub::Exporter::setup_exporter({ ## some utils for the utils ... -sub find_meta { - return unless $_[0]; - return Class::MOP::get_metaclass_by_name(blessed($_[0]) || $_[0]); -} +sub find_meta { Class::MOP::class_of(@_) } ## the functions ... @@ -42,7 +41,7 @@ sub does_role { my ($class_or_obj, $role) = @_; my $meta = find_meta($class_or_obj); - + return unless defined $meta; return unless $meta->can('does_role'); return 1 if $meta->does_role($role); @@ -51,14 +50,14 @@ sub does_role { sub search_class_by_role { my ($class_or_obj, $role_name) = @_; - + my $meta = find_meta($class_or_obj); return unless defined $meta; foreach my $class ($meta->class_precedence_list) { - - my $_meta = find_meta($class); + + my $_meta = find_meta($class); next unless defined $_meta; @@ -70,8 +69,22 @@ sub search_class_by_role { return; } +# this can possibly behave in unexpected ways because the roles being composed +# before being applied could differ from call to call; I'm not sure if or how +# to document this possible quirk. +sub ensure_all_roles { + my $applicant = shift; + _apply_all_roles($applicant, sub { !does_role($applicant, $_) }, @_); +} + sub apply_all_roles { my $applicant = shift; + _apply_all_roles($applicant, sub { 1 }, @_); +} + +sub _apply_all_roles { + my $applicant = shift; + my $role_filter = shift; unless (@_) { require Moose; @@ -80,16 +93,11 @@ sub apply_all_roles { my $roles = Data::OptList::mkopt( [@_] ); - my $meta = ( blessed $applicant ? $applicant : find_meta($applicant) ); - - foreach my $role_spec (@$roles) { - Class::MOP::load_class( $role_spec->[0] ); - } - foreach my $role (@$roles) { - unless ( $role->[0]->can('meta') - && $role->[0]->meta->isa('Moose::Meta::Role') ) { + Class::MOP::load_class( $role->[0] ); + my $meta = Class::MOP::class_of( $role->[0] ); + unless ($meta && $meta->isa('Moose::Meta::Role') ) { require Moose; Moose->throw_error( "You can only consume roles, " . $role->[0] @@ -97,9 +105,16 @@ sub apply_all_roles { } } + @$roles = grep { local $_ = $_->[0]; $role_filter->() } @$roles; + + return unless @$roles; + + my $meta = ( blessed $applicant ? $applicant : find_meta($applicant) ); + if ( scalar @$roles == 1 ) { my ( $role, $params ) = @{ $roles->[0] }; - $role->meta->apply( $meta, ( defined $params ? %$params : () ) ); + my $role_meta = Class::MOP::class_of($role); + $role_meta->apply( $meta, ( defined $params ? %$params : () ) ); } else { Moose::Meta::Role->combine( @$roles )->apply($meta); @@ -113,7 +128,7 @@ sub get_all_attribute_values { return +{ map { $_->name => $_->get_value($instance) } grep { $_->has_value($instance) } - $class->compute_all_applicable_attributes + $class->get_all_attributes }; } @@ -122,8 +137,8 @@ sub get_all_init_args { return +{ map { $_->init_arg => $_->get_value($instance) } grep { $_->has_value($instance) } - grep { defined($_->init_arg) } - $class->compute_all_applicable_attributes + grep { defined($_->init_arg) } + $class->get_all_attributes }; } @@ -142,7 +157,7 @@ sub resolve_metatrait_alias { if $cache{$cache_key}{$metaclass_name}; my $possible_full_name - = 'Moose::Meta::' + = 'Moose::Meta::' . $type . '::Custom::' . ( $options{trait} ? "Trait::" : "" ) @@ -228,7 +243,7 @@ some of them may be useful for use in your own code. =item B This method takes a class name or object and attempts to find a -metaclass for the class, if one exists. It will not create one if it +metaclass for the class, if one exists. It will B create one if it does not yet exist. =item B @@ -255,6 +270,11 @@ The list of C<@roles> should be a list of names, each of which can be followed by an optional hash reference of options (C and C). +=item B + +This function is similar to L, but only applies roles that +C<$applicant> does not already consume. + =item B Returns a hash reference containing all of the C<$instance>'s @@ -305,7 +325,7 @@ Here is a list of possible functions to write =head1 BUGS -All complex software has bugs lurking in it, and this module is no +All complex software has bugs lurking in it, and this module is no exception. If you find a bug please either email me, or add the bug to cpan-RT.