* API: result data generation cleanup, minor cleaning
authorYuri Astrakhan <yurik@users.mediawiki.org>
Sun, 1 Oct 2006 02:02:13 +0000 (02:02 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Sun, 1 Oct 2006 02:02:13 +0000 (02:02 +0000)
17 files changed:
api.php
includes/api/ApiBase.php
includes/api/ApiFormatBase.php
includes/api/ApiFormatJson.php
includes/api/ApiFormatXml.php
includes/api/ApiFormatYaml.php
includes/api/ApiHelp.php
includes/api/ApiLogin.php
includes/api/ApiMain.php
includes/api/ApiPageSet.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllpages.php
includes/api/ApiQueryBase.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 d75ef10..c96c647 100644 (file)
--- a/api.php
+++ b/api.php
@@ -84,7 +84,7 @@ $wgApiFormats = array (
 );\r
 \r
 // Initialise common code\r
-require (dirname(__FILE__) . "/includes/WebStart.php");\r
+require (dirname(__FILE__) . '/includes/WebStart.php');\r
 wfProfileIn('api.php');\r
 \r
 // Verify that the API has not been disabled\r
@@ -114,4 +114,4 @@ function apiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) {
        foreach ($apiAutoloadClasses as $className => $classFile)\r
                $wgAutoloadClasses[$className] = $apiDirectory . $classFile;\r
 }\r
-?>
\ No newline at end of file
+?>\r
index c3ce8e5..46aa903 100644 (file)
@@ -69,11 +69,18 @@ abstract class ApiBase {
                // Main module has getResult() method overriden\r
                // Safety - avoid infinite loop:\r
                if ($this->isMain())\r
-                       $this->dieDebug(__METHOD__ .\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
@@ -115,7 +122,7 @@ abstract class ApiBase {
        public function makeHelpMsgParameters() {\r
                $params = $this->getAllowedParams();\r
                if ($params !== false) {\r
-                       \r
+\r
                        $paramsDescription = $this->getParamDescription();\r
                        $msg = '';\r
                        foreach (array_keys($params) as $paramName) {\r
@@ -125,10 +132,9 @@ abstract class ApiBase {
                                $msg .= sprintf("  %-14s - %s\n", $paramName, $desc);\r
                        }\r
                        return $msg;\r
-               \r
-               }\r
-               else\r
-                       return false; \r
+\r
+               } else\r
+                       return false;\r
        }\r
 \r
        /**\r
@@ -174,7 +180,7 @@ abstract class ApiBase {
                return $results;\r
        }\r
 \r
-       public function getParameter($paramName, $paramSettings){\r
+       public function getParameter($paramName, $paramSettings) {\r
                global $wgRequest;\r
 \r
                if (!is_array($paramSettings)) {\r
@@ -198,12 +204,12 @@ abstract class ApiBase {
                if ($type == 'boolean') {\r
                        if (isset ($default) && $default !== false) {\r
                                // Having a default value of anything other than 'false' is pointless\r
-                               $this->dieDebug("Boolean param $paramName's default is set to '$default'");\r
+                               ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'");\r
                        }\r
 \r
-            $value = $wgRequest->getCheck($paramName);\r
+                       $value = $wgRequest->getCheck($paramName);\r
                } else\r
-               $value = $wgRequest->getVal($paramName, $default);\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
@@ -222,33 +228,33 @@ abstract class ApiBase {
                                        break;\r
                                case 'limit' :\r
                                        if (!isset ($paramSettings[GN_ENUM_MAX1]) || !isset ($paramSettings[GN_ENUM_MAX2]))\r
-                                               $this->dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");\r
+                                               ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");\r
                                        if ($multi)\r
-                                               $this->dieDebug("Multi-values not supported for $paramName");\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
-                                               $this->dieDebug("Multi-values not supported for $paramName");\r
+                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");\r
                                        break;\r
                                case 'timestamp' :\r
                                        if ($multi)\r
-                                               $this->dieDebug("Multi-values not supported for $paramName");\r
+                                               ApiBase :: dieDebug("Multi-values not supported for $paramName");\r
                                        $value = $this->prepareTimestamp($value); // Adds quotes around timestamp                                                       \r
                                        break;\r
                                default :\r
-                                       $this->dieDebug("Param $paramName's type is unknown - $type");\r
+                                       ApiBase :: dieDebug("Param $paramName's type is unknown - $type");\r
 \r
                        }\r
                }\r
 \r
-               return $value;  \r
+               return $value;\r
        }\r
-       \r
+\r
        /**\r
-       * Return an array of values that were given in a "a|b|c" notation,\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
@@ -266,7 +272,7 @@ abstract class ApiBase {
                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
+                               $this->dieUsage('Unrecognised value' . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName");\r
                        }\r
                }\r
 \r
@@ -315,75 +321,70 @@ abstract class ApiBase {
        /**\r
         * Internal code errors should be reported with this method\r
         */\r
-       protected function dieDebug($message) {\r
-               wfDebugDieBacktrace("Internal error in '{get_class($this)}': $message");\r
+       protected static function dieDebug($message) {\r
+               wfDebugDieBacktrace("Internal error: $message");\r
        }\r
-       \r
+\r
        /**\r
         * Profiling: total module execution time\r
         */\r
-       private $mTimeIn = 0, $mModuleTime = 0; \r
-       \r
+       private $mTimeIn = 0, $mModuleTime = 0;\r
+\r
        /**\r
         * Start module profiling\r
         */\r
-       public function profileIn()\r
-       {\r
+       public function profileIn() {\r
                if ($this->mTimeIn !== 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called twice without calling profileOut()');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileOut()');\r
                $this->mTimeIn = microtime(true);\r
        }\r
-       \r
+\r
        /**\r
         * End module profiling\r
         */\r
-       public function profileOut()\r
-       {\r
+       public function profileOut() {\r
                if ($this->mTimeIn === 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called without calling profileIn() first');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileIn() first');\r
                if ($this->mDBTimeIn !== 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' must be called after database profiling is done with profileDBOut()');\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
        /**\r
         * Total time the module was executed\r
         */\r
-       public function getProfileTime()\r
-       {\r
+       public function getProfileTime() {\r
                if ($this->mTimeIn !== 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called without calling profileOut() first');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileOut() first');\r
                return $this->mModuleTime;\r
        }\r
-       \r
+\r
        /**\r
         * Profiling: database execution time\r
         */\r
-       private $mDBTimeIn = 0, $mDBTime = 0; \r
-       \r
+       private $mDBTimeIn = 0, $mDBTime = 0;\r
+\r
        /**\r
         * Start module profiling\r
         */\r
-       public function profileDBIn()\r
-       {\r
+       public function profileDBIn() {\r
                if ($this->mTimeIn === 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
                if ($this->mDBTimeIn !== 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()');\r
                $this->mDBTimeIn = microtime(true);\r
        }\r
-       \r
+\r
        /**\r
         * End database profiling\r
         */\r
-       public function profileDBOut()\r
-       {\r
+       public function profileDBOut() {\r
                if ($this->mTimeIn === 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');\r
                if ($this->mDBTimeIn === 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first');\r
 \r
                $time = microtime(true) - $this->mDBTimeIn;\r
                $this->mDBTimeIn = 0;\r
@@ -391,14 +392,13 @@ abstract class ApiBase {
                $this->mDBTime += $time;\r
                $this->getMain()->mDBTime += $time;\r
        }\r
-       \r
+\r
        /**\r
         * Total time the module used the database\r
         */\r
-       public function getProfileDBTime()\r
-       {\r
+       public function getProfileDBTime() {\r
                if ($this->mDBTimeIn !== 0)\r
-                       $this->dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first');\r
+                       ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first');\r
                return $this->mDBTime;\r
        }\r
 }\r
index f0e9921..e960699 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiBase.php");
+       require_once ('ApiBase.php');
 }
 
 abstract class ApiFormatBase extends ApiBase {
@@ -94,7 +94,7 @@ abstract class ApiFormatBase extends ApiBase {
                        <small>
                        This result is being shown in <?=$this->mFormat?> format,
                        which might not be suitable for your application.<br/>
-                       See <a href="api.php">API help</a> for more information.<br/>
+                       See <a href='api.php'>API help</a> for more information.<br/>
                        </small>
 <?php
 
@@ -131,7 +131,7 @@ abstract class ApiFormatBase extends ApiBase {
 
        /**
        * Prety-print various elements in HTML format, such as xml tags and URLs.
-       * This method also replaces any "<" with &lt;
+       * This method also replaces any '<' with &lt;
        */
        protected function formatHTML($text) {
                // encode all tags as safe blue strings
index b24abfd..bce60d9 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiFormatBase.php");
+       require_once ('ApiFormatBase.php');
 }
 
 class ApiFormatJson extends ApiFormatBase {
index 06b93a0..ad0655a 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiFormatBase.php");
+       require_once ('ApiFormatBase.php');
 }
 
 class ApiFormatXml extends ApiFormatBase {
@@ -53,57 +53,84 @@ class ApiFormatXml extends ApiFormatBase {
                        $xmlindent = null;
 
                $this->printText('<?xml version="1.0" encoding="utf-8"?>');
-               $this->recXmlPrint('api', $this->getResult()->getData(), $xmlindent);
+               $this->recXmlPrint('api', $this->getResultData(), $xmlindent);
        }
 
        /**
        * This method takes an array and converts it into an xml.
        * There are several noteworthy cases:
        *
-       *  If array contains a key "_element", then the code assumes that ALL other keys are not important and replaces them with the value['_element'].
-       *       Example:        name="root",  value = array( "_element"=>"page", "x", "y", "z") creates <root>  <page>x</page>  <page>y</page>  <page>z</page> </root>
+       *  If array contains a key '_element', then the code assumes that ALL other keys are not important and replaces them with the value['_element'].
+       *       Example:        name='root',  value = array( '_element'=>'page', 'x', 'y', 'z') creates <root>  <page>x</page>  <page>y</page>  <page>z</page> </root>
        *
-       *  If any of the array's element key is "*", then the code treats all other key->value pairs as attributes, and the value['*'] as the element's content.
-       *       Example:        name="root",  value = array( "*"=>"text", "lang"=>"en", "id"=>10)   creates  <root lang="en" id="10">text</root>
+       *  If any of the array's element key is '*', then the code treats all other key->value pairs as attributes, and the value['*'] as the element's content.
+       *       Example:        name='root',  value = array( '*'=>'text', 'lang'=>'en', 'id'=>10)   creates  <root lang='en' id='10'>text</root>
        *
        * If neither key is found, all keys become element names, and values become element content.
        * The method is recursive, so the same rules apply to any sub-arrays.
        */
        function recXmlPrint($elemName, $elemValue, $indent) {
-               $indstr = "";
                if (!is_null($indent)) {
                        $indent += 2;
                        $indstr = "\n" . str_repeat(" ", $indent);
+               } else {
+                       $indstr = '';
                }
 
                switch (gettype($elemValue)) {
                        case 'array' :
-                               if (array_key_exists('*', $elemValue)) {
+
+                               if (isset ($elemValue['*'])) {
                                        $subElemContent = $elemValue['*'];
                                        unset ($elemValue['*']);
-                                       if (gettype($subElemContent) === 'array') {
-                                               $this->printText($indstr . wfElement($elemName, $elemValue, null));
-                                               $this->recXmlPrint($elemName, $subElemContent, $indent);
-                                               $this->printText($indstr . "</$elemName>");
-                                       } else {
-                                               $this->printText($indstr . wfElement($elemName, $elemValue, $subElemContent));
-                                       }
                                } else {
-                                       $this->printText($indstr . wfElement($elemName, null, null));
-                                       if (array_key_exists('_element', $elemValue)) {
-                                               $subElemName = $elemValue['_element'];
-                                               foreach ($elemValue as $subElemId => & $subElemValue) {
-                                                       if ($subElemId !== '_element') {
-                                                               $this->recXmlPrint($subElemName, $subElemValue, $indent);
-                                                       }
+                                       $subElemContent = null;
+                               }
+
+                               if (isset ($elemValue['_element'])) {
+                                       $subElemIndName = $elemValue['_element'];
+                                       unset ($elemValue['_element']);
+                               } else {
+                                       $subElemIndName = null;
+                               }
+
+                               $indElements = array ();
+                               $subElements = array ();
+                               foreach ($elemValue as $subElemId => & $subElemValue) {
+                                       if (gettype($subElemId) === 'integer') {
+                                               if (!is_array($subElemValue))
+                                                       ApiBase :: dieDebug(__FUNCTION__ . "($elemName, ...) has a scalar indexed value.");
+                                               $indElements[] = $subElemValue;
+                                               unset ($elemValue[$subElemId]);
+                                       } else
+                                               if (is_array($subElemValue)) {
+                                                       $subElements[$subElemId] = $subElemValue;
+                                                       unset ($elemValue[$subElemId]);
                                                }
+                               }
+
+                               if (is_null($subElemIndName) && !empty ($indElements))
+                                       ApiBase :: dieDebug(__FUNCTION__ . "($elemName, ...) has integer keys without _element value");
+
+                               if (!empty ($subElements) && !empty ($indElements) && !is_null($subElemContent))
+                                       ApiBase :: dieDebug(__FUNCTION__ . "($elemName, ...) has content and subelements");
+
+                               if (!is_null($subElemContent)) {
+                                       $this->printText($indstr . wfElement($elemName, $elemValue, $subElemContent));
+                               } else
+                                       if (empty ($indElements) && empty ($subElements)) {
+                                               $this->printText($indstr . wfElement($elemName, $elemValue));
                                        } else {
-                                               foreach ($elemValue as $subElemName => & $subElemValue) {
-                                                       $this->recXmlPrint($subElemName, $subElemValue, $indent);
-                                               }
+                                               $this->printText($indstr . wfElement($elemName, $elemValue, null));
+
+                                               foreach ($subElements as $subElemId => & $subElemValue)
+                                                       $this->recXmlPrint($subElemId, $subElemValue, $indent);
+
+                                               foreach ($indElements as $subElemId => & $subElemValue)
+                                                       $this->recXmlPrint($subElemIndName, $subElemValue, $indent);
+
+                                               $this->printText($indstr . wfCloseElement($elemName));
                                        }
-                                       $this->printText($indstr . "</$elemName>");
-                               }
                                break;
                        case 'object' :
                                // ignore
index 40b8375..8b74b06 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiFormatBase.php");
+       require_once ('ApiFormatBase.php');
 }
 
 class ApiFormatYaml extends ApiFormatBase {
index bc8aca2..80ca546 100644 (file)
@@ -26,7 +26,7 @@
 \r
 if (!defined('MEDIAWIKI')) {\r
        // Eclipse helper - will be ignored in production\r
-       require_once ("ApiBase.php");\r
+       require_once ('ApiBase.php');\r
 }\r
 \r
 class ApiHelp extends ApiBase {\r
index 4a24545..5158c35 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiBase.php");
+       require_once ('ApiBase.php');
 }
 
 class ApiLogin extends ApiBase {
@@ -76,10 +76,10 @@ class ApiLogin extends ApiBase {
                                $result['result'] = 'AuthEmptyPass';
                                break;
                        default :
-                               $this->dieDebug("Unhandled case value");
+                               $this->dieDebug('Unhandled case value');
                }
 
-               $this->getResult()->addMessage('login', null, $result);
+               $this->getResult()->addValue(null, 'login', $result);
        }
 
        protected function getAllowedParams() {
@@ -104,4 +104,4 @@ class ApiLogin extends ApiBase {
                );
        }
 }
-?>
\ No newline at end of file
+?>
index 2f2c12a..f831fb5 100644 (file)
@@ -26,7 +26,7 @@
 \r
 if (!defined('MEDIAWIKI')) {\r
        // Eclipse helper - will be ignored in production\r
-       require_once ("ApiBase.php");\r
+       require_once ('ApiBase.php');\r
 }\r
 \r
 class ApiMain extends ApiBase {\r
@@ -50,7 +50,7 @@ class ApiMain extends ApiBase {
                $this->mResult = new ApiResult($this);\r
        }\r
 \r
-       public function getResult() {\r
+       public function getResult() {\r
                return $this->mResult;\r
        }\r
 \r
@@ -123,13 +123,16 @@ class ApiMain extends ApiBase {
 \r
        public function mainDieUsage($description, $errorCode, $httpRespCode = 0) {\r
                $this->mResult->Reset();\r
-               $this->mResult->addMessage('error', null, $errorCode);\r
                if ($httpRespCode === 0)\r
                        header($errorCode, true);\r
                else\r
                        header($errorCode, true, $httpRespCode);\r
 \r
-               $this->mResult->addMessage('usage', null, $this->makeHelpMsg());\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
@@ -191,5 +194,4 @@ class UsageException extends Exception {
                return "{$this->codestr}: {$this->message}";\r
        }\r
 }\r
-\r
 ?>
\ No newline at end of file
index eaa97ae..f859d12 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiQueryBase.php");
+       require_once ('ApiQueryBase.php');
 }
 
 class ApiPageSet extends ApiQueryBase {
@@ -83,14 +83,14 @@ class ApiPageSet extends ApiQueryBase {
        public function getGoodTitleCount() {
                return count($this->getGoodTitles());
        }
-       
+
        /**
         * Get the list of revision IDs (requested with revids= parameter)
         */
        public function getRevisionIDs() {
-               $this->dieUsage(__FUNCTION__ . " is not implemented", 'notimplemented');
+               $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented');
        }
-       
+
        /**
         * Returns the number of revisions (requested with revids= parameter)
         */
@@ -113,7 +113,7 @@ class ApiPageSet extends ApiQueryBase {
         * #6 Repeat from step #1     
         */
        private function populateTitles($titles, $redirects) {
-               
+
                $pageFlds = array (
                        'page_id',
                        'page_namespace',
@@ -249,13 +249,13 @@ class ApiPageSet extends ApiQueryBase {
        }
 
        private function populatePageIDs($pageids) {
-               $this->dieUsage(__FUNCTION__ . " is not implemented", 'notimplemented');
+               $this->dieUsage(__FUNCTION__ . ' is not implemented', 'notimplemented');
        }
 
        public function execute() {
                $titles = $pageids = $revids = $redirects = null;
                extract($this->extractRequestParams());
-               
+
                // Only one of the titles/pageids/revids is allowed at the same time
                $dataSource = null;
                if (isset ($titles))
@@ -303,7 +303,7 @@ class ApiPageSet extends ApiQueryBase {
                        'redirects' => false
                );
        }
-       
+
        protected function getParamDescription() {
                return array (
                        'titles' => 'A list of titles to work on',
index d882a53..fe7dd82 100644 (file)
@@ -26,7 +26,7 @@
 \r
 if (!defined('MEDIAWIKI')) {\r
        // Eclipse helper - will be ignored in production\r
-       require_once ("ApiBase.php");\r
+       require_once ('ApiBase.php');\r
 }\r
 \r
 class ApiQuery extends ApiBase {\r
@@ -128,21 +128,31 @@ class ApiQuery extends ApiBase {
                                $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName);\r
 \r
                // Title normalizations\r
+               $normValues = array ();\r
                foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) {\r
-                       $this->getResult()->addMessage('query', 'normalized', array (\r
+                       $normValues[] = array (\r
                                'from' => $rawTitleStr,\r
-                               'to' => $titleStr,\r
-                               '*' => ''\r
-                       ), 'n');\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
-                       $this->getResult()->addMessage('query', 'redirects', array (\r
+                       $redirValues[] = array (\r
                                'from' => $titleStrFrom,\r
-                               'to' => $titleStrTo,\r
-                               '*' => ''\r
-                       ), 'r');\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
@@ -151,6 +161,12 @@ class ApiQuery extends ApiBase {
                        $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
@@ -162,14 +178,14 @@ class ApiQuery extends ApiBase {
                        if (isset ($this->mQueryPropModules[$generator]))\r
                                $className = $this->mQueryPropModules[$generator];\r
                        else\r
-                               $this->dieDebug("Unknown generator=$generator");\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
+               $this->dieUsage('Generator execution has not been implemented', 'notimplemented');\r
        }\r
 \r
        protected function getAllowedParams() {\r
@@ -189,6 +205,8 @@ class ApiQuery extends ApiBase {
                        //                      'generator' => array (\r
                        //                              GN_ENUM_TYPE => $this->mAllowedGenerators\r
                        //                      ),\r
+\r
+                       \r
                );\r
        }\r
 \r
@@ -234,12 +252,11 @@ class ApiQuery extends ApiBase {
 \r
        /**\r
         * Override to add extra parameters from PageSet\r
-        */     \r
+        */\r
        public function makeHelpMsgParameters() {\r
                $module = new ApiPageSet($this);\r
                return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters();\r
        }\r
-       \r
 \r
        protected function getParamDescription() {\r
                return array (\r
@@ -247,6 +264,8 @@ class ApiQuery extends ApiBase {
                        '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
@@ -264,4 +283,4 @@ class ApiQuery extends ApiBase {
                );\r
        }\r
 }\r
-?>
\ No newline at end of file
+?>\r
index 0a715eb..5973250 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiQueryBase.php");
+       require_once ('ApiQueryBase.php');
 }
 
 class ApiQueryAllpages extends ApiQueryBase {
@@ -63,9 +63,9 @@ class ApiQueryAllpages extends ApiQueryBase {
                        'ORDER BY' => 'page_namespace, page_title'
                ));
                $this->profileDBOut();
-               
+
                $data = array ();
-               $data['_element'] = 'p';
+               ApiResult :: setIndexedTagName($data, 'p');
                $count = 0;
                while ($row = $db->fetchObject($res)) {
                        if (++ $count > $aplimit) {
@@ -73,7 +73,7 @@ class ApiQueryAllpages extends ApiQueryBase {
                                $msg = array (
                                        'continue' => 'apfrom=' . ApiQueryBase :: keyToTitle($row->page_title
                                ));
-                               $this->getResult()->addMessage('query-status', 'allpages', $msg);
+                               $this->getResult()->addValue('query-status', 'allpages', $msg);
                                break;
                        }
 
@@ -87,13 +87,12 @@ class ApiQueryAllpages extends ApiQueryBase {
                                if ($title->getNamespace() !== 0)
                                        $pagedata['ns'] = $title->getNamespace();
                                $pagedata['title'] = $title->getPrefixedText();
-                               $pagedata['*'] = '';
 
                                $data[$id] = $pagedata;
                        }
                }
                $db->freeResult($res);
-               $this->getResult()->addMessage('query', 'allpages', $data);
+               $this->getResult()->addValue('query', 'allpages', $data);
        }
 
        protected function getAllowedParams() {
index 771c3ed..10ebc13 100644 (file)
@@ -26,7 +26,7 @@
 \r
 if (!defined('MEDIAWIKI')) {\r
        // Eclipse helper - will be ignored in production\r
-       require_once ("ApiBase.php");\r
+       require_once ('ApiBase.php');\r
 }\r
 \r
 abstract class ApiQueryBase extends ApiBase {\r
index 2387189..732ecf6 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiQueryBase.php");
+       require_once ('ApiQueryBase.php');
 }
 
 class ApiQueryInfo extends ApiQueryBase {
index 83771b9..f35075f 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiQueryBase.php");
+       require_once ('ApiQueryBase.php');
 }
 
 class ApiQueryRevisions extends ApiQueryBase {
@@ -42,7 +42,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                // true when ordered by timestamp from older to newer, false otherwise
                $dirNewer = ($rvdir === 'newer');
 
-               // If any of those parameters are used, work in "enumeration" mode.
+               // If any of those parameters are used, work in 'enumeration' mode.
                // Enum mode can only be used when exactly one page is provided.
                // Enumerating revisions on multiple pages make it extremelly 
                // difficult to manage continuations and require additional sql indexes  
@@ -52,14 +52,15 @@ class ApiQueryRevisions extends ApiQueryBase {
                $pageCount = $data->getGoodTitleCount();
                $revCount = $data->getRevisionCount();
 
+               // Optimization -- nothing to do
+               if ($revCount === 0 && $pageCount === 0)
+                       return;
+
                if ($revCount > 0 && $pageCount > 0)
-                       $this->dieUsage('The rvrevids= parameter may not be used with titles, pageids, and generator options.', 'rv_rvrevids');
+                       $this->dieUsage('The revids= parameter may not be used with titles, pageids, or generator options.', 'rv_revids');
 
                if ($revCount > 0 && $enumRevMode)
-                       $this->dieUsage('The rvrevids= parameter may not be used with the list options (rvlimit, rvstartid, rvendid, dirNewer, rvstart, rvend).', 'rv_rvrevids');
-
-               if ($revCount === 0 && $pageCount === 0)
-                       $this->dieUsage('No pages were given. Please use titles, pageids or a generator to provide page(s) to work on.', 'rv_no_pages');
+                       $this->dieUsage('The revids= parameter may not be used with the list options (rvlimit, rvstartid, rvendid, dirNewer, rvstart, rvend).', 'rv_revids');
 
                if ($revCount === 0 && $pageCount > 1 && $enumRevMode)
                        $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the rvlimit, rvstartid, rvendid, dirNewer, rvstart, and rvend parameters may only be used on a single page.', 'rv_multpages');
@@ -107,7 +108,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                                $showContent = true;
                                                break;
                                        default :
-                                               $this->dieDebug("unknown rvprop $prop");
+                                               ApiBase :: dieDebug("unknown rvprop $prop");
                                }
                        }
                }
@@ -168,7 +169,7 @@ class ApiQueryRevisions extends ApiQueryBase {
 
                                        $rvlimit = $revCount; // assumption testing -- we should never get more then $revCount rows.
                                } else
-                                       $this->dieDebug('param validation?');
+                                       ApiBase :: dieDebug('param validation?');
 
                $options['LIMIT'] = $rvlimit +1;
 
@@ -184,13 +185,13 @@ class ApiQueryRevisions extends ApiQueryBase {
                        if (++ $count > $rvlimit) {
                                // We've reached the one extra which shows that there are additional pages to be had. Stop here...
                                if (!$enumRevMode)
-                                       $this->dieDebug('Got more rows then expected'); // bug report
+                                       ApiBase :: dieDebug('Got more rows then expected'); // bug report
 
                                $startStr = 'rvstartid=' . $row->rev_id;
                                $msg = array (
                                        'continue' => $startStr
                                );
-                               $this->getResult()->addMessage('query-status', 'revisions', $msg);
+                               $this->getResult()->addValue('query-status', 'revisions', $msg);
                                break;
                        }
 
@@ -215,26 +216,28 @@ class ApiQueryRevisions extends ApiQueryBase {
                                $vals['comment'] = $row->rev_comment;
 
                        if ($showContent) {
-                               $vals['xml:space'] = 'preserve';
-                               $vals['*'] = Revision :: getRevisionText($row);
-                       } else {
-                               $vals['*'] = ''; // Force all elements to be attributes
+                               ApiResult :: addContent($vals, Revision :: getRevisionText($row));
                        }
 
-                       $data[$row->rev_page]['revisions']['_element'] = 'rv';
-                       $data[$row->rev_page]['revisions'][$row->rev_id] = $vals;
+                       $this->getResult()->addValue(array (
+                               'query',
+                               'pages',
+                               intval($row->rev_page
+                       ), 'revisions'), intval($row->rev_id), $vals);
                }
                $db->freeResult($res);
 
-               $this->getResult()->addMessage('query', 'allpages', $data);
+               // Ensure that all revisions are shown as '<r>' elements
+               $data = & $this->getResultData();
+               foreach ($data['query']['pages'] as & $page) {
+                       if (isset ($page['revisions'])) {
+                               ApiResult :: setIndexedTagName($page['revisions'], 'rev');
+                       }
+               }
        }
 
        protected function getAllowedParams() {
                return array (
-                       'rvrevids' => array (
-                               GN_ENUM_ISMULTI => true,
-                               GN_ENUM_TYPE => 'integer'
-                       ),
                        'rvlimit' => array (
                                GN_ENUM_DFLT => 0,
                                GN_ENUM_TYPE => 'limit',
@@ -274,14 +277,14 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'Get revision information.',
                        'This module may be used in several ways:',
                        ' 1) Get data about a set of pages (last revision), by setting titles or pageids parameter.',
-                       ' 2) Get revisions for one given page, by using titles/pageids with rvstart*/rvend*/rvlimit params.',
+                       ' 2) Get revisions for one given page, by using titles/pageids with rvstart/rvend/rvlimit params.',
                        ' 3) Get data about a set of revisions by setting their IDs with revids parameter.'
                );
        }
 
        protected function getExamples() {
                return array (
-                       'api.php?action=query&prop=revisions&titles=ArticleA&rvprop=timestamp|user|comment|content'
+                       'api.php?action=query&prop=revisions&titles=Main%20Page&rvprop=timestamp|user|comment|content'
                );
        }
 }
index c561f50..54d3a5c 100644 (file)
@@ -26,7 +26,7 @@
 
 if (!defined('MEDIAWIKI')) {
        // Eclipse helper - will be ignored in production
-       require_once ("ApiQueryBase.php");
+       require_once ('ApiQueryBase.php');
 }
 
 class ApiQuerySiteinfo extends ApiQueryBase {
@@ -51,25 +51,26 @@ class ApiQuerySiteinfo extends ApiQueryBase {
                                        $data['base'] = $mainPage->getFullUrl();
                                        $data['sitename'] = $wgSitename;
                                        $data['generator'] = "MediaWiki $wgVersion";
-                                       $data['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // "case-insensitive" option is reserved for future
-                                       $this->getResult()->addMessage('query', $prop, $data);
+                                       $data['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // 'case-insensitive' option is reserved for future
+                                       $this->getResult()->addValue('query', $prop, $data);
                                        break;
 
                                case 'namespaces' :
 
                                        global $wgContLang;
                                        $data = array ();
-                                       $data['_element'] = 'ns';
-                                       foreach ($wgContLang->getFormattedNamespaces() as $ns => $title)
+                                       foreach ($wgContLang->getFormattedNamespaces() as $ns => $title) {
                                                $data[$ns] = array (
-                                                       'id' => $ns,
-                                                       '*' => $title
+                                                       'id' => $ns
                                                );
-                                       $this->getResult()->addMessage('query', $prop, $data);
+                                               ApiResult :: addContent($data[$ns], $title);
+                                       }
+                                       ApiResult :: setIndexedTagName($data, 'ns');
+                                       $this->getResult()->addValue('query', $prop, $data);
                                        break;
 
                                default :
-                                       $this->dieDebug("Unknown siprop=$prop");
+                                       ApiBase :: dieDebug("Unknown siprop=$prop");
                        }
                }
        }
index b35aed2..d99b759 100644 (file)
@@ -26,7 +26,7 @@
 \r
 if (!defined('MEDIAWIKI')) {\r
        // Eclipse helper - will be ignored in production\r
-       require_once ("ApiBase.php");\r
+       require_once ('ApiBase.php');\r
 }\r
 \r
 class ApiResult extends ApiBase {\r
@@ -45,39 +45,72 @@ class ApiResult extends ApiBase {
                $this->mData = array ();\r
        }\r
 \r
-       function getData() {\r
+       function getData() {\r
                return $this->mData;\r
        }\r
 \r
-       function addMessage($mainSection, $subSection, $value, $multiitem = false, $preserveXmlSpacing = false) {\r
-               if (!array_key_exists($mainSection, $this->mData)) {\r
-                       $this->mData[$mainSection] = array ();\r
-               }\r
-               if ($subSection !== null) {\r
-                       if (!array_key_exists($subSection, $this->mData[$mainSection])) {\r
-                               $this->mData[$mainSection][$subSection] = array ();\r
-                       }\r
-                       $element = & $this->mData[$mainSection][$subSection];\r
-               } else {\r
-                       $element = & $this->mData[$mainSection];\r
-               }\r
-               if ($multiitem) {\r
-                       $element['_element'] = $multiitem;\r
-                       $element[] = $value;\r
-               } else {\r
-                       if (is_array($value)) {\r
-                               $element = array_merge($element, $value);\r
-                       } else {\r
-                               if (array_key_exists('*', $element)) {\r
-                                       $element['*'] .= $value;\r
-                               } else {\r
-                                       $element['*'] = $value;\r
-                               }\r
-                               if ($preserveXmlSpacing) {\r
-                                       $element['xml:space'] = 'preserve';\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
@@ -104,7 +137,7 @@ class ApiResult extends ApiBase {
        }\r
 \r
        public function execute() {\r
-               $this->dieDebug("execute() is not supported on Result object");\r
+               $this->dieDebug('execute() is not supported on Result object');\r
        }\r
 }\r
 ?>\r