API module manager and help rewrite
This is a non-versioned part of the larger patch #41014 https://gerrit.wikimedia.org/r/#/c/41014 It will allow help subsystem optimization (merging paraminfo and help), path towards per-module or per-system versioning, removal of the manually maintained generator lists. Changes: * ApiModuleManager now handles all submodules (actions,props,lists) and instantiation * ApiModuleManager maintains a cache of all instantiated modules * Query stores prop/list/meta as submodules * action=help suports generalized submodules (modules=query+value), querymodules obsolete Change-Id: Ie2dee41e44a29cd5d5935eeaa5240b708d95a8f0
This commit is contained in:
parent
549311b205
commit
a97bb3acfa
8 changed files with 389 additions and 192 deletions
|
|
@ -194,11 +194,14 @@ production.
|
|||
* (bug 43849) ApiQueryImageInfo no longer throws exceptions with ForeignDBRepo
|
||||
redirects.
|
||||
* On error, any warnings generated before that error will be shown in the result.
|
||||
* action=help suports generalized submodules (modules=query+value), querymodules obsolete
|
||||
|
||||
=== API internal changes in 1.21 ===
|
||||
* For debugging only, a new global $wgDebugAPI removes many API restrictions when true.
|
||||
Never use on the production servers, as this flag introduces security holes.
|
||||
Whenever enabled, a warning will also be added to all output.
|
||||
* ApiModuleManager now handles all submodules (actions,props,lists) and instantiation
|
||||
* Query stores prop/list/meta as submodules
|
||||
|
||||
=== Languages updated in 1.21 ===
|
||||
|
||||
|
|
|
|||
|
|
@ -363,6 +363,7 @@ $wgAutoloadLocalClasses = array(
|
|||
'ApiLogin' => 'includes/api/ApiLogin.php',
|
||||
'ApiLogout' => 'includes/api/ApiLogout.php',
|
||||
'ApiMain' => 'includes/api/ApiMain.php',
|
||||
'ApiModuleManager' => 'includes/api/ApiModuleManager.php',
|
||||
'ApiMove' => 'includes/api/ApiMove.php',
|
||||
'ApiOpenSearch' => 'includes/api/ApiOpenSearch.php',
|
||||
'ApiOptions' => 'includes/api/ApiOptions.php',
|
||||
|
|
|
|||
|
|
@ -127,6 +127,16 @@ abstract class ApiBase extends ContextSource {
|
|||
return $this->mModuleName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the module manager, or null if this module has no sub-modules
|
||||
* @since 1.21
|
||||
* @return ApiModuleManager
|
||||
*/
|
||||
public function getModuleManager() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter prefix (usually two letters or an empty string).
|
||||
* @return string
|
||||
|
|
@ -258,6 +268,8 @@ abstract class ApiBase extends ContextSource {
|
|||
}
|
||||
$msg = $lnPrfx . implode( $lnPrfx, $msg ) . "\n";
|
||||
|
||||
$msg .= $this->makeHelpArrayToString( $lnPrfx, false, $this->getHelpUrls() );
|
||||
|
||||
if ( $this->isReadMode() ) {
|
||||
$msg .= "\nThis module requires read rights";
|
||||
}
|
||||
|
|
@ -301,8 +313,6 @@ abstract class ApiBase extends ContextSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$msg .= $this->makeHelpArrayToString( $lnPrfx, "Help page", $this->getHelpUrls() );
|
||||
}
|
||||
|
||||
return $msg;
|
||||
|
|
|
|||
|
|
@ -43,43 +43,62 @@ class ApiHelp extends ApiBase {
|
|||
}
|
||||
|
||||
$this->getMain()->setHelp();
|
||||
|
||||
$result = $this->getResult();
|
||||
$queryObj = new ApiQuery( $this->getMain(), 'query' );
|
||||
$r = array();
|
||||
|
||||
if ( is_array( $params['modules'] ) ) {
|
||||
$modArr = $this->getMain()->getModules();
|
||||
|
||||
foreach ( $params['modules'] as $m ) {
|
||||
if ( !isset( $modArr[$m] ) ) {
|
||||
$r[] = array( 'name' => $m, 'missing' => '' );
|
||||
continue;
|
||||
}
|
||||
$module = new $modArr[$m]( $this->getMain(), $m );
|
||||
|
||||
$r[] = $this->buildModuleHelp( $module, 'action' );
|
||||
}
|
||||
$modules = $params['modules'];
|
||||
} else {
|
||||
$modules = array();
|
||||
}
|
||||
|
||||
if ( is_array( $params['querymodules'] ) ) {
|
||||
$qmodArr = $queryObj->getModules();
|
||||
$queryModules = $params['querymodules'];
|
||||
foreach ( $queryModules as $m ) {
|
||||
$modules[] = 'query+' . $m;
|
||||
}
|
||||
} else {
|
||||
$queryModules = array();
|
||||
}
|
||||
|
||||
foreach ( $params['querymodules'] as $qm ) {
|
||||
if ( !isset( $qmodArr[$qm] ) ) {
|
||||
$r[] = array( 'name' => $qm, 'missing' => '' );
|
||||
continue;
|
||||
$r = array();
|
||||
foreach ( $modules as $m ) {
|
||||
// sub-modules could be given in the form of "name[+name[+name...]]"
|
||||
$subNames = explode( '+', $m );
|
||||
if ( count( $subNames ) === 1 ) {
|
||||
// In case the '+' was typed into URL, it resolves as a space
|
||||
$subNames = explode( ' ', $m );
|
||||
}
|
||||
$module = $this->getMain();
|
||||
for ( $i = 0; $i < count( $subNames ); $i++ ) {
|
||||
$subs = $module->getModuleManager();
|
||||
if ( $subs === null ) {
|
||||
$module = null;
|
||||
} else {
|
||||
$module = $subs->getModule( $subNames[$i] );
|
||||
}
|
||||
$module = new $qmodArr[$qm]( $this, $qm );
|
||||
$type = $queryObj->getModuleType( $qm );
|
||||
|
||||
if ( $type === null ) {
|
||||
$r[] = array( 'name' => $qm, 'missing' => '' );
|
||||
continue;
|
||||
if ( $module === null ) {
|
||||
if ( count( $subNames ) === 2
|
||||
&& $i === 1
|
||||
&& $subNames[0] === 'query'
|
||||
&& in_array( $subNames[1], $queryModules )
|
||||
) {
|
||||
// Legacy: This is one of the renamed 'querymodule=...' parameters,
|
||||
// do not use '+' notation in the output, use submodule's name instead.
|
||||
$name = $subNames[1];
|
||||
} else {
|
||||
$name = implode( '+', array_slice( $subNames, 0, $i + 1 ) );
|
||||
}
|
||||
$r[] = array( 'name' => $name, 'missing' => '' );
|
||||
break;
|
||||
} else {
|
||||
$type = $subs->getModuleGroup( $subNames[$i] );
|
||||
}
|
||||
|
||||
}
|
||||
if ( $module !== null ) {
|
||||
$r[] = $this->buildModuleHelp( $module, $type );
|
||||
}
|
||||
}
|
||||
|
||||
$result->setIndexedTagName( $r, 'module' );
|
||||
$result->addValue( null, $this->getModuleName(), $r );
|
||||
}
|
||||
|
|
@ -114,15 +133,16 @@ class ApiHelp extends ApiBase {
|
|||
ApiBase::PARAM_ISMULTI => true
|
||||
),
|
||||
'querymodules' => array(
|
||||
ApiBase::PARAM_ISMULTI => true
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_DEPRECATED => true
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function getParamDescription() {
|
||||
return array(
|
||||
'modules' => 'List of module names (value of the action= parameter)',
|
||||
'querymodules' => 'List of query module names (value of prop=, meta= or list= parameter)',
|
||||
'modules' => 'List of module names (value of the action= parameter). Can specify submodules with a \'+\'',
|
||||
'querymodules' => 'Use modules=query+value instead. List of query module names (value of prop=, meta= or list= parameter)',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -134,9 +154,8 @@ class ApiHelp extends ApiBase {
|
|||
return array(
|
||||
'api.php?action=help' => 'Whole help page',
|
||||
'api.php?action=help&modules=protect' => 'Module (action) help page',
|
||||
'api.php?action=help&querymodules=categorymembers' => 'Query (list) modules help page',
|
||||
'api.php?action=help&querymodules=info' => 'Query (prop) modules help page',
|
||||
'api.php?action=help&querymodules=siteinfo' => 'Query (meta) modules help page',
|
||||
'api.php?action=help&modules=query+categorymembers' => 'Help for the query/categorymembers module',
|
||||
'api.php?action=help&modules=login|query+info' => 'Help for the login and query/info modules',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,8 +131,9 @@ class ApiMain extends ApiBase {
|
|||
*/
|
||||
private $mPrinter;
|
||||
|
||||
private $mModules, $mModuleNames, $mFormats, $mFormatNames;
|
||||
private $mResult, $mAction, $mEnableWrite;
|
||||
private $mModuleMgr, $mResult;
|
||||
private $mAction;
|
||||
private $mEnableWrite;
|
||||
private $mInternalMode, $mSquidMaxage, $mModule;
|
||||
|
||||
private $mCacheMode = 'private';
|
||||
|
|
@ -180,12 +181,11 @@ class ApiMain extends ApiBase {
|
|||
}
|
||||
}
|
||||
|
||||
global $wgAPIModules; // extension modules
|
||||
$this->mModules = $wgAPIModules + self::$Modules;
|
||||
|
||||
$this->mModuleNames = array_keys( $this->mModules );
|
||||
$this->mFormats = self::$Formats;
|
||||
$this->mFormatNames = array_keys( $this->mFormats );
|
||||
global $wgAPIModules;
|
||||
$this->mModuleMgr = new ApiModuleManager( $this );
|
||||
$this->mModuleMgr->addModules( self::$Modules, 'action' );
|
||||
$this->mModuleMgr->addModules( $wgAPIModules, 'action' );
|
||||
$this->mModuleMgr->addModules( self::$Formats, 'format' );
|
||||
|
||||
$this->mResult = new ApiResult( $this );
|
||||
$this->mEnableWrite = $enableWrite;
|
||||
|
|
@ -332,10 +332,11 @@ class ApiMain extends ApiBase {
|
|||
* @return ApiFormatBase
|
||||
*/
|
||||
public function createPrinterByName( $format ) {
|
||||
if ( !isset( $this->mFormats[$format] ) ) {
|
||||
$printer = $this->mModuleMgr->getModule( $format, 'format' );
|
||||
if ( $printer === null ) {
|
||||
$this->dieUsage( "Unrecognized format: {$format}", 'unknown_format' );
|
||||
}
|
||||
return new $this->mFormats[$format] ( $this, $format );
|
||||
return $printer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -604,7 +605,7 @@ class ApiMain extends ApiBase {
|
|||
if ( !isset ( $this->mPrinter ) ) {
|
||||
// The printer has not been created yet. Try to manually get formatter value.
|
||||
$value = $this->getRequest()->getVal( 'format', self::API_DEFAULT_FORMAT );
|
||||
if ( !in_array( $value, $this->mFormatNames ) ) {
|
||||
if ( !$this->mModuleMgr->isDefined( $value, 'format' ) ) {
|
||||
$value = self::API_DEFAULT_FORMAT;
|
||||
}
|
||||
|
||||
|
|
@ -700,9 +701,10 @@ class ApiMain extends ApiBase {
|
|||
*/
|
||||
protected function setupModule() {
|
||||
// Instantiate the module requested by the user
|
||||
$module = new $this->mModules[$this->mAction] ( $this, $this->mAction );
|
||||
$this->mModule = $module;
|
||||
|
||||
$module = $this->mModuleMgr->getModule( $this->mAction, 'action' );
|
||||
if ( $module === null ) {
|
||||
$this->dieUsage( 'The API requires a valid action parameter', 'unknown_action' );
|
||||
}
|
||||
$moduleParams = $module->extractRequestParams();
|
||||
|
||||
// Die if token required, but not provided (unless there is a gettoken parameter)
|
||||
|
|
@ -814,6 +816,7 @@ class ApiMain extends ApiBase {
|
|||
protected function executeAction() {
|
||||
$params = $this->setupExecuteAction();
|
||||
$module = $this->setupModule();
|
||||
$this->mModule = $module;
|
||||
|
||||
$this->checkExecutePermissions( $module );
|
||||
|
||||
|
|
@ -971,11 +974,11 @@ class ApiMain extends ApiBase {
|
|||
return array(
|
||||
'format' => array(
|
||||
ApiBase::PARAM_DFLT => ApiMain::API_DEFAULT_FORMAT,
|
||||
ApiBase::PARAM_TYPE => $this->mFormatNames
|
||||
ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'format' )
|
||||
),
|
||||
'action' => array(
|
||||
ApiBase::PARAM_DFLT => 'help',
|
||||
ApiBase::PARAM_TYPE => $this->mModuleNames
|
||||
ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'action' )
|
||||
),
|
||||
'maxlag' => array(
|
||||
ApiBase::PARAM_TYPE => 'integer'
|
||||
|
|
@ -1092,7 +1095,7 @@ class ApiMain extends ApiBase {
|
|||
' Victor Vasiliev - vasilvv at gee mail dot com',
|
||||
' Bryan Tong Minh - bryan . tongminh @ gmail . com',
|
||||
' Sam Reed - sam @ reedyboy . net',
|
||||
' Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007)',
|
||||
' Yuri Astrakhan "<Firstname><Lastname>@gmail.com" (creator, lead developer Sep 2006-Sep 2007, 2012)',
|
||||
'',
|
||||
'Please send your comments, suggestions and questions to mediawiki-api@lists.wikimedia.org',
|
||||
'or file a bug report at https://bugzilla.wikimedia.org/'
|
||||
|
|
@ -1143,8 +1146,9 @@ class ApiMain extends ApiBase {
|
|||
|
||||
$astriks = str_repeat( '*** ', 14 );
|
||||
$msg .= "\n\n$astriks Modules $astriks\n\n";
|
||||
foreach ( array_keys( $this->mModules ) as $moduleName ) {
|
||||
$module = new $this->mModules[$moduleName] ( $this, $moduleName );
|
||||
|
||||
foreach ( $this->mModuleMgr->getNames( 'action' ) as $name ) {
|
||||
$module = $this->mModuleMgr->getModule( $name );
|
||||
$msg .= self::makeHelpMsgHeader( $module, 'action' );
|
||||
|
||||
$msg2 = $module->makeHelpMsg();
|
||||
|
|
@ -1162,8 +1166,8 @@ class ApiMain extends ApiBase {
|
|||
}
|
||||
|
||||
$msg .= "\n$astriks Formats $astriks\n\n";
|
||||
foreach ( array_keys( $this->mFormats ) as $formatName ) {
|
||||
$module = $this->createPrinterByName( $formatName );
|
||||
foreach ( $this->mModuleMgr->getNames( 'format' ) as $name ) {
|
||||
$module = $this->mModuleMgr->getModule( $name );
|
||||
$msg .= self::makeHelpMsgHeader( $module, 'format' );
|
||||
$msg2 = $module->makeHelpMsg();
|
||||
if ( $msg2 !== false ) {
|
||||
|
|
@ -1215,45 +1219,57 @@ class ApiMain extends ApiBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides to return this instance's module manager.
|
||||
* @return ApiModuleManager
|
||||
*/
|
||||
public function getModuleManager() {
|
||||
return $this->mModuleMgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or overwrite a module in this ApiMain instance. Intended for use by extending
|
||||
* classes who wish to add their own modules to their lexicon or override the
|
||||
* behavior of inherent ones.
|
||||
*
|
||||
* @param $mdlName String The identifier for this module.
|
||||
* @param $mdlClass String The class where this module is implemented.
|
||||
* @deprecated since 1.21, Use getModuleManager()->addModule() instead.
|
||||
* @param $name string The identifier for this module.
|
||||
* @param $class ApiBase The class where this module is implemented.
|
||||
*/
|
||||
protected function addModule( $mdlName, $mdlClass ) {
|
||||
$this->mModules[$mdlName] = $mdlClass;
|
||||
protected function addModule( $name, $class ) {
|
||||
$this->getModuleManager()->addModule( $name, 'action', $class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or overwrite an output format for this ApiMain. Intended for use by extending
|
||||
* classes who wish to add to or modify current formatters.
|
||||
*
|
||||
* @param $fmtName string The identifier for this format.
|
||||
* @param $fmtClass ApiFormatBase The class implementing this format.
|
||||
* @deprecated since 1.21, Use getModuleManager()->addModule() instead.
|
||||
* @param $name string The identifier for this format.
|
||||
* @param $class ApiFormatBase The class implementing this format.
|
||||
*/
|
||||
protected function addFormat( $fmtName, $fmtClass ) {
|
||||
$this->mFormats[$fmtName] = $fmtClass;
|
||||
protected function addFormat( $name, $class ) {
|
||||
$this->getModuleManager->addModule( $name, 'format', $class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array mapping module names to class names
|
||||
* @deprecated since 1.21, Use getModuleManager()'s methods instead.
|
||||
* @return array
|
||||
*/
|
||||
function getModules() {
|
||||
return $this->mModules;
|
||||
return $this->getModuleManager()->getNamesWithClasses( 'action' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported formats in form ( 'format' => 'ClassName' )
|
||||
*
|
||||
* @since 1.18
|
||||
* @deprecated since 1.21, Use getModuleManager()'s methods instead.
|
||||
* @return array
|
||||
*/
|
||||
public function getFormats() {
|
||||
return $this->mFormats;
|
||||
return $this->getModuleManager()->getNamesWithClasses( 'format' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
171
includes/api/ApiModuleManager.php
Normal file
171
includes/api/ApiModuleManager.php
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Created on Dec 27, 2012
|
||||
*
|
||||
* Copyright © 2012 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
* @since 1.21
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class holds a list of modules and handles instantiation
|
||||
*
|
||||
* @since 1.21
|
||||
* @ingroup API
|
||||
*/
|
||||
class ApiModuleManager extends ContextSource {
|
||||
|
||||
private $mParent;
|
||||
private $mInstances = array();
|
||||
private $mGroups = array();
|
||||
private $mModules = array();
|
||||
|
||||
/**
|
||||
* Construct new module manager
|
||||
* @param ApiBase $parentModule Parent module instance will be used during instantiation
|
||||
*/
|
||||
public function __construct( ApiBase $parentModule ) {
|
||||
$this->mParent = $parentModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a list of modules to the manager
|
||||
* @param array $modules A map of ModuleName => ModuleClass
|
||||
* @param string $group Which group modules belong to (action,format,...)
|
||||
*/
|
||||
public function addModules( array $modules, $group ) {
|
||||
foreach ( $modules as $name => $class ) {
|
||||
$this->addModule( $name, $group, $class );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or overwrite a module in this ApiMain instance. Intended for use by extending
|
||||
* classes who wish to add their own modules to their lexicon or override the
|
||||
* behavior of inherent ones.
|
||||
*
|
||||
* @param $group string Name of the module group
|
||||
* @param $name string The identifier for this module.
|
||||
* @param $class string The class where this module is implemented.
|
||||
*/
|
||||
public function addModule( $name, $group, $class ) {
|
||||
$this->mGroups[$group] = null;
|
||||
$this->mModules[$name] = array( $group, $class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module instance by name, or instantiate it if it does not exist
|
||||
* @param $moduleName string module name
|
||||
* @param $group string optionally validate that the module is in a specific group
|
||||
* @param $ignoreCache bool if true, force-creates a new instance and does not cache it
|
||||
* @return mixed the new module instance, or null if failed
|
||||
*/
|
||||
public function getModule( $moduleName, $group = null, $ignoreCache = false ) {
|
||||
if ( !isset( $this->mModules[$moduleName] ) ) {
|
||||
return null;
|
||||
}
|
||||
$grpCls = $this->mModules[$moduleName];
|
||||
if ( $group !== null && $grpCls[0] !== $group ) {
|
||||
return null;
|
||||
}
|
||||
if ( !$ignoreCache && isset( $this->mInstances[$moduleName] ) ) {
|
||||
// already exists
|
||||
return $this->mInstances[$moduleName];
|
||||
} else {
|
||||
// new instance
|
||||
$class = $grpCls[1];
|
||||
$instance = new $class ( $this->mParent, $moduleName );
|
||||
if ( !$ignoreCache ) {
|
||||
// cache this instance in case it is needed later
|
||||
$this->mInstances[$moduleName] = $instance;
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of modules in a specific group or all if no group is set.
|
||||
* @param string $group optional group filter
|
||||
* @return array list of module names
|
||||
*/
|
||||
public function getNames( $group = null ) {
|
||||
if ( $group === null ) {
|
||||
return array_keys( $this->mModules );
|
||||
}
|
||||
$result = array();
|
||||
foreach ( $this->mModules as $name => $grpCls ) {
|
||||
if ( $grpCls[0] === $group ) {
|
||||
$result[] = $name;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of (moduleName => moduleClass) for a specific group or for all.
|
||||
* @param string $group name of the group to get or null for all
|
||||
* @return array name=>class map
|
||||
*/
|
||||
public function getNamesWithClasses( $group = null ) {
|
||||
$result = array();
|
||||
foreach ( $this->mModules as $name => $grpCls ) {
|
||||
if ( $group === null || $grpCls[0] === $group ) {
|
||||
$result[$name] = $grpCls[1];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specific module is defined at all or in a specific group.
|
||||
* @param string $moduleName module name
|
||||
* @param string $group group name to check against, or null to check all groups,
|
||||
* @return boolean true if defined
|
||||
*/
|
||||
public function isDefined( $moduleName, $group = null ) {
|
||||
if ( isset( $this->mModules[$moduleName] ) ) {
|
||||
return $group === null || $this->mModules[$moduleName][0] === $group;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the group name for the given module
|
||||
* @param string $moduleName
|
||||
* @return string group name or null if missing
|
||||
*/
|
||||
public function getModuleGroup( $moduleName ) {
|
||||
if ( isset( $this->mModules[$moduleName] ) ) {
|
||||
return $this->mModules[$moduleName][0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of groups this manager contains.
|
||||
* @return array
|
||||
*/
|
||||
public function getGroups() {
|
||||
return array_keys( $this->mGroups );
|
||||
}
|
||||
}
|
||||
|
|
@ -42,42 +42,13 @@ class ApiParamInfo extends ApiBase {
|
|||
public function execute() {
|
||||
// Get parameters
|
||||
$params = $this->extractRequestParams();
|
||||
$result = $this->getResult();
|
||||
$resultObj = $this->getResult();
|
||||
|
||||
$res = array();
|
||||
if ( is_array( $params['modules'] ) ) {
|
||||
$modules = $this->getMain()->getModules();
|
||||
$res['modules'] = array();
|
||||
foreach ( $params['modules'] as $mod ) {
|
||||
if ( !isset( $modules[$mod] ) ) {
|
||||
$res['modules'][] = array( 'name' => $mod, 'missing' => '' );
|
||||
continue;
|
||||
}
|
||||
$obj = new $modules[$mod]( $this->getMain(), $mod );
|
||||
|
||||
$item = $this->getClassInfo( $obj );
|
||||
$item['name'] = $mod;
|
||||
$res['modules'][] = $item;
|
||||
}
|
||||
$result->setIndexedTagName( $res['modules'], 'module' );
|
||||
}
|
||||
$this->addModulesInfo( $params, 'modules', $res, $resultObj );
|
||||
|
||||
if ( is_array( $params['querymodules'] ) ) {
|
||||
$queryModules = $this->queryObj->getModules();
|
||||
$res['querymodules'] = array();
|
||||
foreach ( $params['querymodules'] as $qm ) {
|
||||
if ( !isset( $queryModules[$qm] ) ) {
|
||||
$res['querymodules'][] = array( 'name' => $qm, 'missing' => '' );
|
||||
continue;
|
||||
}
|
||||
$obj = new $queryModules[$qm]( $this, $qm );
|
||||
$item = $this->getClassInfo( $obj );
|
||||
$item['name'] = $qm;
|
||||
$item['querytype'] = $this->queryObj->getModuleType( $qm );
|
||||
$res['querymodules'][] = $item;
|
||||
}
|
||||
$result->setIndexedTagName( $res['querymodules'], 'module' );
|
||||
}
|
||||
$this->addModulesInfo( $params, 'querymodules', $res, $resultObj );
|
||||
|
||||
if ( $params['mainmodule'] ) {
|
||||
$res['mainmodule'] = $this->getClassInfo( $this->getMain() );
|
||||
|
|
@ -88,29 +59,50 @@ class ApiParamInfo extends ApiBase {
|
|||
$res['pagesetmodule'] = $this->getClassInfo( $pageSet );
|
||||
}
|
||||
|
||||
if ( is_array( $params['formatmodules'] ) ) {
|
||||
$formats = $this->getMain()->getFormats();
|
||||
$res['formatmodules'] = array();
|
||||
foreach ( $params['formatmodules'] as $f ) {
|
||||
if ( !isset( $formats[$f] ) ) {
|
||||
$res['formatmodules'][] = array( 'name' => $f, 'missing' => '' );
|
||||
continue;
|
||||
}
|
||||
$obj = new $formats[$f]( $this, $f );
|
||||
$item = $this->getClassInfo( $obj );
|
||||
$item['name'] = $f;
|
||||
$res['formatmodules'][] = $item;
|
||||
}
|
||||
$result->setIndexedTagName( $res['formatmodules'], 'module' );
|
||||
$this->addModulesInfo( $params, 'formatmodules', $res, $resultObj );
|
||||
|
||||
$resultObj->addValue( null, $this->getModuleName(), $res );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the type is requested in parameters, adds a section to res with module info.
|
||||
* @param array $params user parameters array
|
||||
* @param string $type parameter name
|
||||
* @param array $res store results in this array
|
||||
* @param array $resultObj results object to set indexed tag.
|
||||
*/
|
||||
private function addModulesInfo( $params, $type, &$res, $resultObj ) {
|
||||
if ( !is_array( $params[$type] ) ) {
|
||||
return;
|
||||
}
|
||||
$result->addValue( null, $this->getModuleName(), $res );
|
||||
$isQuery = ( $type === 'querymodules' );
|
||||
if ( $isQuery ) {
|
||||
$mgr = $this->queryObj->getModuleManager();
|
||||
} else {
|
||||
$mgr = $this->getMain()->getModuleManager();
|
||||
}
|
||||
$res[$type] = array();
|
||||
foreach ( $params[$type] as $mod ) {
|
||||
if ( !$mgr->isDefined( $mod ) ) {
|
||||
$res[$type][] = array( 'name' => $mod, 'missing' => '' );
|
||||
continue;
|
||||
}
|
||||
$obj = $mgr->getModule( $mod );
|
||||
$item = $this->getClassInfo( $obj );
|
||||
$item['name'] = $mod;
|
||||
if ( $isQuery ) {
|
||||
$item['querytype'] = $mgr->getModuleGroup( $mod );
|
||||
}
|
||||
$res[$type][] = $item;
|
||||
}
|
||||
$resultObj->setIndexedTagName( $res[$type], 'module' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $obj ApiBase
|
||||
* @return ApiResult
|
||||
*/
|
||||
function getClassInfo( $obj ) {
|
||||
private function getClassInfo( $obj ) {
|
||||
$result = $this->getResult();
|
||||
$retval['classname'] = get_class( $obj );
|
||||
$retval['description'] = implode( "\n", (array)$obj->getFinalDescription() );
|
||||
|
|
@ -150,7 +142,7 @@ class ApiParamInfo extends ApiBase {
|
|||
if ( is_string( $examples ) ) {
|
||||
$examples = array( $examples );
|
||||
}
|
||||
foreach( $examples as $k => $v ) {
|
||||
foreach ( $examples as $k => $v ) {
|
||||
if ( strlen( $retval['examples'] ) ) {
|
||||
$retval['examples'] .= ' ';
|
||||
}
|
||||
|
|
@ -181,7 +173,7 @@ class ApiParamInfo extends ApiBase {
|
|||
}
|
||||
|
||||
//handle shorthand
|
||||
if( !is_array( $p ) ) {
|
||||
if ( !is_array( $p ) ) {
|
||||
$p = array(
|
||||
ApiBase::PARAM_DFLT => $p,
|
||||
);
|
||||
|
|
@ -208,11 +200,11 @@ class ApiParamInfo extends ApiBase {
|
|||
|
||||
if ( isset( $p[ApiBase::PARAM_DFLT] ) ) {
|
||||
$type = $p[ApiBase::PARAM_TYPE];
|
||||
if( $type === 'boolean' ) {
|
||||
if ( $type === 'boolean' ) {
|
||||
$a['default'] = ( $p[ApiBase::PARAM_DFLT] ? 'true' : 'false' );
|
||||
} elseif( $type === 'string' ) {
|
||||
} elseif ( $type === 'string' ) {
|
||||
$a['default'] = strval( $p[ApiBase::PARAM_DFLT] );
|
||||
} elseif( $type === 'integer' ) {
|
||||
} elseif ( $type === 'integer' ) {
|
||||
$a['default'] = intval( $p[ApiBase::PARAM_DFLT] );
|
||||
} else {
|
||||
$a['default'] = $p[ApiBase::PARAM_DFLT];
|
||||
|
|
@ -319,11 +311,11 @@ class ApiParamInfo extends ApiBase {
|
|||
}
|
||||
|
||||
public function getAllowedParams() {
|
||||
$modules = array_keys( $this->getMain()->getModules() );
|
||||
$modules = $this->getMain()->getModuleManager()->getNames( 'action' );
|
||||
sort( $modules );
|
||||
$querymodules = array_keys( $this->queryObj->getModules() );
|
||||
$querymodules = $this->queryObj->getModuleManager()->getNames();
|
||||
sort( $querymodules );
|
||||
$formatmodules = array_keys( $this->getMain()->getFormats() );
|
||||
$formatmodules = $this->getMain()->getModuleManager()->getNames( 'format' );
|
||||
sort( $formatmodules );
|
||||
return array(
|
||||
'modules' => array(
|
||||
|
|
|
|||
|
|
@ -37,20 +37,11 @@
|
|||
*/
|
||||
class ApiQuery extends ApiBase {
|
||||
|
||||
private $mPropModuleNames, $mListModuleNames, $mMetaModuleNames;
|
||||
|
||||
/**
|
||||
* @var ApiPageSet
|
||||
*/
|
||||
private $mPageSet;
|
||||
|
||||
private $params, $redirects, $convertTitles, $iwUrl;
|
||||
|
||||
/**
|
||||
* List of Api Query prop modules
|
||||
* @var array
|
||||
*/
|
||||
private $mQueryPropModules = array(
|
||||
private static $QueryPropModules = array(
|
||||
'categories' => 'ApiQueryCategories',
|
||||
'categoryinfo' => 'ApiQueryCategoryInfo',
|
||||
'duplicatefiles' => 'ApiQueryDuplicateFiles',
|
||||
|
|
@ -71,7 +62,7 @@ class ApiQuery extends ApiBase {
|
|||
* List of Api Query list modules
|
||||
* @var array
|
||||
*/
|
||||
private $mQueryListModules = array(
|
||||
private static $QueryListModules = array(
|
||||
'allcategories' => 'ApiQueryAllCategories',
|
||||
'allimages' => 'ApiQueryAllImages',
|
||||
'alllinks' => 'ApiQueryAllLinks',
|
||||
|
|
@ -105,7 +96,7 @@ class ApiQuery extends ApiBase {
|
|||
* List of Api Query meta modules
|
||||
* @var array
|
||||
*/
|
||||
private $mQueryMetaModules = array(
|
||||
private static $QueryMetaModules = array(
|
||||
'allmessages' => 'ApiQueryAllMessages',
|
||||
'siteinfo' => 'ApiQuerySiteinfo',
|
||||
'userinfo' => 'ApiQueryUserInfo',
|
||||
|
|
@ -144,8 +135,15 @@ class ApiQuery extends ApiBase {
|
|||
'watchlistraw' => 'ApiQueryWatchlistRaw',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var ApiPageSet
|
||||
*/
|
||||
private $mPageSet;
|
||||
|
||||
private $params, $redirects, $convertTitles, $iwUrl;
|
||||
private $mSlaveDB = null;
|
||||
private $mNamedDB = array();
|
||||
private $mModuleMgr;
|
||||
|
||||
protected $mAllowedGenerators;
|
||||
|
||||
|
|
@ -156,30 +154,32 @@ class ApiQuery extends ApiBase {
|
|||
public function __construct( $main, $action ) {
|
||||
parent::__construct( $main, $action );
|
||||
|
||||
// Allow custom modules to be added in LocalSettings.php
|
||||
global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules, $wgAPIGeneratorModules;
|
||||
self::appendUserModules( $this->mQueryPropModules, $wgAPIPropModules );
|
||||
self::appendUserModules( $this->mQueryListModules, $wgAPIListModules );
|
||||
self::appendUserModules( $this->mQueryMetaModules, $wgAPIMetaModules );
|
||||
self::appendUserModules( $this->mQueryGenerators, $wgAPIGeneratorModules );
|
||||
$this->mModuleMgr = new ApiModuleManager( $this );
|
||||
|
||||
$this->mPropModuleNames = array_keys( $this->mQueryPropModules );
|
||||
$this->mListModuleNames = array_keys( $this->mQueryListModules );
|
||||
$this->mMetaModuleNames = array_keys( $this->mQueryMetaModules );
|
||||
// Allow custom modules to be added in LocalSettings.php
|
||||
global $wgAPIPropModules, $wgAPIListModules, $wgAPIMetaModules;
|
||||
$this->mModuleMgr->addModules( self::$QueryPropModules, 'prop' );
|
||||
$this->mModuleMgr->addModules( $wgAPIPropModules, 'prop' );
|
||||
$this->mModuleMgr->addModules( self::$QueryListModules, 'list' );
|
||||
$this->mModuleMgr->addModules( $wgAPIListModules, 'list' );
|
||||
$this->mModuleMgr->addModules( self::$QueryMetaModules, 'meta' );
|
||||
$this->mModuleMgr->addModules( $wgAPIMetaModules, 'meta' );
|
||||
|
||||
global $wgAPIGeneratorModules;
|
||||
if ( is_array( $wgAPIGeneratorModules ) ) {
|
||||
foreach ( $wgAPIGeneratorModules as $moduleName => $moduleClass ) {
|
||||
$this->mQueryGenerators[$moduleName] = $moduleClass;
|
||||
}
|
||||
}
|
||||
$this->mAllowedGenerators = array_keys( $this->mQueryGenerators );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to append any add-in modules to the list
|
||||
* @param $modules array Module array
|
||||
* @param $newModules array Module array to add to $modules
|
||||
* Overrides to return this instance's module manager.
|
||||
* @return ApiModuleManager
|
||||
*/
|
||||
private static function appendUserModules( &$modules, $newModules ) {
|
||||
if ( is_array( $newModules ) ) {
|
||||
foreach ( $newModules as $moduleName => $moduleClass ) {
|
||||
$modules[$moduleName] = $moduleClass;
|
||||
}
|
||||
}
|
||||
public function getModuleManager() {
|
||||
return $this->mModuleMgr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -224,10 +224,11 @@ class ApiQuery extends ApiBase {
|
|||
|
||||
/**
|
||||
* Get the array mapping module names to class names
|
||||
* @deprecated since 1.21, use getModuleManager()'s methods instead
|
||||
* @return array array(modulename => classname)
|
||||
*/
|
||||
public function getModules() {
|
||||
return array_merge( $this->mQueryPropModules, $this->mQueryListModules, $this->mQueryMetaModules );
|
||||
return $this->getModuleManager()->getNamesWithClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,23 +241,12 @@ class ApiQuery extends ApiBase {
|
|||
|
||||
/**
|
||||
* Get whether the specified module is a prop, list or a meta query module
|
||||
* @deprecated since 1.21, use getModuleManager()->getModuleGroup()
|
||||
* @param $moduleName string Name of the module to find type for
|
||||
* @return mixed string or null
|
||||
*/
|
||||
function getModuleType( $moduleName ) {
|
||||
if ( isset( $this->mQueryPropModules[$moduleName] ) ) {
|
||||
return 'prop';
|
||||
}
|
||||
|
||||
if ( isset( $this->mQueryListModules[$moduleName] ) ) {
|
||||
return 'list';
|
||||
}
|
||||
|
||||
if ( isset( $this->mQueryMetaModules[$moduleName] ) ) {
|
||||
return 'meta';
|
||||
}
|
||||
|
||||
return null;
|
||||
return $this->getModuleManager()->getModuleGroup( $moduleName );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -295,9 +285,9 @@ class ApiQuery extends ApiBase {
|
|||
|
||||
// Instantiate requested modules
|
||||
$modules = array();
|
||||
$this->instantiateModules( $modules, 'prop', $this->mQueryPropModules );
|
||||
$this->instantiateModules( $modules, 'list', $this->mQueryListModules );
|
||||
$this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules );
|
||||
$this->instantiateModules( $modules, 'prop' );
|
||||
$this->instantiateModules( $modules, 'list' );
|
||||
$this->instantiateModules( $modules, 'meta' );
|
||||
|
||||
$cacheMode = 'public';
|
||||
|
||||
|
|
@ -378,12 +368,11 @@ class ApiQuery extends ApiBase {
|
|||
* Create instances of all modules requested by the client
|
||||
* @param $modules Array to append instantiated modules to
|
||||
* @param $param string Parameter name to read modules from
|
||||
* @param $moduleList Array array(modulename => classname)
|
||||
*/
|
||||
private function instantiateModules( &$modules, $param, $moduleList ) {
|
||||
private function instantiateModules( &$modules, $param ) {
|
||||
if ( isset( $this->params[$param] ) ) {
|
||||
foreach ( $this->params[$param] as $moduleName ) {
|
||||
$modules[] = new $moduleList[$moduleName] ( $this, $moduleName );
|
||||
$modules[] = $this->mModuleMgr->getModule( $moduleName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -594,15 +583,10 @@ class ApiQuery extends ApiBase {
|
|||
* @return ApiQueryGeneratorBase
|
||||
*/
|
||||
public function newGenerator( $generatorName ) {
|
||||
// Find class that implements requested generator
|
||||
if ( isset( $this->mQueryListModules[$generatorName] ) ) {
|
||||
$className = $this->mQueryListModules[$generatorName];
|
||||
} elseif ( isset( $this->mQueryPropModules[$generatorName] ) ) {
|
||||
$className = $this->mQueryPropModules[$generatorName];
|
||||
} else {
|
||||
ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" );
|
||||
$generator = $this->mModuleMgr->getModule( $generatorName );
|
||||
if ( $generator === null ) {
|
||||
$this->dieUsage( "Unknown generator=$generatorName", 'badgenerator' );
|
||||
}
|
||||
$generator = new $className ( $this, $generatorName );
|
||||
if ( !$generator instanceof ApiQueryGeneratorBase ) {
|
||||
$this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
|
||||
}
|
||||
|
|
@ -642,15 +626,15 @@ class ApiQuery extends ApiBase {
|
|||
return array(
|
||||
'prop' => array(
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TYPE => $this->mPropModuleNames
|
||||
ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'prop' )
|
||||
),
|
||||
'list' => array(
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TYPE => $this->mListModuleNames
|
||||
ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'list' )
|
||||
),
|
||||
'meta' => array(
|
||||
ApiBase::PARAM_ISMULTI => true,
|
||||
ApiBase::PARAM_TYPE => $this->mMetaModuleNames
|
||||
ApiBase::PARAM_TYPE => $this->mModuleMgr->getNames( 'meta' )
|
||||
),
|
||||
'generator' => array(
|
||||
ApiBase::PARAM_TYPE => $this->mAllowedGenerators
|
||||
|
|
@ -676,11 +660,11 @@ class ApiQuery extends ApiBase {
|
|||
$querySeparator = str_repeat( '--- ', 12 );
|
||||
$moduleSeparator = str_repeat( '*** ', 14 );
|
||||
$msg = "\n$querySeparator Query: Prop $querySeparator\n\n";
|
||||
$msg .= $this->makeHelpMsgHelper( $this->mQueryPropModules, 'prop' );
|
||||
$msg .= $this->makeHelpMsgHelper( 'prop' );
|
||||
$msg .= "\n$querySeparator Query: List $querySeparator\n\n";
|
||||
$msg .= $this->makeHelpMsgHelper( $this->mQueryListModules, 'list' );
|
||||
$msg .= $this->makeHelpMsgHelper( 'list' );
|
||||
$msg .= "\n$querySeparator Query: Meta $querySeparator\n\n";
|
||||
$msg .= $this->makeHelpMsgHelper( $this->mQueryMetaModules, 'meta' );
|
||||
$msg .= $this->makeHelpMsgHelper( 'meta' );
|
||||
$msg .= "\n\n$moduleSeparator Modules: continuation $moduleSeparator\n\n";
|
||||
|
||||
// Use parent to make default message for the query module
|
||||
|
|
@ -690,21 +674,22 @@ class ApiQuery extends ApiBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* For all modules in $moduleList, generate help messages and join them together
|
||||
* @param $moduleList Array array(modulename => classname)
|
||||
* @param $paramName string Parameter name
|
||||
* For all modules of a given group, generate help messages and join them together
|
||||
* @param $group string Module group
|
||||
* @return string
|
||||
*/
|
||||
private function makeHelpMsgHelper( $moduleList, $paramName ) {
|
||||
private function makeHelpMsgHelper( $group ) {
|
||||
$moduleDescriptions = array();
|
||||
|
||||
foreach ( $moduleList as $moduleName => $moduleClass ) {
|
||||
$moduleNames = $this->mModuleMgr->getNames( $group );
|
||||
sort( $moduleNames );
|
||||
foreach ( $moduleNames as $name ) {
|
||||
/**
|
||||
* @var $module ApiQueryBase
|
||||
*/
|
||||
$module = new $moduleClass( $this, $moduleName, null );
|
||||
$module = $this->mModuleMgr->getModule( $name );
|
||||
|
||||
$msg = ApiMain::makeHelpMsgHeader( $module, $paramName );
|
||||
$msg = ApiMain::makeHelpMsgHeader( $module, $group );
|
||||
$msg2 = $module->makeHelpMsg();
|
||||
if ( $msg2 !== false ) {
|
||||
$msg .= $msg2;
|
||||
|
|
|
|||
Loading…
Reference in a new issue