ApiFormatBase.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. /*
  3. * Created on Sep 19, 2006
  4. *
  5. * API for MediaWiki 1.8+
  6. *
  7. * Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. * http://www.gnu.org/copyleft/gpl.html
  23. */
  24. if (!defined('MEDIAWIKI')) {
  25. // Eclipse helper - will be ignored in production
  26. require_once ('ApiBase.php');
  27. }
  28. /**
  29. * This is the abstract base class for API formatters.
  30. *
  31. * @ingroup API
  32. */
  33. abstract class ApiFormatBase extends ApiBase {
  34. private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp, $mCleared;
  35. /**
  36. * Constructor
  37. * If $format ends with 'fm', pretty-print the output in HTML.
  38. * @param $main ApiMain
  39. * @param $format string Format name
  40. */
  41. public function __construct($main, $format) {
  42. parent :: __construct($main, $format);
  43. $this->mIsHtml = (substr($format, -2, 2) === 'fm'); // ends with 'fm'
  44. if ($this->mIsHtml)
  45. $this->mFormat = substr($format, 0, -2); // remove ending 'fm'
  46. else
  47. $this->mFormat = $format;
  48. $this->mFormat = strtoupper($this->mFormat);
  49. $this->mCleared = false;
  50. }
  51. /**
  52. * Overriding class returns the mime type that should be sent to the client.
  53. * This method is not called if getIsHtml() returns true.
  54. * @return string
  55. */
  56. public abstract function getMimeType();
  57. /**
  58. * Whether this formatter needs raw data such as _element tags
  59. * @return bool
  60. */
  61. public function getNeedsRawData() {
  62. return false;
  63. }
  64. /**
  65. * Get the internal format name
  66. * @return string
  67. */
  68. public function getFormat() {
  69. return $this->mFormat;
  70. }
  71. /**
  72. * Specify whether or not sequences like &amp;quot; should be unescaped
  73. * to &quot; . This should only be set to true for the help message
  74. * when rendered in the default (xmlfm) format. This is a temporary
  75. * special-case fix that should be removed once the help has been
  76. * reworked to use a fully HTML interface.
  77. *
  78. * @param $b bool Whether or not ampersands should be escaped.
  79. */
  80. public function setUnescapeAmps ( $b ) {
  81. $this->mUnescapeAmps = $b;
  82. }
  83. /**
  84. * Returns true when the HTML pretty-printer should be used.
  85. * The default implementation assumes that formats ending with 'fm'
  86. * should be formatted in HTML.
  87. * @return bool
  88. */
  89. public function getIsHtml() {
  90. return $this->mIsHtml;
  91. }
  92. /**
  93. * Initialize the printer function and prepare the output headers, etc.
  94. * This method must be the first outputing method during execution.
  95. * A help screen's header is printed for the HTML-based output
  96. * @param $isError bool Whether an error message is printed
  97. */
  98. function initPrinter($isError) {
  99. $isHtml = $this->getIsHtml();
  100. $mime = $isHtml ? 'text/html' : $this->getMimeType();
  101. $script = wfScript( 'api' );
  102. // Some printers (ex. Feed) do their own header settings,
  103. // in which case $mime will be set to null
  104. if (is_null($mime))
  105. return; // skip any initialization
  106. header("Content-Type: $mime; charset=utf-8");
  107. if ($isHtml) {
  108. ?>
  109. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  110. <html>
  111. <head>
  112. <?php if ($this->mUnescapeAmps) {
  113. ?> <title>MediaWiki API</title>
  114. <?php } else {
  115. ?> <title>MediaWiki API Result</title>
  116. <?php } ?>
  117. </head>
  118. <body>
  119. <?php
  120. if( !$isError ) {
  121. ?>
  122. <br/>
  123. <small>
  124. You are looking at the HTML representation of the <?php echo( $this->mFormat ); ?> format.<br/>
  125. HTML is good for debugging, but probably is not suitable for your application.<br/>
  126. See <a href='http://www.mediawiki.org/wiki/API'>complete documentation</a>, or
  127. <a href='<?php echo( $script ); ?>'>API help</a> for more information.
  128. </small>
  129. <?php
  130. }
  131. ?>
  132. <pre>
  133. <?php
  134. }
  135. }
  136. /**
  137. * Finish printing. Closes HTML tags.
  138. */
  139. public function closePrinter() {
  140. if ($this->getIsHtml()) {
  141. ?>
  142. </pre>
  143. </body>
  144. </html>
  145. <?php
  146. }
  147. }
  148. /**
  149. * The main format printing function. Call it to output the result
  150. * string to the user. This function will automatically output HTML
  151. * when format name ends in 'fm'.
  152. * @param $text string
  153. */
  154. public function printText($text) {
  155. if ($this->getIsHtml())
  156. echo $this->formatHTML($text);
  157. else
  158. {
  159. // For non-HTML output, clear all errors that might have been
  160. // displayed if display_errors=On
  161. // Do this only once, of course
  162. if(!$this->mCleared)
  163. {
  164. ob_clean();
  165. $this->mCleared = true;
  166. }
  167. echo $text;
  168. }
  169. }
  170. /**
  171. * Sets whether the pretty-printer should format *bold* and $italics$
  172. * @param $help bool
  173. */
  174. public function setHelp( $help = true ) {
  175. $this->mHelp = true;
  176. }
  177. /**
  178. * Prety-print various elements in HTML format, such as xml tags and
  179. * URLs. This method also escapes characters like <
  180. * @param $text string
  181. * @return string
  182. */
  183. protected function formatHTML($text) {
  184. global $wgUrlProtocols;
  185. // Escape everything first for full coverage
  186. $text = htmlspecialchars($text);
  187. // encode all comments or tags as safe blue strings
  188. $text = preg_replace('/\&lt;(!--.*?--|.*?)\&gt;/', '<span style="color:blue;">&lt;\1&gt;</span>', $text);
  189. // identify URLs
  190. $protos = implode("|", $wgUrlProtocols);
  191. # This regex hacks around bug 13218 (&quot; included in the URL)
  192. $text = preg_replace("#(($protos).*?)(&quot;)?([ \\'\"<>\n]|&lt;|&gt;|&quot;)#", '<a href="\\1">\\1</a>\\3\\4', $text);
  193. // identify requests to api.php
  194. $text = preg_replace("#api\\.php\\?[^ \\()<\n\t]+#", '<a href="\\0">\\0</a>', $text);
  195. if( $this->mHelp ) {
  196. // make strings inside * bold
  197. $text = preg_replace("#\\*[^<>\n]+\\*#", '<b>\\0</b>', $text);
  198. // make strings inside $ italic
  199. $text = preg_replace("#\\$[^<>\n]+\\$#", '<b><i>\\0</i></b>', $text);
  200. }
  201. /* Temporary fix for bad links in help messages. As a special case,
  202. * XML-escaped metachars are de-escaped one level in the help message
  203. * for legibility. Should be removed once we have completed a fully-html
  204. * version of the help message. */
  205. if ( $this->mUnescapeAmps )
  206. $text = preg_replace( '/&amp;(amp|quot|lt|gt);/', '&\1;', $text );
  207. return $text;
  208. }
  209. protected function getExamples() {
  210. return 'api.php?action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName();
  211. }
  212. public function getDescription() {
  213. return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
  214. }
  215. public static function getBaseVersion() {
  216. return __CLASS__ . ': $Id: ApiFormatBase.php 48521 2009-03-18 19:25:29Z ialex $';
  217. }
  218. }
  219. /**
  220. * This printer is used to wrap an instance of the Feed class
  221. * @ingroup API
  222. */
  223. class ApiFormatFeedWrapper extends ApiFormatBase {
  224. public function __construct($main) {
  225. parent :: __construct($main, 'feed');
  226. }
  227. /**
  228. * Call this method to initialize output data. See execute()
  229. * @param $result ApiResult
  230. * @param $feed object an instance of one of the $wgFeedClasses classes
  231. * @param $feedItems array of FeedItem objects
  232. */
  233. public static function setResult($result, $feed, $feedItems) {
  234. // Store output in the Result data.
  235. // This way we can check during execution if any error has occured
  236. // Disable size checking for this because we can't continue
  237. // cleanly; size checking would cause more problems than it'd
  238. // solve
  239. $result->disableSizeCheck();
  240. $result->addValue(null, '_feed', $feed);
  241. $result->addValue(null, '_feeditems', $feedItems);
  242. $result->enableSizeCheck();
  243. }
  244. /**
  245. * Feed does its own headers
  246. */
  247. public function getMimeType() {
  248. return null;
  249. }
  250. /**
  251. * Optimization - no need to sanitize data that will not be needed
  252. */
  253. public function getNeedsRawData() {
  254. return true;
  255. }
  256. /**
  257. * This class expects the result data to be in a custom format set by self::setResult()
  258. * $result['_feed'] - an instance of one of the $wgFeedClasses classes
  259. * $result['_feeditems'] - an array of FeedItem instances
  260. */
  261. public function execute() {
  262. $data = $this->getResultData();
  263. if (isset ($data['_feed']) && isset ($data['_feeditems'])) {
  264. $feed = $data['_feed'];
  265. $items = $data['_feeditems'];
  266. $feed->outHeader();
  267. foreach ($items as & $item)
  268. $feed->outItem($item);
  269. $feed->outFooter();
  270. } else {
  271. // Error has occured, print something useful
  272. ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
  273. }
  274. }
  275. public function getVersion() {
  276. return __CLASS__ . ': $Id: ApiFormatBase.php 48521 2009-03-18 19:25:29Z ialex $';
  277. }
  278. }