| | 245 | sub _install_modifier { |
| | 246 | my($pkg, $name) = @_; |
| | 247 | my $modifier = _init_modifier($pkg, $name); |
| | 248 | my $before = $modifier->{before}; |
| | 249 | my $after = $modifier->{after}; |
| | 250 | my $around = $modifier->{around}; |
| | 251 | |
| | 252 | if (@$before && @$after) { |
| | 253 | $modifier->{cache} = sub { |
| | 254 | $_->(@_) for @{$before}; |
| | 255 | my @rval; |
| | 256 | ((defined wantarray) ? |
| | 257 | ((wantarray) ? |
| | 258 | (@rval = $modifier->{around_cache}->(@_)) |
| | 259 | : |
| | 260 | ($rval[0] = $modifier->{around_cache}->(@_))) |
| | 261 | : |
| | 262 | $modifier->{around_cache}->(@_)); |
| | 263 | $_->(@_) for @{$after}; |
| | 264 | return unless defined wantarray; |
| | 265 | return wantarray ? @rval : $rval[0]; |
| | 266 | } |
| | 267 | } elsif (@$before && !@$after) { |
| | 268 | $modifier->{cache} = sub { |
| | 269 | $_->(@_) for @{$before}; |
| | 270 | return $modifier->{around_cache}->(@_); |
| | 271 | } |
| | 272 | } elsif (@$after && !@$before) { |
| | 273 | $modifier->{cache} = sub { |
| | 274 | my @rval; |
| | 275 | ((defined wantarray) ? |
| | 276 | ((wantarray) ? |
| | 277 | (@rval = $modifier->{around_cache}->(@_)) |
| | 278 | : |
| | 279 | ($rval[0] = $modifier->{around_cache}->(@_))) |
| | 280 | : |
| | 281 | $modifier->{around_cache}->(@_)); |
| | 282 | $_->(@_) for @{$after}; |
| | 283 | return unless defined wantarray; |
| | 284 | return wantarray ? @rval : $rval[0]; |
| | 285 | } |
| | 286 | } else { |
| | 287 | $modifier->{cache} = $modifier->{around_cache}; |
| | 288 | } |
| | 289 | |
| | 290 | no strict 'refs'; |
| | 291 | no warnings 'redefine'; |
| | 292 | *{"$pkg\::$name"} = sub { goto $modifier->{cache} }; |
| | 293 | } |
| | 294 | |
| | 295 | sub _init_modifier { |
| | 296 | my($pkg, $name) = @_; |
| | 297 | die "The method '$name' is not found in the inheritance hierarchy for class $pkg" |
| | 298 | unless $pkg->can($name); |
| | 299 | my $code = $pkg->can($name); |
| | 300 | $pkg->meta->{modifier}->{$name} ||= +{ |
| | 301 | around_cache => $code, |
| | 302 | cache => $code, |
| | 303 | orig => $code, |
| | 304 | around => [], |
| | 305 | before => [], |
| | 306 | after => [], |
| | 307 | }; |
| | 308 | } |
| | 309 | |
| | 310 | sub _before { |
| | 311 | my $pkg = caller(0); |
| | 312 | my $name = shift; |
| | 313 | my $modifier = _init_modifier($pkg, $name); |
| | 314 | unshift @{ $modifier->{before} }, $_[0]; |
| | 315 | _install_modifier($pkg, $name); |
| | 316 | } |
| | 317 | |
| | 318 | sub _after { |
| | 319 | my $pkg = caller(0); |
| | 320 | my $name = shift; |
| | 321 | my $modifier = _init_modifier($pkg, $name); |
| | 322 | push @{ $modifier->{after} }, $_[0]; |
| | 323 | _install_modifier($pkg, $name); |
| | 324 | } |
| | 325 | |
| | 326 | # utils |
| | 327 | |