2007-01-20 12:50:56 +00:00
< ? php
2012-08-06 14:18:02 +00:00
2010-08-22 14:31:05 +00:00
/**
2012-08-06 14:18:02 +00:00
* Output of the PHP parser .
2010-08-22 14:31:05 +00:00
*
2012-04-30 09:22:16 +00:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
* http :// www . gnu . org / copyleft / gpl . html
*
2010-08-22 14:31:05 +00:00
* @ file
* @ ingroup Parser
*/
2010-12-28 09:54:25 +00:00
class ParserOutput extends CacheTime {
2008-07-25 01:27:51 +00:00
var $mText , # The output text
$mLanguageLinks , # List of the full text of language links, in the order they appear
$mCategories , # Map of category names to sort keys
$mTitleText , # title text of the chosen language variant
$mLinks = array (), # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken.
$mTemplates = array (), # 2-D map of NS/DBK to ID for the template references. ID=zero for broken.
$mTemplateIds = array (), # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken.
$mImages = array (), # DB keys of the images used, in the array key only
2011-09-14 19:05:43 +00:00
$mFileSearchOptions = array (), # DB keys of the images used mapped to sha1 and MW timestamp
2008-07-25 01:27:51 +00:00
$mExternalLinks = array (), # External link URLs, in the key only
2010-04-16 01:40:05 +00:00
$mInterwikiLinks = array (), # 2-D map of prefix/DBK (in keys only) for the inline interwiki links in the document.
2008-07-25 01:27:51 +00:00
$mNewSection = false , # Show a new section link?
2009-02-19 22:14:59 +00:00
$mHideNewSection = false , # Hide the new section link?
2008-07-25 01:27:51 +00:00
$mNoGallery = false , # No gallery on category page? (__NOGALLERY__)
$mHeadItems = array (), # Items to put in the <head> section
2010-09-27 12:30:04 +00:00
$mModules = array (), # Modules to be loaded by the resource loader
2011-08-02 15:40:03 +00:00
$mModuleScripts = array (), # Modules of which only the JS will be loaded by the resource loader
$mModuleStyles = array (), # Modules of which only the CSSS will be loaded by the resource loader
$mModuleMessages = array (), # Modules of which only the messages will be loaded by the resource loader
2008-07-25 01:27:51 +00:00
$mOutputHooks = array (), # Hook tags as per $wgParserOutputHooks
$mWarnings = array (), # Warning text to be returned to the user. Wikitext formatted, in the key only
$mSections = array (), # Table of contents
2011-01-03 20:17:20 +00:00
$mEditSectionTokens = false , # prefix/suffix markers if edit sections were output as tokens
2009-06-20 21:47:10 +00:00
$mProperties = array (), # Name/value pairs to be cached in the DB
2011-12-10 16:30:40 +00:00
$mTOCHTML = '' , # HTML of the TOC
$mTimestamp ; # Timestamp of the revision
2012-05-08 15:09:30 +00:00
private $mIndexPolicy = '' ; # 'index' or 'noindex'? Any other value will result in no change.
private $mAccessedOptions = array (); # List of ParserOptions (stored in the keys)
private $mSecondaryDataUpdates = array (); # List of instances of SecondaryDataObject(), used to cause some information extracted from the page in a custom place.
2008-02-20 08:53:12 +00:00
2011-02-08 01:31:21 +00:00
const EDITSECTION_REGEX = '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#' ;
2010-08-30 16:52:51 +00:00
function __construct ( $text = '' , $languageLinks = array (), $categoryLinks = array (),
2007-01-20 12:50:56 +00:00
$containsOldMagic = false , $titletext = '' )
{
$this -> mText = $text ;
$this -> mLanguageLinks = $languageLinks ;
$this -> mCategories = $categoryLinks ;
$this -> mContainsOldMagic = $containsOldMagic ;
$this -> mTitleText = $titletext ;
}
2011-01-03 20:17:20 +00:00
function getText () {
if ( $this -> mEditSectionTokens ) {
2011-02-08 01:31:21 +00:00
return preg_replace_callback ( ParserOutput :: EDITSECTION_REGEX ,
array ( & $this , 'replaceEditSectionLinksCallback' ), $this -> mText );
2011-01-03 20:17:20 +00:00
}
2011-10-29 01:17:26 +00:00
return preg_replace ( ParserOutput :: EDITSECTION_REGEX , '' , $this -> mText );
2011-01-03 20:17:20 +00:00
}
2011-08-01 15:40:02 +00:00
2011-01-03 20:17:20 +00:00
/**
* callback used by getText to replace editsection tokens
* @ private
2012-02-09 21:35:05 +00:00
* @ return mixed
2011-01-03 20:17:20 +00:00
*/
function replaceEditSectionLinksCallback ( $m ) {
2011-04-03 11:44:11 +00:00
global $wgOut , $wgLang ;
2011-01-04 04:20:09 +00:00
$args = array (
htmlspecialchars_decode ( $m [ 1 ]),
htmlspecialchars_decode ( $m [ 2 ]),
2011-01-04 04:23:01 +00:00
isset ( $m [ 4 ]) ? $m [ 3 ] : null ,
2011-01-04 04:20:09 +00:00
);
2011-01-03 20:17:20 +00:00
$args [ 0 ] = Title :: newFromText ( $args [ 0 ] );
2011-01-03 21:04:05 +00:00
if ( ! is_object ( $args [ 0 ]) ) {
throw new MWException ( " Bad parser output text. " );
}
2011-01-03 20:17:20 +00:00
$args [] = $wgLang -> getCode ();
2011-04-03 11:44:11 +00:00
$skin = $wgOut -> getSkin ();
2011-01-03 20:17:20 +00:00
return call_user_func_array ( array ( $skin , 'doEditSectionLink' ), $args );
}
2007-05-31 16:01:26 +00:00
function & getLanguageLinks () { return $this -> mLanguageLinks ; }
2010-04-16 01:40:05 +00:00
function getInterwikiLinks () { return $this -> mInterwikiLinks ; }
2007-01-20 12:50:56 +00:00
function getCategoryLinks () { return array_keys ( $this -> mCategories ); }
function & getCategories () { return $this -> mCategories ; }
function getTitleText () { return $this -> mTitleText ; }
2007-12-27 20:14:07 +00:00
function getSections () { return $this -> mSections ; }
2011-01-03 20:17:20 +00:00
function getEditSectionTokens () { return $this -> mEditSectionTokens ; }
2007-01-20 12:50:56 +00:00
function & getLinks () { return $this -> mLinks ; }
function & getTemplates () { return $this -> mTemplates ; }
2011-03-23 17:35:40 +00:00
function & getTemplateIds () { return $this -> mTemplateIds ; }
2007-01-20 12:50:56 +00:00
function & getImages () { return $this -> mImages ; }
2011-09-14 19:05:43 +00:00
function & getFileSearchOptions () { return $this -> mFileSearchOptions ; }
2007-01-20 12:50:56 +00:00
function & getExternalLinks () { return $this -> mExternalLinks ; }
function getNoGallery () { return $this -> mNoGallery ; }
2010-01-16 13:07:58 +00:00
function getHeadItems () { return $this -> mHeadItems ; }
2010-09-27 12:30:04 +00:00
function getModules () { return $this -> mModules ; }
2011-08-02 15:40:03 +00:00
function getModuleScripts () { return $this -> mModuleScripts ; }
function getModuleStyles () { return $this -> mModuleStyles ; }
function getModuleMessages () { return $this -> mModuleMessages ; }
2007-08-15 20:46:51 +00:00
function getOutputHooks () { return ( array ) $this -> mOutputHooks ; }
2008-05-19 21:33:47 +00:00
function getWarnings () { return array_keys ( $this -> mWarnings ); }
2008-07-23 19:49:46 +00:00
function getIndexPolicy () { return $this -> mIndexPolicy ; }
2009-06-20 21:47:10 +00:00
function getTOCHTML () { return $this -> mTOCHTML ; }
2011-12-10 16:30:40 +00:00
function getTimestamp () { return $this -> mTimestamp ; }
2007-01-20 12:50:56 +00:00
function setText ( $text ) { return wfSetVar ( $this -> mText , $text ); }
function setLanguageLinks ( $ll ) { return wfSetVar ( $this -> mLanguageLinks , $ll ); }
function setCategoryLinks ( $cl ) { return wfSetVar ( $this -> mCategories , $cl ); }
2010-06-01 14:28:51 +00:00
2007-12-27 20:14:07 +00:00
function setTitleText ( $t ) { return wfSetVar ( $this -> mTitleText , $t ); }
function setSections ( $toc ) { return wfSetVar ( $this -> mSections , $toc ); }
2011-01-04 04:20:09 +00:00
function setEditSectionTokens ( $t ) { return wfSetVar ( $this -> mEditSectionTokens , $t ); }
2008-07-23 19:49:46 +00:00
function setIndexPolicy ( $policy ) { return wfSetVar ( $this -> mIndexPolicy , $policy ); }
2009-06-20 21:47:10 +00:00
function setTOCHTML ( $tochtml ) { return wfSetVar ( $this -> mTOCHTML , $tochtml ); }
2011-12-10 16:30:40 +00:00
function setTimestamp ( $timestamp ) { return wfSetVar ( $this -> mTimestamp , $timestamp ); }
2007-01-20 12:50:56 +00:00
function addCategory ( $c , $sort ) { $this -> mCategories [ $c ] = $sort ; }
function addLanguageLink ( $t ) { $this -> mLanguageLinks [] = $t ; }
2008-05-19 21:33:47 +00:00
function addWarning ( $s ) { $this -> mWarnings [ $s ] = 1 ; }
2007-01-20 12:50:56 +00:00
2008-04-14 07:45:50 +00:00
function addOutputHook ( $hook , $data = false ) {
Basic integrated audio/video support, with Ogg implementation.
* JavaScript video player based loosely on Greg Maxwell's player
* Image page text snippet customisation
* Abstraction of transform parameters in the parser. Introduced Linker::makeImageLink2().
* Made canRender(), mustRender() depend on file, not just on handler. Moved width=0, height=0 checking to ImageHandler::canRender(), since audio streams have width=height=0 but should be rendered.
Also:
* Automatic upgrade for oldimage rows on image page view, allows media handler selection based on oi_*_mime
* oi_*_mime unconditionally referenced, REQUIRES SCHEMA UPGRADE
* Don't destroy file info for missing files on upgrade
* Simple, centralised extension message file handling
* Made MessageCache::loadAllMessages non-static, optimised for repeated-call case due to abuse in User.php
* Support for lightweight parser output hooks, with callback whitelist for security
* Moved Linker::formatSize() to Language, to join the new formatTimePeriod() and formatBitrate()
* Introduced MagicWordArray, regex capture trick requires that magic word IDs DO NOT CONTAIN HYPHENS.
2007-08-15 10:50:09 +00:00
$this -> mOutputHooks [] = array ( $hook , $data );
}
2007-01-20 12:50:56 +00:00
function setNewSection ( $value ) {
$this -> mNewSection = ( bool ) $value ;
}
2009-02-19 22:14:59 +00:00
function hideNewSection ( $value ) {
$this -> mHideNewSection = ( bool ) $value ;
}
function getHideNewSection () {
return ( bool ) $this -> mHideNewSection ;
}
2007-01-20 12:50:56 +00:00
function getNewSection () {
return ( bool ) $this -> mNewSection ;
}
2009-07-11 08:04:31 +00:00
function addExternalLink ( $url ) {
# We don't register links pointing to our own server, unless... :-)
global $wgServer , $wgRegisterInternalExternals ;
2009-07-11 08:15:37 +00:00
if ( $wgRegisterInternalExternals or stripos ( $url , $wgServer . '/' ) !== 0 )
2011-08-01 15:40:02 +00:00
$this -> mExternalLinks [ $url ] = 1 ;
2009-07-11 08:04:31 +00:00
}
2010-04-16 01:40:05 +00:00
/**
* Record a local or interwiki inline link for saving in future link tables .
*
2010-05-15 20:16:26 +00:00
* @ param $title Title object
* @ param $id Mixed : optional known page_id so we can skip the lookup
2010-04-16 01:40:05 +00:00
*/
2007-01-20 12:50:56 +00:00
function addLink ( $title , $id = null ) {
2009-07-18 22:49:31 +00:00
if ( $title -> isExternal () ) {
// Don't record interwikis in pagelinks
2010-04-16 01:40:05 +00:00
$this -> addInterwikiLink ( $title );
2009-07-18 22:49:31 +00:00
return ;
}
2007-01-20 12:50:56 +00:00
$ns = $title -> getNamespace ();
$dbk = $title -> getDBkey ();
2009-01-01 00:05:08 +00:00
if ( $ns == NS_MEDIA ) {
// Normalize this pseudo-alias if it makes it down here...
$ns = NS_FILE ;
} elseif ( $ns == NS_SPECIAL ) {
// We don't record Special: links currently
// It might actually be wise to, but we'd need to do some normalization.
return ;
2009-01-11 03:42:13 +00:00
} elseif ( $dbk === '' ) {
// Don't record self links - [[#Foo]]
return ;
2009-01-01 00:05:08 +00:00
}
2007-01-20 12:50:56 +00:00
if ( ! isset ( $this -> mLinks [ $ns ] ) ) {
$this -> mLinks [ $ns ] = array ();
}
if ( is_null ( $id ) ) {
$id = $title -> getArticleID ();
}
$this -> mLinks [ $ns ][ $dbk ] = $id ;
}
2008-04-14 07:45:50 +00:00
2011-03-23 17:35:40 +00:00
/**
2011-04-04 01:22:08 +00:00
* Register a file dependency for this output
2011-03-23 17:35:40 +00:00
* @ param $name string Title dbKey
2011-04-04 01:22:08 +00:00
* @ param $timestamp string MW timestamp of file creation ( or false if non - existing )
2012-02-01 20:53:38 +00:00
* @ param $sha1 string base 36 SHA - 1 of file ( or false if non - existing )
2012-01-12 19:41:18 +00:00
* @ return void
2011-03-23 17:35:40 +00:00
*/
2011-03-23 21:45:32 +00:00
function addImage ( $name , $timestamp = null , $sha1 = null ) {
2007-05-31 16:01:26 +00:00
$this -> mImages [ $name ] = 1 ;
2011-04-04 01:22:08 +00:00
if ( $timestamp !== null && $sha1 !== null ) {
2011-09-14 19:05:43 +00:00
$this -> mFileSearchOptions [ $name ] = array ( 'time' => $timestamp , 'sha1' => $sha1 );
2011-04-04 01:22:08 +00:00
}
2007-05-31 16:01:26 +00:00
}
2007-01-20 12:50:56 +00:00
2011-02-19 01:02:56 +00:00
/**
2011-04-04 01:22:08 +00:00
* Register a template dependency for this output
2011-02-19 01:02:56 +00:00
* @ param $title Title
2011-03-23 17:35:40 +00:00
* @ param $page_id
* @ param $rev_id
2012-01-12 19:41:18 +00:00
* @ return void
2011-02-19 01:02:56 +00:00
*/
2007-05-31 16:01:26 +00:00
function addTemplate ( $title , $page_id , $rev_id ) {
2007-01-20 12:50:56 +00:00
$ns = $title -> getNamespace ();
$dbk = $title -> getDBkey ();
if ( ! isset ( $this -> mTemplates [ $ns ] ) ) {
$this -> mTemplates [ $ns ] = array ();
}
2007-05-31 16:01:26 +00:00
$this -> mTemplates [ $ns ][ $dbk ] = $page_id ;
if ( ! isset ( $this -> mTemplateIds [ $ns ] ) ) {
$this -> mTemplateIds [ $ns ] = array ();
}
$this -> mTemplateIds [ $ns ][ $dbk ] = $rev_id ; // For versioning
2007-01-20 12:50:56 +00:00
}
2011-08-01 15:40:02 +00:00
2010-04-16 01:40:05 +00:00
/**
2010-05-15 20:16:26 +00:00
* @ param $title Title object , must be an interwiki link
2010-04-16 01:40:05 +00:00
* @ throws MWException if given invalid input
*/
function addInterwikiLink ( $title ) {
$prefix = $title -> getInterwiki ();
if ( $prefix == '' ) {
throw new MWException ( 'Non-interwiki link passed, internal parser error.' );
}
if ( ! isset ( $this -> mInterwikiLinks [ $prefix ])) {
$this -> mInterwikiLinks [ $prefix ] = array ();
}
$this -> mInterwikiLinks [ $prefix ][ $title -> getDBkey ()] = 1 ;
}
2007-01-20 12:50:56 +00:00
2007-04-03 21:58:18 +00:00
/**
2012-07-10 12:48:06 +00:00
* Add some text to the " <head> " .
2008-04-14 07:45:50 +00:00
* If $tag is set , the section with that tag will only be included once
2007-04-03 21:58:18 +00:00
* in a given page .
*/
function addHeadItem ( $section , $tag = false ) {
if ( $tag !== false ) {
$this -> mHeadItems [ $tag ] = $section ;
} else {
$this -> mHeadItems [] = $section ;
}
}
2011-08-01 15:40:02 +00:00
2011-08-02 15:40:03 +00:00
public function addModules ( $modules ) {
2010-09-04 04:00:09 +00:00
$this -> mModules = array_merge ( $this -> mModules , ( array ) $modules );
}
2008-04-14 07:45:50 +00:00
2011-08-02 15:40:03 +00:00
public function addModuleScripts ( $modules ) {
$this -> mModuleScripts = array_merge ( $this -> mModuleScripts , ( array ) $modules );
}
public function addModuleStyles ( $modules ) {
$this -> mModuleStyles = array_merge ( $this -> mModuleStyles , ( array ) $modules );
}
public function addModuleMessages ( $modules ) {
$this -> mModuleMessages = array_merge ( $this -> mModuleMessages , ( array ) $modules );
}
/**
* Copy items from the OutputPage object into this one
*
* @ param $out OutputPage object
*/
2011-08-02 16:31:22 +00:00
public function addOutputPageMetadata ( OutputPage $out ) {
2011-08-02 15:40:03 +00:00
$this -> addModules ( $out -> getModules () );
$this -> addModuleScripts ( $out -> getModuleScripts () );
$this -> addModuleStyles ( $out -> getModuleStyles () );
$this -> addModuleMessages ( $out -> getModuleMessages () );
$this -> mHeadItems = array_merge ( $this -> mHeadItems , $out -> getHeadItemsArray () );
}
2007-06-25 15:51:09 +00:00
/**
* Override the title to be used for display
* -- this is assumed to have been validated
* ( check equal normalisation , etc . )
*
2010-05-15 20:16:26 +00:00
* @ param $text String : desired title text
2007-06-25 15:51:09 +00:00
*/
public function setDisplayTitle ( $text ) {
2010-01-15 19:14:23 +00:00
$this -> setTitleText ( $text );
2010-07-10 11:30:11 +00:00
$this -> setProperty ( 'displaytitle' , $text );
2007-06-25 15:51:09 +00:00
}
2008-12-31 16:49:38 +00:00
/**
* Get the title to be used for display
*
2010-05-15 20:16:26 +00:00
* @ return String
2008-12-31 16:49:38 +00:00
*/
public function getDisplayTitle () {
2010-12-28 09:54:25 +00:00
$t = $this -> getTitleText ();
2010-01-15 19:14:23 +00:00
if ( $t === '' ) {
return false ;
}
2010-02-16 03:37:19 +00:00
return $t ;
2007-06-25 15:51:09 +00:00
}
2008-04-14 07:45:50 +00:00
2007-11-15 02:54:28 +00:00
/**
* Fairly generic flag setter thingy .
*/
public function setFlag ( $flag ) {
$this -> mFlags [ $flag ] = true ;
}
2008-04-14 07:45:50 +00:00
2007-11-15 02:54:28 +00:00
public function getFlag ( $flag ) {
return isset ( $this -> mFlags [ $flag ] );
}
2008-02-20 08:53:12 +00:00
/**
* Set a property to be cached in the DB
*/
public function setProperty ( $name , $value ) {
$this -> mProperties [ $name ] = $value ;
}
2008-04-14 07:45:50 +00:00
public function getProperty ( $name ){
2008-02-20 08:53:12 +00:00
return isset ( $this -> mProperties [ $name ] ) ? $this -> mProperties [ $name ] : false ;
}
public function getProperties () {
if ( ! isset ( $this -> mProperties ) ) {
$this -> mProperties = array ();
}
return $this -> mProperties ;
}
2011-08-01 15:40:02 +00:00
2010-12-26 19:21:45 +00:00
/**
2011-08-01 15:40:02 +00:00
* Returns the options from its ParserOptions which have been taken
2010-12-26 19:21:45 +00:00
* into account to produce this output or false if not available .
2011-08-01 15:50:49 +00:00
* @ return mixed Array
2010-12-26 19:21:45 +00:00
*/
public function getUsedOptions () {
if ( ! isset ( $this -> mAccessedOptions ) ) {
2011-08-01 15:50:49 +00:00
return array ();
2010-12-26 19:21:45 +00:00
}
return array_keys ( $this -> mAccessedOptions );
}
2011-08-01 15:40:02 +00:00
2010-12-26 19:21:45 +00:00
/**
* Callback passed by the Parser to the ParserOptions to keep track of which options are used .
* @ access private
*/
function recordOption ( $option ) {
$this -> mAccessedOptions [ $option ] = true ;
}
2012-05-08 15:09:30 +00:00
/**
* Adds an update job to the output . Any update jobs added to the output will eventually bexecuted in order to
* store any secondary information extracted from the page ' s content .
*
2012-08-06 13:56:23 +00:00
* @ since 1.20
*
* @ param DataUpdate $update
2012-05-08 15:09:30 +00:00
*/
public function addSecondaryDataUpdate ( DataUpdate $update ) {
$this -> mSecondaryDataUpdates [] = $update ;
}
/**
* Returns any DataUpdate jobs to be executed in order to store secondary information
* extracted from the page ' s content , including a LinksUpdate object for all links stored in
* this ParserOutput object .
*
2012-08-06 13:56:23 +00:00
* @ since 1.20
*
2012-05-08 15:09:30 +00:00
* @ param $title Title of the page we ' re updating . If not given , a title object will be created based on $this -> getTitleText ()
* @ param $recursive Boolean : queue jobs for recursive updates ?
*
* @ return Array . An array of instances of DataUpdate
*/
public function getSecondaryDataUpdates ( Title $title = null , $recursive = true ) {
2012-08-06 13:56:23 +00:00
if ( is_null ( $title ) ) {
2012-05-08 15:09:30 +00:00
$title = Title :: newFromText ( $this -> getTitleText () );
}
$linksUpdate = new LinksUpdate ( $title , $this , $recursive );
2012-08-06 13:56:23 +00:00
if ( $this -> mSecondaryDataUpdates === array () ) {
2012-05-08 15:09:30 +00:00
return array ( $linksUpdate );
} else {
$updates = array_merge ( $this -> mSecondaryDataUpdates , array ( $linksUpdate ) );
}
return $updates ;
}
2012-08-06 13:56:23 +00:00
2007-01-20 12:50:56 +00:00
}