MediaWiki  REL1_24
ApiFormatBase.php
Go to the documentation of this file.
00001 <?php
00032 abstract class ApiFormatBase extends ApiBase {
00033     private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp, $mCleared;
00034     private $mBufferResult = false, $mBuffer, $mDisabled = false;
00035 
00041     public function __construct( ApiMain $main, $format ) {
00042         parent::__construct( $main, $format );
00043 
00044         $this->mIsHtml = ( substr( $format, -2, 2 ) === 'fm' ); // ends with 'fm'
00045         if ( $this->mIsHtml ) {
00046             $this->mFormat = substr( $format, 0, -2 ); // remove ending 'fm'
00047         } else {
00048             $this->mFormat = $format;
00049         }
00050         $this->mFormat = strtoupper( $this->mFormat );
00051         $this->mCleared = false;
00052     }
00053 
00059     abstract public function getMimeType();
00060 
00065     public function getNeedsRawData() {
00066         return false;
00067     }
00068 
00073     public function getFormat() {
00074         return $this->mFormat;
00075     }
00076 
00086     public function setUnescapeAmps( $b ) {
00087         $this->mUnescapeAmps = $b;
00088     }
00089 
00096     public function getIsHtml() {
00097         return $this->mIsHtml;
00098     }
00099 
00106     public function getWantsHelp() {
00107         return $this->getIsHtml();
00108     }
00109 
00114     public function disable() {
00115         $this->mDisabled = true;
00116     }
00117 
00118     public function isDisabled() {
00119         return $this->mDisabled;
00120     }
00121 
00128     public function canPrintErrors() {
00129         return true;
00130     }
00131 
00140     function initPrinter( $isHelpScreen ) {
00141         if ( $this->mDisabled ) {
00142             return;
00143         }
00144         $isHtml = $this->getIsHtml();
00145         $mime = $isHtml ? 'text/html' : $this->getMimeType();
00146         $script = wfScript( 'api' );
00147 
00148         // Some printers (ex. Feed) do their own header settings,
00149         // in which case $mime will be set to null
00150         if ( is_null( $mime ) ) {
00151             return; // skip any initialization
00152         }
00153 
00154         $this->getMain()->getRequest()->response()->header( "Content-Type: $mime; charset=utf-8" );
00155 
00156         //Set X-Frame-Options API results (bug 39180)
00157         $apiFrameOptions = $this->getConfig()->get( 'ApiFrameOptions' );
00158         if ( $apiFrameOptions ) {
00159             $this->getMain()->getRequest()->response()->header( "X-Frame-Options: $apiFrameOptions" );
00160         }
00161 
00162         if ( $isHtml ) {
00163 ?>
00164 <!DOCTYPE HTML>
00165 <html>
00166 <head>
00167 <?php
00168             if ( $this->mUnescapeAmps ) {
00169 ?>  <title>MediaWiki API</title>
00170 <?php
00171             } else {
00172 ?>  <title>MediaWiki API Result</title>
00173 <?php
00174             }
00175 ?>
00176 </head>
00177 <body>
00178 <?php
00179             if ( !$isHelpScreen ) {
00180 // @codingStandardsIgnoreStart Exclude long line from CodeSniffer checks
00181 ?>
00182 <br />
00183 <small>
00184 You are looking at the HTML representation of the <?php echo $this->mFormat; ?> format.<br />
00185 HTML is good for debugging, but is unsuitable for application use.<br />
00186 Specify the format parameter to change the output format.<br />
00187 To see the non HTML representation of the <?php echo $this->mFormat; ?> format, set format=<?php echo strtolower( $this->mFormat ); ?>.<br />
00188 See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>, or
00189 <a href='<?php echo $script; ?>'>API help</a> for more information.
00190 </small>
00191 <pre style='white-space: pre-wrap;'>
00192 <?php
00193 // @codingStandardsIgnoreEnd
00194             // don't wrap the contents of the <pre> for help screens
00195             // because these are actually formatted to rely on
00196             // the monospaced font for layout purposes
00197             } else {
00198 ?>
00199 <pre>
00200 <?php
00201             }
00202         }
00203     }
00204 
00208     public function closePrinter() {
00209         if ( $this->mDisabled ) {
00210             return;
00211         }
00212         if ( $this->getIsHtml() ) {
00213 ?>
00214 
00215 </pre>
00216 </body>
00217 </html>
00218 <?php
00219         }
00220     }
00221 
00228     public function printText( $text ) {
00229         if ( $this->mDisabled ) {
00230             return;
00231         }
00232         if ( $this->mBufferResult ) {
00233             $this->mBuffer = $text;
00234         } elseif ( $this->getIsHtml() ) {
00235             echo $this->formatHTML( $text );
00236         } else {
00237             // For non-HTML output, clear all errors that might have been
00238             // displayed if display_errors=On
00239             // Do this only once, of course
00240             if ( !$this->mCleared ) {
00241                 ob_clean();
00242                 $this->mCleared = true;
00243             }
00244             echo $text;
00245         }
00246     }
00247 
00252     public function getBuffer() {
00253         return $this->mBuffer;
00254     }
00255 
00260     public function setBufferResult( $value ) {
00261         $this->mBufferResult = $value;
00262     }
00263 
00268     public function setHelp( $help = true ) {
00269         $this->mHelp = $help;
00270     }
00271 
00278     protected function formatHTML( $text ) {
00279         // Escape everything first for full coverage
00280         $text = htmlspecialchars( $text );
00281         // encode all comments or tags as safe blue strings
00282         $text = str_replace( '&lt;', '<span style="color:blue;">&lt;', $text );
00283         $text = str_replace( '&gt;', '&gt;</span>', $text );
00284 
00285         // identify requests to api.php
00286         $text = preg_replace( '#^(\s*)(api\.php\?[^ <\n\t]+)$#m', '\1<a href="\2">\2</a>', $text );
00287         if ( $this->mHelp ) {
00288             // make lines inside * bold
00289             $text = preg_replace( '#^(\s*)(\*[^<>\n]+\*)(\s*)$#m', '$1<b>$2</b>$3', $text );
00290         }
00291 
00292         // Armor links (bug 61362)
00293         $masked = array();
00294         $text = preg_replace_callback( '#<a .*?</a>#', function ( $matches ) use ( &$masked ) {
00295             $sha = sha1( $matches[0] );
00296             $masked[$sha] = $matches[0];
00297             return "<$sha>";
00298         }, $text );
00299 
00300         // identify URLs
00301         $protos = wfUrlProtocolsWithoutProtRel();
00302         // This regex hacks around bug 13218 (&quot; included in the URL)
00303         $text = preg_replace(
00304             "#(((?i)$protos).*?)(&quot;)?([ \\'\"<>\n]|&lt;|&gt;|&quot;)#",
00305             '<a href="\\1">\\1</a>\\3\\4',
00306             $text
00307         );
00308 
00309         // Unarmor links
00310         $text = preg_replace_callback( '#<([0-9a-f]{40})>#', function ( $matches ) use ( &$masked ) {
00311             $sha = $matches[1];
00312             return isset( $masked[$sha] ) ? $masked[$sha] : $matches[0];
00313         }, $text );
00314 
00321         if ( $this->mUnescapeAmps ) {
00322             $text = preg_replace( '/&amp;(amp|quot|lt|gt);/', '&\1;', $text );
00323         }
00324 
00325         return $text;
00326     }
00327 
00328     public function getExamples() {
00329         return array(
00330             'api.php?action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName()
00331                 => "Format the query result in the {$this->getModuleName()} format",
00332         );
00333     }
00334 
00335     public function getHelpUrls() {
00336         return 'https://www.mediawiki.org/wiki/API:Data_formats';
00337     }
00338 
00339     public function getDescription() {
00340         return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
00341     }
00342 
00348     protected function markDeprecated() {
00349         $fm = $this->getIsHtml() ? 'fm' : '';
00350         $name = $this->getModuleName();
00351         $this->logFeatureUsage( "format=$name" );
00352         $this->setWarning( "format=$name has been deprecated. Please use format=json$fm instead." );
00353     }
00354 }