* This means queries could possibly return fewer results than the limit and still set a query-continue * Add iicontinue, rvcontinue, cicontinue, incontinue, amfrom to faciliate query-continue for these modules * Implemented by blocking additions to the ApiResult object if they would make it too large ** Important things like query-continue values and warnings are exempt from this check ** RSS feeds and exported XML are also exempted (size-checking them would be too messy) ** Result size is checked against $wgAPIMaxResultSize, which defaults to 8 MB For those who really care, per-file details follow: ApiResult.php: * Introduced ApiResult::$mSize which keeps track of the result size. * Introduced ApiResult::size() which calculates an array's size (which is the sum of the strlen()s of its elements). * ApiResult::addValue() now checks that the result size stays below $wgAPIMaxResultSize. If the item won't fit, it won't be added and addValue() will return false. Callers should check the return value and set a query-continue if it's false. * Closed the back door that is ApiResult::getData(): callers can't manipulate the data array directly anymore so they can't bypass the result size limit. * Added ApiResult::setIndexedTagName_internal() which will call setIndexedTagName() on an array already in the result. This is needed for the 'new' order of adding results, which means addValue()ing one result at a time until you hit the limit or run out, then calling this function to set the tag name. * Added ApiResult::disableSizeCheck() and enableSizeCheck() which disable and enable size checking in addValue(). This is used for stuff like query-continue elements and warnings which shouldn't count towards the result size. * Added ApiResult::unsetValue() which removes an element from the result and decreases $mSize. ApiBase.php: * Like ApiResult::getData(), ApiBase::getResultData() no longer returns a reference. * Use ApiResult::disableSizeCheck() in ApiBase::setWarning() ApiQueryBase.php: * Added ApiQueryBase::addPageSubItem(), which adds page subitems one item at a time. * addPageSubItem() and addPageSubItems() now return whether the subitem fit in the result. * Use ApiResult::disableSizeCheck() in setContinueEnumParameter() ApiMain.php: * Use ApiResult::disableSizeCheck() in ApiMain::substituteResultWithError() * Use getParameter() rather than $mRequest to obtain requestid DefaultSettings.php: * Added $wgAPIMaxResultSize, with a default value of 8 MB ApiQuery*.php: * Added results one at a time, and set a query-continue if the result is full. ApiQueryLangLinks.php and friends: * Migrated from addPageSubItems() to addPageSubItem(). This eliminates the need for $lastId. ApiQueryAllLinks.php, ApiQueryWatchlist.php, ApiQueryAllimages.php, ApiQuerySearch.php: * Renamed $data to something more appropriate ($pageids, $ids or $titles) ApiQuerySiteinfo.php: * Abuse siprop as a query-continue parameter and set it to all props that couldn't be processed. ApiQueryRandom.php: * Doesn't do continuations, because the result is supposed to be random. * Be smart enough to not run the second query if the results of the first didn't fit. ApiQueryImageInfo.php, ApiQueryRevisions.php, ApiQueryCategoryInfo.php, ApiQueryInfo.php: * Added continue parameter which basically skips the first so many items ApiQueryBacklinks.php: * Throw the result in a big array first and addValue() that one element at a time if necessary ** This is necessary because the results aren't retrieved in order * Introduced $this->pageMap to map namespace and title to page ID * Rewritten extractRowInfo() and extractRedirRowInfo() a little * Declared all private member variables explicitly ApiQueryDeletedrevs.php: * Use a pagemap just like in Backlinks * Introduce fake page IDs and keep track of them so we know where to add what ** This doesn't change the output format, because the fake page IDs start at 0 and are consecutive ApiQueryAllmessages.php: * Add amfrom to facilitate query-continue ApiQueryUsers.php: * Rewrite: put the getOtherUsersInfo() code in execute()
311 lines
No EOL
8.4 KiB
PHP
311 lines
No EOL
8.4 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Created on Sep 19, 2006
|
|
*
|
|
* API for MediaWiki 1.8+
|
|
*
|
|
* Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 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');
|
|
}
|
|
|
|
/**
|
|
* This is the abstract base class for API formatters.
|
|
*
|
|
* @ingroup API
|
|
*/
|
|
abstract class ApiFormatBase extends ApiBase {
|
|
|
|
private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp, $mCleared;
|
|
|
|
/**
|
|
* Create a new instance of the formatter.
|
|
* If the format name ends with 'fm', wrap its output in the proper HTML.
|
|
*/
|
|
public function __construct($main, $format) {
|
|
parent :: __construct($main, $format);
|
|
|
|
$this->mIsHtml = (substr($format, -2, 2) === 'fm'); // ends with 'fm'
|
|
if ($this->mIsHtml)
|
|
$this->mFormat = substr($format, 0, -2); // remove ending 'fm'
|
|
else
|
|
$this->mFormat = $format;
|
|
$this->mFormat = strtoupper($this->mFormat);
|
|
$this->mCleared = false;
|
|
}
|
|
|
|
/**
|
|
* Overriding class returns the mime type that should be sent to the client.
|
|
* This method is not called if getIsHtml() returns true.
|
|
* @return string
|
|
*/
|
|
public abstract function getMimeType();
|
|
|
|
/**
|
|
* If formatter outputs data results as is, the results must first be sanitized.
|
|
* An XML formatter on the other hand uses special tags, such as "_element" for special handling,
|
|
* and thus needs to override this function to return true.
|
|
*/
|
|
public function getNeedsRawData() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get the internal format name
|
|
*/
|
|
public function getFormat() {
|
|
return $this->mFormat;
|
|
}
|
|
|
|
/**
|
|
* Specify whether or not ampersands should be escaped to '&' when rendering. This
|
|
* should only be set to true for the help message when rendered in the default (xmlfm)
|
|
* format. This is a temporary special-case fix that should be removed once the help
|
|
* has been reworked to use a fully html interface.
|
|
*
|
|
* @param boolean Whether or not ampersands should be escaped.
|
|
*/
|
|
public function setUnescapeAmps ( $b ) {
|
|
$this->mUnescapeAmps = $b;
|
|
}
|
|
|
|
/**
|
|
* Returns true when an HTML filtering printer should be used.
|
|
* The default implementation assumes that formats ending with 'fm'
|
|
* should be formatted in HTML.
|
|
*/
|
|
public function getIsHtml() {
|
|
return $this->mIsHtml;
|
|
}
|
|
|
|
/**
|
|
* Initialize the printer function and prepares the output headers, etc.
|
|
* This method must be the first outputing method during execution.
|
|
* A help screen's header is printed for the HTML-based output
|
|
*/
|
|
function initPrinter($isError) {
|
|
$isHtml = $this->getIsHtml();
|
|
$mime = $isHtml ? 'text/html' : $this->getMimeType();
|
|
$script = wfScript( 'api' );
|
|
|
|
// Some printers (ex. Feed) do their own header settings,
|
|
// in which case $mime will be set to null
|
|
if (is_null($mime))
|
|
return; // skip any initialization
|
|
|
|
header("Content-Type: $mime; charset=utf-8");
|
|
|
|
if ($isHtml) {
|
|
?>
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<?php if ($this->mUnescapeAmps) {
|
|
?> <title>MediaWiki API</title>
|
|
<?php } else {
|
|
?> <title>MediaWiki API Result</title>
|
|
<?php } ?>
|
|
</head>
|
|
<body>
|
|
<?php
|
|
|
|
|
|
if( !$isError ) {
|
|
?>
|
|
<br/>
|
|
<small>
|
|
You are looking at the HTML representation of the <?php echo( $this->mFormat ); ?> format.<br/>
|
|
HTML is good for debugging, but probably is not suitable for your application.<br/>
|
|
See <a href='http://www.mediawiki.org/wiki/API'>complete documentation</a>, or
|
|
<a href='<?php echo( $script ); ?>'>API help</a> for more information.
|
|
</small>
|
|
<?php
|
|
|
|
|
|
}
|
|
?>
|
|
<pre>
|
|
<?php
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finish printing. Closes HTML tags.
|
|
*/
|
|
public function closePrinter() {
|
|
if ($this->getIsHtml()) {
|
|
?>
|
|
|
|
</pre>
|
|
</body>
|
|
</html>
|
|
<?php
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The main format printing function. Call it to output the result string to the user.
|
|
* This function will automatically output HTML when format name ends in 'fm'.
|
|
*/
|
|
public function printText($text) {
|
|
if ($this->getIsHtml())
|
|
echo $this->formatHTML($text);
|
|
else
|
|
{
|
|
// For non-HTML output, clear all errors that might have been
|
|
// displayed if display_errors=On
|
|
// Do this only once, of course
|
|
if(!$this->mCleared)
|
|
{
|
|
ob_clean();
|
|
$this->mCleared = true;
|
|
}
|
|
echo $text;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Says pretty-printer that it should use *bold* and $italics$ formatting
|
|
*/
|
|
public function setHelp( $help = true ) {
|
|
$this->mHelp = true;
|
|
}
|
|
|
|
/**
|
|
* Prety-print various elements in HTML format, such as xml tags and URLs.
|
|
* This method also replaces any '<' with <
|
|
*/
|
|
protected function formatHTML($text) {
|
|
global $wgUrlProtocols;
|
|
|
|
// Escape everything first for full coverage
|
|
$text = htmlspecialchars($text);
|
|
|
|
// encode all comments or tags as safe blue strings
|
|
$text = preg_replace('/\<(!--.*?--|.*?)\>/', '<span style="color:blue;"><\1></span>', $text);
|
|
// identify URLs
|
|
$protos = implode("|", $wgUrlProtocols);
|
|
# This regex hacks around bug 13218 (" included in the URL)
|
|
$text = preg_replace("#(($protos).*?)(")?([ \\'\"<\n])#", '<a href="\\1">\\1</a>\\3\\4', $text);
|
|
// identify requests to api.php
|
|
$text = preg_replace("#api\\.php\\?[^ \\()<\n\t]+#", '<a href="\\0">\\0</a>', $text);
|
|
if( $this->mHelp ) {
|
|
// make strings inside * bold
|
|
$text = ereg_replace("\\*[^<>\n]+\\*", '<b>\\0</b>', $text);
|
|
// make strings inside $ italic
|
|
$text = ereg_replace("\\$[^<>\n]+\\$", '<b><i>\\0</i></b>', $text);
|
|
}
|
|
|
|
/* Temporary fix for bad links in help messages. As a special case,
|
|
* XML-escaped metachars are de-escaped one level in the help message
|
|
* for legibility. Should be removed once we have completed a fully-html
|
|
* version of the help message. */
|
|
if ( $this->mUnescapeAmps )
|
|
$text = preg_replace( '/&(amp|quot|lt|gt);/', '&\1;', $text );
|
|
|
|
return $text;
|
|
}
|
|
|
|
/**
|
|
* Returns usage examples for this format.
|
|
*/
|
|
protected function getExamples() {
|
|
return 'api.php?action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName();
|
|
}
|
|
|
|
public function getDescription() {
|
|
return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
|
|
}
|
|
|
|
public static function getBaseVersion() {
|
|
return __CLASS__ . ': $Id$';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This printer is used to wrap an instance of the Feed class
|
|
* @ingroup API
|
|
*/
|
|
class ApiFormatFeedWrapper extends ApiFormatBase {
|
|
|
|
public function __construct($main) {
|
|
parent :: __construct($main, 'feed');
|
|
}
|
|
|
|
/**
|
|
* Call this method to initialize output data. See self::execute()
|
|
*/
|
|
public static function setResult($result, $feed, $feedItems) {
|
|
// Store output in the Result data.
|
|
// This way we can check during execution if any error has occured
|
|
// Disable size checking for this because we can't continue
|
|
// cleanly; size checking would cause more problems than it'd
|
|
// solve
|
|
$result->disableSizeCheck();
|
|
$result->addValue(null, '_feed', $feed);
|
|
$result->addValue(null, '_feeditems', $feedItems);
|
|
$result->enableSizeCheck();
|
|
}
|
|
|
|
/**
|
|
* Feed does its own headers
|
|
*/
|
|
public function getMimeType() {
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Optimization - no need to sanitize data that will not be needed
|
|
*/
|
|
public function getNeedsRawData() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* This class expects the result data to be in a custom format set by self::setResult()
|
|
* $result['_feed'] - an instance of one of the $wgFeedClasses classes
|
|
* $result['_feeditems'] - an array of FeedItem instances
|
|
*/
|
|
public function execute() {
|
|
$data = $this->getResultData();
|
|
if (isset ($data['_feed']) && isset ($data['_feeditems'])) {
|
|
$feed = $data['_feed'];
|
|
$items = $data['_feeditems'];
|
|
|
|
$feed->outHeader();
|
|
foreach ($items as & $item)
|
|
$feed->outItem($item);
|
|
$feed->outFooter();
|
|
} else {
|
|
// Error has occured, print something useful
|
|
ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
|
|
}
|
|
}
|
|
|
|
public function getVersion() {
|
|
return __CLASS__ . ': $Id$';
|
|
}
|
|
}
|