require the minimum version of Class::Load that has load_first_existing_class
[gitmo/Moose.git] / lib / Moose / Util.pm
index 55ad20e..8b4c34f 100644 (file)
@@ -3,17 +3,16 @@ package Moose::Util;
 use strict;
 use warnings;
 
+use Class::Load 0.07 qw(load_class load_first_existing_class);
 use Data::OptList;
 use Params::Util qw( _STRING );
 use Sub::Exporter;
 use Scalar::Util 'blessed';
 use List::Util qw(first);
 use List::MoreUtils qw(any all);
-use Class::MOP   0.60;
-
-our $VERSION   = '1.15';
-$VERSION = eval $VERSION;
-our $AUTHORITY = 'cpan:STEVAN';
+use overload ();
+use Try::Tiny;
+use Class::MOP;
 
 my @exports = qw[
     find_meta
@@ -46,6 +45,10 @@ sub find_meta { Class::MOP::class_of(@_) }
 sub does_role {
     my ($class_or_obj, $role) = @_;
 
+    if (try { $class_or_obj->isa('Moose::Object') }) {
+        return $class_or_obj->does($role);
+    }
+
     my $meta = find_meta($class_or_obj);
 
     return unless defined $meta;
@@ -99,7 +102,18 @@ sub _apply_all_roles {
         Moose->throw_error("Must specify at least one role to apply to $applicant");
     }
 
-    my $roles = Data::OptList::mkopt( [@_] );
+    # If @_ contains role meta objects, mkopt will think that they're values,
+    # because they're references.  In other words (roleobj1, roleobj2,
+    # roleobj3) will become [ [ roleobj1, roleobj2 ], [ roleobj3, undef ] ]
+    # -- this is no good.  We'll preprocess @_ first to eliminate the potential
+    # bug.
+    # -- rjbs, 2011-04-08
+    my $roles = Data::OptList::mkopt( [@_], {
+      moniker   => 'role',
+      name_test => sub {
+        ! ref $_[0] or blessed($_[0]) && $_[0]->isa('Moose::Meta::Role')
+      }
+    });
 
     my @role_metas;
     foreach my $role (@$roles) {
@@ -109,8 +123,8 @@ sub _apply_all_roles {
             $meta = $role->[0];
         }
         else {
-            Class::MOP::load_class( $role->[0] , $role->[1] );
-            $meta = Class::MOP::class_of( $role->[0] );
+            load_class( $role->[0] , $role->[1] );
+            $meta = find_meta( $role->[0] );
         }
 
         unless ($meta && $meta->isa('Moose::Meta::Role') ) {
@@ -129,7 +143,11 @@ sub _apply_all_roles {
 
     return unless @role_metas;
 
-    my $meta = ( blessed $applicant ? $applicant : find_meta($applicant) );
+    load_class($applicant)
+        unless blessed($applicant)
+            || Class::MOP::class_of($applicant);
+
+    my $meta = ( blessed $applicant ? $applicant : Moose::Meta::Class->initialize($applicant) );
 
     if ( scalar @role_metas == 1 ) {
         my ( $role, $params ) = @{ $role_metas[0] };
@@ -198,7 +216,7 @@ sub _build_alias_package_name {
             $type, $metaclass_name, $options{trait}
         );
 
-        my $loaded_class = Class::MOP::load_first_existing_class(
+        my $loaded_class = load_first_existing_class(
             $possible_full_name,
             $metaclass_name
         );
@@ -289,8 +307,10 @@ sub meta_class_alias {
 }
 
 # XXX - this should be added to Params::Util
-sub _STRINGLIKE ($) {
+sub _STRINGLIKE0 ($) {
     return _STRING( $_[0] )
+        || ( defined $_[0]
+        && $_[0] eq q{} )
         || ( blessed $_[0]
         && overload::Method( $_[0], q{""} )
         && length "$_[0]" );
@@ -306,7 +326,7 @@ sub _reconcile_roles_for_metaclass {
     # handle the case where we need to fix compatibility between a class and
     # its parent, but all roles in the class are already also done by the
     # parent
-    # see t/050/054.t
+    # see t/metaclasses/metaclass_compat_no_fixing_bug.t
     return $super_meta_name
         unless @role_differences;
 
@@ -319,16 +339,20 @@ sub _reconcile_roles_for_metaclass {
 
 sub _role_differences {
     my ($class_meta_name, $super_meta_name) = @_;
-    my @super_role_metas = $super_meta_name->meta->can('calculate_all_roles_with_inheritance')
-                         ? $super_meta_name->meta->calculate_all_roles_with_inheritance
-                         : $super_meta_name->meta->can('calculate_all_roles')
-                         ? $super_meta_name->meta->calculate_all_roles
-                         : ();
-    my @role_metas       = $class_meta_name->meta->can('calculate_all_roles_with_inheritance')
-                         ? $class_meta_name->meta->calculate_all_roles_with_inheritance
-                         : $class_meta_name->meta->can('calculate_all_roles')
-                         ? $class_meta_name->meta->calculate_all_roles
-                         : ();
+    my @super_role_metas
+        = grep { !$_->isa('Moose::Meta::Role::Composite') }
+               $super_meta_name->meta->can('calculate_all_roles_with_inheritance')
+                   ? $super_meta_name->meta->calculate_all_roles_with_inheritance
+                   : $super_meta_name->meta->can('calculate_all_roles')
+                   ? $super_meta_name->meta->calculate_all_roles
+                   : ();
+    my @role_metas
+        = grep { !$_->isa('Moose::Meta::Role::Composite') }
+               $class_meta_name->meta->can('calculate_all_roles_with_inheritance')
+                   ? $class_meta_name->meta->calculate_all_roles_with_inheritance
+                   : $class_meta_name->meta->can('calculate_all_roles')
+                   ? $class_meta_name->meta->calculate_all_roles
+                   : ();
     my @differences;
     for my $role_meta (@role_metas) {
         push @differences, $role_meta
@@ -446,14 +470,12 @@ sub _is_role_only_subclass {
 
 1;
 
+# ABSTRACT: Utilities for working with Moose classes
+
 __END__
 
 =pod
 
-=head1 NAME
-
-Moose::Util - Utilities for working with Moose classes
-
 =head1 SYNOPSIS
 
   use Moose::Util qw/find_meta does_role search_class_by_role/;
@@ -512,7 +534,7 @@ each of which can be followed by an optional hash reference of options
 
 =item B<ensure_all_roles($applicant, @roles)>
 
-This function is similar to L</apply_all_roles>, but only applies roles that
+This function is similar to C<apply_all_roles>, but only applies roles that
 C<$applicant> does not already consume.
 
 =item B<with_traits($class_name, @role_names)>
@@ -580,24 +602,5 @@ Here is a list of possible functions to write
 
 See L<Moose/BUGS> for details on reporting bugs.
 
-=head1 AUTHOR
-
-Anders Nor Berle E<lt>debolaz@gmail.comE<gt>
-
-B<with contributions from:>
-
-Robert (phaylon) Sedlacek
-
-Stevan Little
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2007-2009 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
 =cut