API/HookManager

From aMember Pro Documentation
Revision as of 19:15, 14 September 2012 by Grpmax (Talk | contribs)

Jump to: navigation, search

aMember Pro provides a flexible mechanism to change or add new behaviour to existing actions. It utilises the well-known [Observer] programming pattern.

To wait for an event the code must set up a "hook". Then, on some occasion, the core code or add-on code(!) sends Events (instances of Am_Event class or successors) to all interested parties. Parties handle events by executing pieces of code and, for some events, by adding return values to an event object. Then, the event object is returned to the called core code where it can be inspected and used. It is lengthy to explain, but easy to understand by example:

Setting Hooks. Method 1 - from any part of code

<?php
// you can enter this example to am/application/configs/site.php
// define handlers for an event
function my_custom_function1(Am_Event $event) { $event->addReturn($event->getX() + 1); }
function my_custom_function2(Am_Event $event) { $event->addReturn($event->getX() + 2); }
 
// setup hooks
Am_Di::getInstance()->hook->
   ->add('myCustomEvent', 'my_custom_function1')
   ->add('myCustomEvent', 'my_custom_function2');
 
// now raise the event with variable x = 5 and get returned event object
$event = Am_Di::getInstance()->hook->call('myCustomEvent', array('x' => 5));
 
// now check the return. it will be array(5+1, 5+2) == array(6, 7)
print_rr($event->getReturn());

Setting Hooks. Method 2 - from a plugin or a module

// within file am/application/default/plugins/misc/my.php
class MyPlugin extends Am_Plugin
{
    function onMyCustomEvent(Am_Event $event) 
    { 
        $event->addReturn($event->getX() + 1); 
    }
}

You do not need to set up a hook in the plugin explicitly. Just add a plugin named onHookname() to the plugin class, and, if the plugin is enabled and configured, the hook will be set up automatically.

Example continues: within am/application/configs/site.php

// now raise the event with variable x = 5 and get returned event object
$event = Am_Di::getInstance()->hook->call('myCustomEvent', array('x' => 5));
 
// now check the return. it will be array(5+1, 5+2) == array(6, 7)
print_rr($event->getReturn());

Available Events

You can check for available core events in class Am_Event. There are many constants defined for events. Also, please note that different events may receive difference event objects (all derived for Am_Event parent). For example, event userBeforeInsert will receive object of Am_Event_UserBeforeInsert as parameter.

There is list of currently available events:

class Am_Event
{
    const HOURLY = 'hourly';
    const DAILY  = 'daily';
    const INIT_FINISHED  = 'initFinished';
    const INVOICE_STARTED = 'invoiceStarted';
 
    const USER_BEFORE_DELETE = 'userBeforeDelete';
    const USER_AFTER_DELETE = 'userAfterDelete';
    const USER_BEFORE_INSERT = 'userBeforeInsert';
    const USER_AFTER_INSERT = 'userAfterInsert';
    const USER_BEFORE_UPDATE = 'userBeforeUpdate';
    const USER_AFTER_UPDATE = 'userAfterUpdate';
    const USER_UNSUBSCRIBED_CHANGED = 'userUnsubscribedChanged';
 
    const SET_PASSWORD = 'setPassword';
    /** User (or affiliate) record is added after submitting signup form - before payment */
    const SIGNUP_USER_ADDED = 'signupUserAdded';
    /** User record is added after submitting signup form - before payment */
    const SIGNUP_AFF_ADDED = 'signupAffAdded';
    /** User record is updated after submitting signup form - before payment */
    const SIGNUP_USER_UPDATED  = 'signupUserUpdated';
    /** Payment record insered into database. Is not called for free subscriptions */
    const PAYMENT_AFTER_INSERT = 'paymentAfterInsert';
    const AUTH_CHECK_LOGGED_IN = 'authCheckLoggedIn';
    const AUTH_AFTER_LOGIN = 'authAfterLogin';
    const AUTH_TRY_LOGIN = 'authTryLogin';
    const AUTH_AFTER_LOGOUT = 'authAfterLogout';
 
    const GET_MEMBER_LINKS = 'getMemberLinks';
    const GET_LEFT_MEMBER_LINKS = 'getLeftMemberLinks';
 
    const SUBSCRIPTION_ADDED = 'subscriptionAdded';
    const SUBSCRIPTION_DELETED = 'subscriptionDeleted';
    const SUBSCRIPTION_CHANGED = 'subscriptionChanged';
    const SUBSCRIPTION_UPDATED = 'subscriptionUpdated';
    const SUBSCRIPTION_REMOVED = 'subscriptionRemoved';
 
    /**
     * Access record inserted 
     * NOTE - record may be in not-active state - check dates
     * @param Access access
     */
    const ACCESS_AFTER_INSERT = 'accessAfterInsert';
    /**
     * Access record updated
     * @param Access access
     * @param Access old - record before changes
     */
    const ACCESS_AFTER_UPDATE = 'accessAfterUpdate';
    /**
     * Access record deleted
     * NOTE - record may be in not-active state - check dates
     * @param Access access
     */
    const ACCESS_AFTER_DELETE = 'accessAfterDelete';
 
    const CHECK_UNIQ_LOGIN = 'checkUniqLogin';
    const CHECK_UNIQ_EMAIL = 'checkUniqEmail';
 
    const VALIDATE_SAVED_FORM = 'validateSavedForm';
    const GLOBAL_INCLUDES = 'globalIncludes';
    const GLOBAL_INCLUDES_FINISHED = 'globalIncludesFinished';
 
    const REBUILD = 'rebuild';
    /** if your plugin has a table that must not be backed up, 
     *  call $event->addReturn('tablewithoutprefix') on this hook */
    const SKIP_BACKUP = 'skipBackup';
    const PRODUCT_FORM = 'productForm';
    const SETUP_FORMS = 'setupForms';
    const USER_FORM = 'userForm';
    const THANKS_PAGE = 'thanksPage';
    const GET_PERMISSIONS_LIST = 'getPermissionsList';
    const GET_UPLOAD_PREFIX_LIST = 'getUploadPrefixList';
 
    const SAVED_FORM_TYPES = 'savedFormTypes';
    /**
     * Add new pages into existing "pageable" controllers
     * like AdminContentController
     */
    const INIT_CONTROLLER_PAGES = 'initControllerPages';
    const LOAD_BRICKS = 'loadBricks';
    const ADMIN_MENU = 'adminMenu';
    const ADMIN_WARNINGS = 'adminWarnings';
    const USER_MENU = 'userMenu';
    const USER_TABS = 'userTabs';
    const USER_SEARCH_CONDITIONS = 'userSearchConditions';
    const LOAD_REPORTS = 'loadReports';
    const BEFORE_RENDER = 'beforeRender';
    const AFTER_RENDER = 'afterRender';    
 
    const INIT_CONTENT_PAGES = 'initContentPages';
 
    /**
     * Add sample data to database (@link AdminBuildController)
     * $user->save() will be called after hook finished
     * @param User $user
     * @param string $demoId
     * @param int $usersCreated
     * @param int $usersTotal
     */
    const BUILD_DEMO = 'buildDemo';
    ....
}