PHP Classes
Icontem

File: lib/PluginManager.class.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of David N. Q. Duong  >  XIRE  >  lib/PluginManager.class.php  
File: lib/PluginManager.class.php
Role: Class source
Content type: text/plain
Description: Plugin Manager Class
Class: XIRE
Template engine extensible with plug-in classes
 

Contents

Class file image Download
<?php
/* --------------------------------------------------------------------------
 * XIRE - eXtendable Information Rendering Engine
 * --------------------------------------------------------------------------
 * LICENSE
 * Copyright (C) 2006  David Duong
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * -------------------------------------------------------------------------- */
/**
 * Handles the registration and utilization of plugins.
 *
 */
class XIRE_PluginManager {
    private $plugins;       // Registered plugins
    private $instances;
    private $directories;   // Registered plugin directories

    public function __construct () {
        $this->plugins = array();
        $this->directories = array(dirname(__FILE__) . '/plugins');
    }

    /**
     * Register a plugin with an editable node name
     *
     * @param string $name the local name of a node
     * @param string $filename the filename of the plugin class
     */
    public function set ($name, $filename) {
        $this->plugins[$name] = $filename;
    }

    /**
     * Register a plugin directory
     *
     * If a node is found without a registered plugin, all registered plugin directories 
     * will be searched for a plugin that handles the node.
     * @param string $directory
     */
    public function addDirectory ($directory) {
        $this->directories[] = $directory;
    }

    /**
     * Call the plugin that is associated with a node
     *
     * When a process finds a editable node, it will have this plugin manager locate and 
     * call the corresponding plugin for the node. Plugins, or directories containing a 
     * group of plugins, are registered so when a process finds a node that matches the 
     * registration, it will load, instantiate, and call the plugin, handing control of the 
     * node, and child nodes, to the plugin.
     * @param DOMNode $node this method will seek a plugin that is associated (by the 
     * node's local name) and have the plugin handle the node
     * @param XIRE_Template $sender the template making this request
     * @throws XIRE_MissingPluginException if a the plugin could not be found
     */
    public function call (DOMNode $node, XIRE_Process $sender) {
        isset($this->plugins[$node->localName]) or $this->load($node);
        $plugin = new $this->plugins[$node->localName]($node, $sender);
        $plugin->execute();
    }

    /**
     * @param string $name this method will search for a plugin that will handle the given
     * node
     * @throws XIRE_MissingPluginException if a the plugin could not be found
     */
    private function load (DOMNode $node) {
        // Convert element names to class names, ie. something like node-name to NodeName
        if (strpos($node->localName, '-') !== false) {
            $base_name = str_replace(' ', '', ucwords(strtr($node->localName, '-', ' ')));
        } else {
            $base_name = ucfirst($node->localName);
        }
        // Search each registered directory
        foreach ($this->directories as $directory) {
            if ($node instanceof DOMElement
              && file_exists("$directory/Element_$base_name.class.php")) {
                include "$directory/Element_$base_name.class.php";
                $class_name = "XIRE_Plugin_Element_$base_name";
                break;
            } elseif ($node instanceof DOMAttr
              && file_exists("$directory/Attribute_$base_name.class.php")) {
                include "$directory/Attribute_$base_name.class.php";
                $class_name = "XIRE_Plugin_Attribute_$base_name";
                break;
            } elseif (file_exists("$directory/$base_name.class.php")) {
                include "$directory/$base_name.class.php";
                $class_name = "XIRE_Plugin_$base_name";
                break;
            }
        }
        if (!isset($class_name)) {
            // Plugin file not found!
            throw new XIRE_MissingPluginException(
              "Missing plugin file for: {$node->localName}", $node, 0);
        } elseif (class_exists($class_name)) {
            $this->plugins[$node->localName] = $class_name;
        } elseif (class_exists($base_name)) {
            $this->plugins[$node->localName] = $base_name;
        } else {
            // Plugin class not found!
            throw new XIRE_MissingPluginException(
              "Missing plugin class for: {$node->localName}", $node, 1);
        }
    }
}

/**
 * Required superclass of all plugins
 */
abstract class XIRE_Plugin {
    protected $template;    // The template that is calling the plugin
    protected $document;
    protected $process;
    protected $node;
    protected $id;
    private static $ids;

    /**
     * This method is called when a node is to be parsed and must be implemented
     */
    abstract public function execute ();

    public function __construct (DOMNode $node, XIRE_Process $sender) {
        $this->node = $node;
        $this->process = $sender;
        $this->template = $sender->template;
        $this->document = $sender->template->document;

        // All XIRL elements must have a unique id
        if ($node instanceof DOMElement) {
            $current_id = $node->getAttribute('id');
            if (empty($current_id)
              || $this->template->document->getElementById($current_id) !== $node) {
                $current_id = $node->localName;
                if (isset(self::$ids[$node->localName])) {
                    $current_id .= '_' . self::$ids[$node->localName]++;
                } else {
                    self::$ids[$node->localName] = 1;
                }
                while ($this->template->document->getElementById($current_id) !== null) {
                    $current_id = "{$node->localName}_" . self::$ids[$node->localName]++;
                }
                $this->id = $current_id;
                $node->setAttribute('id', $current_id);
            }
        }
    }

    /**
     * Set a template variable called $name with the value $value within the scope of the
     * current node
     */
    protected function setVariable ($name, $value) {
        $this->template["{$this->id}::$name"] = $value;
    }

    /**
     * @param string $name
     * @param boolean $cascade if set to true, this function will also search parent nodes
     * @return bool true if the variable is found or false otherwise
     */
    protected function hasVariable ($name, $cascade = false) {
        if ($cumulative) {
            return $this->template->has($name);
        }
        $current = $this->node;
        do {
            if ($current->namespaceURI === XIRL_NAMESPACE) {
                $current_id = $current->getAttribute('id');
                if (isset($this->template["$current_id::$name"])) {
                    return true;
                }
            }
            $current = ($cumulative)? $current->parentNode : null;
        } while ($current instanceof DOMElement);
    }

    /**
     * @param string $name
     * @param mixed $default determine what should be returned if the variable is not 
     * found
     * @throws XIRE_MissingVariableException when $default is not set and the template 
     * variable is not set
     * @return the template variable with the given name in the current node's scope
     */
    protected function getVariable ($name, $default = null) {
        if (isset($this->template["{$this->id}::$name"])) {
            return $this->template["{$this->id}::$name"];
        } elseif (func_num_args() > 1) {
            return $default;
        }
        throw new XIRE_MissingVariableException("{$this->id}::$name");
    }

    /**
     * @param string $name
     * @param mixed $default determine what should be returned if the variable is not 
     * found
     * @return the template variable with the given name in the node or the closest closest 
     * ancestors' scope
     */
    protected function getVariable_cascade ($name, $default = null) {
        $current = $this->node;
        do {
            if ($current->namespaceURI === XIRL_NAMESPACE) {
                $current_id = $current->getAttribute('id');
                if (isset($this->template["$current_id::$name"])) {
                    return $this->template["$current_id::$name"];
                }
            }
            $current = $current->parentNode;
        } while ($current instanceof DOMElement);
        if (func_num_args() > 1) {
            return $this->template->get($name, $default);
        }
        return $this->template->get($name);
    }
}

class XIRE_MissingAttributeException extends XIRE_ProcessingNodeException
{
    private $name;

    public function __construct($name, DOMNode $node) {
        $this->name = $name;
        parent::__construct(
          "{$node->localName} is missing required attribute: $name", $node);
    }

    /**
     * @return the name of the missing required attribute
     */
    public function getName () {
        return $this->name;
    }
}

class XIRE_MissingPluginException extends XIRE_ProcessingNodeException
{
    private $template;

    public function __construct($message = null, DOMNode $node, $code = 0) {
        func_num_args() === 0 and $message = "Missing plugin: {$node->localName}";
        parent::__construct($message, $node, $code);
    }

    /**
     * @return the template that uses the missing plugin
     */
    public function getTemplate () {
        return $this->template;
    }
}

/**
 * Recomended superclass of exceptions originating from a plugin
 */
class XIRE_PluginException extends XIRE_ProcessingNodeException {}
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products