Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision f1c874c3

Von Moritz Bunkus vor fast 14 Jahren hinzugefügt

  • ID f1c874c3725f159f1b00295bf825b2a270cf57bc
  • Vorgänger 27381768
  • Nachfolger b89137f8

Ein System von Hooks, die vor oder nach Actions ausgeführt werden können

Unterschiede anzeigen:

SL/Controller/Base.pm
77 77
  return $output;
78 78
}
79 79

  
80
#
81
# Before/after run hooks
82
#
83

  
84
sub run_before {
85
  _add_hook('before', @_);
86
}
87

  
88
sub run_after {
89
  _add_hook('after', @_);
90
}
91

  
92
my %hooks;
93

  
94
sub _add_hook {
95
  my ($when, $class, $sub, %params) = @_;
96

  
97
  foreach my $key (qw(only except)) {
98
    $params{$key} = { map { ( $_ => 1 ) } @{ $params{$key} } } if $params{$key};
99
  }
100

  
101
  my $idx = "${when}/${class}";
102
  $hooks{$idx} ||= [ ];
103
  push @{ $hooks{$idx} }, { %params, code => $sub };
104
}
105

  
106
sub _run_hooks {
107
  my ($self, $when, $action) = @_;
108

  
109
  my $idx = "${when}/" . ref($self);
110

  
111
  foreach my $hook (@{ $hooks{$idx} || [] }) {
112
    next if ($hook->{only  } && !$hook->{only  }->{$action})
113
         || ($hook->{except} &&  $hook->{except}->{$action});
114

  
115
    if (ref($hook->{code}) eq 'CODE') {
116
      $hook->{code}->($self);
117
    } else {
118
      my $sub = $hook->{code};
119
      $self->$sub;
120
    }
121
  }
122
}
123

  
80 124
#
81 125
# private functions -- for use in Base only
82 126
#
83 127

  
84 128
sub _run_action {
85 129
  my $self   = shift;
86
  my $action = "action_" . shift;
130
  my $action = shift;
131
  my $sub    = "action_${action}";
132

  
133
  return $self->_dispatch(@_) if $action eq 'dispatch';
87 134

  
88
  return $self->_dispatch(@_) if $action eq 'action_dispatch';
135
  $::form->error("Invalid action '${action}' for controller " . ref($self)) if !$self->can($sub);
89 136

  
90
  $::form->error("Invalid action ${action} for controller " . ref($self)) if !$self->can($action);
91
  $self->$action(@_);
137
  $self->_run_hooks('before', $action);
138
  $self->$sub(@_);
139
  $self->_run_hooks('after', $action);
92 140
}
93 141

  
94 142
sub _controller_name {
......
99 147
  my $self    = shift;
100 148

  
101 149
  no strict 'refs';
102
  my @actions = grep { m/^action_/ } keys %{ ref($self) . "::" };
103
  my $action  = first { $::form->{$_} } @actions;
150
  my @actions = map { s/^action_//; $_ } grep { m/^action_/ } keys %{ ref($self) . "::" };
151
  my $action  = first { $::form->{"action_${_}"} } @actions;
152
  my $sub     = "action_${action}";
104 153

  
105
  $self->$action(@_);
154
  $self->_run_hooks('before', $action);
155
  $self->$sub(@_);
156
  $self->_run_hooks('after', $action);
106 157
}
107 158

  
108 159
sub _template_obj {
......
201 252

  
202 253
The dispatching is handled by the function L</_dispatch>.
203 254

  
255
=head2 HOOKS
256

  
257
Hooks are functions that are called before or after the controller's
258
action is called. The controller package defines the hooks, and those
259
hooks themselves are run as instance methods.
260

  
261
Hooks are run in the order they're added.
262

  
263
The return value of the hooks is discarded.
264

  
265
Hooks can be defined to run for all actions, for only specific actions
266
or for all actions except a list of actions. Each entry is the action
267
name, not the sub's name. Therefore in order to run a hook before one
268
of the subs C<action_edit> or C<action_save> is called the following
269
code can be used:
270

  
271
  __PACKAGE__->run_before('things_to_do_before_edit_and_save', only => [ 'edit', 'save' ]);
272

  
204 273
=head1 FUNCTIONS
205 274

  
206 275
=head2 PUBLIC HELPER FUNCTIONS
......
298 367
header. The URL is generated by calling L</url_for> with
299 368
C<%url_params>.
300 369

  
370
=item C<run_before $sub, %params>
371

  
372
=item C<run_after $sub, %params>
373

  
374
Adds a hook to run before or after certain actions are run for the
375
current package. The code to run is C<$sub> which is either the name
376
of an instance method or a code reference. If it's the latter then the
377
first parameter will be C<$self>.
378

  
379
C<%params> can contain two possible values that restrict the code to
380
be run only for certain actions:
381

  
382
=over 2
383

  
384
=item C<< only => \@list >>
385

  
386
Only run the code for actions given in C<@list>. The entries are the
387
action names, not the names of the sub (so it's C<list> instead of
388
C<action_list>).
389

  
390
=item C<< except => \@list >>
391

  
392
Run the code for all actions but for those given in C<@list>. The
393
entries are the action names, not the names of the sub (so it's
394
C<list> instead of C<action_list>).
395

  
396
=back
397

  
398
If neither restriction is used then the code will be run for any
399
action.
400

  
401
The hook's return values are discarded.
402

  
301 403
=back
302 404

  
303 405
=head2 PRIVATE FUNCTIONS

Auch abrufbar als: Unified diff