MediaWiki  REL1_23
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 
00042     public function __construct( $main, $format ) {
00043         parent::__construct( $main, $format );
00044 
00045         $this->mIsHtml = ( substr( $format, -2, 2 ) === 'fm' ); // ends with 'fm'
00046         if ( $this->mIsHtml ) {
00047             $this->mFormat = substr( $format, 0, -2 ); // remove ending 'fm'
00048         } else {
00049             $this->mFormat = $format;
00050         }
00051         $this->mFormat = strtoupper( $this->mFormat );
00052         $this->mCleared = false;
00053     }
00054 
00060     abstract public function getMimeType();
00061 
00066     public function getNeedsRawData() {
00067         return false;
00068     }
00069 
00074     public function getFormat() {
00075         return $this->mFormat;
00076     }
00077 
00087     public function setUnescapeAmps( $b ) {
00088         $this->mUnescapeAmps = $b;
00089     }
00090 
00097     public function getIsHtml() {
00098         return $this->mIsHtml;
00099     }
00100 
00107     public function getWantsHelp() {
00108         return $this->getIsHtml();
00109     }
00110 
00115     public function disable() {
00116         $this->mDisabled = true;
00117     }
00118 
00119     public function isDisabled() {
00120         return $this->mDisabled;
00121     }
00122 
00129     public function canPrintErrors() {
00130         return true;
00131     }
00132 
00141     function initPrinter( $isHelpScreen ) {
00142         if ( $this->mDisabled ) {
00143             return;
00144         }
00145         $isHtml = $this->getIsHtml();
00146         $mime = $isHtml ? 'text/html' : $this->getMimeType();
00147         $script = wfScript( 'api' );
00148 
00149         // Some printers (ex. Feed) do their own header settings,
00150         // in which case $mime will be set to null
00151         if ( is_null( $mime ) ) {
00152             return; // skip any initialization
00153         }
00154 
00155         $this->getMain()->getRequest()->response()->header( "Content-Type: $mime; charset=utf-8" );
00156 
00157         //Set X-Frame-Options API results (bug 39180)
00158         global $wgApiFrameOptions;
00159         if ( $wgApiFrameOptions ) {
00160             $this->getMain()->getRequest()->response()->header( "X-Frame-Options: $wgApiFrameOptions" );
00161         }
00162 
00163         if ( $isHtml ) {
00164 ?>
00165 <!DOCTYPE HTML>
00166 <html>
00167 <head>
00168 <?php
00169             if ( $this->mUnescapeAmps ) {
00170 ?>  <title>MediaWiki API</title>
00171 <?php
00172             } else {
00173 ?>  <title>MediaWiki API Result</title>
00174 <?php
00175             }
00176 ?>
00177 </head>
00178 <body>
00179 <?php
00180             if ( !$isHelpScreen ) {
00181 // @codingStandardsIgnoreStart Exclude long line from CodeSniffer checks
00182 ?>
00183 <br />
00184 <small>
00185 You are looking at the HTML representation of the <?php echo $this->mFormat; ?> format.<br />
00186 HTML is good for debugging, but is unsuitable for application use.<br />
00187 Specify the format parameter to change the output format.<br />
00188 To see the non HTML representation of the <?php echo $this->mFormat; ?> format, set format=<?php echo strtolower( $this->mFormat ); ?>.<br />
00189 See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>, or
00190 <a href='<?php echo $script; ?>'>API help</a> for more information.
00191 </small>
00192 <pre style='white-space: pre-wrap;'>
00193 <?php
00194 // @codingStandardsIgnoreEnd
00195             // don't wrap the contents of the <pre> for help screens
00196             // because these are actually formatted to rely on
00197             // the monospaced font for layout purposes
00198             } else {
00199 ?>
00200 <pre>
00201 <?php
00202             }
00203         }
00204     }
00205 
00209     public function closePrinter() {
00210         if ( $this->mDisabled ) {
00211             return;
00212         }
00213         if ( $this->getIsHtml() ) {
00214 ?>
00215 
00216 </pre>
00217 </body>
00218 </html>
00219 <?php
00220         }
00221     }
00222 
00229     public function printText( $text ) {
00230         if ( $this->mDisabled ) {
00231             return;
00232         }
00233         if ( $this->mBufferResult ) {
00234             $this->mBuffer = $text;
00235         } elseif ( $this->getIsHtml() ) {
00236             echo $this->formatHTML( $text );
00237         } else {
00238             // For non-HTML output, clear all errors that might have been
00239             // displayed if display_errors=On
00240             // Do this only once, of course
00241             if ( !$this->mCleared ) {
00242                 ob_clean();
00243                 $this->mCleared = true;
00244             }
00245             echo $text;
00246         }
00247     }
00248 
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 }
00343 
00348 class ApiFormatFeedWrapper extends ApiFormatBase {
00349 
00350     public function __construct( $main ) {
00351         parent::__construct( $main, 'feed' );
00352     }
00353 
00360     public static function setResult( $result, $feed, $feedItems ) {
00361         // Store output in the Result data.
00362         // This way we can check during execution if any error has occurred
00363         // Disable size checking for this because we can't continue
00364         // cleanly; size checking would cause more problems than it'd
00365         // solve
00366         $result->disableSizeCheck();
00367         $result->addValue( null, '_feed', $feed );
00368         $result->addValue( null, '_feeditems', $feedItems );
00369         $result->enableSizeCheck();
00370     }
00371 
00377     public function getMimeType() {
00378         return null;
00379     }
00380 
00386     public function getNeedsRawData() {
00387         return true;
00388     }
00389 
00395     public function canPrintErrors() {
00396         return false;
00397     }
00398 
00404     public function execute() {
00405         $data = $this->getResultData();
00406         if ( isset( $data['_feed'] ) && isset( $data['_feeditems'] ) ) {
00407             $feed = $data['_feed'];
00408             $items = $data['_feeditems'];
00409 
00410             $feed->outHeader();
00411             foreach ( $items as & $item ) {
00412                 $feed->outItem( $item );
00413             }
00414             $feed->outFooter();
00415         } else {
00416             // Error has occurred, print something useful
00417             ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
00418         }
00419     }
00420 }