123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- <?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;
- }
- }
|