Dynamic Hooking

Derek Jones edited this page Jul 5, 2012 · 9 revisions
Clone this wiki locally

Intro I was writing a Session class and looking thought CI's default Session class and noticed it would set a new cookie every time you set/unset and userdata or flashdata and i started to think about the hooking feature and thought why not make it dynamic so any class can insert a hook on the fly. With this ability the session class could add a hook 'post_controller' so it would be able to send only one cookie. The best part is you don't have to enable hooking for this to work. Just drop the file in to your application's library directory. It works as an extension of CI's hooks class.

The bad news You can only hook the hooks that haven't happened yet.

Hooks that can be hooked.. 1: scaffolding_override, post_controller_constructor, post_controller, display_override, and post_system 2: pre_controller 3: hook cache_override

Most of the places you can hook list 1. If hooking from an extended CI class you can hook others. If you extended Input, or Language you can hook lists 1 and 2. If you extended Config, URI, Router, or Output you can hook lists 1, 2, and 3.

Example


$hook['classref'] = &$this;
$hook['method'] = 'sess_write';
$hook['params'] = '';
if($GLOBALS['EXT']->add_hook('post_controller', $hook) == false)
    log_message('error', "Presence class could not set a dynamic hook");

Files MY_Hooks.php


<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * MY_Hooks Class
 *
 * @package        CodeIgniter
 * @subpackage    Libraries
 * @category    Miscallenous
 * @author        dazoe
 * @link        http://codeigniter.com/wiki/Dynamic_Hooking
 */

class MY_Hooks extends CI_Hooks {
    var $myhooks = array();
    var $my_in_progress = false;
    function MY_Hooks() {
        parent::CI_Hooks();
    }

    /**
     * --Add Hook--
     * Adds a particular hook
     * @access    public
     * @param    string the hook name
     * @param    array(classref, method, params)
     * @return    mixed
     */
    function add_hook($hookwhere, $hook) {
        if (is_array($hook)) {
            if (isset($hook['classref']) AND isset($hook['method']) AND isset($hook['params'])) {
                if (is_object($hook['classref']) AND method_exists($hook['classref'], $hook['method'])) {
                    $this->myhooks[$hookwhere][] = $hook;
                    return true;
                }
            }
        }
        return false;
    }


    function _call_hook($which = '') {
        if (!isset($this->myhooks[$which])) {
            return parent::_call_hook($which);
        }
        if (isset($this->myhooks[$which][0]) AND is_array($this->myhooks[$which][0])) {
            foreach ($this->myhooks[$which] as $val) {
                $this->_my_run_hook($val);
            }
        } else {
            $this->_my_run_hook($this->myhooks[$which]);
        }
        return parent::_call_hook($which);
    }

    function _my_run_hook($data)
    {
        if ( ! is_array($data)) {
            return FALSE;
        }

        // -----------------------------------
        // Safety - Prevents run-away loops
        // -----------------------------------
        // If the script being called happens to have the same
        // hook call within it a loop can happen
        if ($this->my_in_progress == TRUE) {
            return;
        }

        // -----------------------------------
        // Set class/method name
        // -----------------------------------
        $class        = NULL;
        $method        = NULL;
        $params        = '';

        if (isset($data['classref'])) {
            $class =& $data['classref'];
        }

        if (isset($data['method'])) {
            $method = $data['method'];
        }
        if (isset($data['params'])) {
            $params = $data['params'];
        }

        if (!is_object($class) OR !method_exists($class, $method)) {
            return FALSE;
        }

        // -----------------------------------
        // Set the in_progress flag
        // -----------------------------------
        $this->my_in_progress = TRUE;

        // -----------------------------------
        // Call the requested class and/or function
        // -----------------------------------
        $class->$method($params);
        $this->my_in_progress = FALSE;
        return TRUE;
    }
}

If there are any bugs and question feel free to pm/email me. Author: dazoe

Category:Contributions::Libraries::Miscallenous