Skip to content

Latest commit

 

History

History
214 lines (130 loc) · 6.77 KB

Plugins.pod

File metadata and controls

214 lines (130 loc) · 6.77 KB

NAME

RevBank::Plugins - Plugin mechanism for RevBank

DESCRIPTION

RevBank itself consists of a simple command line interface and a really brain dead shopping cart. All transactions, even deposits and withdrawals, are handled by plugins.

Plugins are defined in the revbank.plugins file. Each plugin is a Perl source file in the plugins directory. Plugins are always iterated over in the order they were defined in.

Methods

RevBank::Plugins::load

Reads the revbank.plugins file and load the plugins.

RevBank::Plugins->new

Returns a list of fresh plugin instances.

RevBank::Plugins::register($package)

Registers a plugin.

RevBank::Plugins::call_hooks($hook, @arguments)

Calls the given hook in each of the plugins. Non-standard hooks, called only by plugins, SHOULD be prefixed with the name of the plugin, and an underscore. For example, a plugin called cow can call a hook called cow_moo (which calls the hook_cow_moo methods).

There is no protection against infinite loops. Be careful!

WRITING PLUGINS

*** CAUTION ***
It is the responsibility of the PLUGINS to verify and normalize all
input. Behaviour for bad input is UNDEFINED. Weird things could
happen. Always use parse_user() and parse_amount() and test the
outcome for defined()ness. Use the result of the parse_*() functions
because that's canonicalised.

Don't do this:
    $entry->add_contra($u, $a, "Bad example");

But do this:
    $u = parse_user($u)   or return REJECT, "$u: No such user.";
    $a = parse_amount($a) or return REJECT, "$a: Invalid amount.";
    $entry->add_contra($u, $a, 'Good, except that $a is special in Perl :)');

There are two kinds of plugin methods: input methods and hooks. A plugin may define one command input method, and can have any number of hooks.

Input methods

Whenever a command is given in the 'outer' loop of revbank, the command method of the plugins is called until one of the plugins returns either ACCEPT or DONE. An input method receives three arguments: the plugin object, the shopping cart, and the given input string. The plugin object (please call it $self) is temporary but persists as long as your plugin keeps control. It can be used as a scratchpad for carrying over values from one method call to the next.

A command method MUST return with one of the following statements:

return NEXT;

The plugin declines handling of the given command, and revbank should proceed with the next one.

Input methods other than command MUST NOT return NEXT.

return REJECT, "Reason";

The plugin decides that the input should be rejected for the given reason. RevBank will either query the user again, or (if there is any remaining input in the buffer) abort the transaction to avoid confusion.

return ABORT, "Reason";
return ABORT;

The plugin decides that the transaction should be aborted.

return ACCEPT;

The plugin has finished processing the command. No other plugins will be called.

return "Prompt", $method;

The plugin requires arguments for the command, which will be taken from the input buffer if extra input was given, or else, requested interactively.

The given method, which can be a reference or the name of the method, will be called with the given input.

The literal input string abort is a hard coded special case, and will never reach the plugin's input methods.

Hooks

Hooks are called at specific points in the processing flow, and MAY introspect the shopping cart. They SHOULD NOT manipulate the shopping cart, but this option is provided anyway, to allow for interesting hacks. If you do manipulate the cart, re-evaluate your assumptions when upgrading!

Hooks SHOULD NOT prompt for input or execute programs that do so.

Hooks are called as class methods. The return value MUST be either ABORT, which causes the ongoing transaction to be aborted, or a non-reference, which will be ignored.

Hooks SHOULD have a dummy @ parameter at the end of their signatures, so they don't break when more information is added

The following hooks are available, with their respective arguments:

hook_register($class, $plugin, @)

Called when a new plugin is registered.

hook_abort($class, $cart, @)

Called when a transaction is being aborted, right before the shopping cart is emptied.

hook_prompt($class, $cart, $prompt, @)

Called just before the user is prompted for input interactively. The prompt MAY be altered by the plugin.

hook_input($class, $cart, $input, $split_input, @)

Called when user input was given. $split_input is a boolean that is true if the input will be split on whitespace, rather than treated as a whole. The input MAY be altered by the plugin.

hook_add($class, $cart, $user, $item, @)

Called when something is added to the cart. Of course, like in $cart->add, $user will be undef if the product is added for the current user.

$item is a reference to a hash with the keys amount, description and the metadata given in the add call. Changing the values changes the actual item going into the cart!

Be careful to avoid infinite loops if you add new stuff.

hook_checkout_prepare($class, $cart, $user, $transaction_id, @)

Called when the transaction is about to be processed. In this phase, the cart and its entries can still be manipulated. If the hook throws an exception, the transaction is aborted.

hook_checkout($class, $cart, $user, $transaction_id, @)

Called when the transaction is finalized, before accounts are updated. The cart and cart entries must not be changed.

hook_checkout_done($class, $cart, $user, $transaction_id, @)

Called when the transaction is finalized, after accounts were updated.

hook_reject($class, $plugin, $reason, $abort, @)

Called when input is rejected by a plugin. $abort is true when the transaction will be aborted because of the rejection.

hook_invalid_input($class, $cart, $word, @)

Called when input was not recognised by any of the plugins.

hook_plugin_fail($class, $plugin, $error, @)

Called when a plugin fails.

hook_user_created($class, $username, @)

Called when a new user account was created.

hook_user_balance($class, $username, $old, $delta, $new, $transaction_id, @)

Called when a user account is updated.

Default messages can be silenced by overriding the hooks in RevBank::Messages. Such a hack might look like:

undef &RevBank::Messages::hook_abort;

sub hook_abort($class, $cart, @) {
    print "This message is much better!\n"
}

Utility functions

Several global utility functions are available. See RevBank::Global

AUTHOR

Juerd Waalboer <#####@juerd.nl>

LICENSE

Pick your favorite OSI license.