PHP Classes

File: lib/PluginManager.class.php

Recommend this page to a friend!
  Classes of David N. Q. Duong   XIRE   lib/PluginManager.class.php   Download  
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
Author: By
Last change:
Date: 18 years ago
Size: 10,587 bytes
 

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 {} ?>