195 lines
6.7 KiB
PHP
195 lines
6.7 KiB
PHP
<?php
|
|
/** @file
|
|
* This file contains the Query Path extension tools.
|
|
*
|
|
* Query Path can be extended to support additional features. To do this,
|
|
* you need only create a new class that implements {@link QueryPathExtension}
|
|
* and add your own methods. This class can then be registered as an extension.
|
|
* It will then be available through Query Path.
|
|
*
|
|
* For information on building your own extension, see {@link QueryPathExtension}.
|
|
* If you are trying to load an extension you have downloaded, chances are good that
|
|
* all you need to do is {@link require_once} the file that contains the extension.
|
|
*
|
|
* @author M Butcher <matt@aleph-null.tv>
|
|
* @license http://opensource.org/licenses/lgpl-2.1.php LGPL or MIT-like license.
|
|
* @see QueryPathExtension
|
|
* @see QueryPathExtensionRegistry::extend()
|
|
*/
|
|
|
|
/** @addtogroup querypath_extensions Extensions
|
|
* The QueryPath extension system and bundled extensions.
|
|
*
|
|
* Much like jQuery, QueryPath provides a simple extension mechanism that allows
|
|
* extensions to auto-register themselves upon being loaded. For a simple example, see
|
|
* QPXML. For the internals, see QueryPathExntesion and QueryPath::__construct().
|
|
*/
|
|
|
|
/**
|
|
* A QueryPathExtension is a tool that extends the capabilities of a QueryPath object.
|
|
*
|
|
* Extensions to QueryPath should implement the QueryPathExtension interface. The
|
|
* only requirement is that the extension provide a constructor that takes a
|
|
* QueryPath object as a parameter.
|
|
*
|
|
* Here is an example QueryPath extension:
|
|
* <code><?php
|
|
* class StubExtensionOne implements QueryPathExtension {
|
|
* private $qp = NULL;
|
|
* public function __construct(QueryPath $qp) {
|
|
* $this->qp = $qp;
|
|
* }
|
|
*
|
|
* public function stubToe() {
|
|
* $this->qp->find(':root')->append('<toe/>')->end();
|
|
* return $this->qp;
|
|
* }
|
|
* }
|
|
* QueryPathExtensionRegistry::extend('StubExtensionOne');
|
|
* ?></code>
|
|
* In this example, the StubExtensionOne class implements QueryPathExtension.
|
|
* The constructor stores a local copyof the QueryPath object. This is important
|
|
* if you are planning on fully integrating with QueryPath's Fluent Interface.
|
|
*
|
|
* Finally, the stubToe() function illustrates how the extension makes use of
|
|
* QueryPath internally, and remains part of the fluent interface by returning
|
|
* the $qp object.
|
|
*
|
|
* Notice that beneath the class, there is a single call to register the
|
|
* extension with QueryPath's registry. Your extension should end with a line
|
|
* similar to this.
|
|
*
|
|
* <b>How is a QueryPath extension called?</b>
|
|
*
|
|
* QueryPath extensions are called like regular QueryPath functions. For
|
|
* example, the extension above can be called like this:
|
|
* <code>
|
|
* qp('some.xml')->stubToe();
|
|
* </code>
|
|
* Since it returns the QueryPath ($qp) object, chaining is supported:
|
|
* <code>
|
|
* print qp('some.xml')->stubToe()->xml();
|
|
* </code>
|
|
* When you write your own extensions, anything that does not need to return a
|
|
* specific value should return the QueryPath object. Between that and the
|
|
* extension registry, this will provide the best developer experience.
|
|
*
|
|
* @ingroup querypath_extensions
|
|
*/
|
|
interface QueryPathExtension {
|
|
public function __construct(QueryPath $qp);
|
|
}
|
|
|
|
/**
|
|
* A registry for QueryPath extensions.
|
|
*
|
|
* QueryPath extensions should call the {@link QueryPathExtensionRegistry::extend()}
|
|
* function to register their extension classes. The QueryPath library then
|
|
* uses this information to determine what QueryPath extensions should be loaded and
|
|
* executed.
|
|
*
|
|
* @ingroup querypath_extensions
|
|
*/
|
|
class QueryPathExtensionRegistry {
|
|
/**
|
|
* Internal flag indicating whether or not the registry should
|
|
* be used for automatic extension loading. If this is false, then
|
|
* implementations should not automatically load extensions.
|
|
*/
|
|
public static $useRegistry = TRUE;
|
|
/**
|
|
* The extension registry. This should consist of an array of class
|
|
* names.
|
|
*/
|
|
protected static $extensionRegistry = array();
|
|
protected static $extensionMethodRegistry = array();
|
|
/**
|
|
* Extend QueryPath with the given extension class.
|
|
*/
|
|
public static function extend($classname) {
|
|
self::$extensionRegistry[] = $classname;
|
|
$class = new ReflectionClass($classname);
|
|
$methods = $class->getMethods();
|
|
foreach ($methods as $method) {
|
|
self::$extensionMethodRegistry[$method->getName()] = $classname;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check to see if a method is known.
|
|
* This checks to see if the given method name belongs to one of the
|
|
* registered extensions. If it does, then this will return TRUE.
|
|
*
|
|
* @param string $name
|
|
* The name of the method to search for.
|
|
* @return boolean
|
|
* TRUE if the method exists, false otherwise.
|
|
*/
|
|
public static function hasMethod($name) {
|
|
return isset(self::$extensionMethodRegistry[$name]);
|
|
}
|
|
|
|
/**
|
|
* Check to see if the given extension class is registered.
|
|
* Given a class name for a {@link QueryPathExtension} class, this
|
|
* will check to see if that class is registered. If so, it will return
|
|
* TRUE.
|
|
*
|
|
* @param string $name
|
|
* The name of the class.
|
|
* @return boolean
|
|
* TRUE if the class is registered, FALSE otherwise.
|
|
*/
|
|
public static function hasExtension($name) {
|
|
return in_array($name, self::$extensionRegistry);
|
|
}
|
|
|
|
/**
|
|
* Get the class that a given method belongs to.
|
|
* Given a method name, this will check all registered extension classes
|
|
* to see if any of them has the named method. If so, this will return
|
|
* the classname.
|
|
*
|
|
* Note that if two extensions are registered that contain the same
|
|
* method name, the last one registred will be the only one recognized.
|
|
*
|
|
* @param string $name
|
|
* The name of the method.
|
|
* @return string
|
|
* The name of the class.
|
|
*/
|
|
public static function getMethodClass($name) {
|
|
return self::$extensionMethodRegistry[$name];
|
|
}
|
|
|
|
/**
|
|
* Get extensions for the given QueryPath object.
|
|
*
|
|
* Given a {@link QueryPath} object, this will return
|
|
* an associative array of extension names to (new) instances.
|
|
* Generally, this is intended to be used internally.
|
|
*
|
|
* @param QueryPath $qp
|
|
* The QueryPath into which the extensions should be registered.
|
|
* @return array
|
|
* An associative array of classnames to instances.
|
|
*/
|
|
public static function getExtensions(QueryPath $qp) {
|
|
$extInstances = array();
|
|
foreach (self::$extensionRegistry as $ext) {
|
|
$extInstances[$ext] = new $ext($qp);
|
|
}
|
|
return $extInstances;
|
|
}
|
|
|
|
/**
|
|
* Enable or disable automatic extension loading.
|
|
*
|
|
* If extension autoloading is disabled, then QueryPath will not
|
|
* automatically load all registred extensions when a new QueryPath
|
|
* object is created using {@link qp()}.
|
|
*/
|
|
public static function autoloadExtensions($boolean = TRUE) {
|
|
self::$useRegistry = $boolean;
|
|
}
|
|
} |