MediaWiki
REL1_24
|
00001 <?php 00002 00024 class ParserOutput extends CacheTime { 00025 public $mText, # The output text 00026 $mLanguageLinks, # List of the full text of language links, in the order they appear 00027 $mCategories, # Map of category names to sort keys 00028 $mTitleText, # title text of the chosen language variant 00029 $mLinks = array(), # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken. 00030 $mTemplates = array(), # 2-D map of NS/DBK to ID for the template references. ID=zero for broken. 00031 $mTemplateIds = array(), # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken. 00032 $mImages = array(), # DB keys of the images used, in the array key only 00033 $mFileSearchOptions = array(), # DB keys of the images used mapped to sha1 and MW timestamp 00034 $mExternalLinks = array(), # External link URLs, in the key only 00035 $mInterwikiLinks = array(), # 2-D map of prefix/DBK (in keys only) for the inline interwiki links in the document. 00036 $mNewSection = false, # Show a new section link? 00037 $mHideNewSection = false, # Hide the new section link? 00038 $mNoGallery = false, # No gallery on category page? (__NOGALLERY__) 00039 $mHeadItems = array(), # Items to put in the <head> section 00040 $mModules = array(), # Modules to be loaded by the resource loader 00041 $mModuleScripts = array(), # Modules of which only the JS will be loaded by the resource loader 00042 $mModuleStyles = array(), # Modules of which only the CSSS will be loaded by the resource loader 00043 $mModuleMessages = array(), # Modules of which only the messages will be loaded by the resource loader 00044 $mJsConfigVars = array(), # JavaScript config variable for mw.config combined with this page 00045 $mOutputHooks = array(), # Hook tags as per $wgParserOutputHooks 00046 $mWarnings = array(), # Warning text to be returned to the user. Wikitext formatted, in the key only 00047 $mSections = array(), # Table of contents 00048 $mEditSectionTokens = false, # prefix/suffix markers if edit sections were output as tokens 00049 $mProperties = array(), # Name/value pairs to be cached in the DB 00050 $mTOCHTML = '', # HTML of the TOC 00051 $mTimestamp, # Timestamp of the revision 00052 $mTOCEnabled = true; # Whether TOC should be shown, can't override __NOTOC__ 00053 private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change. 00054 private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys) 00055 private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else. 00056 private $mExtensionData = array(); # extra data used by extensions 00057 private $mLimitReportData = array(); # Parser limit report data 00058 private $mParseStartTime = array(); # Timestamps for getTimeSinceStart() 00059 private $mPreventClickjacking = false; # Whether to emit X-Frame-Options: DENY 00060 00061 const EDITSECTION_REGEX = 00062 '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#'; 00063 00064 public function __construct( $text = '', $languageLinks = array(), $categoryLinks = array(), 00065 $containsOldMagic = false, $titletext = '' 00066 ) { 00067 $this->mText = $text; 00068 $this->mLanguageLinks = $languageLinks; 00069 $this->mCategories = $categoryLinks; 00070 $this->mContainsOldMagic = $containsOldMagic; 00071 $this->mTitleText = $titletext; 00072 } 00073 00074 public function getText() { 00075 wfProfileIn( __METHOD__ ); 00076 $text = $this->mText; 00077 if ( $this->mEditSectionTokens ) { 00078 $text = preg_replace_callback( 00079 ParserOutput::EDITSECTION_REGEX, 00080 function ( $m ) { 00081 global $wgOut, $wgLang; 00082 $editsectionPage = Title::newFromText( htmlspecialchars_decode( $m[1] ) ); 00083 $editsectionSection = htmlspecialchars_decode( $m[2] ); 00084 $editsectionContent = isset( $m[4] ) ? $m[3] : null; 00085 00086 if ( !is_object( $editsectionPage ) ) { 00087 throw new MWException( "Bad parser output text." ); 00088 } 00089 00090 $skin = $wgOut->getSkin(); 00091 return call_user_func_array( 00092 array( $skin, 'doEditSectionLink' ), 00093 array( $editsectionPage, $editsectionSection, 00094 $editsectionContent, $wgLang->getCode() ) 00095 ); 00096 }, 00097 $text 00098 ); 00099 } else { 00100 $text = preg_replace( ParserOutput::EDITSECTION_REGEX, '', $text ); 00101 } 00102 00103 // If you have an old cached version of this class - sorry, you can't disable the TOC 00104 if ( isset( $this->mTOCEnabled ) && $this->mTOCEnabled ) { 00105 $text = str_replace( array( Parser::TOC_START, Parser::TOC_END ), '', $text ); 00106 } else { 00107 $text = preg_replace( 00108 '#' . preg_quote( Parser::TOC_START ) . '.*?' . preg_quote( Parser::TOC_END ) . '#s', 00109 '', 00110 $text 00111 ); 00112 } 00113 wfProfileOut( __METHOD__ ); 00114 return $text; 00115 } 00116 00117 public function &getLanguageLinks() { 00118 return $this->mLanguageLinks; 00119 } 00120 00121 public function getInterwikiLinks() { 00122 return $this->mInterwikiLinks; 00123 } 00124 00125 public function getCategoryLinks() { 00126 return array_keys( $this->mCategories ); 00127 } 00128 00129 public function &getCategories() { 00130 return $this->mCategories; 00131 } 00132 00133 public function getTitleText() { 00134 return $this->mTitleText; 00135 } 00136 00137 public function getSections() { 00138 return $this->mSections; 00139 } 00140 00141 public function getEditSectionTokens() { 00142 return $this->mEditSectionTokens; 00143 } 00144 00145 public function &getLinks() { 00146 return $this->mLinks; 00147 } 00148 00149 public function &getTemplates() { 00150 return $this->mTemplates; 00151 } 00152 00153 public function &getTemplateIds() { 00154 return $this->mTemplateIds; 00155 } 00156 00157 public function &getImages() { 00158 return $this->mImages; 00159 } 00160 00161 public function &getFileSearchOptions() { 00162 return $this->mFileSearchOptions; 00163 } 00164 00165 public function &getExternalLinks() { 00166 return $this->mExternalLinks; 00167 } 00168 00169 public function getNoGallery() { 00170 return $this->mNoGallery; 00171 } 00172 00173 public function getHeadItems() { 00174 return $this->mHeadItems; 00175 } 00176 00177 public function getModules() { 00178 return $this->mModules; 00179 } 00180 00181 public function getModuleScripts() { 00182 return $this->mModuleScripts; 00183 } 00184 00185 public function getModuleStyles() { 00186 return $this->mModuleStyles; 00187 } 00188 00189 public function getModuleMessages() { 00190 return $this->mModuleMessages; 00191 } 00192 00194 public function getJsConfigVars() { 00195 return $this->mJsConfigVars; 00196 } 00197 00198 public function getOutputHooks() { 00199 return (array)$this->mOutputHooks; 00200 } 00201 00202 public function getWarnings() { 00203 return array_keys( $this->mWarnings ); 00204 } 00205 00206 public function getIndexPolicy() { 00207 return $this->mIndexPolicy; 00208 } 00209 00210 public function getTOCHTML() { 00211 return $this->mTOCHTML; 00212 } 00213 00214 public function getTimestamp() { 00215 return $this->mTimestamp; 00216 } 00217 00218 public function getLimitReportData() { 00219 return $this->mLimitReportData; 00220 } 00221 00222 public function getTOCEnabled() { 00223 return $this->mTOCEnabled; 00224 } 00225 00226 public function setText( $text ) { 00227 return wfSetVar( $this->mText, $text ); 00228 } 00229 00230 public function setLanguageLinks( $ll ) { 00231 return wfSetVar( $this->mLanguageLinks, $ll ); 00232 } 00233 00234 public function setCategoryLinks( $cl ) { 00235 return wfSetVar( $this->mCategories, $cl ); 00236 } 00237 00238 public function setTitleText( $t ) { 00239 return wfSetVar( $this->mTitleText, $t ); 00240 } 00241 00242 public function setSections( $toc ) { 00243 return wfSetVar( $this->mSections, $toc ); 00244 } 00245 00246 public function setEditSectionTokens( $t ) { 00247 return wfSetVar( $this->mEditSectionTokens, $t ); 00248 } 00249 00250 public function setIndexPolicy( $policy ) { 00251 return wfSetVar( $this->mIndexPolicy, $policy ); 00252 } 00253 00254 public function setTOCHTML( $tochtml ) { 00255 return wfSetVar( $this->mTOCHTML, $tochtml ); 00256 } 00257 00258 public function setTimestamp( $timestamp ) { 00259 return wfSetVar( $this->mTimestamp, $timestamp ); 00260 } 00261 00262 public function setTOCEnabled( $flag ) { 00263 return wfSetVar( $this->mTOCEnabled, $flag ); 00264 } 00265 00266 public function addCategory( $c, $sort ) { 00267 $this->mCategories[$c] = $sort; 00268 } 00269 00270 public function addLanguageLink( $t ) { 00271 $this->mLanguageLinks[] = $t; 00272 } 00273 00274 public function addWarning( $s ) { 00275 $this->mWarnings[$s] = 1; 00276 } 00277 00278 public function addOutputHook( $hook, $data = false ) { 00279 $this->mOutputHooks[] = array( $hook, $data ); 00280 } 00281 00282 public function setNewSection( $value ) { 00283 $this->mNewSection = (bool)$value; 00284 } 00285 public function hideNewSection( $value ) { 00286 $this->mHideNewSection = (bool)$value; 00287 } 00288 public function getHideNewSection() { 00289 return (bool)$this->mHideNewSection; 00290 } 00291 public function getNewSection() { 00292 return (bool)$this->mNewSection; 00293 } 00294 00302 public static function isLinkInternal( $internal, $url ) { 00303 return (bool)preg_match( '/^' . 00304 # If server is proto relative, check also for http/https links 00305 ( substr( $internal, 0, 2 ) === '//' ? '(?:https?:)?' : '' ) . 00306 preg_quote( $internal, '/' ) . 00307 # check for query/path/anchor or end of link in each case 00308 '(?:[\?\/\#]|$)/i', 00309 $url 00310 ); 00311 } 00312 00313 public function addExternalLink( $url ) { 00314 # We don't register links pointing to our own server, unless... :-) 00315 global $wgServer, $wgRegisterInternalExternals; 00316 00317 $registerExternalLink = true; 00318 if ( !$wgRegisterInternalExternals ) { 00319 $registerExternalLink = !self::isLinkInternal( $wgServer, $url ); 00320 } 00321 if ( $registerExternalLink ) { 00322 $this->mExternalLinks[$url] = 1; 00323 } 00324 } 00325 00332 public function addLink( Title $title, $id = null ) { 00333 if ( $title->isExternal() ) { 00334 // Don't record interwikis in pagelinks 00335 $this->addInterwikiLink( $title ); 00336 return; 00337 } 00338 $ns = $title->getNamespace(); 00339 $dbk = $title->getDBkey(); 00340 if ( $ns == NS_MEDIA ) { 00341 // Normalize this pseudo-alias if it makes it down here... 00342 $ns = NS_FILE; 00343 } elseif ( $ns == NS_SPECIAL ) { 00344 // We don't record Special: links currently 00345 // It might actually be wise to, but we'd need to do some normalization. 00346 return; 00347 } elseif ( $dbk === '' ) { 00348 // Don't record self links - [[#Foo]] 00349 return; 00350 } 00351 if ( !isset( $this->mLinks[$ns] ) ) { 00352 $this->mLinks[$ns] = array(); 00353 } 00354 if ( is_null( $id ) ) { 00355 $id = $title->getArticleID(); 00356 } 00357 $this->mLinks[$ns][$dbk] = $id; 00358 } 00359 00367 public function addImage( $name, $timestamp = null, $sha1 = null ) { 00368 $this->mImages[$name] = 1; 00369 if ( $timestamp !== null && $sha1 !== null ) { 00370 $this->mFileSearchOptions[$name] = array( 'time' => $timestamp, 'sha1' => $sha1 ); 00371 } 00372 } 00373 00381 public function addTemplate( $title, $page_id, $rev_id ) { 00382 $ns = $title->getNamespace(); 00383 $dbk = $title->getDBkey(); 00384 if ( !isset( $this->mTemplates[$ns] ) ) { 00385 $this->mTemplates[$ns] = array(); 00386 } 00387 $this->mTemplates[$ns][$dbk] = $page_id; 00388 if ( !isset( $this->mTemplateIds[$ns] ) ) { 00389 $this->mTemplateIds[$ns] = array(); 00390 } 00391 $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning 00392 } 00393 00398 public function addInterwikiLink( $title ) { 00399 if ( !$title->isExternal() ) { 00400 throw new MWException( 'Non-interwiki link passed, internal parser error.' ); 00401 } 00402 $prefix = $title->getInterwiki(); 00403 if ( !isset( $this->mInterwikiLinks[$prefix] ) ) { 00404 $this->mInterwikiLinks[$prefix] = array(); 00405 } 00406 $this->mInterwikiLinks[$prefix][$title->getDBkey()] = 1; 00407 } 00408 00416 public function addHeadItem( $section, $tag = false ) { 00417 if ( $tag !== false ) { 00418 $this->mHeadItems[$tag] = $section; 00419 } else { 00420 $this->mHeadItems[] = $section; 00421 } 00422 } 00423 00424 public function addModules( $modules ) { 00425 $this->mModules = array_merge( $this->mModules, (array)$modules ); 00426 } 00427 00428 public function addModuleScripts( $modules ) { 00429 $this->mModuleScripts = array_merge( $this->mModuleScripts, (array)$modules ); 00430 } 00431 00432 public function addModuleStyles( $modules ) { 00433 $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules ); 00434 } 00435 00436 public function addModuleMessages( $modules ) { 00437 $this->mModuleMessages = array_merge( $this->mModuleMessages, (array)$modules ); 00438 } 00439 00447 public function addJsConfigVars( $keys, $value = null ) { 00448 if ( is_array( $keys ) ) { 00449 foreach ( $keys as $key => $value ) { 00450 $this->mJsConfigVars[$key] = $value; 00451 } 00452 return; 00453 } 00454 00455 $this->mJsConfigVars[$keys] = $value; 00456 } 00457 00463 public function addOutputPageMetadata( OutputPage $out ) { 00464 $this->addModules( $out->getModules() ); 00465 $this->addModuleScripts( $out->getModuleScripts() ); 00466 $this->addModuleStyles( $out->getModuleStyles() ); 00467 $this->addModuleMessages( $out->getModuleMessages() ); 00468 $this->addJsConfigVars( $out->getJsConfigVars() ); 00469 00470 $this->mHeadItems = array_merge( $this->mHeadItems, $out->getHeadItemsArray() ); 00471 $this->mPreventClickjacking = $this->mPreventClickjacking || $out->getPreventClickjacking(); 00472 } 00473 00481 public function setDisplayTitle( $text ) { 00482 $this->setTitleText( $text ); 00483 $this->setProperty( 'displaytitle', $text ); 00484 } 00485 00491 public function getDisplayTitle() { 00492 $t = $this->getTitleText(); 00493 if ( $t === '' ) { 00494 return false; 00495 } 00496 return $t; 00497 } 00498 00503 public function setFlag( $flag ) { 00504 $this->mFlags[$flag] = true; 00505 } 00506 00507 public function getFlag( $flag ) { 00508 return isset( $this->mFlags[$flag] ); 00509 } 00510 00571 public function setProperty( $name, $value ) { 00572 $this->mProperties[$name] = $value; 00573 } 00574 00583 public function getProperty( $name ) { 00584 return isset( $this->mProperties[$name] ) ? $this->mProperties[$name] : false; 00585 } 00586 00587 public function unsetProperty( $name ) { 00588 unset( $this->mProperties[$name] ); 00589 } 00590 00591 public function getProperties() { 00592 if ( !isset( $this->mProperties ) ) { 00593 $this->mProperties = array(); 00594 } 00595 return $this->mProperties; 00596 } 00597 00603 public function getUsedOptions() { 00604 if ( !isset( $this->mAccessedOptions ) ) { 00605 return array(); 00606 } 00607 return array_keys( $this->mAccessedOptions ); 00608 } 00609 00620 public function recordOption( $option ) { 00621 $this->mAccessedOptions[$option] = true; 00622 } 00623 00634 public function addSecondaryDataUpdate( DataUpdate $update ) { 00635 $this->mSecondaryDataUpdates[] = $update; 00636 } 00637 00654 public function getSecondaryDataUpdates( Title $title = null, $recursive = true ) { 00655 if ( is_null( $title ) ) { 00656 $title = Title::newFromText( $this->getTitleText() ); 00657 } 00658 00659 $linksUpdate = new LinksUpdate( $title, $this, $recursive ); 00660 00661 return array_merge( $this->mSecondaryDataUpdates, array( $linksUpdate ) ); 00662 } 00663 00704 public function setExtensionData( $key, $value ) { 00705 if ( $value === null ) { 00706 unset( $this->mExtensionData[$key] ); 00707 } else { 00708 $this->mExtensionData[$key] = $value; 00709 } 00710 } 00711 00723 public function getExtensionData( $key ) { 00724 if ( isset( $this->mExtensionData[$key] ) ) { 00725 return $this->mExtensionData[$key]; 00726 } 00727 00728 return null; 00729 } 00730 00731 private static function getTimes( $clock = null ) { 00732 $ret = array(); 00733 if ( !$clock || $clock === 'wall' ) { 00734 $ret['wall'] = microtime( true ); 00735 } 00736 if ( !$clock || $clock === 'cpu' ) { 00737 $ru = wfGetRusage(); 00738 if ( $ru ) { 00739 $ret['cpu'] = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6; 00740 $ret['cpu'] += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6; 00741 } 00742 } 00743 return $ret; 00744 } 00745 00750 public function resetParseStartTime() { 00751 $this->mParseStartTime = self::getTimes(); 00752 } 00753 00765 public function getTimeSinceStart( $clock ) { 00766 if ( !isset( $this->mParseStartTime[$clock] ) ) { 00767 return null; 00768 } 00769 00770 $end = self::getTimes( $clock ); 00771 return $end[$clock] - $this->mParseStartTime[$clock]; 00772 } 00773 00793 public function setLimitReportData( $key, $value ) { 00794 $this->mLimitReportData[$key] = $value; 00795 } 00796 00804 public function preventClickjacking( $flag = null ) { 00805 return wfSetVar( $this->mPreventClickjacking, $flag ); 00806 } 00807 00812 public function __sleep() { 00813 return array_diff( 00814 array_keys( get_object_vars( $this ) ), 00815 array( 'mSecondaryDataUpdates', 'mParseStartTime' ) 00816 ); 00817 } 00818 }