MediaWiki  REL1_22
ApiFormatBase.php
Go to the documentation of this file.
00001 <?php
00032 abstract class ApiFormatBase extends ApiBase {
00033 
00034     private $mIsHtml, $mFormat, $mUnescapeAmps, $mHelp, $mCleared;
00035     private $mBufferResult = false, $mBuffer, $mDisabled = false;
00036 
00043     public function __construct( $main, $format ) {
00044         parent::__construct( $main, $format );
00045 
00046         $this->mIsHtml = ( substr( $format, - 2, 2 ) === 'fm' ); // ends with 'fm'
00047         if ( $this->mIsHtml ) {
00048             $this->mFormat = substr( $format, 0, - 2 ); // remove ending 'fm'
00049         } else {
00050             $this->mFormat = $format;
00051         }
00052         $this->mFormat = strtoupper( $this->mFormat );
00053         $this->mCleared = false;
00054     }
00055 
00061     abstract public function getMimeType();
00062 
00067     public function getNeedsRawData() {
00068         return false;
00069     }
00070 
00075     public function getFormat() {
00076         return $this->mFormat;
00077     }
00078 
00088     public function setUnescapeAmps( $b ) {
00089         $this->mUnescapeAmps = $b;
00090     }
00091 
00098     public function getIsHtml() {
00099         return $this->mIsHtml;
00100     }
00101 
00108     public function getWantsHelp() {
00109         return $this->getIsHtml();
00110     }
00111 
00116     public function disable() {
00117         $this->mDisabled = true;
00118     }
00119 
00120     public function isDisabled() {
00121         return $this->mDisabled;
00122     }
00123 
00132     function initPrinter( $isHelpScreen ) {
00133         if ( $this->mDisabled ) {
00134             return;
00135         }
00136         $isHtml = $this->getIsHtml();
00137         $mime = $isHtml ? 'text/html' : $this->getMimeType();
00138         $script = wfScript( 'api' );
00139 
00140         // Some printers (ex. Feed) do their own header settings,
00141         // in which case $mime will be set to null
00142         if ( is_null( $mime ) ) {
00143             return; // skip any initialization
00144         }
00145 
00146         $this->getMain()->getRequest()->response()->header( "Content-Type: $mime; charset=utf-8" );
00147 
00148         //Set X-Frame-Options API results (bug 39180)
00149         global $wgApiFrameOptions;
00150         if ( $wgApiFrameOptions ) {
00151             $this->getMain()->getRequest()->response()->header( "X-Frame-Options: $wgApiFrameOptions" );
00152         }
00153 
00154         if ( $isHtml ) {
00155 ?>
00156 <!DOCTYPE HTML>
00157 <html>
00158 <head>
00159 <?php if ( $this->mUnescapeAmps ) {
00160 ?>  <title>MediaWiki API</title>
00161 <?php } else {
00162 ?>  <title>MediaWiki API Result</title>
00163 <?php } ?>
00164 </head>
00165 <body>
00166 <?php
00167 
00168 
00169             if ( !$isHelpScreen ) {
00170 ?>
00171 <br />
00172 <small>
00173 You are looking at the HTML representation of the <?php echo $this->mFormat; ?> format.<br />
00174 HTML is good for debugging, but is unsuitable for application use.<br />
00175 Specify the format parameter to change the output format.<br />
00176 To see the non HTML representation of the <?php echo $this->mFormat; ?> format, set format=<?php echo strtolower( $this->mFormat ); ?>.<br />
00177 See the <a href='https://www.mediawiki.org/wiki/API'>complete documentation</a>, or
00178 <a href='<?php echo $script; ?>'>API help</a> for more information.
00179 </small>
00180 <pre style='white-space: pre-wrap;'>
00181 <?php
00182 
00183 
00184             } else { // don't wrap the contents of the <pre> for help screens
00185                       // because these are actually formatted to rely on
00186                       // the monospaced font for layout purposes
00187 ?>
00188 <pre>
00189 <?php
00190 
00191             }
00192         }
00193     }
00194 
00198     public function closePrinter() {
00199         if ( $this->mDisabled ) {
00200             return;
00201         }
00202         if ( $this->getIsHtml() ) {
00203 ?>
00204 
00205 </pre>
00206 </body>
00207 </html>
00208 <?php
00209 
00210 
00211         }
00212     }
00213 
00220     public function printText( $text ) {
00221         if ( $this->mDisabled ) {
00222             return;
00223         }
00224         if ( $this->mBufferResult ) {
00225             $this->mBuffer = $text;
00226         } elseif ( $this->getIsHtml() ) {
00227             echo $this->formatHTML( $text );
00228         } else {
00229             // For non-HTML output, clear all errors that might have been
00230             // displayed if display_errors=On
00231             // Do this only once, of course
00232             if ( !$this->mCleared ) {
00233                 ob_clean();
00234                 $this->mCleared = true;
00235             }
00236             echo $text;
00237         }
00238     }
00239 
00243     public function getBuffer() {
00244         return $this->mBuffer;
00245     }
00246 
00251     public function setBufferResult( $value ) {
00252         $this->mBufferResult = $value;
00253     }
00254 
00259     public function setHelp( $help = true ) {
00260         $this->mHelp = $help;
00261     }
00262 
00269     protected function formatHTML( $text ) {
00270         // Escape everything first for full coverage
00271         $text = htmlspecialchars( $text );
00272         // encode all comments or tags as safe blue strings
00273         $text = str_replace( '&lt;', '<span style="color:blue;">&lt;', $text );
00274         $text = str_replace( '&gt;', '&gt;</span>', $text );
00275 
00276         // identify requests to api.php
00277         $text = preg_replace( '#^(\s*)(api\.php\?[^ <\n\t]+)$#m', '\1<a href="\2">\2</a>', $text );
00278         if ( $this->mHelp ) {
00279             // make strings inside * bold
00280             $text = preg_replace( "#\\*[^<>\n]+\\*#", '<b>\\0</b>', $text );
00281         }
00282 
00283         // Armor links (bug 61362)
00284         $masked = array();
00285         $text = preg_replace_callback( '#<a .*?</a>#', function ( $matches ) use ( &$masked ) {
00286             $sha = sha1( $matches[0] );
00287             $masked[$sha] = $matches[0];
00288             return "<$sha>";
00289         }, $text );
00290 
00291         // identify URLs
00292         $protos = wfUrlProtocolsWithoutProtRel();
00293         // This regex hacks around bug 13218 (&quot; included in the URL)
00294         $text = preg_replace( "#(((?i)$protos).*?)(&quot;)?([ \\'\"<>\n]|&lt;|&gt;|&quot;)#", '<a href="\\1">\\1</a>\\3\\4', $text );
00295 
00296         // Unarmor links
00297         $text = preg_replace_callback( '#<([0-9a-f]{40})>#', function ( $matches ) use ( &$masked ) {
00298             $sha = $matches[1];
00299             return isset( $masked[$sha] ) ? $masked[$sha] : $matches[0];
00300         }, $text );
00301 
00308         if ( $this->mUnescapeAmps ) {
00309             $text = preg_replace( '/&amp;(amp|quot|lt|gt);/', '&\1;', $text );
00310         }
00311 
00312         return $text;
00313     }
00314 
00315     public function getExamples() {
00316         return array(
00317             'api.php?action=query&meta=siteinfo&siprop=namespaces&format=' . $this->getModuleName()
00318                 => "Format the query result in the {$this->getModuleName()} format",
00319         );
00320     }
00321 
00322     public function getHelpUrls() {
00323         return 'https://www.mediawiki.org/wiki/API:Data_formats';
00324     }
00325 
00326     public function getDescription() {
00327         return $this->getIsHtml() ? ' (pretty-print in HTML)' : '';
00328     }
00329 }
00330 
00335 class ApiFormatFeedWrapper extends ApiFormatBase {
00336 
00337     public function __construct( $main ) {
00338         parent::__construct( $main, 'feed' );
00339     }
00340 
00347     public static function setResult( $result, $feed, $feedItems ) {
00348         // Store output in the Result data.
00349         // This way we can check during execution if any error has occurred
00350         // Disable size checking for this because we can't continue
00351         // cleanly; size checking would cause more problems than it'd
00352         // solve
00353         $result->disableSizeCheck();
00354         $result->addValue( null, '_feed', $feed );
00355         $result->addValue( null, '_feeditems', $feedItems );
00356         $result->enableSizeCheck();
00357     }
00358 
00364     public function getMimeType() {
00365         return null;
00366     }
00367 
00373     public function getNeedsRawData() {
00374         return true;
00375     }
00376 
00382     public function execute() {
00383         $data = $this->getResultData();
00384         if ( isset( $data['_feed'] ) && isset( $data['_feeditems'] ) ) {
00385             $feed = $data['_feed'];
00386             $items = $data['_feeditems'];
00387 
00388             $feed->outHeader();
00389             foreach ( $items as & $item ) {
00390                 $feed->outItem( $item );
00391             }
00392             $feed->outFooter();
00393         } else {
00394             // Error has occurred, print something useful
00395             ApiBase::dieDebug( __METHOD__, 'Invalid feed class/item' );
00396         }
00397     }
00398 }