3
\$\begingroup\$

I've built a small hooks class for adding some capabilities of basic plug-in functionality.

Is there room for improvement? I am just beginning to learn OOP. I have two ways to manually add execution points and delete them:

  • autoloading method for plugins in a specific folder
  • method for execution

defined('BASE_PATH') || (header("HTTP/1.1 403 Forbidden") & die('403 - Acces direct interzis.'));
class hooks
{
private  static $hooks = [];
private static $instance;

    /**
     * @param null $plugin_dir
     * @return hooks
     * @desc ne asiguram ca avem o singura instanta globala
     */
    public static function init($plugin_dir = null)
    {
        if(self::$instance == null)
            self::$instance = new self($plugin_dir);
        return self::$instance;
    }

    /**
     * @param $plugin_dir
     * @desc instantierea efectiva, nu cred ca e nevoie de descriere si rulam load_action
     */
    private function __construct($plugin_dir)
    {
        self::load_action($plugin_dir);
    }

    /**
     * @desc ne aisguram ca obiectul nu poate fi clonat
     */
    private function __clone(){}

    /**
     * @param $plugin_dir
     * @return bool
     * @desc incarcarea dinamica de pluginuri (se efectueaza doar daca clasa este instantiata)
     * cautam directorul pt pluginuri le includem si le inregistram cu self::add_action
     */
    private static function load_action($plugin_dir)
    {
        if($plugin_dir == null)
            return null;
        $hooks = new GlobIterator($plugin_dir.DIRECTORY_SEPARATOR.'*.php', FilesystemIterator::KEY_AS_FILENAME);
        foreach($hooks as $hook => $file)
        {
            require_once $file;
            (empty($priority)) ? self::add_action($where, $callback) : self::add_action($where, $callback, $priority);
        }
        return null;
    }

    /**
     * @param $where punctul de executie
     * @param $callback metoda chemata poate fi functie sau metoda
     * @ex add_action('punct executie',[SomeClass, 'someStaticMethod']);
     * @param int $priority ordinea in care sant executate callbackurile pt fiecare pct de executie
     * @desc inregistram pluginuri
     */
    public static function add_action($where, $callback, $priority = 50)
    {
        if(!isset(self::$hooks[$where]))
            self::$hooks[$where] = [];
        self::$hooks[$where][$callback] = $priority;
    }

    /**
     * @param $where
     * @param $callback
     * @desc stergem un callback pt un pct de executie
     */
    public static function remove_action($where, $callback)
    {
        if(isset(self::$hooks[$where][$callback]))
            unset(self::$hooks[$where][$callback]);
    }

    /**
     * @param $where
     * @param array $args
     * @desc executam callbackurile pt un pct de executie si ai dam parametri necesari (optionali)
     */
    public static function execute_action($where, $args = [])
    {
        if(isset(self::$hooks[$where]) && is_array(self::$hooks[$where]))
        {
            arsort(self::$hooks[$where]);
            foreach(self::$hooks[$where] as $callback => &$priority)
                call_user_func_array($callback, $args);
        }
    }
}

index.php

define('BASE_PATH', realpath(__DIR__).DIRECTORY_SEPARATOR);
require_once BASE_PATH.'hooks.php';
hooks::init(BASE_PATH.'plugin'.DIRECTORY_SEPARATOR);
$array_pt_test = [
    'Home' => 'Home.php',
    'Top' => 'Top.php',
    'Hello' => 'Hello.php'
];
function render_nav($array =[])
{
    $output = '';
    foreach($array as $key => $value)
    {
        $output .= '<li>';
        $output .= '<a href="'.$value.'">'.$key.'</a>';
        $output .= '</li>';
    }
    echo $output;
}
hooks::add_action('nav', 'render_nav');

<nav id="nav">
                <ul>
                    <?php
                    hooks::execute_action('nav', [$array_pt_test]);
                    ?>
                </ul>
                <br class="clear" />
            </nav>

This is a simple example of displaying a navigation menu. We register a default function (action) to process the array. In overwrite.php, the plugin directory, we register another function and give the overwrite_nav function a higher priority to be processed, and then call the hooks::remove_action method to unregister the default one. Just play with the $priority value in overwrite.php to see the effects. You can have multiple actions tied to the same execution point.

overwrite.php

 defined('BASE_PATH') || (header("HTTP/1.1 403 Forbidden") & die('403 - Acces direct interzis.'));
$where = 'nav';
$callback = 'overwrite_nav';
$priority = 57 ;

function overwrite_nav($array = [])
{
    hooks::remove_action('nav','render_nav');
        $output = '';
        foreach($array as $key => $value)
        {
            $output .= '<li>';
            $output .= '<a href="'.$value.'">'.strtolower($key).'</a>';
            $output .= '</li>';
        }
        echo $output;
}
\$\endgroup\$
1
  • \$\begingroup\$ Two suggestions immediately comes to my mind: don't use Singletons (they are just disguised globals) and always write in English both comments and code. \$\endgroup\$
    – Shoe
    Feb 10, 2013 at 2:09

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.