=pod

=head1 NAME

RPC::ExtDirect::API::Hook - Ext.Direct Method wrappers

=head1 DESCRIPTION

Hooks are L<RPC::ExtDirect>'s way of implementing
L<Method|RPC::ExtDirect::Intro/Method> modifiers for the (relatively)
rare cases when you need them but don't want to bring in the whole
nine yards of L<Moose>.

=head1 TYPES

A hook is a Perl subroutine (can be anonymous, too). Hooks can be of
three types:

=over 4

=item C<before>

C<before> hook is called before a L<Method|RPC::ExtDirect::Intro/Method>
is invoked, and can be used to change Method arguments or cancel Method
execution. This hook must return numeric value C<1> to allow Method call.
Any other value will be interpreted as an Ext.Direct
L<Result|RPC::ExtDirect::Intro/Result>; it will be returned to the
client side and the Method never gets called.

Note that RPC::ExtDirect will not make any assumptions about this hook's
return value; a false value like C<''> or C<0> will probably not look
too helpful from the client side's point of view.

If this hook throws an exception, it will be returned as an Ext.Direct
L<Exception|RPC::ExtDirect::Intro/Exception> to the client side, and
the Method does not execute.

=item C<instead>

C<instead> hook replaces the Method it is assigned to. It is
the hook sub's responsibility to invoke (or not) the Method code
and return appropriate L<Result|RPC::ExtDirect::Intro/Result>.

If this hook throws an exception, it is interpreted as if the
Method threw it.

This hook is analogous to Moose's C<around> method modifier, except
that C<around> would be a bit of a misnomer since the hook code is
actually called I<instead> of the Method. Hence the name.

=item C<after>

C<after> hook is called after the Method code or C<instead> hook.
This hook cannot affect Method execution, it is intended mostly for
logging and testing purposes; its input includes Method's
L<Result|RPC::ExtDirect::Intro/Result> or
L<Exception|RPC::ExtDirect::Intro/Exception>.

This hook's return value and thrown exceptions are ignored.

=back

=head1 HIERARCHY

Hooks can be defined on three levels, in order of precedence: Method,
Action, and global. For each Method, only one hook of each type can be
applied. Hooks specified in Method definition take precedence over all
other; if no Method hook is found then Action level hook applies; and if
there is no Action hook then global hook gets called, if any.

To avoid using hooks for a particular method, use C<"NONE"> or C<undef>
instead of coderef; this way you can specify global and/or Action hooks
and exclude some specific Methods piecemeal.

See more in the documentation for the constructor: L</new>.

=head1 CALLING CONVENTION

Hook subroutine is called as a class method, i.e. first argument
is name of the package in which this sub was defined. Ignore it
if you don't need it.

Hooks receive a hash of the following arguments:

=over 4

=item C<action>

Ext.Direct L<Action|RPC::ExtDirect::Intro/Action> name for the
L<Method|RPC::ExtDirect::Intro/Method>.

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->action >>

=item C<method>

Ext.Direct L<Method|RPC::ExtDirect::Intro/Method> name

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->name >>

=item C<package>

Name of the package (not Action) where the Method is declared

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->package >>

=item C<code>

Coderef to the Method subroutine

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->code >>

=item C<param_no>
 
Number of parameters when Method accepts ordered arguments

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->len >>

=item C<param_names>

Arrayref with names of parameters when Method accepts named arguments

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->params >>

=item C<formHandler>

True if Method handles form submits

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->formHandler >>

=item C<pollHandler>

True if Method handles Event poll requests

B<DEPRECATED>. Use L<method_ref|/method_ref> instead:
C<< $method_ref->pollHandler >>

=item C<arg>

Arrayref with the invocation arguments when Method accepts ordered args,
single L<Environment object|RPC::ExtDirect/"ENVIRONMENT OBJECTS"> for
L<Poll handlers|RPC::ExtDirect::Intro/"Poll Handler Method">, hashref
otherwise.

Note that this is a direct link to the Method's C<@_> so it is possible
to modify the arguments in C<before> hook if you need to.

=item C<env>

L<Environment object|RPC::ExtDirect/"ENVIRONMENT OBJECTS"> for the
invocation. Like L<arg|/arg>, this is a direct reference to the same
object that will be passed to the Method, so it's possible to modify
the env object in the C<before> hook.

=item C<before>

Coderef to C<before> hook for that Method, or undef

B<DEPRECATED>. Use L<before_ref|/before_ref> instead:
C<< $before_ref->code >>

=item C<instead>

Coderef to C<instead> hook for that Method, or undef

B<DEPRECATED>. Use L<instead_ref|/instead_ref> instead:
C<< $instead_ref->code >>

=item C<after>

Coderef to "after" hook for that Method, or undef

B<DEPRECATED>. Use L<after_ref|/after_ref> instead:
C<< $after_ref->code >>

=item C<result>

For C<after> hooks, the L<Result|RPC::ExtDirect::Intro/Result> returned
by the Method or C<instead> hook, whichever got called. Not defined for
C<before> and C<instead> hooks.

=item C<exception>

For C<after> hooks, an exception (C<$@>) thrown by the Method or
C<instead> hook, if any. Not defined for C<before> and C<instead> hooks.

=item C<method_called>

For C<after> hooks, a reference to the actual code called as Method, if
any. Can be either the Method code itself, C<instead> hook or C<undef>
if the invocation was canceled.

=item C<orig>

A closure that binds Method coderef to its current arguments, allowing to call
it as easily as C<< $params{orig}->() >>

=back

=head1 HOOK OBJECT INTERFACE

L<RPC::ExtDirect::API::Hook> provides several public methods:

=over 4

=item C<HOOK_TYPES>

Class/instance method. Returns the list of supported hook types.

=item C<new>

Constructor. Returns a new L<RPC::ExtDirect::API::Hook> object. Accepts
named arguments in a hash.

Parameters:

=over 8

=item C<type>

Hook L<type|/TYPES>. This parameter is mandatory.

=item C<code>

Hook code. This parameter is mandatory, and it can take one of the
following forms:

=over 12

=item *

C<'NONE'> or C<undef> to cancel hook execution for the corresponding type

=item *

A coderef for the hook sub to run for the corresponding type

=item *

Package and subroutine address to call at the hook execution time, like
C<'Foo::Bar::baz'>. This allows late code binding without loading the
corresponding package early.

=back

=back

=item C<run>

Run the hook and return the result. This method accepts named arguments
in a hash.

Parameters:

=over 8

=item C<api>

An instance of L<RPC::ExtDirect::API>.

This parameter is mandatory.

=item C<env>

An L<environment object|RPC::ExtDirect/"ENVIRONMENT OBJECTS"> for this
hook invocation.

This parameter is mandatory.

=item C<arg>

Method arguments, either array- or hashref depending on the Method's
calling convention.

This parameter is mandatory.

=item C<result>

The result of a Method's invocation for an C<after> hook.

This parameter is mandatory for C<after> hooks.

=item C<exception>

An exception thrown by a Method or a hook. This parameter is only
meaningful for C<after> hooks, and is optional.

=item C<method_ref>

An instance of L<RPC::ExtDirect::API::Method>.

This parameter is mandatory.

=item C<callee>

A reference to the code executed for a Method; can be either the
Method code, or its C<instead> hook code.

This parameter is mandatory for C<after> hooks.

=back

=back

=head1 ACCESSOR METHODS

For L<RPC::ExtDirect::API::Hook>, the following
L<accessor methods|RPC::ExtDirect::Config/"ACCESSOR METHODS"> are
provided:

=over 4

=item C<type>

Return the L</type> of this Hook object.

=item C<code>

Return the L</code> of this Hook object.

=item C<package>

Return the package name for the Hook code.

=item C<sub_name>

Return the subroutine name for the Hook code. This will yield meaningful
result only when L</code> was set to a string 'Package::sub'.

=item C<runnable>

Return true if this Hook's code is runnable and can be executed.

=back

=cut
