Revision f1c874c3
Von Moritz Bunkus vor fast 14 Jahren hinzugefügt
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
Ein System von Hooks, die vor oder nach Actions ausgeführt werden können