* Code cleanup per TimStarling's suggestions
authorYuri Astrakhan <yurik@users.mediawiki.org>
Sun, 1 Oct 2006 04:38:31 +0000 (04:38 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Sun, 1 Oct 2006 04:38:31 +0000 (04:38 +0000)
api.php
includes/api/ApiBase.php
includes/api/ApiLogin.php
includes/api/ApiMain.php
includes/api/ApiPageSet.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllpages.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQuerySiteinfo.php
includes/api/ApiResult.php

diff --git a/api.php b/api.php
index c96c647..a2c2c05 100644 (file)
--- a/api.php
+++ b/api.php
-<?php\r
-\r
-\r
-/**\r
-* API for MediaWiki 1.8+\r
-*\r
-* Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>\r
-*\r
-* This program is free software; you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation; either version 2 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* This program is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License along\r
-* with this program; if not, write to the Free Software Foundation, Inc.,\r
-* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
-* http://www.gnu.org/copyleft/gpl.html\r
-*/\r
-\r
-$wgApiStartTime = microtime(true);\r
-\r
-/**\r
- * When no format parameter is given, this format will be used\r
- */\r
-define('API_DEFAULT_FORMAT', 'xmlfm');\r
-\r
-/**\r
- * List of classes and containing files.\r
- */\r
-$wgApiAutoloadClasses = array (\r
-\r
-       'ApiMain' => 'ApiMain.php',\r
-\r
-               // Utility classes\r
-       'ApiBase' => 'ApiBase.php',\r
-       'ApiQueryBase' => 'ApiQueryBase.php',\r
-       'ApiResult' => 'ApiResult.php',\r
-       'ApiPageSet' => 'ApiPageSet.php',\r
-\r
-               // Formats\r
-       'ApiFormatBase' => 'ApiFormatBase.php',\r
-       'ApiFormatYaml' => 'ApiFormatYaml.php',\r
-       'ApiFormatXml' => 'ApiFormatXml.php',\r
-       'ApiFormatJson' => 'ApiFormatJson.php',\r
-\r
-               // Modules (action=...) - should match the $apiModules list\r
-       'ApiHelp' => 'ApiHelp.php',\r
-       'ApiLogin' => 'ApiLogin.php',\r
-       'ApiQuery' => 'ApiQuery.php',\r
-\r
-               // Query items (meta/prop/list=...)\r
-       'ApiQuerySiteinfo' => 'ApiQuerySiteinfo.php',\r
-       'ApiQueryInfo' => 'ApiQueryInfo.php',\r
-       'ApiQueryRevisions' => 'ApiQueryRevisions.php',\r
-       'ApiQueryAllpages' => 'ApiQueryAllpages.php'\r
-);\r
-\r
-/**\r
- * List of available modules: action name => module class\r
- * The class must also be listed in the $wgApiAutoloadClasses array. \r
- */\r
-$wgApiModules = array (\r
-       'help' => 'ApiHelp',\r
-       'login' => 'ApiLogin',\r
-       'query' => 'ApiQuery'\r
-);\r
-\r
-/**\r
- * List of available formats: format name => format class\r
- * The class must also be listed in the $wgApiAutoloadClasses array. \r
- */\r
-$wgApiFormats = array (\r
-       'json' => 'ApiFormatJson',\r
-       'jsonfm' => 'ApiFormatJson',\r
-       'xml' => 'ApiFormatXml',\r
-       'xmlfm' => 'ApiFormatXml',\r
-       'yaml' => 'ApiFormatYaml',\r
-       'yamlfm' => 'ApiFormatYaml'\r
-);\r
-\r
-// Initialise common code\r
-require (dirname(__FILE__) . '/includes/WebStart.php');\r
-wfProfileIn('api.php');\r
-\r
-// Verify that the API has not been disabled\r
-// The next line should be \r
-//      if (isset ($wgEnableAPI) && !$wgEnableAPI) {\r
-// but will be in a safe mode until api is stabler\r
-if (!isset ($wgEnableAPI) || !$wgEnableAPI) {\r
-       echo 'MediaWiki API is not enabled for this site. Add the following line to your LocalSettings.php';\r
-       echo '<pre><b>$wgEnableAPI=true;</b></pre>';\r
-       die(-1);\r
-}\r
-\r
-apiInitAutoloadClasses($wgApiAutoloadClasses, "$IP/includes/api/");\r
-$processor = new ApiMain($wgApiStartTime, $wgApiModules, $wgApiFormats);\r
-$processor->execute();\r
-\r
-wfProfileOut('api.php');\r
-wfLogProfilingData();\r
-exit; // Done!\r
-\r
-function apiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) {\r
-\r
-       // Prefix each api class with the proper prefix,\r
-       // and append them to $wgAutoloadClasses\r
-       global $wgAutoloadClasses;\r
-\r
-       foreach ($apiAutoloadClasses as $className => $classFile)\r
-               $wgAutoloadClasses[$className] = $apiDirectory . $classFile;\r
-}\r
-?>\r
+<?php
+
+
+/**
+* API for MediaWiki 1.8+
+*
+* Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@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.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+* http://www.gnu.org/copyleft/gpl.html
+*/
+
+$wgApiStartTime = microtime(true);
+
+/**
+ * When no format parameter is given, this format will be used
+ */
+define('API_DEFAULT_FORMAT', 'xmlfm');
+
+/**
+ * Location of all api-related files (must end with a slash '/')
+ */
+define('API_DIR', 'includes/api/');
+
+/**
+ * List of classes and containing files.
+ */
+$wgApiAutoloadClasses = array (
+
+       'ApiMain' => API_DIR . 'ApiMain.php',
+
+               // Utility classes
+       'ApiBase' => API_DIR . 'ApiBase.php',
+       'ApiQueryBase' => API_DIR . 'ApiQueryBase.php',
+       'ApiResult' => API_DIR . 'ApiResult.php',
+       'ApiPageSet' => API_DIR . 'ApiPageSet.php',
+
+               // Formats
+       'ApiFormatBase' => API_DIR . 'ApiFormatBase.php',
+       'ApiFormatYaml' => API_DIR . 'ApiFormatYaml.php',
+       'ApiFormatXml' => API_DIR . 'ApiFormatXml.php',
+       'ApiFormatJson' => API_DIR . 'ApiFormatJson.php',
+
+               // Modules (action=...) - should match the $apiModules list
+       'ApiHelp' => API_DIR . 'ApiHelp.php',
+       'ApiLogin' => API_DIR . 'ApiLogin.php',
+       'ApiQuery' => API_DIR . 'ApiQuery.php',
+
+               // Query items (meta/prop/list=...)
+       'ApiQuerySiteinfo' => API_DIR . 'ApiQuerySiteinfo.php',
+       'ApiQueryInfo' => API_DIR . 'ApiQueryInfo.php',
+       'ApiQueryRevisions' => API_DIR . 'ApiQueryRevisions.php',
+       'ApiQueryAllpages' => API_DIR . 'ApiQueryAllpages.php'
+);
+
+/**
+ * List of available modules: action name => module class
+ * The class must also be listed in the $wgApiAutoloadClasses array. 
+ */
+$wgApiModules = array (
+       'help' => 'ApiHelp',
+       'login' => 'ApiLogin',
+       'query' => 'ApiQuery'
+);
+
+/**
+ * List of available formats: format name => format class
+ * The class must also be listed in the $wgApiAutoloadClasses array. 
+ */
+$wgApiFormats = array (
+       'json' => 'ApiFormatJson',
+       'jsonfm' => 'ApiFormatJson',
+       'xml' => 'ApiFormatXml',
+       'xmlfm' => 'ApiFormatXml',
+       'yaml' => 'ApiFormatYaml',
+       'yamlfm' => 'ApiFormatYaml'
+);
+
+// Initialise common code
+require (dirname(__FILE__) . '/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 '<pre><b>$wgEnableAPI=true;</b></pre>';
+       die(-1);
+}
+
+$wgAutoloadClasses = array_merge($wgAutoloadClasses, $wgApiAutoloadClasses);
+$processor = new ApiMain($wgApiStartTime, $wgApiModules, $wgApiFormats);
+$processor->execute();
+
+wfProfileOut('api.php');
+wfLogProfilingData();
+exit; // Done!
+?>
index 46aa903..d0aab37 100644 (file)
-<?php\r
-\r
-\r
-/*\r
- * Created on Sep 5, 2006\r
- *\r
- * API for MediaWiki 1.8+\r
- *\r
- * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * http://www.gnu.org/copyleft/gpl.html\r
- */\r
-\r
-// Multi-valued enums, limit the values user can supply for the parameter\r
-define('GN_ENUM_DFLT', 'dflt');\r
-define('GN_ENUM_ISMULTI', 'multi');\r
-define('GN_ENUM_TYPE', 'type');\r
-define('GN_ENUM_MAX1', 'max1');\r
-define('GN_ENUM_MAX2', 'max2');\r
-define('GN_ENUM_MIN', 'min');\r
-\r
-abstract class ApiBase {\r
-\r
-       private $mMainModule;\r
-\r
-       /**\r
-       * Constructor\r
-       */\r
-       public function __construct($mainModule) {\r
-               $this->mMainModule = $mainModule;\r
-       }\r
-\r
-       /**\r
-        * Executes this module\r
-        */\r
-       abstract function execute();\r
-\r
-       /**\r
-        * Get main module\r
-        */\r
-       public function getMain() {\r
-               return $this->mMainModule;\r
-       }\r
-\r
-       /**\r
-        * If this module's $this is the same as $this->mMainModule, its the root, otherwise no\r
-        */\r
-       public function isMain() {\r
-               return $this === $this->mMainModule;\r
-       }\r
-\r
-       /**\r
-        * Get result object\r
-        */\r
-       public function getResult() {\r
-               // Main module has getResult() method overriden\r
-               // Safety - avoid infinite loop:\r
-               if ($this->isMain())\r
-                       ApiBase :: dieDebug(__METHOD__ .\r
-                       ' base method was called on main module. ');\r
-               return $this->getMain()->getResult();\r
-       }\r
-\r
-       /**\r
-        * Get the result data array\r
-        */\r
-       public function & getResultData() {\r
-               return $this->getResult()->getData();\r
-       }\r
-\r
-       /**\r
-        * Generates help message for this module, or false if there is no description\r
-        */\r
-       public function makeHelpMsg() {\r
-\r
-               static $lnPrfx = "\n  ";\r
-\r
-               $msg = $this->getDescription();\r
-\r
-               if ($msg !== false) {\r
-\r
-                       if (!is_array($msg))\r
-                               $msg = array (\r
-                                       $msg\r
-                               );\r
-                       $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n";\r
-\r
-                       // Parameters\r
-                       $paramsMsg = $this->makeHelpMsgParameters();\r
-                       if ($paramsMsg !== false) {\r
-                               $msg .= "Parameters:\n$paramsMsg";\r
-                       }\r
-\r
-                       // Examples\r
-                       $examples = $this->getExamples();\r
-                       if ($examples !== false) {\r
-                               if (!is_array($examples))\r
-                                       $examples = array (\r
-                                               $examples\r
-                                       );\r
-                               $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n  ";\r
-                               $msg .= implode($lnPrfx, $examples) . "\n";\r
-                       }\r
-               }\r
-\r
-               return $msg;\r
-       }\r
-\r
-       public function makeHelpMsgParameters() {\r
-               $params = $this->getAllowedParams();\r
-               if ($params !== false) {\r
-\r
-                       $paramsDescription = $this->getParamDescription();\r
-                       $msg = '';\r
-                       foreach (array_keys($params) as $paramName) {\r
-                               $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';\r
-                               if (is_array($desc))\r
-                                       $desc = implode("\n" . str_repeat(' ', 19), $desc);\r
-                               $msg .= sprintf("  %-14s - %s\n", $paramName, $desc);\r
-                       }\r
-                       return $msg;\r
-\r
-               } else\r
-                       return false;\r
-       }\r
-\r
-       /**\r
-        * Returns the description string for this module\r
-        */\r
-       protected function getDescription() {\r
-               return false;\r
-       }\r
-\r
-       /**\r
-        * Returns usage examples for this module. Return null if no examples are available.\r
-        */\r
-       protected function getExamples() {\r
-               return false;\r
-       }\r
-\r
-       /**\r
-        * Returns an array of allowed parameters (keys) => default value for that parameter\r
-        */\r
-       protected function getAllowedParams() {\r
-               return false;\r
-       }\r
-\r
-       /**\r
-        * Returns the description string for the given parameter.\r
-        */\r
-       protected function getParamDescription() {\r
-               return false;\r
-       }\r
-\r
-       /**\r
-       * Using getAllowedParams(), makes an array of the values provided by the user,\r
-       * with key being the name of the variable, and value - validated value from user or default.\r
-       * This method can be used to generate local variables using extract().\r
-       */\r
-       public function extractRequestParams() {\r
-               $params = $this->getAllowedParams();\r
-               $results = array ();\r
-\r
-               foreach ($params as $paramName => $paramSettings)\r
-                       $results[$paramName] = $this->getParameter($paramName, $paramSettings);\r
-\r
-               return $results;\r
-       }\r
-\r
-       public function getParameter($paramName, $paramSettings) {\r
-               global $wgRequest;\r
-\r
-               if (!is_array($paramSettings)) {\r
-                       $default = $paramSettings;\r
-                       $multi = false;\r
-                       $type = gettype($paramSettings);\r
-               } else {\r
-                       $default = isset ($paramSettings[GN_ENUM_DFLT]) ? $paramSettings[GN_ENUM_DFLT] : null;\r
-                       $multi = isset ($paramSettings[GN_ENUM_ISMULTI]) ? $paramSettings[GN_ENUM_ISMULTI] : false;\r
-                       $type = isset ($paramSettings[GN_ENUM_TYPE]) ? $paramSettings[GN_ENUM_TYPE] : null;\r
-\r
-                       // When type is not given, and no choices, the type is the same as $default\r
-                       if (!isset ($type)) {\r
-                               if (isset ($default))\r
-                                       $type = gettype($default);\r
-                               else\r
-                                       $type = 'NULL'; // allow everything\r
-                       }\r
-               }\r
-\r
-               if ($type == 'boolean') {\r
-                       if (isset ($default) && $default !== false) {\r
-                               // Having a default value of anything other than 'false' is pointless\r
-                               ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'");\r
-                       }\r
-\r
-                       $value = $wgRequest->getCheck($paramName);\r
-               } else\r
-                       $value = $wgRequest->getVal($paramName, $default);\r
-\r
-               if (isset ($value) && ($multi || is_array($type)))\r
-                       $value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null);\r
-\r
-               // More validation only when choices were not given\r
-               // choices were validated in parseMultiValue()\r
-               if (!is_array($type) && isset ($value)) {\r
-\r
-                       switch ($type) {\r
-                               case 'NULL' : // nothing to do\r
-                                       break;\r
-                               case 'string' : // nothing to do\r
-                                       break;\r
-                               case 'integer' : // Force everything using intval()\r
-                                       $value = is_array($value) ? array_map('intval', $value) : intval($value);\r
-                                       break;\r
-                               case 'limit' :\r
-                                       if (!isset ($paramSettings[GN_ENUM_MAX1]) || !isset ($paramSettings[GN_ENUM_MAX2]))\r
-                                               ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");\r
-                                       if ($multi)\r
-                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");\r
-                                       $min = isset ($paramSettings[GN_ENUM_MIN]) ? $paramSettings[GN_ENUM_MIN] : 0;\r
-                                       $value = intval($value);\r
-                                       $this->validateLimit($paramName, $value, $min, $paramSettings[GN_ENUM_MAX1], $paramSettings[GN_ENUM_MAX2]);\r
-                                       break;\r
-                               case 'boolean' :\r
-                                       if ($multi)\r
-                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");\r
-                                       break;\r
-                               case 'timestamp' :\r
-                                       if ($multi)\r
-                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");\r
-                                       $value = $this->prepareTimestamp($value); // Adds quotes around timestamp                                                       \r
-                                       break;\r
-                               default :\r
-                                       ApiBase :: dieDebug("Param $paramName's type is unknown - $type");\r
-\r
-                       }\r
-               }\r
-\r
-               return $value;\r
-       }\r
-\r
-       /**\r
-       * Return an array of values that were given in a 'a|b|c' notation,\r
-       * after it optionally validates them against the list allowed values.\r
-       * \r
-       * @param valueName - The name of the parameter (for error reporting)\r
-       * @param value - The value being parsed\r
-       * @param allowMultiple - Can $value contain more than one value separated by '|'?\r
-       * @param allowedValues - An array of values to check against. If null, all values are accepted.\r
-       * @return (allowMultiple ? an_array_of_values : a_single_value) \r
-       */\r
-       protected function parseMultiValue($valueName, $value, $allowMultiple, $allowedValues) {\r
-               $valuesList = explode('|', $value);\r
-               if (!$allowMultiple && count($valuesList) != 1) {\r
-                       $possibleValues = is_array($allowedValues) ? "of '" . implode("', '", $allowedValues) . "'" : '';\r
-                       $this->dieUsage("Only one $possibleValues is allowed for parameter '$valueName'", "multival_$valueName");\r
-               }\r
-               if (is_array($allowedValues)) {\r
-                       $unknownValues = array_diff($valuesList, $allowedValues);\r
-                       if ($unknownValues) {\r
-                               $this->dieUsage('Unrecognised value' . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName");\r
-                       }\r
-               }\r
-\r
-               return $allowMultiple ? $valuesList : $valuesList[0];\r
-       }\r
-\r
-       /**\r
-       * Validate the proper format of the timestamp string (14 digits), and add quotes to it.\r
-       */\r
-       function prepareTimestamp($value) {\r
-               if (preg_match('/^[0-9]{14}$/', $value)) {\r
-                       return $this->db->addQuotes($value);\r
-               } else {\r
-                       $this->dieUsage('Incorrect timestamp format', 'badtimestamp');\r
-               }\r
-       }\r
-\r
-       /**\r
-       * Validate the value against the minimum and user/bot maximum limits. Prints usage info on failure.\r
-       */\r
-       function validateLimit($varname, $value, $min, $max, $botMax) {\r
-               global $wgUser;\r
-\r
-               if ($value < $min) {\r
-                       $this->dieUsage("$varname may not be less than $min (set to $value)", $varname);\r
-               }\r
-\r
-               if ($this->getMain()->isBot()) {\r
-                       if ($value > $botMax) {\r
-                               $this->dieUsage("$varname may not be over $botMax (set to $value) for bots", $varname);\r
-                       }\r
-               } else {\r
-                       if ($value > $max) {\r
-                               $this->dieUsage("$varname may not be over $max (set to $value) for users", $varname);\r
-                       }\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Call main module's error handler \r
-        */\r
-       public function dieUsage($description, $errorCode, $httpRespCode = 0) {\r
-               $this->getMain()->mainDieUsage($description, $errorCode, $httpRespCode);\r
-       }\r
-\r
-       /**\r
-        * Internal code errors should be reported with this method\r
-        */\r
-       protected static function dieDebug($message) {\r
-               wfDebugDieBacktrace("Internal error: $message");\r
-       }\r
-\r
-       /**\r
-        * Profiling: total module execution time\r
-        */\r
-       private $mTimeIn = 0, $mModuleTime = 0;\r
-\r
-       /**\r
-        * Start module profiling\r
-        */\r
-       public function profileIn() {\r
-               if ($this->mTimeIn !== 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileOut()');\r
-               $this->mTimeIn = microtime(true);\r
-       }\r
-\r
-       /**\r
-        * End module profiling\r
-        */\r
-       public function profileOut() {\r
-               if ($this->mTimeIn === 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileIn() first');\r
-               if ($this->mDBTimeIn !== 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' must be called after database profiling is done with profileDBOut()');\r
-\r
-               $this->mModuleTime += microtime(true) - $this->mTimeIn;\r
-               $this->mTimeIn = 0;\r
-       }\r
-\r
-       /**\r
-        * Total time the module was executed\r
-        */\r
-       public function getProfileTime() {\r
-               if ($this->mTimeIn !== 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileOut() first');\r
-               return $this->mModuleTime;\r
-       }\r
-\r
-       /**\r
-        * Profiling: database execution time\r
-        */\r
-       private $mDBTimeIn = 0, $mDBTime = 0;\r
-\r
-       /**\r
-        * Start module profiling\r
-        */\r
-       public function profileDBIn() {\r
-               if ($this->mTimeIn === 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
-               if ($this->mDBTimeIn !== 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()');\r
-               $this->mDBTimeIn = microtime(true);\r
-       }\r
-\r
-       /**\r
-        * End database profiling\r
-        */\r
-       public function profileDBOut() {\r
-               if ($this->mTimeIn === 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
-               if ($this->mDBTimeIn === 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first');\r
-\r
-               $time = microtime(true) - $this->mDBTimeIn;\r
-               $this->mDBTimeIn = 0;\r
-\r
-               $this->mDBTime += $time;\r
-               $this->getMain()->mDBTime += $time;\r
-       }\r
-\r
-       /**\r
-        * Total time the module used the database\r
-        */\r
-       public function getProfileDBTime() {\r
-               if ($this->mDBTimeIn !== 0)\r
-                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first');\r
-               return $this->mDBTime;\r
-       }\r
-}\r
+<?php
+
+
+/*
+ * Created on Sep 5, 2006
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+abstract class ApiBase {
+
+       // These constants allow modules to specify exactly how to treat incomming parameters.
+
+       const PARAM_DFLT = 0;
+       const PARAM_ISMULTI = 1;
+       const PARAM_TYPE = 2;
+       const PARAM_MAX1 = 3;
+       const PARAM_MAX2 = 4;
+       const PARAM_MIN = 5;
+
+       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())
+                       ApiBase :: dieDebug(__METHOD__ .
+                       ' base method was called on main module. ');
+               return $this->getMain()->getResult();
+       }
+
+       /**
+        * Get the result data array
+        */
+       public function & getResultData() {
+               return $this->getResult()->getData();
+       }
+
+       /**
+        * Generates help message for this module, or false if there is no description
+        */
+       public function makeHelpMsg() {
+
+               static $lnPrfx = "\n  ";
+
+               $msg = $this->getDescription();
+
+               if ($msg !== false) {
+
+                       if (!is_array($msg))
+                               $msg = array (
+                                       $msg
+                               );
+                       $msg = $lnPrfx . implode($lnPrfx, $msg) . "\n";
+
+                       // Parameters
+                       $paramsMsg = $this->makeHelpMsgParameters();
+                       if ($paramsMsg !== false) {
+                               $msg .= "Parameters:\n$paramsMsg";
+                       }
+
+                       // Examples
+                       $examples = $this->getExamples();
+                       if ($examples !== false) {
+                               if (!is_array($examples))
+                                       $examples = array (
+                                               $examples
+                                       );
+                               $msg .= 'Example' . (count($examples) > 1 ? 's' : '') . ":\n  ";
+                               $msg .= implode($lnPrfx, $examples) . "\n";
+                       }
+               }
+
+               return $msg;
+       }
+
+       public function makeHelpMsgParameters() {
+               $params = $this->getAllowedParams();
+               if ($params !== false) {
+
+                       $paramsDescription = $this->getParamDescription();
+                       $msg = '';
+                       foreach (array_keys($params) as $paramName) {
+                               $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';
+                               if (is_array($desc))
+                                       $desc = implode("\n" . str_repeat(' ', 19), $desc);
+                               $msg .= sprintf("  %-14s - %s\n", $paramName, $desc);
+                       }
+                       return $msg;
+
+               } else
+                       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 an array of allowed parameters (keys) => default value for that parameter
+        */
+       protected function getAllowedParams() {
+               return false;
+       }
+
+       /**
+        * Returns the description string for the given parameter.
+        */
+       protected function getParamDescription() {
+               return false;
+       }
+
+       /**
+       * 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() {
+               $params = $this->getAllowedParams();
+               $results = array ();
+
+               foreach ($params as $paramName => $paramSettings)
+                       $results[$paramName] = $this->getParameter($paramName, $paramSettings);
+
+               return $results;
+       }
+
+       public function getParameter($paramName, $paramSettings) {
+               global $wgRequest;
+
+               if (!is_array($paramSettings)) {
+                       $default = $paramSettings;
+                       $multi = false;
+                       $type = gettype($paramSettings);
+               } else {
+                       $default = isset ($paramSettings[self::PARAM_DFLT]) ? $paramSettings[self::PARAM_DFLT] : null;
+                       $multi = isset ($paramSettings[self::PARAM_ISMULTI]) ? $paramSettings[self::PARAM_ISMULTI] : false;
+                       $type = isset ($paramSettings[self::PARAM_TYPE]) ? $paramSettings[self::PARAM_TYPE] : null;
+
+                       // When type is not given, and no choices, the type is the same as $default
+                       if (!isset ($type)) {
+                               if (isset ($default))
+                                       $type = gettype($default);
+                               else
+                                       $type = 'NULL'; // allow everything
+                       }
+               }
+
+               if ($type == 'boolean') {
+                       if (isset ($default) && $default !== false) {
+                               // Having a default value of anything other than 'false' is pointless
+                               ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'");
+                       }
+
+                       $value = $wgRequest->getCheck($paramName);
+               } else
+                       $value = $wgRequest->getVal($paramName, $default);
+
+               if (isset ($value) && ($multi || is_array($type)))
+                       $value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null);
+
+               // More validation only when choices were not given
+               // choices were validated in parseMultiValue()
+               if (!is_array($type) && isset ($value)) {
+
+                       switch ($type) {
+                               case 'NULL' : // nothing to do
+                                       break;
+                               case 'string' : // nothing to do
+                                       break;
+                               case 'integer' : // Force everything using intval()
+                                       $value = is_array($value) ? array_map('intval', $value) : intval($value);
+                                       break;
+                               case 'limit' :
+                                       if (!isset ($paramSettings[self::PARAM_MAX1]) || !isset ($paramSettings[self::PARAM_MAX2]))
+                                               ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");
+                                       if ($multi)
+                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");
+                                       $min = isset ($paramSettings[self::PARAM_MIN]) ? $paramSettings[self::PARAM_MIN] : 0;
+                                       $value = intval($value);
+                                       $this->validateLimit($paramName, $value, $min, $paramSettings[self::PARAM_MAX1], $paramSettings[self::PARAM_MAX2]);
+                                       break;
+                               case 'boolean' :
+                                       if ($multi)
+                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");
+                                       break;
+                               case 'timestamp' :
+                                       if ($multi)
+                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");
+                                       $value = $this->prepareTimestamp($value); // Adds quotes around timestamp                                                       
+                                       break;
+                               default :
+                                       ApiBase :: dieDebug("Param $paramName's type is unknown - $type");
+
+                       }
+               }
+
+               return $value;
+       }
+
+       /**
+       * Return an array of values that were given in a 'a|b|c' notation,
+       * after it optionally validates them against the list allowed values.
+       * 
+       * @param valueName - The name of the parameter (for error reporting)
+       * @param value - The value being parsed
+       * @param allowMultiple - Can $value contain more than one value separated by '|'?
+       * @param allowedValues - An array of values to check against. If null, all values are accepted.
+       * @return (allowMultiple ? an_array_of_values : a_single_value) 
+       */
+       protected function parseMultiValue($valueName, $value, $allowMultiple, $allowedValues) {
+               $valuesList = explode('|', $value);
+               if (!$allowMultiple && count($valuesList) != 1) {
+                       $possibleValues = is_array($allowedValues) ? "of '" . implode("', '", $allowedValues) . "'" : '';
+                       $this->dieUsage("Only one $possibleValues is allowed for parameter '$valueName'", "multival_$valueName");
+               }
+               if (is_array($allowedValues)) {
+                       $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];
+       }
+
+       /**
+       * Validate the proper format of the timestamp string (14 digits), and add quotes to it.
+       */
+       function prepareTimestamp($value) {
+               if (preg_match('/^[0-9]{14}$/', $value)) {
+                       return $this->db->addQuotes($value);
+               } else {
+                       $this->dieUsage('Incorrect timestamp format', 'badtimestamp');
+               }
+       }
+
+       /**
+       * Validate the value against the minimum and user/bot maximum limits. Prints usage info on failure.
+       */
+       function validateLimit($varname, $value, $min, $max, $botMax) {
+               global $wgUser;
+
+               if ($value < $min) {
+                       $this->dieUsage("$varname may not be less than $min (set to $value)", $varname);
+               }
+
+               if ($this->getMain()->isBot()) {
+                       if ($value > $botMax) {
+                               $this->dieUsage("$varname may not be over $botMax (set to $value) for bots", $varname);
+                       }
+               } else {
+                       if ($value > $max) {
+                               $this->dieUsage("$varname may not be over $max (set to $value) for users", $varname);
+                       }
+               }
+       }
+
+       /**
+        * Call main module's error handler 
+        */
+       public function dieUsage($description, $errorCode, $httpRespCode = 0) {
+               $this->getMain()->mainDieUsage($description, $errorCode, $httpRespCode);
+       }
+
+       /**
+        * Internal code errors should be reported with this method
+        */
+       protected static function dieDebug($message) {
+               wfDebugDieBacktrace("Internal error: $message");
+       }
+
+       /**
+        * Profiling: total module execution time
+        */
+       private $mTimeIn = 0, $mModuleTime = 0;
+
+       /**
+        * Start module profiling
+        */
+       public function profileIn() {
+               if ($this->mTimeIn !== 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called twice without calling profileOut()');
+               $this->mTimeIn = microtime(true);
+       }
+
+       /**
+        * End module profiling
+        */
+       public function profileOut() {
+               if ($this->mTimeIn === 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called without calling profileIn() first');
+               if ($this->mDBTimeIn !== 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' must be called after database profiling is done with profileDBOut()');
+
+               $this->mModuleTime += microtime(true) - $this->mTimeIn;
+               $this->mTimeIn = 0;
+       }
+
+       /**
+        * Total time the module was executed
+        */
+       public function getProfileTime() {
+               if ($this->mTimeIn !== 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called without calling profileOut() first');
+               return $this->mModuleTime;
+       }
+
+       /**
+        * Profiling: database execution time
+        */
+       private $mDBTimeIn = 0, $mDBTime = 0;
+
+       /**
+        * Start module profiling
+        */
+       public function profileDBIn() {
+               if ($this->mTimeIn === 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' must be called while profiling the entire module with profileIn()');
+               if ($this->mDBTimeIn !== 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called twice without calling profileDBOut()');
+               $this->mDBTimeIn = microtime(true);
+       }
+
+       /**
+        * End database profiling
+        */
+       public function profileDBOut() {
+               if ($this->mTimeIn === 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' must be called while profiling the entire module with profileIn()');
+               if ($this->mDBTimeIn === 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called without calling profileDBIn() first');
+
+               $time = microtime(true) - $this->mDBTimeIn;
+               $this->mDBTimeIn = 0;
+
+               $this->mDBTime += $time;
+               $this->getMain()->mDBTime += $time;
+       }
+
+       /**
+        * Total time the module used the database
+        */
+       public function getProfileDBTime() {
+               if ($this->mDBTimeIn !== 0)
+                       ApiBase :: dieDebug(__METHOD__ . ' called without calling profileDBOut() first');
+               return $this->mDBTime;
+       }
+}
 ?>
\ No newline at end of file
index 5158c35..b01691f 100644 (file)
@@ -50,30 +50,35 @@ class ApiLogin extends ApiBase {
 
                $loginForm = new LoginForm($params);
                switch ($loginForm->authenticateUserData()) {
-                       case (AuthSuccess) :
+                       case LoginForm :: SUCCESS :
+                               global $wgUser;
+
+                               $wgUser->setOption('rememberpassword', 1);
+                               $wgUser->setCookies();
+
                                $result['result'] = 'Success';
                                $result['lguserid'] = $_SESSION['wsUserID'];
                                $result['lgusername'] = $_SESSION['wsUserName'];
                                $result['lgtoken'] = $_SESSION['wsToken'];
                                break;
 
-                       case (AuthNoName) :
-                               $result['result'] = 'AuthNoName';
+                       case LoginForm :: NO_NAME :
+                               $result['result'] = 'NoName';
                                break;
-                       case (AuthIllegal) :
-                               $result['result'] = 'AuthIllegal';
+                       case LoginForm :: ILLEGAL :
+                               $result['result'] = 'Illegal';
                                break;
-                       case (AuthWrongPluginPass) :
-                               $result['result'] = 'AuthWrongPluginPass';
+                       case LoginForm :: WRONG_PLUGIN_PASS :
+                               $result['result'] = 'WrongPluginPass';
                                break;
-                       case (AuthNotExists) :
-                               $result['result'] = 'AuthNotExists';
+                       case LoginForm :: NOT_EXISTS :
+                               $result['result'] = 'NotExists';
                                break;
-                       case (AuthWrongPass) :
-                               $result['result'] = 'AuthWrongPass';
+                       case LoginForm :: WRONG_PASS :
+                               $result['result'] = 'WrongPass';
                                break;
-                       case (AuthEmptyPass) :
-                               $result['result'] = 'AuthEmptyPass';
+                       case LoginForm :: EMPTY_PASS :
+                               $result['result'] = 'EmptyPass';
                                break;
                        default :
                                $this->dieDebug('Unhandled case value');
index f831fb5..60e0ff0 100644 (file)
-<?php\r
-\r
-\r
-/*\r
- * Created on Sep 4, 2006\r
- *\r
- * API for MediaWiki 1.8+\r
- *\r
- * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * http://www.gnu.org/copyleft/gpl.html\r
- */\r
-\r
-if (!defined('MEDIAWIKI')) {\r
-       // Eclipse helper - will be ignored in production\r
-       require_once ('ApiBase.php');\r
-}\r
-\r
-class ApiMain extends ApiBase {\r
-\r
-       private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $mApiStartTime, $mResult;\r
-\r
-       /**\r
-       * Constructor\r
-       * $apiStartTime - time of the originating call for profiling purposes\r
-       * $modules - an array of actions (keys) and classes that handle them (values) \r
-       */\r
-       public function __construct($apiStartTime, $modules, $formats) {\r
-               // Special handling for the main module: $parent === $this\r
-               parent :: __construct($this);\r
-\r
-               $this->mModules = $modules;\r
-               $this->mModuleNames = array_keys($modules);\r
-               $this->mFormats = $formats;\r
-               $this->mFormatNames = array_keys($formats);\r
-               $this->mApiStartTime = $apiStartTime;\r
-               $this->mResult = new ApiResult($this);\r
-       }\r
-\r
-       public function & getResult() {\r
-               return $this->mResult;\r
-       }\r
-\r
-       protected function getAllowedParams() {\r
-               return array (\r
-                       'format' => array (\r
-                               GN_ENUM_DFLT => API_DEFAULT_FORMAT,\r
-                               GN_ENUM_TYPE => $this->mFormatNames\r
-                       ),\r
-                       'action' => array (\r
-                               GN_ENUM_DFLT => 'help',\r
-                               GN_ENUM_TYPE => $this->mModuleNames\r
-                       )\r
-               );\r
-       }\r
-\r
-       protected function getParamDescription() {\r
-               return array (\r
-                       'format' => 'The format of the output',\r
-                       'action' => 'What action you would like to perform'\r
-               );\r
-       }\r
-\r
-       public function execute() {\r
-               $this->profileIn();\r
-               $action = $format = null;\r
-               try {\r
-                       extract($this->extractRequestParams());\r
-\r
-                       // Create an appropriate printer\r
-                       $this->mPrinter = new $this->mFormats[$format] ($this, $format);\r
-\r
-                       // Instantiate and execute module requested by the user\r
-                       $module = new $this->mModules[$action] ($this, $action);\r
-                       $module->profileIn();\r
-                       $module->execute();\r
-                       $module->profileOut();\r
-                       $this->printResult(false);\r
-               } catch (UsageException $e) {\r
-                       // Printer may not be initialized if the extractRequestParams() fails for the main module\r
-                       if (!isset ($this->mPrinter))\r
-                               $this->mPrinter = new $this->mFormats[API_DEFAULT_FORMAT] ($this, API_DEFAULT_FORMAT);\r
-                       $this->printResult(true);\r
-               }\r
-               $this->profileOut();\r
-       }\r
-\r
-       /**\r
-        * Internal printer\r
-        */\r
-       private function printResult($isError) {\r
-               $printer = $this->mPrinter;\r
-               $printer->profileIn();\r
-               $printer->initPrinter($isError);\r
-               if (!$printer->getNeedsRawData())\r
-                       $this->getResult()->SanitizeData();\r
-               $printer->execute();\r
-               $printer->closePrinter();\r
-               $printer->profileOut();\r
-       }\r
-\r
-       protected function getDescription() {\r
-               return array (\r
-                       '',\r
-                       'This API allows programs to access various functions of MediaWiki software.',\r
-                       'For more details see API Home Page @ http://meta.wikimedia.org/wiki/API',\r
-                       ''\r
-               );\r
-       }\r
-\r
-       public function mainDieUsage($description, $errorCode, $httpRespCode = 0) {\r
-               $this->mResult->Reset();\r
-               if ($httpRespCode === 0)\r
-                       header($errorCode, true);\r
-               else\r
-                       header($errorCode, true, $httpRespCode);\r
-\r
-               $data = array (\r
-                       'code' => $errorCode\r
-               );\r
-               ApiResult :: addContent($data, $this->makeHelpMsg());\r
-               $this->mResult->addValue(null, 'error', $data);\r
-\r
-               throw new UsageException($description, $errorCode);\r
-       }\r
-\r
-       /**\r
-        * Override the parent to generate help messages for all available modules.\r
-        */\r
-       public function makeHelpMsg() {\r
-\r
-               // Use parent to make default message for the main module\r
-               $msg = parent :: makeHelpMsg();\r
-\r
-               $astriks = str_repeat('*** ', 10);\r
-               $msg .= "\n\n$astriks Modules  $astriks\n\n";\r
-               foreach ($this->mModules as $moduleName => $moduleClass) {\r
-                       $msg .= "* action=$moduleName *";\r
-                       $module = new $this->mModules[$moduleName] ($this, $moduleName);\r
-                       $msg2 = $module->makeHelpMsg();\r
-                       if ($msg2 !== false)\r
-                               $msg .= $msg2;\r
-                       $msg .= "\n";\r
-               }\r
-\r
-               $msg .= "\n$astriks Formats  $astriks\n\n";\r
-               foreach ($this->mFormats as $moduleName => $moduleClass) {\r
-                       $msg .= "* format=$moduleName *";\r
-                       $module = new $this->mFormats[$moduleName] ($this, $moduleName);\r
-                       $msg2 = $module->makeHelpMsg();\r
-                       if ($msg2 !== false)\r
-                               $msg .= $msg2;\r
-                       $msg .= "\n";\r
-               }\r
-\r
-               return $msg;\r
-       }\r
-\r
-       private $mIsBot = null;\r
-       public function isBot() {\r
-               if (!isset ($this->mIsBot)) {\r
-                       global $wgUser;\r
-                       $this->mIsBot = $wgUser->isAllowed('bot');\r
-               }\r
-               return $this->mIsBot;\r
-       }\r
-}\r
-\r
-/**\r
-* @desc This exception will be thrown when dieUsage is called to stop module execution.\r
-*/\r
-class UsageException extends Exception {\r
-\r
-       private $codestr;\r
-\r
-       public function __construct($message, $codestr) {\r
-               parent :: __construct($message);\r
-               $this->codestr = $codestr;\r
-       }\r
-       public function __toString() {\r
-               return "{$this->codestr}: {$this->message}";\r
-       }\r
-}\r
+<?php
+
+
+/*
+ * Created on Sep 4, 2006
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@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.,
+ * 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 $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames, $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, $formats) {
+               // Special handling for the main module: $parent === $this
+               parent :: __construct($this);
+
+               $this->mModules = $modules;
+               $this->mModuleNames = array_keys($modules);
+               $this->mFormats = $formats;
+               $this->mFormatNames = array_keys($formats);
+               $this->mApiStartTime = $apiStartTime;
+               $this->mResult = new ApiResult($this);
+       }
+
+       public function & getResult() {
+               return $this->mResult;
+       }
+
+       protected function getAllowedParams() {
+               return array (
+                       'format' => array (
+                               ApiBase::PARAM_DFLT => API_DEFAULT_FORMAT,
+                               ApiBase::PARAM_TYPE => $this->mFormatNames
+                       ),
+                       'action' => array (
+                               ApiBase::PARAM_DFLT => 'help',
+                               ApiBase::PARAM_TYPE => $this->mModuleNames
+                       )
+               );
+       }
+
+       protected function getParamDescription() {
+               return array (
+                       'format' => 'The format of the output',
+                       'action' => 'What action you would like to perform'
+               );
+       }
+
+       public function execute() {
+               $this->profileIn();
+               $action = $format = null;
+               try {
+                       extract($this->extractRequestParams());
+
+                       // Create an appropriate printer
+                       $this->mPrinter = new $this->mFormats[$format] ($this, $format);
+
+                       // Instantiate and execute module requested by the user
+                       $module = new $this->mModules[$action] ($this, $action);
+                       $module->profileIn();
+                       $module->execute();
+                       $module->profileOut();
+                       $this->printResult(false);
+               } catch (UsageException $e) {
+                       // Printer may not be initialized if the extractRequestParams() fails for the main module
+                       if (!isset ($this->mPrinter))
+                               $this->mPrinter = new $this->mFormats[API_DEFAULT_FORMAT] ($this, API_DEFAULT_FORMAT);
+                       $this->printResult(true);
+               }
+               $this->profileOut();
+       }
+
+       /**
+        * Internal printer
+        */
+       private function printResult($isError) {
+               $printer = $this->mPrinter;
+               $printer->profileIn();
+               $printer->initPrinter($isError);
+               if (!$printer->getNeedsRawData())
+                       $this->getResult()->SanitizeData();
+               $printer->execute();
+               $printer->closePrinter();
+               $printer->profileOut();
+       }
+
+       protected function getDescription() {
+               return array (
+                       '',
+                       'This API allows programs to access various functions of MediaWiki software.',
+                       'For more details see API Home Page @ http://meta.wikimedia.org/wiki/API',
+                       ''
+               );
+       }
+
+       public function mainDieUsage($description, $errorCode, $httpRespCode = 0) {
+               $this->mResult->Reset();
+               if ($httpRespCode === 0)
+                       header($errorCode, true);
+               else
+                       header($errorCode, true, $httpRespCode);
+
+               $data = array (
+                       'code' => $errorCode
+               );
+               ApiResult :: addContent($data, $this->makeHelpMsg());
+               $this->mResult->addValue(null, 'error', $data);
+
+               throw new UsageException($description, $errorCode);
+       }
+
+       /**
+        * Override the parent to generate help messages for all available modules.
+        */
+       public function makeHelpMsg() {
+
+               // Use parent to make default message for the main module
+               $msg = parent :: makeHelpMsg();
+
+               $astriks = str_repeat('*** ', 10);
+               $msg .= "\n\n$astriks Modules  $astriks\n\n";
+               foreach ($this->mModules as $moduleName => $moduleClass) {
+                       $msg .= "* action=$moduleName *";
+                       $module = new $this->mModules[$moduleName] ($this, $moduleName);
+                       $msg2 = $module->makeHelpMsg();
+                       if ($msg2 !== false)
+                               $msg .= $msg2;
+                       $msg .= "\n";
+               }
+
+               $msg .= "\n$astriks Formats  $astriks\n\n";
+               foreach ($this->mFormats as $moduleName => $moduleClass) {
+                       $msg .= "* format=$moduleName *";
+                       $module = new $this->mFormats[$moduleName] ($this, $moduleName);
+                       $msg2 = $module->makeHelpMsg();
+                       if ($msg2 !== false)
+                               $msg .= $msg2;
+                       $msg .= "\n";
+               }
+
+               return $msg;
+       }
+
+       private $mIsBot = null;
+       public function isBot() {
+               if (!isset ($this->mIsBot)) {
+                       global $wgUser;
+                       $this->mIsBot = $wgUser->isAllowed('bot');
+               }
+               return $this->mIsBot;
+       }
+}
+
+/**
+* @desc This exception will be thrown when dieUsage is called to stop module execution.
+*/
+class UsageException extends Exception {
+
+       private $codestr;
+
+       public function __construct($message, $codestr) {
+               parent :: __construct($message);
+               $this->codestr = $codestr;
+       }
+       public function __toString() {
+               return "{$this->codestr}: {$this->message}";
+       }
+}
 ?>
\ No newline at end of file
index f859d12..1343c1e 100644 (file)
@@ -34,6 +34,8 @@ class ApiPageSet extends ApiQueryBase {
        private $mAllPages; // [ns][dbkey] => page_id or 0 when missing
        private $mGoodTitles, $mMissingTitles, $mRedirectTitles, $mNormalizedTitles;
 
+       private $mRequestedFields;
+
        public function __construct($query) {
                parent :: __construct($query, __CLASS__);
 
@@ -42,6 +44,12 @@ class ApiPageSet extends ApiQueryBase {
                $this->mMissingTitles = array ();
                $this->mRedirectTitles = array ();
                $this->mNormalizedTitles = array ();
+
+               $this->mRequestedFields = array ();
+       }
+
+       public function requestField($fieldName) {
+               $this->mRequestedFields[$fieldName] = null;
        }
 
        /**
@@ -88,7 +96,7 @@ class ApiPageSet extends ApiQueryBase {
         * Get the list of revision IDs (requested with revids= parameter)
         */
        public function getRevisionIDs() {
-               $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented');
+               $this->dieUsage(__METHOD__ . ' is not implemented', 'notimplemented');
        }
 
        /**
@@ -114,14 +122,20 @@ class ApiPageSet extends ApiQueryBase {
         */
        private function populateTitles($titles, $redirects) {
 
+               // Ensure we get minimum required fields
                $pageFlds = array (
-                       'page_id',
-                       'page_namespace',
-                       'page_title'
+                       'page_id' => null,
+                       'page_namespace' => null,
+                       'page_title' => null
                );
-               if ($redirects) {
-                       $pageFlds[] = 'page_is_redirect';
-               }
+
+               // only store non-default fields
+               $this->mRequestedFields = array_diff_key($this->mRequestedFields, $pageFlds);
+
+               if ($redirects)
+                       $pageFlds['page_is_redirect'] = null;
+
+               $pageFlds = array_keys(array_merge($this->mRequestedFields, $pageFlds));
 
                // Get validated and normalized title objects
                $linkBatch = $this->processTitlesStrArray($titles);
@@ -142,7 +156,7 @@ class ApiPageSet extends ApiQueryBase {
                        // Get data about $linkBatch from `page` table
                        //
                        $this->profileDBIn();
-                       $res = $db->select('page', $pageFlds, $set, __CLASS__ . '::' . __FUNCTION__);
+                       $res = $db->select('page', $pageFlds, $set, __METHOD__);
                        $this->profileDBOut();
                        while ($row = $db->fetchObject($res)) {
 
@@ -186,7 +200,7 @@ class ApiPageSet extends ApiQueryBase {
                                'pl_title'
                        ), array (
                                'pl_from' => array_keys($redirectIds
-                       )), __CLASS__ . '::' . __FUNCTION__);
+                       )), __METHOD__);
                        $this->profileDBOut();
 
                        while ($row = $db->fetchObject($res)) {
@@ -249,7 +263,7 @@ class ApiPageSet extends ApiQueryBase {
        }
 
        private function populatePageIDs($pageids) {
-               $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented');
+               $this->dieUsage(__METHOD__ . ' is not implemented', 'notimplemented');
        }
 
        public function execute() {
@@ -290,15 +304,15 @@ class ApiPageSet extends ApiQueryBase {
        protected function getAllowedParams() {
                return array (
                        'titles' => array (
-                               GN_ENUM_ISMULTI => true
+                               ApiBase::PARAM_ISMULTI => true
                        ),
                        'pageids' => array (
-                               GN_ENUM_TYPE => 'integer',
-                               GN_ENUM_ISMULTI => true
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_ISMULTI => true
                        ),
                        'revids' => array (
-                               GN_ENUM_TYPE => 'integer',
-                               GN_ENUM_ISMULTI => true
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_ISMULTI => true
                        ),
                        'redirects' => false
                );
index fe7dd82..458007b 100644 (file)
-<?php\r
-\r
-\r
-/*\r
- * Created on Sep 7, 2006\r
- *\r
- * API for MediaWiki 1.8+\r
- *\r
- * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * http://www.gnu.org/copyleft/gpl.html\r
- */\r
-\r
-if (!defined('MEDIAWIKI')) {\r
-       // Eclipse helper - will be ignored in production\r
-       require_once ('ApiBase.php');\r
-}\r
-\r
-class ApiQuery extends ApiBase {\r
-\r
-       private $mMetaModuleNames, $mPropModuleNames, $mListModuleNames;\r
-       private $mData;\r
-\r
-       private $mQueryMetaModules = array (\r
-               'siteinfo' => 'ApiQuerySiteinfo'\r
-       );\r
-       //      'userinfo' => 'ApiQueryUserinfo',\r
-\r
-       private $mQueryPropModules = array (\r
-               'info' => 'ApiQueryInfo',\r
-               'revisions' => 'ApiQueryRevisions'\r
-       );\r
-       //      'categories' => 'ApiQueryCategories',\r
-       //      'imageinfo' => 'ApiQueryImageinfo',\r
-       //      'langlinks' => 'ApiQueryLanglinks',\r
-       //      'links' => 'ApiQueryLinks',\r
-       //      'templates' => 'ApiQueryTemplates',\r
-\r
-       private $mQueryListModules = array (\r
-               'allpages' => 'ApiQueryAllpages'\r
-       );\r
-       //      'backlinks' => 'ApiQueryBacklinks',\r
-       //      'categorymembers' => 'ApiQueryCategorymembers',\r
-       //      'embeddedin' => 'ApiQueryEmbeddedin',\r
-       //      'imagelinks' => 'ApiQueryImagelinks',\r
-       //      'logevents' => 'ApiQueryLogevents',\r
-       //      'recentchanges' => 'ApiQueryRecentchanges',\r
-       //      'usercontribs' => 'ApiQueryUsercontribs',\r
-       //      'users' => 'ApiQueryUsers',\r
-       //      'watchlist' => 'ApiQueryWatchlist',\r
-\r
-       private $mSlaveDB = null;\r
-\r
-       public function __construct($main, $action) {\r
-               parent :: __construct($main);\r
-               $this->mMetaModuleNames = array_keys($this->mQueryMetaModules);\r
-               $this->mPropModuleNames = array_keys($this->mQueryPropModules);\r
-               $this->mListModuleNames = array_keys($this->mQueryListModules);\r
-\r
-               // Allow the entire list of modules at first,\r
-               // but during module instantiation check if it can be used as a generator.\r
-               $this->mAllowedGenerators = array_merge($this->mListModuleNames, $this->mPropModuleNames);\r
-       }\r
-\r
-       public function getDB() {\r
-               if (!isset ($this->mSlaveDB))\r
-                       $this->mSlaveDB = & wfGetDB(DB_SLAVE);\r
-               return $this->mSlaveDB;\r
-       }\r
-\r
-       public function getData() {\r
-               return $this->mData;\r
-       }\r
-\r
-       /**\r
-        * Query execution happens in the following steps:\r
-        * #1 Create a PageSet object with any pages requested by the user\r
-        * #2 If using generator, execute it to get a new PageSet object\r
-        * #3 Instantiate all requested modules. \r
-        *    This way the PageSet object will know what shared data is required,\r
-        *    and minimize DB calls. \r
-        * #4 Output all normalization and redirect resolution information\r
-        * #5 Execute all requested modules\r
-        */\r
-       public function execute() {\r
-               $meta = $prop = $list = $generator = null;\r
-               extract($this->extractRequestParams());\r
-\r
-               //\r
-               // Create and initialize PageSet\r
-               //\r
-               $this->mData = new ApiPageSet($this);\r
-               $this->mData->profileIn();\r
-               $this->mData->execute();\r
-               $this->mData->profileOut();\r
-\r
-               //\r
-               // If generator is provided, get a new dataset to work on\r
-               //\r
-               if (isset ($generator))\r
-                       $this->executeGenerator($generator);\r
-\r
-               // Instantiate required modules\r
-               // During instantiation, modules may optimize data requests through the $this->mData object \r
-               // $this->mData will be lazy loaded when modules begin to request data during execution\r
-               $modules = array ();\r
-               if (isset ($meta))\r
-                       foreach ($meta as $moduleName)\r
-                               $modules[] = new $this->mQueryMetaModules[$moduleName] ($this, $moduleName);\r
-               if (isset ($prop))\r
-                       foreach ($prop as $moduleName)\r
-                               $modules[] = new $this->mQueryPropModules[$moduleName] ($this, $moduleName);\r
-               if (isset ($list))\r
-                       foreach ($list as $moduleName)\r
-                               $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName);\r
-\r
-               // Title normalizations\r
-               $normValues = array ();\r
-               foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) {\r
-                       $normValues[] = array (\r
-                               'from' => $rawTitleStr,\r
-                               'to' => $titleStr\r
-                       );\r
-               }\r
-\r
-               if (!empty ($normValues)) {\r
-                       ApiResult :: setIndexedTagName($normValues, 'n');\r
-                       $this->getResult()->addValue('query', 'normalized', $normValues);\r
-               }\r
-\r
-               // Show redirect information\r
-               $redirValues = array ();\r
-               foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) {\r
-                       $redirValues[] = array (\r
-                               'from' => $titleStrFrom,\r
-                               'to' => $titleStrTo\r
-                       );\r
-               }\r
-\r
-               if (!empty ($redirValues)) {\r
-                       ApiResult :: setIndexedTagName($redirValues, 'r');\r
-                       $this->getResult()->addValue('query', 'redirects', $redirValues);\r
-               }\r
-\r
-               // Execute all requested modules.\r
-               foreach ($modules as $module) {\r
-                       $module->profileIn();\r
-                       $module->execute();\r
-                       $module->profileOut();\r
-               }\r
-\r
-               // Ensure that pages are shown as '<page>' elements\r
-               $data = & $this->getResultData();\r
-               if (isset ($data['query']['pages'])) {\r
-                       ApiResult :: setIndexedTagName($data['query']['pages'], 'page');\r
-               }\r
-       }\r
-\r
-       protected function executeGenerator($generator) {\r
-\r
-               // Find class that implements requested generator\r
-               if (isset ($this->mQueryListModules[$generator]))\r
-                       $className = $this->mQueryListModules[$generator];\r
-               else\r
-                       if (isset ($this->mQueryPropModules[$generator]))\r
-                               $className = $this->mQueryPropModules[$generator];\r
-                       else\r
-                               ApiBase :: dieDebug("Unknown generator=$generator");\r
-\r
-               $module = new $className ($this, $generator, true);\r
-\r
-               // change $this->mData\r
-\r
-               // TODO: implement\r
-               $this->dieUsage('Generator execution has not been implemented', 'notimplemented');\r
-       }\r
-\r
-       protected function getAllowedParams() {\r
-               return array (\r
-                       'meta' => array (\r
-                               GN_ENUM_ISMULTI => true,\r
-                               GN_ENUM_TYPE => $this->mMetaModuleNames\r
-                       ),\r
-                       'prop' => array (\r
-                               GN_ENUM_ISMULTI => true,\r
-                               GN_ENUM_TYPE => $this->mPropModuleNames\r
-                       ),\r
-                       'list' => array (\r
-                               GN_ENUM_ISMULTI => true,\r
-                               GN_ENUM_TYPE => $this->mListModuleNames\r
-                       )\r
-                       //                      'generator' => array (\r
-                       //                              GN_ENUM_TYPE => $this->mAllowedGenerators\r
-                       //                      ),\r
-\r
-                       \r
-               );\r
-       }\r
-\r
-       /**\r
-        * Override the parent to generate help messages for all available query modules.\r
-        */\r
-       public function makeHelpMsg() {\r
-\r
-               // Use parent to make default message for the query module\r
-               $msg = parent :: makeHelpMsg();\r
-\r
-               // Make sure the internal object is empty\r
-               // (just in case a sub-module decides to optimize during instantiation)\r
-               $this->mData = null;\r
-\r
-               $astriks = str_repeat('--- ', 8);\r
-               $msg .= "\n$astriks Query: Meta  $astriks\n\n";\r
-               $msg .= $this->makeHelpMsgHelper($this->mQueryMetaModules, 'meta');\r
-               $msg .= "\n$astriks Query: Prop  $astriks\n\n";\r
-               $msg .= $this->makeHelpMsgHelper($this->mQueryPropModules, 'prop');\r
-               $msg .= "\n$astriks Query: List  $astriks\n\n";\r
-               $msg .= $this->makeHelpMsgHelper($this->mQueryListModules, 'list');\r
-\r
-               return $msg;\r
-       }\r
-\r
-       private function makeHelpMsgHelper($moduleList, $paramName) {\r
-               $msg = '';\r
-\r
-               foreach ($moduleList as $moduleName => $moduleClass) {\r
-                       $msg .= "* $paramName=$moduleName *";\r
-                       $module = new $moduleClass ($this, $moduleName, null);\r
-                       $msg2 = $module->makeHelpMsg();\r
-                       if ($msg2 !== false)\r
-                               $msg .= $msg2;\r
-                       $msg .= "\n";\r
-                       if ($module->getCanGenerate())\r
-                               $msg .= "  * Can be used as a generator\n";\r
-               }\r
-\r
-               return $msg;\r
-       }\r
-\r
-       /**\r
-        * Override to add extra parameters from PageSet\r
-        */\r
-       public function makeHelpMsgParameters() {\r
-               $module = new ApiPageSet($this);\r
-               return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters();\r
-       }\r
-\r
-       protected function getParamDescription() {\r
-               return array (\r
-                       'meta' => 'Which meta data to get about the site',\r
-                       'prop' => 'Which properties to get for the titles/revisions/pageids',\r
-                       'list' => 'Which lists to get',\r
-                       'generator' => 'Use the output of a list as the input for other prop/list/meta items',\r
-\r
-                       \r
-               );\r
-       }\r
-\r
-       protected function getDescription() {\r
-               return array (\r
-                       'Query API module allows applications to get needed pieces of data from the MediaWiki databases,',\r
-                       'and is loosely based on the Query API interface currently available on all MediaWiki servers.',\r
-                       'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.'\r
-               );\r
-       }\r
-\r
-       protected function getExamples() {\r
-               return array (\r
-                       'api.php?action=query&what=content&titles=ArticleA|ArticleB'\r
-               );\r
-       }\r
-}\r
-?>\r
+<?php
+
+
+/*
+ * Created on Sep 7, 2006
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@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.,
+ * 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 $mMetaModuleNames, $mPropModuleNames, $mListModuleNames;
+       private $mData;
+
+       private $mQueryMetaModules = array (
+               'siteinfo' => 'ApiQuerySiteinfo'
+       );
+       //      'userinfo' => 'ApiQueryUserinfo',
+
+       private $mQueryPropModules = array (
+               'info' => 'ApiQueryInfo',
+               'revisions' => 'ApiQueryRevisions'
+       );
+       //      'categories' => 'ApiQueryCategories',
+       //      'imageinfo' => 'ApiQueryImageinfo',
+       //      'langlinks' => 'ApiQueryLanglinks',
+       //      'links' => 'ApiQueryLinks',
+       //      'templates' => 'ApiQueryTemplates',
+
+       private $mQueryListModules = array (
+               'allpages' => 'ApiQueryAllpages'
+       );
+       //      'backlinks' => 'ApiQueryBacklinks',
+       //      'categorymembers' => 'ApiQueryCategorymembers',
+       //      'embeddedin' => 'ApiQueryEmbeddedin',
+       //      'imagelinks' => 'ApiQueryImagelinks',
+       //      'logevents' => 'ApiQueryLogevents',
+       //      'recentchanges' => 'ApiQueryRecentchanges',
+       //      'usercontribs' => 'ApiQueryUsercontribs',
+       //      'users' => 'ApiQueryUsers',
+       //      'watchlist' => 'ApiQueryWatchlist',
+
+       private $mSlaveDB = null;
+
+       public function __construct($main, $action) {
+               parent :: __construct($main);
+               $this->mMetaModuleNames = array_keys($this->mQueryMetaModules);
+               $this->mPropModuleNames = array_keys($this->mQueryPropModules);
+               $this->mListModuleNames = array_keys($this->mQueryListModules);
+
+               // Allow the entire list of modules at first,
+               // but during module instantiation check if it can be used as a generator.
+               $this->mAllowedGenerators = array_merge($this->mListModuleNames, $this->mPropModuleNames);
+       }
+
+       public function getDB() {
+               if (!isset ($this->mSlaveDB))
+                       $this->mSlaveDB = & wfGetDB(DB_SLAVE);
+               return $this->mSlaveDB;
+       }
+
+       public function getData() {
+               return $this->mData;
+       }
+
+       /**
+        * Query execution happens in the following steps:
+        * #1 Create a PageSet object with any pages requested by the user
+        * #2 If using generator, execute it to get a new PageSet object
+        * #3 Instantiate all requested modules. 
+        *    This way the PageSet object will know what shared data is required,
+        *    and minimize DB calls. 
+        * #4 Output all normalization and redirect resolution information
+        * #5 Execute all requested modules
+        */
+       public function execute() {
+               $meta = $prop = $list = $generator = null;
+               extract($this->extractRequestParams());
+
+               //
+               // Create PageSet
+               //
+               $this->mData = new ApiPageSet($this);
+
+               //
+               // If generator is provided, get a new dataset to work on
+               //
+               if (isset ($generator))
+                       $this->executeGenerator($generator);
+
+               // Instantiate required modules
+               // During instantiation, modules may optimize data requests through the $this->mData object 
+               // $this->mData will be lazy loaded when modules begin to request data during execution
+               $modules = array ();
+               if (isset ($meta))
+                       foreach ($meta as $moduleName)
+                               $modules[] = new $this->mQueryMetaModules[$moduleName] ($this, $moduleName);
+               if (isset ($prop))
+                       foreach ($prop as $moduleName)
+                               $modules[] = new $this->mQueryPropModules[$moduleName] ($this, $moduleName);
+               if (isset ($list))
+                       foreach ($list as $moduleName)
+                               $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName);
+
+               //
+               // Get page information for the given pageSet
+               //
+               $this->mData->profileIn();
+               $this->mData->execute();
+               $this->mData->profileOut();
+
+               // Title normalizations
+               $normValues = array ();
+               foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) {
+                       $normValues[] = array (
+                               'from' => $rawTitleStr,
+                               'to' => $titleStr
+                       );
+               }
+
+               if (!empty ($normValues)) {
+                       ApiResult :: setIndexedTagName($normValues, 'n');
+                       $this->getResult()->addValue('query', 'normalized', $normValues);
+               }
+
+               // Show redirect information
+               $redirValues = array ();
+               foreach ($this->mData->getRedirectTitles() as $titleStrFrom => $titleStrTo) {
+                       $redirValues[] = array (
+                               'from' => $titleStrFrom,
+                               'to' => $titleStrTo
+                       );
+               }
+
+               if (!empty ($redirValues)) {
+                       ApiResult :: setIndexedTagName($redirValues, 'r');
+                       $this->getResult()->addValue('query', 'redirects', $redirValues);
+               }
+
+               // Execute all requested modules.
+               foreach ($modules as $module) {
+                       $module->profileIn();
+                       $module->execute();
+                       $module->profileOut();
+               }
+
+               // Ensure that pages are shown as '<page>' elements
+               $data = & $this->getResultData();
+               if (isset ($data['query']['pages'])) {
+                       ApiResult :: setIndexedTagName($data['query']['pages'], 'page');
+               }
+       }
+
+       protected function executeGenerator($generator) {
+
+               // Find class that implements requested generator
+               if (isset ($this->mQueryListModules[$generator]))
+                       $className = $this->mQueryListModules[$generator];
+               else
+                       if (isset ($this->mQueryPropModules[$generator]))
+                               $className = $this->mQueryPropModules[$generator];
+                       else
+                               ApiBase :: dieDebug("Unknown generator=$generator");
+
+               $module = new $className ($this, $generator, true);
+
+               // execute pageSet here to get the data required by the generator module
+               $this->mData->profileIn();
+               $this->mData->execute();
+               $this->mData->profileOut();
+
+               // change $this->mData
+
+               // TODO: implement
+               $this->dieUsage('Generator execution has not been implemented', 'notimplemented');
+       }
+
+       protected function getAllowedParams() {
+               return array (
+                       'meta' => array (
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => $this->mMetaModuleNames
+                       ),
+                       'prop' => array (
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => $this->mPropModuleNames
+                       ),
+                       'list' => array (
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => $this->mListModuleNames
+                       )
+                       //                      'generator' => array (
+                       //                              ApiBase::PARAM_TYPE => $this->mAllowedGenerators
+                       //                      ),
+
+                       
+               );
+       }
+
+       /**
+        * Override the parent to generate help messages for all available query modules.
+        */
+       public function makeHelpMsg() {
+
+               // Use parent to make default message for the query module
+               $msg = parent :: makeHelpMsg();
+
+               // Make sure the internal object is empty
+               // (just in case a sub-module decides to optimize during instantiation)
+               $this->mData = null;
+
+               $astriks = str_repeat('--- ', 8);
+               $msg .= "\n$astriks Query: Meta  $astriks\n\n";
+               $msg .= $this->makeHelpMsgHelper($this->mQueryMetaModules, 'meta');
+               $msg .= "\n$astriks Query: Prop  $astriks\n\n";
+               $msg .= $this->makeHelpMsgHelper($this->mQueryPropModules, 'prop');
+               $msg .= "\n$astriks Query: List  $astriks\n\n";
+               $msg .= $this->makeHelpMsgHelper($this->mQueryListModules, 'list');
+
+               return $msg;
+       }
+
+       private function makeHelpMsgHelper($moduleList, $paramName) {
+               $msg = '';
+
+               foreach ($moduleList as $moduleName => $moduleClass) {
+                       $msg .= "* $paramName=$moduleName *";
+                       $module = new $moduleClass ($this, $moduleName, null);
+                       $msg2 = $module->makeHelpMsg();
+                       if ($msg2 !== false)
+                               $msg .= $msg2;
+                       $msg .= "\n";
+                       if ($module->getCanGenerate())
+                               $msg .= "  * Can be used as a generator\n";
+               }
+
+               return $msg;
+       }
+
+       /**
+        * Override to add extra parameters from PageSet
+        */
+       public function makeHelpMsgParameters() {
+               $module = new ApiPageSet($this);
+               return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters();
+       }
+
+       protected function getParamDescription() {
+               return array (
+                       'meta' => 'Which meta data to get about the site',
+                       'prop' => 'Which properties to get for the titles/revisions/pageids',
+                       'list' => 'Which lists to get',
+                       'generator' => 'Use the output of a list as the input for other prop/list/meta items',
+
+                       
+               );
+       }
+
+       protected function getDescription() {
+               return array (
+                       'Query API module allows applications to get needed pieces of data from the MediaWiki databases,',
+                       'and is loosely based on the Query API interface currently available on all MediaWiki servers.',
+                       'All data modifications will first have to use query to acquire a token to prevent abuse from malicious sites.'
+               );
+       }
+
+       protected function getExamples() {
+               return array (
+                       'api.php?action=query&prop=revisions&meta=siteinfo&titles=Main%20Page&rvprop=user|comment'
+               );
+       }
+}
+?>
index 5973250..db7f9ef 100644 (file)
@@ -107,23 +107,23 @@ class ApiQueryAllpages extends ApiQueryBase {
                return array (
                        'apfrom' => null,
                        'apnamespace' => array (
-                               GN_ENUM_DFLT => 0,
-                               GN_ENUM_TYPE => $validNamespaces
+                               ApiBase::PARAM_DFLT => 0,
+                               ApiBase::PARAM_TYPE => $validNamespaces
                        ),
                        'apfilterredir' => array (
-                               GN_ENUM_DFLT => 'all',
-                               GN_ENUM_TYPE => array (
+                               ApiBase::PARAM_DFLT => 'all',
+                               ApiBase::PARAM_TYPE => array (
                                        'all',
                                        'redirects',
                                        'nonredirects'
                                )
                        ),
                        'aplimit' => array (
-                               GN_ENUM_DFLT => 10,
-                               GN_ENUM_TYPE => 'limit',
-                               GN_ENUM_MIN => 1,
-                               GN_ENUM_MAX1 => 500,
-                               GN_ENUM_MAX2 => 5000
+                               ApiBase::PARAM_DFLT => 10,
+                               ApiBase::PARAM_TYPE => 'limit',
+                               ApiBase::PARAM_MIN => 1,
+                               ApiBase::PARAM_MAX1 => 500,
+                               ApiBase::PARAM_MAX2 => 5000
                        )
                );
        }
index 732ecf6..dccad67 100644 (file)
@@ -43,9 +43,9 @@ class ApiQueryInfo extends ApiQueryBase {
                return array (
                        'param' => 'default',
                        'enumparam' => array (
-                               GN_ENUM_DFLT => 'default',
-                               GN_ENUM_ISMULTI => false,
-                               GN_ENUM_TYPE => array (
+                               ApiBase::PARAM_DFLT => 'default',
+                               ApiBase::PARAM_ISMULTI => false,
+                               ApiBase::PARAM_TYPE => array (
                                        'a',
                                        'b'
                                )
index f35075f..e8e6efb 100644 (file)
@@ -175,7 +175,7 @@ class ApiQueryRevisions extends ApiQueryBase {
 
                $db = $this->getDB();
                $this->profileDBIn();
-               $res = $db->select($tables, $fields, $conds, __CLASS__ . '::' . __FUNCTION__, $options);
+               $res = $db->select($tables, $fields, $conds, __METHOD__, $options);
                $this->profileDBOut();
 
                $data = array ();
@@ -239,30 +239,30 @@ class ApiQueryRevisions extends ApiQueryBase {
        protected function getAllowedParams() {
                return array (
                        'rvlimit' => array (
-                               GN_ENUM_DFLT => 0,
-                               GN_ENUM_TYPE => 'limit',
-                               GN_ENUM_MIN => 0,
-                               GN_ENUM_MAX1 => 50,
-                               GN_ENUM_MAX2 => 500
+                               ApiBase::PARAM_DFLT => 0,
+                               ApiBase::PARAM_TYPE => 'limit',
+                               ApiBase::PARAM_MIN => 0,
+                               ApiBase::PARAM_MAX1 => 50,
+                               ApiBase::PARAM_MAX2 => 500
                        ),
                        'rvstartid' => 0,
                        'rvendid' => 0,
                        'rvstart' => array (
-                               GN_ENUM_TYPE => 'timestamp'
+                               ApiBase::PARAM_TYPE => 'timestamp'
                        ),
                        'rvend' => array (
-                               GN_ENUM_TYPE => 'timestamp'
+                               ApiBase::PARAM_TYPE => 'timestamp'
                        ),
                        'rvdir' => array (
-                               GN_ENUM_DFLT => 'older',
-                               GN_ENUM_TYPE => array (
+                               ApiBase::PARAM_DFLT => 'older',
+                               ApiBase::PARAM_TYPE => array (
                                        'newer',
                                        'older'
                                )
                        ),
                        'rvprop' => array (
-                               GN_ENUM_ISMULTI => true,
-                               GN_ENUM_TYPE => array (
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => array (
                                        'timestamp',
                                        'user',
                                        'comment',
index 54d3a5c..6bddee2 100644 (file)
@@ -78,9 +78,9 @@ class ApiQuerySiteinfo extends ApiQueryBase {
        protected function getAllowedParams() {
                return array (
                        'siprop' => array (
-                               GN_ENUM_DFLT => 'general',
-                               GN_ENUM_ISMULTI => true,
-                               GN_ENUM_TYPE => array (
+                               ApiBase::PARAM_DFLT => 'general',
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => array (
                                        'general',
                                        'namespaces'
                                )
index d99b759..3e65b57 100644 (file)
-<?php\r
-\r
-\r
-/*\r
- * Created on Sep 4, 2006\r
- *\r
- * API for MediaWiki 1.8+\r
- *\r
- * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@gmail.com>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * http://www.gnu.org/copyleft/gpl.html\r
- */\r
-\r
-if (!defined('MEDIAWIKI')) {\r
-       // Eclipse helper - will be ignored in production\r
-       require_once ('ApiBase.php');\r
-}\r
-\r
-class ApiResult extends ApiBase {\r
-\r
-       private $mData;\r
-\r
-       /**\r
-       * Constructor\r
-       */\r
-       public function __construct($main) {\r
-               parent :: __construct($main);\r
-               $this->Reset();\r
-       }\r
-\r
-       public function Reset() {\r
-               $this->mData = array ();\r
-       }\r
-\r
-       function & getData() {\r
-               return $this->mData;\r
-       }\r
-\r
-       /**\r
-        * Add an output value to the array by name.\r
-        * Verifies that value with the same name has not been added before.\r
-        */\r
-       public static function addElement(& $arr, $name, $value) {\r
-               if ($arr === null || $name === null || $value === null || !is_array($arr) || is_array($name))\r
-                       ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__);\r
-               if (isset ($arr[$name]))\r
-                       ApiBase :: dieDebug("Attempting to add element $name=$value, existing value is {$arr[$name]}");\r
-               $arr[$name] = $value;\r
-       }\r
-\r
-       /**\r
-        * Adds the content element to the array.\r
-        * Use this function instead of hardcoding the '*' element.\r
-        */\r
-       public static function addContent(& $arr, $value) {\r
-               if (is_array($value))\r
-                       ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__);\r
-               ApiResult :: addElement($arr, '*', $value);\r
-       }\r
-\r
-       //      public static function makeContentElement($tag, $value) {\r
-       //              $result = array();\r
-       //              ApiResult::addContent($result, )\r
-       //      }\r
-       //\r
-       /**\r
-        * In case the array contains indexed values (in addition to named),\r
-        * all indexed values will have the given tag name.\r
-        */\r
-       public static function setIndexedTagName(& $arr, $tag) {\r
-               // Do not use addElement() as it is ok to call this more than once\r
-               if ($arr === null || $tag === null || !is_array($arr) || is_array($tag))\r
-                       ApiBase :: dieDebug('Bad parameter for ' . __FUNCTION__);\r
-               $arr['_element'] = $tag;\r
-       }\r
-\r
-       /**\r
-        * Add value to the output data at the given path.\r
-        * Path is an indexed array, each element specifing the branch at which to add the new value\r
-        * Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value  \r
-        */\r
-       public function addValue($path, $name, $value) {\r
-\r
-               $data = & $this->getData();\r
-\r
-               if (isset ($path)) {\r
-                       if (is_array($path)) {\r
-                               foreach ($path as $p) {\r
-                                       if (!isset ($data[$p]))\r
-                                               $data[$p] = array ();\r
-                                       $data = & $data[$p];\r
-                               }\r
-                       } else {\r
-                               if (!isset ($data[$path]))\r
-                                       $data[$path] = array ();\r
-                               $data = & $data[$path];\r
-                       }\r
-               }\r
-\r
-               ApiResult :: addElement($data, $name, $value);\r
-       }\r
-\r
-       /**\r
-       * Recursivelly removes any elements from the array that begin with an '_'.\r
-       * The content element '*' is the only special element that is left.\r
-       * Use this method when the entire data object gets sent to the user.\r
-       */\r
-       public function SanitizeData() {\r
-               ApiResult :: SanitizeDataInt($this->mData);\r
-       }\r
-\r
-       private static function SanitizeDataInt(& $data) {\r
-               foreach ($data as $key => & $value) {\r
-                       if ($key[0] === '_') {\r
-                               unset ($data[$key]);\r
-                       }\r
-                       elseif ($key === '*' && $value === '') {\r
-                               unset ($data[$key]);\r
-                       }\r
-                       elseif (is_array($value)) {\r
-                               ApiResult :: SanitizeDataInt($value);\r
-                       }\r
-               }\r
-       }\r
-\r
-       public function execute() {\r
-               $this->dieDebug('execute() is not supported on Result object');\r
-       }\r
-}\r
-?>\r
+<?php
+
+
+/*
+ * Created on Sep 4, 2006
+ *
+ * API for MediaWiki 1.8+
+ *
+ * Copyright (C) 2006 Yuri Astrakhan <FirstnameLastname@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.,
+ * 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;
+       }
+
+       /**
+        * Add an output value to the array by name.
+        * Verifies that value with the same name has not been added before.
+        */
+       public static function addElement(& $arr, $name, $value) {
+               if ($arr === null || $name === null || $value === null || !is_array($arr) || is_array($name))
+                       ApiBase :: dieDebug('Bad parameter for ' . __METHOD__);
+               if (isset ($arr[$name]))
+                       ApiBase :: dieDebug("Attempting to add element $name=$value, existing value is {$arr[$name]}");
+               $arr[$name] = $value;
+       }
+
+       /**
+        * Adds the content element to the array.
+        * Use this function instead of hardcoding the '*' element.
+        */
+       public static function addContent(& $arr, $value) {
+               if (is_array($value))
+                       ApiBase :: dieDebug('Bad parameter for ' . __METHOD__);
+               ApiResult :: addElement($arr, '*', $value);
+       }
+
+       //      public static function makeContentElement($tag, $value) {
+       //              $result = array();
+       //              ApiResult::addContent($result, )
+       //      }
+       //
+       /**
+        * In case the array contains indexed values (in addition to named),
+        * all indexed values will have the given tag name.
+        */
+       public static function setIndexedTagName(& $arr, $tag) {
+               // Do not use addElement() as it is ok to call this more than once
+               if ($arr === null || $tag === null || !is_array($arr) || is_array($tag))
+                       ApiBase :: dieDebug('Bad parameter for ' . __METHOD__);
+               $arr['_element'] = $tag;
+       }
+
+       /**
+        * Add value to the output data at the given path.
+        * Path is an indexed array, each element specifing the branch at which to add the new value
+        * Setting $path to array('a','b','c') is equivalent to data['a']['b']['c'] = $value  
+        */
+       public function addValue($path, $name, $value) {
+
+               $data = & $this->getData();
+
+               if (isset ($path)) {
+                       if (is_array($path)) {
+                               foreach ($path as $p) {
+                                       if (!isset ($data[$p]))
+                                               $data[$p] = array ();
+                                       $data = & $data[$p];
+                               }
+                       } else {
+                               if (!isset ($data[$path]))
+                                       $data[$path] = array ();
+                               $data = & $data[$path];
+                       }
+               }
+
+               ApiResult :: addElement($data, $name, $value);
+       }
+
+       /**
+       * 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');
+       }
+}
+?>