From e7ad7f3d41618b908e806251d9efb64e1e6008d9 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 8 Sep 2006 14:27:58 +0000 Subject: [PATCH] * Non-working API to facilitate dev collaboration. Do not enable this yet in localsettings.php. --- api.php | 87 ++++++++++++++ includes/api/ApiBase.php | 196 +++++++++++++++++++++++++++++++ includes/api/ApiHelp.php | 48 ++++++++ includes/api/ApiMain.php | 100 ++++++++++++++++ includes/api/ApiQuery.php | 104 ++++++++++++++++ includes/api/ApiQueryBase.php | 48 ++++++++ includes/api/ApiQueryContent.php | 90 ++++++++++++++ includes/api/ApiResult.php | 115 ++++++++++++++++++ 8 files changed, 788 insertions(+) create mode 100644 api.php create mode 100644 includes/api/ApiBase.php create mode 100644 includes/api/ApiHelp.php create mode 100644 includes/api/ApiMain.php create mode 100644 includes/api/ApiQuery.php create mode 100644 includes/api/ApiQueryBase.php create mode 100644 includes/api/ApiQueryContent.php create mode 100644 includes/api/ApiResult.php diff --git a/api.php b/api.php new file mode 100644 index 0000000000..a286134574 --- /dev/null +++ b/api.php @@ -0,0 +1,87 @@ + +* +* 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., +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* http://www.gnu.org/copyleft/gpl.html +*/ + +$apiStartTime = microtime(true); + +/** + * List of classes and containing files. + */ +$apiAutoloadClasses = array ( + 'ApiBase' => 'includes/api/ApiBase.php', + 'ApiMain' => 'includes/api/ApiMain.php', + 'ApiResult' => 'includes/api/ApiResult.php', + + // Available modules - should match the $apiModules list + 'ApiHelp' => 'includes/api/ApiHelp.php', + 'ApiLogin' => 'includes/api/ApiLogin.php', + 'ApiQuery' => 'includes/api/ApiQuery.php' +); + +/** + * List of available modules: action name => module class + * The class must also be listed in the $apiAutoloadClasses array. + */ +$apiModules = array ( + 'help' => 'ApiHelp', + 'login' => 'ApiLogin', + 'query' => 'ApiQuery' +); + + +// Initialise common code +require_once ('./includes/WebStart.php'); +wfProfileIn('api.php'); + + +// Verify that the API has not been disabled +// The next line should be +// if (isset ($wgEnableAPI) && !$wgEnableAPI) { +// but will be in a safe mode until api is stabler +if (!isset ($wgEnableAPI) || !$wgEnableAPI) { + echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php'; + echo '
$wgEnableAPI=true;
'; + die(-1); +} + + +ApiInitAutoloadClasses($apiAutoloadClasses); +$processor = new ApiMain($apiStartTime, $apiModules); +$processor->Execute(); + +wfProfileOut('api.php'); +wfLogProfilingData(); +exit; // Done! + + +function ApiInitAutoloadClasses($apiAutoloadClasses) { + + // Append $apiAutoloadClasses to $wgAutoloadClasses + global $wgAutoloadClasses; + if (isset ($wgAutoloadClasses)) { + $wgAutoloadClasses = array_merge($wgAutoloadClasses, $apiAutoloadClasses); + } else { + $wgAutoloadClasses = $apiAutoloadClasses; + } +} +?> diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php new file mode 100644 index 0000000000..e482be45f1 --- /dev/null +++ b/includes/api/ApiBase.php @@ -0,0 +1,196 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +// Multi-valued enums, limit the values user can supply for the parameter +define('GN_ENUM_DFLT', 0); +define('GN_ENUM_ISMULTI', 1); +define('GN_ENUM_CHOICES', 2); + +abstract class ApiBase { + + private $mMainModule; + + /** + * Constructor + */ + public function __construct($mainModule) { + $this->mMainModule = $mainModule; + } + + /** + * Executes this module + */ + abstract function Execute(); + + /** + * Get main module + */ + public function GetMain() { + return $this->mMainModule; + } + + /** + * If this module's $this is the same as $this->mMainModule, its the root, otherwise no + */ + public function IsMain() { + return $this === $this->mMainModule; + } + + /** + * Get result object + */ + public function GetResult() { + // Main module has GetResult() method overriden + // Safety - avoid infinite loop: + if ($this->IsMain()) + $this->DieDebug(__METHOD__.' base method was called on main module. '); + return $this->GetMain()->GetResult(); + } + + /** + * Returns an array of allowed parameters (keys) => default value for that parameter + */ + protected function GetAllowedParams() { + return false; + } + + /** + * Returns the description string for this module + */ + protected function GetDescription() { + return false; + } + + /** + * Returns usage examples for this module. Return null if no examples are available. + */ + protected function GetExamples() { + return false; + } + + /** + * Returns the description string for the given parameter. + */ + protected function GetParamDescription($paramName) { + return ''; + } + + /** + * Generates help message for this module, or false if there is no description + */ + public function MakeHelpMsg() { + + $msg = $this->GetDescription(); + + if ($msg !== false) { + $msg .= "\n"; + + // Parameters + $params = $this->GetAllowedParams(); + if ($params !== false) { + $msg .= "Supported Parameters:\n"; + foreach (array_keys($params) as $paramName) { + $msg .= sprintf(" %-14s - %s\n", $paramName, $this->GetParamDescription($paramName)); + } + } + + // Examples + $examples = $this->GetExamples(); + if ($examples !== false) { + $msg .= "Examples:\n "; + $msg .= implode("\n ", $examples) . "\n"; + } + } + + return $msg; + } + + /** + * Using GetAllowedParams(), makes an array of the values provided by the user, + * with key being the name of the variable, and value - validated value from user or default. + * This method can be used to generate local variables using extract(). + */ + public function ExtractRequestParams() { + global $wgRequest; + + $params = $this->GetAllowedParams(); + $results = array (); + + foreach ($params as $param => $dflt) { + switch (gettype($dflt)) { + case 'NULL' : + case 'string' : + $result = $wgRequest->getVal($param, $dflt); + break; + case 'integer' : + $result = $wgRequest->getInt($param, $dflt); + break; + case 'boolean' : + // Having a default value of 'true' is pointless + $result = $wgRequest->getCheck($param); + break; + case 'array' : + if (count($dflt) != 3) + $this->DieDebug("In '$param', the default enum must have 3 parts - default, allowmultiple, and array of values " . gettype($dflt)); + $values = $wgRequest->getVal($param, $dflt[GN_ENUM_DFLT]); + $result = $this->ParseMultiValue($param, $values, $dflt[GN_ENUM_ISMULTI], $dflt[GN_ENUM_CHOICES]); + break; + default : + $this->DieDebug("In '$param', unprocessed type " . gettype($dflt)); + } + $results[$param] = $result; + } + + return $results; + } + + /** + * Return an array of values that were given in a "a|b|c" notation, after it validates them against the list allowed values. + */ + protected function ParseMultiValue($valueName, $values, $allowMultiple, $allowedValues) { + $valuesList = explode('|', $values); + if (!$allowMultiple && count($valuesList) != 1) + $this->DieUsage("Only one value is allowed: '" . implode("', '", $allowedValues) . "' for parameter '$valueName'", "multival_$valueName"); + $unknownValues = array_diff($valuesList, $allowedValues); + if ($unknownValues) { + $this->DieUsage("Unrecognised value" . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName"); + } + + return $allowMultiple ? $valuesList : $valuesList[0]; + } + + /** + * Call main module's error handler + */ + public function DieUsage($description, $errorCode, $httpRespCode = 0) { + $this->GetMain()->MainDieUsage($description, $errorCode, $httpRespCode); + } + + protected function DieDebug($message) { + wfDebugDieBacktrace("Internal error in '{get_class($this)}': $message"); + } +} +?> diff --git a/includes/api/ApiHelp.php b/includes/api/ApiHelp.php new file mode 100644 index 0000000000..80c96d6e2f --- /dev/null +++ b/includes/api/ApiHelp.php @@ -0,0 +1,48 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiBase.php"); +} + +class ApiHelp extends ApiBase { + + /** + * Constructor + */ + public function __construct($main, $action) { + parent :: __construct($main); + } + + /** + * Stub module for displaying help when no parameters are given + */ + public function Execute() { + $this->DieUsage('', 'help'); + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php new file mode 100644 index 0000000000..ad3cd28f50 --- /dev/null +++ b/includes/api/ApiMain.php @@ -0,0 +1,100 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiBase.php"); +} + +class ApiMain extends ApiBase { + + private $mModules, $mModuleNames, $mApiStartTime, $mResult; + + /** + * Constructor + * $apiStartTime - time of the originating call for profiling purposes + * $modules - an array of actions (keys) and classes that handle them (values) + */ + public function __construct($apiStartTime, $modules) { + // Special handling for the main module: $parent === $this + parent :: __construct($this); + + $this->mModules = $modules; + $this->mModuleNames = array_keys($modules); + $this->mApiStartTime = $apiStartTime; + $this->mResult = new ApiResult($this); + } + + public function GetResult() { + return $this->mResult; + } + + protected function GetAllowedParams() { + return array ( + 'format' => 'xmlfm', + 'action' => array ( + GN_ENUM_DFLT => 'help', + GN_ENUM_ISMULTI => false, + GN_ENUM_CHOICES => $this->mModuleNames + ) + ); + } + + public function Execute() { + $action = $format = null; + extract($this->ExtractRequestParams()); + + // Instantiate and execute module requested by the user + $module = new $this->mModules[$action] ($this, $action); + $module->Execute(); + } + + protected function GetDescription() { + return "This API allows programs to access various functions of MediaWiki software."; + } + + protected function GetParamDescription($paramName) { + switch($paramName) { + case 'format': return "The format of the output"; + case 'action': return "What action you would like to perform"; + default: return parent :: GetParamDescription($paramName); + } + } + + public function MainDieUsage($description, $errorCode, $httpRespCode = 0) { + $this->mResult->Reset(); + $this->mResult->addMessage('error', null, $errorCode); + if ($httpRespCode === 0) + header($errorCode, true); + else + header($errorCode, true, $httpRespCode); + + $this->mResult->addMessage('usage', null, $this->MakeHelpMsg()); + + var_export($this->mResult->GetData()); + } +} +?> diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php new file mode 100644 index 0000000000..c10a57db87 --- /dev/null +++ b/includes/api/ApiQuery.php @@ -0,0 +1,104 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiBase.php"); +} + +class ApiQuery extends ApiBase { + + private static $apiAutoloadClasses_Query = array ( + 'ApiQueryContent' => 'includes/api/ApiQueryContent.php', + + ); + + private static $sQueryModules = array ( + 'content' => 'ApiQueryContent' + ); + + /** + * Constructor + */ + public function __construct($main, $action) { + parent :: __construct($main); + ApiInitAutoloadClasses($this->apiAutoloadClasses_Query); + $this->mModuleNames = array_keys($this->sQueryModules); + $this->mDb =& wfGetDB( DB_SLAVE ); + } + + public function GetDB() { + return $this->mDb; + } + + + public function Execute() { + + } + + /** + * Returns an array of allowed parameters (keys) => default value for that parameter + */ + protected function GetAllowedParams() { + return array ( + 'what' => 'default', + 'enumparam' => array ( + GN_ENUM_DFLT => null, + GN_ENUM_ISMULTI => true, + GN_ENUM_CHOICES => $this->mModuleNames + ) + ); + } + + /** + * Returns the description string for this module + */ + protected function GetDescription() { + return 'module a'; + } + + /** + * Returns usage examples for this module. Return null if no examples are available. + */ + protected function GetExamples() { + return array ( + 'http://...' + ); + } + + /** + * Returns the description string for the given parameter. + */ + protected function GetParamDescription($paramName) { + switch ($paramName) { + case 'param' : + return 'description'; + default : + return parent :: GetParamDescription($paramName); + } + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiQueryBase.php b/includes/api/ApiQueryBase.php new file mode 100644 index 0000000000..78d98ffc9b --- /dev/null +++ b/includes/api/ApiQueryBase.php @@ -0,0 +1,48 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiBase.php"); +} + +abstract class ApiQueryBase extends ApiBase { + + private $mQueryModule; + + /** + * Constructor + */ + public function __construct($main, $query) { + parent :: __construct($main); + $this->mQueryModule = $query; + } + + public function GetQuery() { + return $this->mQueryModule; + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiQueryContent.php b/includes/api/ApiQueryContent.php new file mode 100644 index 0000000000..d01bc78cd0 --- /dev/null +++ b/includes/api/ApiQueryContent.php @@ -0,0 +1,90 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiQueryBase.php"); +} + +class ApiQueryContent extends ApiQueryBase { + + /** + * Constructor + */ + public function __construct($main, $action) { + parent :: __construct($main); + } + + public function Execute() { + + } + + /** + * Returns an array of allowed parameters (keys) => default value for that parameter + */ + protected function GetAllowedParams() { + return array ( + 'param' => 'default', + 'enumparam' => array ( + GN_ENUM_DFLT => 'default', + GN_ENUM_ISMULTI => false, + GN_ENUM_CHOICES => array ( + 'a', + 'b' + ) + ) + ); + } + + /** + * Returns the description string for this module + */ + protected function GetDescription() { + return 'module a'; + } + + /** + * Returns usage examples for this module. Return null if no examples are available. + */ + protected function GetExamples() { + return array ( + 'http://...' + ); + } + + /** + * Returns the description string for the given parameter. + */ + protected function GetParamDescription($paramName) { + switch ($paramName) { + case 'param' : + return 'description'; + default : + return parent :: GetParamDescription($paramName); + } + } +} +?> \ No newline at end of file diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php new file mode 100644 index 0000000000..0a5abd3bae --- /dev/null +++ b/includes/api/ApiResult.php @@ -0,0 +1,115 @@ + + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ("ApiBase.php"); +} + +class ApiResult extends ApiBase { + + private $mData; + + /** + * Constructor + */ + public function __construct($main) { + parent :: __construct($main); + $this->Reset(); + } + + public function Reset() { + $this->mData = array(); + } + + function GetData() { + return $this->mData; + } + + /* function addPage($title) + { + if (!isset($this->mPages)) + $this->mPages &= $this->mData['pages']; + } + */ + + function AddMessage($mainSection, $subSection, $value, $preserveXmlSpacing = false) { + if (!array_key_exists($mainSection, $this->mData)) { + $this->mData[$mainSection] = array (); + } + if ($subSection !== null) { + if (!array_key_exists($subSection, $this->mData[$mainSection])) { + $this->mData[$mainSection][$subSection] = array (); + } + $element = & $this->mData[$mainSection][$subSection]; + } else { + $element = & $this->mData[$mainSection]; + } + if (is_array($value)) { + $element = array_merge($element, $value); + if (!array_key_exists('*', $element)) { + $element['*'] = ''; + } + } else { + if (array_key_exists('*', $element)) { + $element['*'] .= $value; + } else { + $element['*'] = $value; + } + if ($preserveXmlSpacing) { + $element['xml:space'] = 'preserve'; + } + } + } + + /** + * Recursivelly removes any elements from the array that begin with an '_'. + * The content element '*' is the only special element that is left. + * Use this method when the entire data object gets sent to the user. + */ + public function SanitizeData() { + ApiResult :: SanitizeDataInt($this->mData); + } + + private static function SanitizeDataInt(& $data) { + foreach ($data as $key => & $value) { + if ($key[0] === '_') { + unset ($data[$key]); + } + elseif ($key === '*' && $value === '') { + unset ($data[$key]); + } + elseif (is_array($value)) { + ApiResult :: SanitizeDataInt($value); + } + } + } + + public function Execute() { + $this->DieDebug("Execute() is not supported on Result object"); + } +} +?> -- 2.20.1