Changeset 11209
- Timestamp:
- 05/06/08 19:24:34 (5 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
lang/perl/Class-Component/trunk/lib/Class/Component/Component/Moosenize.pm
r11127 r11209 7 7 $class->NEXT( import => %args ); 8 8 9 my $role_pkg = "$class\::Role"; 10 # instasll import method to Plugin base class 11 no strict 'refs'; 12 *{"$role_pkg\::import"} = \&{"Class::Component::Component::Moosenize::Implement::inject_import"}; 13 unshift @{"$role_pkg\::ISA"}, 'Class::Component::Component::Moosenize::Role'; 14 9 15 my $plugin_pkg = "$class\::Plugin"; 10 # install Moose like methods to Plugin base class11 Class::Component::Component::Moosenize::Implement::install_moose_methods($plugin_pkg);12 16 # install register method or wrapping to Plugin base class 13 17 Class::Component::Component::Moosenize::Implement::install_register_method($plugin_pkg); 14 15 # instasll import method to Plugin base class16 no strict 'refs';17 *{"$plugin_pkg\::import"} = \&{"Class::Component::Component::Moosenize::Implement::inject_import"};18 18 } 19 19 … … 25 25 26 26 use Carp::Clan qw/Class::Component/; 27 use Class::Inspector; 27 28 use UNIVERSAL::require; 28 29 29 30 my $requires_map = {}; 31 my $requires_with_map = {}; 30 32 31 33 sub install_moose_methods { 32 34 my $pkg = shift; 33 35 34 for my $method (qw/ requires /) {36 for my $method (qw/ requires with /) { 35 37 no strict 'refs'; 36 38 *{"$pkg\::$method"} = sub { unshift @_, $pkg; goto &$method }; … … 52 54 }; 53 55 } else { 54 eval"package $pkg;56 my $code = "package $pkg; 55 57 *register = sub { 56 58 my \$class = shift; … … 60 62 }; 61 63 "; 62 } 63 } 64 64 eval $code;## no critic 65 } 66 } 67 68 # MyApp::Role->import 65 69 sub inject_import { 66 70 my $class = shift; … … 69 73 # instasll Moose like methods to caller class 70 74 install_moose_methods($caller); 71 } 72 75 $class->import_after($caller, @_); 76 } 77 78 # MyApp::Plugin->register 73 79 sub inject_register { 74 80 check_requires(@_); … … 79 85 my $self = shift; 80 86 my $c = shift; 81 my $kaller = ref $self || $self; 82 return if $moosenized_cache->{$kaller}++; 87 my $caller = ref $self || $self; 88 return if $moosenized_cache->{$caller}++; 89 return unless $requires_with_map->{$caller}; 83 90 84 91 my @error; 85 for my $class ( @{ Class::Component::Implement->isa_list_cache($kaller) }) {86 next if $kaller eq $class; 87 while (my($method, $attr) = each %{ $requires_map->{$class} }) {88 my $code = $self->can($method);89 push @error, sprintf("'%s' requires the method '%s' to be implemented by '%s'", $class, $method, $kaller)90 unless $code;91 92 next unless $attr;93 94 my $attribute = $attr;95 if (ref $attr) {96 if (ref $attr eq 'HASH') {97 $attribute = delete $attr->{attribute};98 $attr = $attr->{args};92 for my $class (reverse(@{ Class::Component::Implement->isa_list_cache($caller, $caller) }), $caller) { 93 94 my %class_requires; # not role class requires 95 if ($requires_map->{$class} && $caller ne $class) { 96 %class_requires = %{ $requires_map->{$class} }; 97 } else { 98 next unless $requires_with_map->{$class}; 99 } 100 101 for my $role (@{ $requires_with_map->{$class} }) { 102 next unless $requires_map->{$role}; 103 while (my($method, $attr) = each %{ $requires_map->{$role} }) { 104 if (my $msg = _check_requires($self, $c, $role, $caller, $method, $attr)) { 105 push @error, $msg; 99 106 } 100 } else {101 $attr = undef;102 107 } 103 104 my $attr_class; 105 if (($attr_class = $attribute) =~ s/^\+//) { 106 $attr_class->require or croak $@; 107 } else { 108 $attr_class = Class::Component::Implement->pkg_require($c => "Attribute::$attribute"); 108 } 109 110 while (my($method, $attr) = each %class_requires) { 111 if (my $msg = _check_requires($self, $c, $class, $caller, $method, $attr)) { 112 push @error, $msg; 109 113 } 110 111 $attr_class->register($self, $c, $method, $attr, $code);112 114 } 113 115 } 114 116 @error and croak join("\n", @error); 115 117 } 118 sub _check_requires { 119 my($self, $c, $caller, $role, $method, $attr) = @_; 120 121 my $code = $self->can($method); 122 unless ($code) { 123 return sprintf("'%s' requires the method '%s' to be implemented by '%s'", $role, $method, $caller); 124 } 125 return unless $attr; 126 127 # set attribute 128 my $attributes; 129 if (ref $attr eq 'HASH') { 130 $attributes = [ $attr ] 131 } elsif (ref $attr eq 'ARRAY') { 132 $attributes = $attr; 133 } else { 134 croak 'unimplimented refarence type'; 135 } 136 137 # fetch attribute class, value and go 138 for my $data (@{ $attributes }) { 139 my($attribute, $value); 140 if (ref $data eq 'HASH') { 141 ($attribute, $value) = each %{ $data }; 142 } else { 143 $attribute = $data; 144 } 145 146 my $attr_class; 147 if (($attr_class = $attribute) =~ s/^\+//) { 148 $attr_class->require or croak $@; 149 } else { 150 $attr_class = Class::Component::Implement->pkg_require($c => "Attribute::$attribute"); 151 } 152 153 $attr_class->register($self, $c, $method, $value, $code); 154 } 155 156 return; 157 } 158 116 159 117 160 # moose like methods … … 119 162 sub requires { 120 163 my $caller = shift; 121 my %methods = @_ == 1 ? ( $_[0] => undef ) : @_; 164 my %methods = (@_ == 1) ? ( $_[0] => undef ) : 165 ref $_[1] ? @_ : 166 map { $_ => undef } @_; 122 167 my $kaller = ref $caller || $caller; 123 168 $requires_map->{$kaller} ||= {}; … … 128 173 } 129 174 175 sub with { 176 my $caller = shift; 177 my $role = shift; 178 179 $role->require or croak $@; 180 my %has_methods = map { $_ => 1 } @{ Class::Inspector->functions($caller) }; 181 for my $method (@{ Class::Inspector->functions($role) }) { 182 next if $has_methods{$method}; 183 no strict 'refs'; 184 *{"$caller\::$method"} = *{"$role\::$method"}; 185 } 186 $requires_with_map->{$caller} ||= []; 187 push @{ $requires_with_map->{$caller} }, $role; 188 } 189 130 190 sub before { 131 191 } … … 134 194 } 135 195 196 use Data::Dumper; 197 198 package # hide pause 199 Class::Component::Component::Moosenize::Role; 200 use strict; 201 use warnings; 202 use Carp::Clan qw/Class::Component/; 203 204 sub import_after {} 136 205 1; 137 206 … … 147 216 =head1 EXPORT METHODS 148 217 149 =ov ar 4150 151 =item requires 218 =over 4 219 220 =item requires, with 152 221 153 222 package MyApp; … … 157 226 package MyApp::Plugin; 158 227 use base 'Class::Component::Plugin'; 228 use MyApp::Role; 159 229 requires 'foo'; 160 requires bar => 'Method', baz => '+Foo::MyAttribute'; 161 requires hop => { attribute => 'Method', args => 'jump' }; 230 requires bar => ['Method'], baz => ['+Foo::MyAttribute']; 231 requires hop => +{ Method => 'jump' }; 232 233 package MyApp::Role; 162 234 163 235 package MyApp::Role::Blah; 164 use MyApp:: Plugin;236 use MyApp::Role; 165 237 requires 'blah'; 166 238 167 239 package MyApp::Plugin::Hoge; 168 use MyApp::Plugin; 169 use base qw( MyApp::Plugin MyApp::Role::Blah ); 240 use base qw( MyApp::Plugin ); 241 use MyApp::Role; 242 with 'MyApp::Role::Blah'; 170 243 171 244 sub foo { # simple method
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)