* API: result data generation cleanup, minor cleaning

This commit is contained in:
Yuri Astrakhan 2006-10-01 02:02:13 +00:00
parent 7fd01d7d45
commit f97b323e00
17 changed files with 274 additions and 190 deletions

View file

@ -84,7 +84,7 @@ $wgApiFormats = array (
);
// Initialise common code
require (dirname(__FILE__) . "/includes/WebStart.php");
require (dirname(__FILE__) . '/includes/WebStart.php');
wfProfileIn('api.php');
// Verify that the API has not been disabled
@ -114,4 +114,4 @@ function apiInitAutoloadClasses($apiAutoloadClasses, $apiDirectory) {
foreach ($apiAutoloadClasses as $className => $classFile)
$wgAutoloadClasses[$className] = $apiDirectory . $classFile;
}
?>
?>

View file

@ -69,11 +69,18 @@ abstract class ApiBase {
// Main module has getResult() method overriden
// Safety - avoid infinite loop:
if ($this->isMain())
$this->dieDebug(__METHOD__ .
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
*/
@ -115,7 +122,7 @@ abstract class ApiBase {
public function makeHelpMsgParameters() {
$params = $this->getAllowedParams();
if ($params !== false) {
$paramsDescription = $this->getParamDescription();
$msg = '';
foreach (array_keys($params) as $paramName) {
@ -125,10 +132,9 @@ abstract class ApiBase {
$msg .= sprintf(" %-14s - %s\n", $paramName, $desc);
}
return $msg;
}
else
return false;
} else
return false;
}
/**
@ -174,7 +180,7 @@ abstract class ApiBase {
return $results;
}
public function getParameter($paramName, $paramSettings){
public function getParameter($paramName, $paramSettings) {
global $wgRequest;
if (!is_array($paramSettings)) {
@ -198,12 +204,12 @@ abstract class ApiBase {
if ($type == 'boolean') {
if (isset ($default) && $default !== false) {
// Having a default value of anything other than 'false' is pointless
$this->dieDebug("Boolean param $paramName's default is set to '$default'");
ApiBase :: dieDebug("Boolean param $paramName's default is set to '$default'");
}
$value = $wgRequest->getCheck($paramName);
$value = $wgRequest->getCheck($paramName);
} else
$value = $wgRequest->getVal($paramName, $default);
$value = $wgRequest->getVal($paramName, $default);
if (isset ($value) && ($multi || is_array($type)))
$value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null);
@ -222,33 +228,33 @@ abstract class ApiBase {
break;
case 'limit' :
if (!isset ($paramSettings[GN_ENUM_MAX1]) || !isset ($paramSettings[GN_ENUM_MAX2]))
$this->dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");
ApiBase :: dieDebug("MAX1 or MAX2 are not defined for the limit $paramName");
if ($multi)
$this->dieDebug("Multi-values not supported for $paramName");
ApiBase :: dieDebug("Multi-values not supported for $paramName");
$min = isset ($paramSettings[GN_ENUM_MIN]) ? $paramSettings[GN_ENUM_MIN] : 0;
$value = intval($value);
$this->validateLimit($paramName, $value, $min, $paramSettings[GN_ENUM_MAX1], $paramSettings[GN_ENUM_MAX2]);
break;
case 'boolean' :
if ($multi)
$this->dieDebug("Multi-values not supported for $paramName");
ApiBase :: dieDebug("Multi-values not supported for $paramName");
break;
case 'timestamp' :
if ($multi)
$this->dieDebug("Multi-values not supported for $paramName");
ApiBase :: dieDebug("Multi-values not supported for $paramName");
$value = $this->prepareTimestamp($value); // Adds quotes around timestamp
break;
default :
$this->dieDebug("Param $paramName's type is unknown - $type");
ApiBase :: dieDebug("Param $paramName's type is unknown - $type");
}
}
return $value;
return $value;
}
/**
* Return an array of values that were given in a "a|b|c" notation,
* 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)
@ -266,7 +272,7 @@ abstract class ApiBase {
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");
$this->dieUsage('Unrecognised value' . (count($unknownValues) > 1 ? "s '" : " '") . implode("', '", $unknownValues) . "' for parameter '$valueName'", "unknown_$valueName");
}
}
@ -315,75 +321,70 @@ abstract class ApiBase {
/**
* Internal code errors should be reported with this method
*/
protected function dieDebug($message) {
wfDebugDieBacktrace("Internal error in '{get_class($this)}': $message");
protected static function dieDebug($message) {
wfDebugDieBacktrace("Internal error: $message");
}
/**
* Profiling: total module execution time
*/
private $mTimeIn = 0, $mModuleTime = 0;
private $mTimeIn = 0, $mModuleTime = 0;
/**
* Start module profiling
*/
public function profileIn()
{
public function profileIn() {
if ($this->mTimeIn !== 0)
$this->dieDebug(__FUNCTION__ . ' called twice without calling profileOut()');
ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileOut()');
$this->mTimeIn = microtime(true);
}
/**
* End module profiling
*/
public function profileOut()
{
public function profileOut() {
if ($this->mTimeIn === 0)
$this->dieDebug(__FUNCTION__ . ' called without calling profileIn() first');
ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileIn() first');
if ($this->mDBTimeIn !== 0)
$this->dieDebug(__FUNCTION__ . ' must be called after database profiling is done with profileDBOut()');
ApiBase :: dieDebug(__FUNCTION__ . ' 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()
{
public function getProfileTime() {
if ($this->mTimeIn !== 0)
$this->dieDebug(__FUNCTION__ . ' called without calling profileOut() first');
ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileOut() first');
return $this->mModuleTime;
}
/**
* Profiling: database execution time
*/
private $mDBTimeIn = 0, $mDBTime = 0;
private $mDBTimeIn = 0, $mDBTime = 0;
/**
* Start module profiling
*/
public function profileDBIn()
{
public function profileDBIn() {
if ($this->mTimeIn === 0)
$this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');
ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');
if ($this->mDBTimeIn !== 0)
$this->dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()');
ApiBase :: dieDebug(__FUNCTION__ . ' called twice without calling profileDBOut()');
$this->mDBTimeIn = microtime(true);
}
/**
* End database profiling
*/
public function profileDBOut()
{
public function profileDBOut() {
if ($this->mTimeIn === 0)
$this->dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');
ApiBase :: dieDebug(__FUNCTION__ . ' must be called while profiling the entire module with profileIn()');
if ($this->mDBTimeIn === 0)
$this->dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first');
ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBIn() first');
$time = microtime(true) - $this->mDBTimeIn;
$this->mDBTimeIn = 0;
@ -391,14 +392,13 @@ abstract class ApiBase {
$this->mDBTime += $time;
$this->getMain()->mDBTime += $time;
}
/**
* Total time the module used the database
*/
public function getProfileDBTime()
{
public function getProfileDBTime() {
if ($this->mDBTimeIn !== 0)
$this->dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first');
ApiBase :: dieDebug(__FUNCTION__ . ' called without calling profileDBOut() first');
return $this->mDBTime;
}
}

View 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

View 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 {

View 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);
}
}
} else {
foreach ($elemValue as $subElemName => & $subElemValue) {
$this->recXmlPrint($subElemName, $subElemValue, $indent);
}
}
$this->printText($indstr . "</$elemName>");
$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 {
$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));
}
break;
case 'object' :
// ignore

View 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 {

View file

@ -26,7 +26,7 @@
if (!defined('MEDIAWIKI')) {
// Eclipse helper - will be ignored in production
require_once ("ApiBase.php");
require_once ('ApiBase.php');
}
class ApiHelp extends ApiBase {

View 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 {
);
}
}
?>
?>

View file

@ -26,7 +26,7 @@
if (!defined('MEDIAWIKI')) {
// Eclipse helper - will be ignored in production
require_once ("ApiBase.php");
require_once ('ApiBase.php');
}
class ApiMain extends ApiBase {
@ -50,7 +50,7 @@ class ApiMain extends ApiBase {
$this->mResult = new ApiResult($this);
}
public function getResult() {
public function & getResult() {
return $this->mResult;
}
@ -123,13 +123,16 @@ class ApiMain extends ApiBase {
public function mainDieUsage($description, $errorCode, $httpRespCode = 0) {
$this->mResult->Reset();
$this->mResult->addMessage('error', null, $errorCode);
if ($httpRespCode === 0)
header($errorCode, true);
else
header($errorCode, true, $httpRespCode);
$this->mResult->addMessage('usage', null, $this->makeHelpMsg());
$data = array (
'code' => $errorCode
);
ApiResult :: addContent($data, $this->makeHelpMsg());
$this->mResult->addValue(null, 'error', $data);
throw new UsageException($description, $errorCode);
}
@ -191,5 +194,4 @@ class UsageException extends Exception {
return "{$this->codestr}: {$this->message}";
}
}
?>

View 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',

View file

@ -26,7 +26,7 @@
if (!defined('MEDIAWIKI')) {
// Eclipse helper - will be ignored in production
require_once ("ApiBase.php");
require_once ('ApiBase.php');
}
class ApiQuery extends ApiBase {
@ -128,21 +128,31 @@ class ApiQuery extends ApiBase {
$modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName);
// Title normalizations
$normValues = array ();
foreach ($this->mData->getNormalizedTitles() as $rawTitleStr => $titleStr) {
$this->getResult()->addMessage('query', 'normalized', array (
$normValues[] = array (
'from' => $rawTitleStr,
'to' => $titleStr,
'*' => ''
), 'n');
'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) {
$this->getResult()->addMessage('query', 'redirects', array (
$redirValues[] = array (
'from' => $titleStrFrom,
'to' => $titleStrTo,
'*' => ''
), 'r');
'to' => $titleStrTo
);
}
if (!empty ($redirValues)) {
ApiResult :: setIndexedTagName($redirValues, 'r');
$this->getResult()->addValue('query', 'redirects', $redirValues);
}
// Execute all requested modules.
@ -151,6 +161,12 @@ class ApiQuery extends ApiBase {
$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) {
@ -162,14 +178,14 @@ class ApiQuery extends ApiBase {
if (isset ($this->mQueryPropModules[$generator]))
$className = $this->mQueryPropModules[$generator];
else
$this->dieDebug("Unknown generator=$generator");
ApiBase :: dieDebug("Unknown generator=$generator");
$module = new $className ($this, $generator, true);
// change $this->mData
// TODO: implement
$this->dieUsage("Generator execution has not been implemented", 'notimplemented');
$this->dieUsage('Generator execution has not been implemented', 'notimplemented');
}
protected function getAllowedParams() {
@ -189,6 +205,8 @@ class ApiQuery extends ApiBase {
// 'generator' => array (
// GN_ENUM_TYPE => $this->mAllowedGenerators
// ),
);
}
@ -234,12 +252,11 @@ class ApiQuery extends ApiBase {
/**
* Override to add extra parameters from PageSet
*/
*/
public function makeHelpMsgParameters() {
$module = new ApiPageSet($this);
return $module->makeHelpMsgParameters() . parent :: makeHelpMsgParameters();
}
protected function getParamDescription() {
return array (
@ -247,6 +264,8 @@ class ApiQuery extends ApiBase {
'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',
);
}
@ -264,4 +283,4 @@ class ApiQuery extends ApiBase {
);
}
}
?>
?>

View 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() {

View 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 ApiQueryBase extends ApiBase {

View 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 {

View 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'
);
}
}

View 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");
}
}
}

View file

@ -26,7 +26,7 @@
if (!defined('MEDIAWIKI')) {
// Eclipse helper - will be ignored in production
require_once ("ApiBase.php");
require_once ('ApiBase.php');
}
class ApiResult extends ApiBase {
@ -45,39 +45,72 @@ class ApiResult extends ApiBase {
$this->mData = array ();
}
function getData() {
function & getData() {
return $this->mData;
}
function addMessage($mainSection, $subSection, $value, $multiitem = false, $preserveXmlSpacing = false) {
if (!array_key_exists($mainSection, $this->mData)) {
$this->mData[$mainSection] = array ();
}
if ($subSection !== null) {
if (!array_key_exists($subSection, $this->mData[$mainSection])) {
$this->mData[$mainSection][$subSection] = array ();
}
$element = & $this->mData[$mainSection][$subSection];
} else {
$element = & $this->mData[$mainSection];
}
if ($multiitem) {
$element['_element'] = $multiitem;
$element[] = $value;
} else {
if (is_array($value)) {
$element = array_merge($element, $value);
/**
* 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 ' . __FUNCTION__);
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 ' . __FUNCTION__);
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 ' . __FUNCTION__);
$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 (array_key_exists('*', $element)) {
$element['*'] .= $value;
} else {
$element['*'] = $value;
}
if ($preserveXmlSpacing) {
$element['xml:space'] = 'preserve';
}
if (!isset ($data[$path]))
$data[$path] = array ();
$data = & $data[$path];
}
}
ApiResult :: addElement($data, $name, $value);
}
/**
@ -104,7 +137,7 @@ class ApiResult extends ApiBase {
}
public function execute() {
$this->dieDebug("execute() is not supported on Result object");
$this->dieDebug('execute() is not supported on Result object');
}
}
?>