summaryrefslogtreecommitdiff
path: root/lib/querypath/QueryPathExtension.php
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2016-10-11 14:01:29 +0200
committeremkael <emkael@tlen.pl>2016-10-11 14:01:29 +0200
commit51609351f2c4b5082b7e6f0744cd3811c325303f (patch)
tree739015e9ec69bc185ebe30db21369ae0b8b692ce /lib/querypath/QueryPathExtension.php
parent8d1b0dad63e3906efa9393ef01d08b77d83417b5 (diff)
* initial template
Diffstat (limited to 'lib/querypath/QueryPathExtension.php')
-rw-r--r--lib/querypath/QueryPathExtension.php195
1 files changed, 195 insertions, 0 deletions
diff --git a/lib/querypath/QueryPathExtension.php b/lib/querypath/QueryPathExtension.php
new file mode 100644
index 0000000..31e2694
--- /dev/null
+++ b/lib/querypath/QueryPathExtension.php
@@ -0,0 +1,195 @@
+<?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;
+ }
+} \ No newline at end of file