HTML::...:Plugin(3pm)

okay bestie, sit DOWN because we're reading the manual for HTML::Mason::Plugin(3pm) together and honestly? it's giving foundational πŸ’…βœ¨


🌸 NAME 🌸

HTML::Mason::Plugin β€” the Plugin Base class for Mason πŸ‘‘


🌈 SYNOPIS 🌈

(yes it's spelled like that in the original and we respect the chaos πŸ™ˆ)

package MasonX::Plugin::Timer;
use base qw(HTML::Mason::Plugin);
use Time::HiRes;

sub start_component_hook {
    my ($self, $context) = @_;
    push @{$self->{ timers }}, Time::HiRes::time;
}

sub end_component_hook {
    my ($self, $context) = @_;
    my $elapsed = Time::HiRes::time - pop @{$self->{ timers }};
    printf STDERR "Component '%s' took %.1f seconds\n",
        $context->comp->title, $elapsed;
}

1;

look at that. a whole little timer plugin. she's cute, she's functional, she ate πŸ”₯


πŸ’– DESCRIPTION πŸ’–

so the whole point of a Mason plugin is: you want stuff to happen at the beginning or the end of requests or components. that's it, that's the vibe πŸ¦‹

plugins get activated by passing plugins in the interpreter or the request object. and here's the tea β€” every plugin in that list can be given as either:

  • a class name β€” in which case the plugin object gets created once for each request ✨
  • or an actual object of the plugin class πŸŽ€

if your plugin is configurable, bestie, put that configuration in class variables. like literally:

$MasonX::Plugin::Timer::Units = 'seconds';

and those can be set either from httpd.conf via PerlSetVar directives, or in perl directly from a handler.pl file. two roads, one destination, iconic 🌈


πŸͺ PLUGIN HOOKS πŸͺ

a plugin class defines one or more of these hooks (they're just methods, babe):

  • start_request_hook
  • end_request_hook
  • start_component_hook
  • end_component_hook

every single hook receives two arguments: the plugin object itself, and a context object with various methods πŸ‘―


⭐ start_request_hook ⭐

start_request_hook gets called before the Mason request begins execution. its context has these read-only methods:

request # the current request ($m)
args    # arguments the request was called with

when it's called in scalar context, args returns a list reference β€” and you can modify that to change or add to the arguments passed to the first component πŸ‘€ when it's called in list context, args returns a list (which may be assigned to a hash).

heads up bestie: subrequests (see HTML::Mason::Request) will create a new plugin object and execute this code again. you can skip your code for subrequests by checking is_subrequest on request. like this:
sub start_request_hook {
    my ($self, $context) = @_;
    unless ($context->request->is_subrequest()) {
        # perform hook action
    }
}

and rn, currently, this hook gets called before any information about the requested component is available, so you literally cannot call methods like base_comp() or request_args() on the Request object. no cap, it's just not available yet 😭


⭐ end_request_hook ⭐

end_request_hook gets called before the Mason request exits. its context has these read-only methods:

request     # the current request ($m)
args        # arguments the request was called with
output      # reference to the contents of the output buffer
wantarray   # value of wantarray the request was called with
result      # arrayref of value(s) that the request is about to return
error       # reference to error, if any, that the request is about to throw

in scalar context, args returns a list reference; in list context, it returns a list (which may be assigned to a hash).

result always contains an array ref β€” and if wantarray is 0, the return value is the first element of that array. the plugin may modify output to affect what the request outputs, and modify result and error to affect what the request returns πŸ’…


⭐ start_component_hook ⭐

start_component_hook gets called before a component begins executing. its context has these read-only methods:

request     # the current request ($m)
comp        # the component object
args        # arrayref of arguments the component was called with
and the plugin may NOT modify args currently. sorry babe πŸ™ˆ

⭐ end_component_hook ⭐

end_component_hook() gets called after a component has completed. its context has these read-only methods:

request     # the current request ($m)
comp        # the component object
args        # arrayref of arguments the component was called with
wantarray   # value of wantarray the component was called with
result      # arrayref of value(s) that the component is about to return
error       # reference to error, if any, that the component is about to throw

result always contains an array ref β€” and if wantarray is 0, the return value is the first element of that array. the plugin may modify both result and error to affect how the request returns ✨

it would genuinely be so desirable for this hook to have access to the component's output as well as its return value, but this is currently impossible because output from multiple components combines into a single buffer. the audacity of a shared buffer, honestly πŸ’€


⚠️ WARNINGS ⚠️

do NOT keep an unweakened reference to a request or component object in your plugin object, or you will create a nasty circular reference. bestie I am begging you. weaken it. free yourself 🫢


and that's the whole page, my love πŸ’œ this was perl v5.38.2, dated 2024-03-05, straight from the HTML::...:Plugin(3pm) page β€” go forth and hook responsibly, you absolute main character πŸ‘‘πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from