[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/api/ -> ApiModuleManager.php (source)

   1  <?php
   2  /**
   3   *
   4   *
   5   * Created on Dec 27, 2012
   6   *
   7   * Copyright © 2012 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
   8   *
   9   * This program is free software; you can redistribute it and/or modify
  10   * it under the terms of the GNU General Public License as published by
  11   * the Free Software Foundation; either version 2 of the License, or
  12   * (at your option) any later version.
  13   *
  14   * This program is distributed in the hope that it will be useful,
  15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17   * GNU General Public License for more details.
  18   *
  19   * You should have received a copy of the GNU General Public License along
  20   * with this program; if not, write to the Free Software Foundation, Inc.,
  21   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22   * http://www.gnu.org/copyleft/gpl.html
  23   *
  24   * @file
  25   * @since 1.21
  26   */
  27  
  28  /**
  29   * This class holds a list of modules and handles instantiation
  30   *
  31   * @since 1.21
  32   * @ingroup API
  33   */
  34  class ApiModuleManager extends ContextSource {
  35  
  36      /**
  37       * @var ApiBase
  38       */
  39      private $mParent;
  40      /**
  41       * @var ApiBase[]
  42       */
  43      private $mInstances = array();
  44      /**
  45       * @var null[]
  46       */
  47      private $mGroups = array();
  48      /**
  49       * @var array[]
  50       */
  51      private $mModules = array();
  52  
  53      /**
  54       * Construct new module manager
  55       * @param ApiBase $parentModule Parent module instance will be used during instantiation
  56       */
  57  	public function __construct( ApiBase $parentModule ) {
  58          $this->mParent = $parentModule;
  59      }
  60  
  61      /**
  62       * Add a list of modules to the manager. Each module is described
  63       * by a module spec.
  64       *
  65       * Each module spec is an associative array containing at least
  66       * the 'class' key for the module's class, and optionally a
  67       * 'factory' key for the factory function to use for the module.
  68       *
  69       * That factory function will be called with two parameters,
  70       * the parent module (an instance of ApiBase, usually ApiMain)
  71       * and the name the module was registered under. The return
  72       * value must be an instance of the class given in the 'class'
  73       * field.
  74       *
  75       * For backward compatibility, the module spec may also be a
  76       * simple string containing the module's class name. In that
  77       * case, the class' constructor will be called with the parent
  78       * module and module name as parameters, as described above.
  79       *
  80       * Examples for defining module specs:
  81       *
  82       * @code
  83       *  $modules['foo'] = 'ApiFoo';
  84       *  $modules['bar'] = array(
  85       *      'class' => 'ApiBar',
  86       *      'factory' => function( $main, $name ) { ... }
  87       *  );
  88       *  $modules['xyzzy'] = array(
  89       *      'class' => 'ApiXyzzy',
  90       *      'factory' => array( 'XyzzyFactory', 'newApiModule' )
  91       *  );
  92       * @endcode
  93       *
  94       * @param array $modules A map of ModuleName => ModuleSpec; The ModuleSpec
  95       *        is either a string containing the module's class name, or an associative
  96       *        array (see above for details).
  97       * @param string $group Which group modules belong to (action,format,...)
  98       */
  99  	public function addModules( array $modules, $group ) {
 100  
 101          foreach ( $modules as $name => $moduleSpec ) {
 102              if ( is_array( $moduleSpec ) ) {
 103                  $class = $moduleSpec['class'];
 104                  $factory = ( isset( $moduleSpec['factory'] ) ? $moduleSpec['factory'] : null );
 105              } else {
 106                  $class = $moduleSpec;
 107                  $factory = null;
 108              }
 109  
 110              $this->addModule( $name, $group, $class, $factory );
 111          }
 112      }
 113  
 114      /**
 115       * Add or overwrite a module in this ApiMain instance. Intended for use by extending
 116       * classes who wish to add their own modules to their lexicon or override the
 117       * behavior of inherent ones.
 118       *
 119       * @param string $name The identifier for this module.
 120       * @param string $group Name of the module group
 121       * @param string $class The class where this module is implemented.
 122       * @param callable|null $factory Callback for instantiating the module.
 123       *
 124       * @throws InvalidArgumentException
 125       */
 126  	public function addModule( $name, $group, $class, $factory = null ) {
 127          if ( !is_string( $name ) ) {
 128              throw new InvalidArgumentException( '$name must be a string' );
 129          }
 130  
 131          if ( !is_string( $group ) ) {
 132              throw new InvalidArgumentException( '$group must be a string' );
 133          }
 134  
 135          if ( !is_string( $class ) ) {
 136              throw new InvalidArgumentException( '$class must be a string' );
 137          }
 138  
 139          if ( $factory !== null && !is_callable( $factory ) ) {
 140              throw new InvalidArgumentException( '$factory must be a callable (or null)' );
 141          }
 142  
 143          $this->mGroups[$group] = null;
 144          $this->mModules[$name] = array( $group, $class, $factory );
 145      }
 146  
 147      /**
 148       * Get module instance by name, or instantiate it if it does not exist
 149       *
 150       * @param string $moduleName Module name
 151       * @param string $group Optionally validate that the module is in a specific group
 152       * @param bool $ignoreCache If true, force-creates a new instance and does not cache it
 153       *
 154       * @return ApiBase|null The new module instance, or null if failed
 155       */
 156  	public function getModule( $moduleName, $group = null, $ignoreCache = false ) {
 157          if ( !isset( $this->mModules[$moduleName] ) ) {
 158              return null;
 159          }
 160  
 161          list( $moduleGroup, $moduleClass, $moduleFactory ) = $this->mModules[$moduleName];
 162  
 163          if ( $group !== null && $moduleGroup !== $group ) {
 164              return null;
 165          }
 166  
 167          if ( !$ignoreCache && isset( $this->mInstances[$moduleName] ) ) {
 168              // already exists
 169              return $this->mInstances[$moduleName];
 170          } else {
 171              // new instance
 172              $instance = $this->instantiateModule( $moduleName, $moduleClass, $moduleFactory );
 173  
 174              if ( !$ignoreCache ) {
 175                  // cache this instance in case it is needed later
 176                  $this->mInstances[$moduleName] = $instance;
 177              }
 178  
 179              return $instance;
 180          }
 181      }
 182  
 183      /**
 184       * Instantiate the module using the given class or factory function.
 185       *
 186       * @param string $name The identifier for this module.
 187       * @param string $class The class where this module is implemented.
 188       * @param callable|null $factory Callback for instantiating the module.
 189       *
 190       * @throws MWException
 191       * @return ApiBase
 192       */
 193  	private function instantiateModule( $name, $class, $factory = null ) {
 194          if ( $factory !== null ) {
 195              // create instance from factory
 196              $instance = call_user_func( $factory, $this->mParent, $name );
 197  
 198              if ( !$instance instanceof $class ) {
 199                  throw new MWException( "The factory function for module $name did not return an instance of $class!" );
 200              }
 201          } else {
 202              // create instance from class name
 203              $instance = new $class( $this->mParent, $name );
 204          }
 205  
 206          return $instance;
 207      }
 208  
 209      /**
 210       * Get an array of modules in a specific group or all if no group is set.
 211       * @param string $group Optional group filter
 212       * @return array List of module names
 213       */
 214  	public function getNames( $group = null ) {
 215          if ( $group === null ) {
 216              return array_keys( $this->mModules );
 217          }
 218          $result = array();
 219          foreach ( $this->mModules as $name => $grpCls ) {
 220              if ( $grpCls[0] === $group ) {
 221                  $result[] = $name;
 222              }
 223          }
 224  
 225          return $result;
 226      }
 227  
 228      /**
 229       * Create an array of (moduleName => moduleClass) for a specific group or for all.
 230       * @param string $group Name of the group to get or null for all
 231       * @return array Name=>class map
 232       */
 233  	public function getNamesWithClasses( $group = null ) {
 234          $result = array();
 235          foreach ( $this->mModules as $name => $grpCls ) {
 236              if ( $group === null || $grpCls[0] === $group ) {
 237                  $result[$name] = $grpCls[1];
 238              }
 239          }
 240  
 241          return $result;
 242      }
 243  
 244      /**
 245       * Returns the class name of the given module
 246       *
 247       * @param string $module Module name
 248       * @return string|bool class name or false if the module does not exist
 249       * @since 1.24
 250       */
 251  	public function getClassName( $module ) {
 252          if ( isset( $this->mModules[$module] ) ) {
 253              return $this->mModules[$module][1];
 254          }
 255  
 256          return false;
 257      }
 258  
 259      /**
 260       * Returns true if the specific module is defined at all or in a specific group.
 261       * @param string $moduleName Module name
 262       * @param string $group Group name to check against, or null to check all groups,
 263       * @return bool True if defined
 264       */
 265  	public function isDefined( $moduleName, $group = null ) {
 266          if ( isset( $this->mModules[$moduleName] ) ) {
 267              return $group === null || $this->mModules[$moduleName][0] === $group;
 268          }
 269  
 270          return false;
 271      }
 272  
 273      /**
 274       * Returns the group name for the given module
 275       * @param string $moduleName
 276       * @return string Group name or null if missing
 277       */
 278  	public function getModuleGroup( $moduleName ) {
 279          if ( isset( $this->mModules[$moduleName] ) ) {
 280              return $this->mModules[$moduleName][0];
 281          }
 282  
 283          return null;
 284      }
 285  
 286      /**
 287       * Get a list of groups this manager contains.
 288       * @return array
 289       */
 290  	public function getGroups() {
 291          return array_keys( $this->mGroups );
 292      }
 293  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1