r86304 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86303‎ | r86304 | r86305 >
Date:12:43, 18 April 2011
Author:reedy
Status:resolved (Comments)
Tags:
Comment:
* (bug 28532) wfMsgExt() and wfMsgWikiHtml() use $wgOut->parse()
* (bug 16129) Transcluded special pages expose strip markers when they output parsed messages

Also adding some related documentation during my travels around the code
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/GlobalFunctions.php (modified) (history)
  • /trunk/phase3/includes/Message.php (modified) (history)
  • /trunk/phase3/includes/MessageCache.php (modified) (history)
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/includes/parser/Parser.php (modified) (history)

Diff [purge]

Index: trunk/phase3/RELEASE-NOTES
@@ -238,6 +238,8 @@
239239 * UtfNormal::cleanUp on an invalid utf-8 sequence no longer returns false if intl installed.
240240 * (bug 28561) The css class small will no longer make nested elements even smaller.
241241 * (bug 13172) Array type exif data (like GPS) was not being extracted from images.
 242+* (bug 28532) wfMsgExt() and wfMsgWikiHtml() use $wgOut->parse()
 243+* (bug 16129) Transcluded special pages expose strip markers when they output parsed messages
242244
243245 === API changes in 1.18 ===
244246 * (bug 26339) Throw warning when truncating an overlarge API result
Index: trunk/phase3/includes/MessageCache.php
@@ -68,6 +68,11 @@
6969 private static $instance;
7070
7171 /**
 72+ * @var bool
 73+ */
 74+ protected $mInParser = false;
 75+
 76+ /**
7277 * Get the signleton instance of this class
7378 *
7479 * @since 1.18
@@ -102,6 +107,8 @@
103108
104109 /**
105110 * ParserOptions is lazy initialised.
 111+ *
 112+ * @return ParserOptions
106113 */
107114 function getParserOptions() {
108115 if ( !$this->mParserOptions ) {
@@ -220,6 +227,8 @@
221228
222229 /**
223230 * Set the cache to $cache, if it is valid. Otherwise set the cache to false.
 231+ *
 232+ * @return bool
224233 */
225234 function setCache( $cache, $code ) {
226235 if ( isset( $cache['VERSION'] ) && $cache['VERSION'] == MSG_CACHE_VERSION ) {
@@ -728,12 +737,41 @@
729738 return $message;
730739 }
731740
 741+ /**
 742+ * @param $message string
 743+ * @param $interface bool
 744+ * @param $language
 745+ * @param $title Title
 746+ * @return string
 747+ */
732748 function transform( $message, $interface = false, $language = null, $title = null ) {
733749 // Avoid creating parser if nothing to transform
734750 if( strpos( $message, '{{' ) === false ) {
735751 return $message;
736752 }
737753
 754+ if ( $this->mInParser ) {
 755+ return $message;
 756+ }
 757+
 758+ $parser = $this->getParser();
 759+ if ( $parser ) {
 760+ $popts = $this->getParserOptions();
 761+ $popts->setInterfaceMessage( $interface );
 762+ $popts->setTargetLanguage( $language );
 763+ $popts->setUserLang( $language );
 764+
 765+ $this->mInParser = true;
 766+ $message = $parser->transformMsg( $message, $popts, $title );
 767+ $this->mInParser = false;
 768+ }
 769+ return $message;
 770+ }
 771+
 772+ /**
 773+ * @return Parser
 774+ */
 775+ function getParser() {
738776 global $wgParser, $wgParserConf;
739777 if ( !$this->mParser && isset( $wgParser ) ) {
740778 # Do some initialisation so that we don't have to do it twice
@@ -746,16 +784,38 @@
747785 } else {
748786 $this->mParser = clone $wgParser;
749787 }
750 - #wfDebug( __METHOD__ . ": following contents triggered transform: $message\n" );
751788 }
752 - if ( $this->mParser ) {
753 - $popts = $this->getParserOptions();
754 - $popts->setInterfaceMessage( $interface );
 789+ return $this->mParser;
 790+ }
 791+
 792+ /**
 793+ * @param $text string
 794+ * @param $title Title
 795+ * @param $interface bool
 796+ * @param $linestart bool
 797+ * @param $language
 798+ * @return ParserOutput
 799+ */
 800+ public function parse( $text, $title = null, $linestart = true, $interface = false, $language = null ) {
 801+ if ( $this->mInParser ) {
 802+ return htmlspecialchars( $text );
 803+ }
 804+
 805+ $parser = $this->getParser();
 806+ $popts = $this->getParserOptions();
 807+
 808+ if ( $interface ) {
 809+ $popts->setInterfaceMessage( true );
 810+ }
 811+ if ( $language !== null ) {
755812 $popts->setTargetLanguage( $language );
756 - $popts->setUserLang( $language );
757 - $message = $this->mParser->transformMsg( $message, $popts, $title );
758813 }
759 - return $message;
 814+
 815+ $this->mInParser = true;
 816+ $res = $parser->parse( $text, $title, $popts, $linestart );
 817+ $this->mInParser = false;
 818+
 819+ return $res;
760820 }
761821
762822 function disable() {
Index: trunk/phase3/includes/Message.php
@@ -65,6 +65,8 @@
6666 /**
6767 * In which language to get this message. Overrides the $interface
6868 * variable.
 69+ *
 70+ * @var Language
6971 */
7072 protected $language = null;
7173
@@ -370,10 +372,18 @@
371373 return $message === false || $message === '' || $message === '-';
372374 }
373375
 376+ /**
 377+ * @param $value
 378+ * @return array
 379+ */
374380 public static function rawParam( $value ) {
375381 return array( 'raw' => $value );
376382 }
377 -
 383+
 384+ /**
 385+ * @param $value
 386+ * @return array
 387+ */
378388 public static function numParam( $value ) {
379389 return array( 'num' => $value );
380390 }
@@ -419,17 +429,16 @@
420430 /**
421431 * Wrapper for what ever method we use to parse wikitext.
422432 * @param $string String: Wikitext message contents
423 - * @return Wikitext parsed into HTML
 433+ * @return string Wikitext parsed into HTML
424434 */
425435 protected function parseText( $string ) {
426 - global $wgOut;
427 - return $wgOut->parse( $string, /*linestart*/true, $this->interface, $this->language );
 436+ return MessageCache::singleton()->parse( $string, /*linestart*/true, $this->interface, $this->language );
428437 }
429438
430439 /**
431440 * Wrapper for what ever method we use to {{-transform wikitext.
432441 * @param $string String: Wikitext message contents
433 - * @return Wikitext with {{-constructs replaced with their values.
 442+ * @return string Wikitext with {{-constructs replaced with their values.
434443 */
435444 protected function transformText( $string ) {
436445 return MessageCache::singleton()->transform( $string, $this->interface, $this->language, $this->title );
@@ -450,6 +459,8 @@
451460
452461 /**
453462 * Wrapper for what ever method we use to get message contents
 463+ *
 464+ * @return string
454465 */
455466 protected function fetchMessage() {
456467 if ( !isset( $this->message ) ) {
Index: trunk/phase3/includes/parser/Parser.php
@@ -278,7 +278,7 @@
279279 * Do not call this function recursively.
280280 *
281281 * @param $text String: text we want to parse
282 - * @param $title A title object
 282+ * @param $title Title object
283283 * @param $options ParserOptions
284284 * @param $linestart boolean
285285 * @param $clearState boolean
Index: trunk/phase3/includes/OutputPage.php
@@ -792,7 +792,7 @@
793793 * @param $t Title object
794794 */
795795 public function setTitle( $t ) {
796 - $this->getContext()->setTitle($t);
 796+ $this->getContext()->setTitle( $t );
797797 }
798798
799799 /**
Index: trunk/phase3/includes/GlobalFunctions.php
@@ -716,10 +716,12 @@
717717 * @return string
718718 */
719719 function wfMsgWikiHtml( $key ) {
720 - global $wgOut;
 720+ global $wgMessageCache;
721721 $args = func_get_args();
722722 array_shift( $args );
723 - return wfMsgReplaceArgs( $wgOut->parse( wfMsgGetKey( $key, true ), /* can't be set to false */ true ), $args );
 723+ return wfMsgReplaceArgs(
 724+ $wgMessageCache->parse( wfMsgGetKey( $key, true ), null, /* can't be set to false */ true ),
 725+ $args );
724726 }
725727
726728 /**
@@ -741,7 +743,7 @@
742744 * Behavior for conflicting options (e.g., parse+parseinline) is undefined.
743745 */
744746 function wfMsgExt( $key, $options ) {
745 - global $wgOut;
 747+ global $wgMessageCache;
746748
747749 $args = func_get_args();
748750 array_shift( $args );
@@ -781,9 +783,9 @@
782784 }
783785
784786 if( in_array( 'parse', $options, true ) ) {
785 - $string = $wgOut->parse( $string, true, !$forContent, $langCodeObj );
 787+ $string = $wgMessageCache->parse( $string, null, true, !$forContent, $langCodeObj );
786788 } elseif ( in_array( 'parseinline', $options, true ) ) {
787 - $string = $wgOut->parse( $string, true, !$forContent, $langCodeObj );
 789+ $string = $wgMessageCache->parse( $string, null, true, !$forContent, $langCodeObj );
788790 $m = array();
789791 if( preg_match( '/^<p>(.*)\n?<\/p>\n?$/sU', $string, $m ) ) {
790792 $string = $m[1];

Follow-up revisions

RevisionCommit summaryAuthorDate
r86306Replace $wgMessageCache with MessageCache::singleton()...reedy12:59, 18 April 2011
r86311Followup r86304...reedy13:53, 18 April 2011
r86312Followup rr86304...reedy14:02, 18 April 2011
r86735Followup to r86312...reedy20:17, 22 April 2011
r97050Followup r86304, guard against $title AND $wgTitle being null...reedy12:32, 14 September 2011
r112872Fix for r86304: if MessageCache::parse() is called twice, once with $interfac...tstarling04:00, 2 March 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r44858API: Fixing issue mentioned on bug 16129 comment #3: for certain inputs, acti...catrope20:00, 20 December 2008

Comments

#Comment by MarkAHershberger (talk | contribs)   01:54, 20 May 2011

This bit is causing a test failure.

+			$this->mInParser = true;
+			$message = $parser->transformMsg( $message, $popts, $title );
+			$this->mInParser = false;

Test failure shows up here: http://ci.tesla.usability.wikimedia.org/cruisecontrol/buildresults/mw?log=log20110520005929&tab=testResults

#Comment by Reedy (talk | contribs)   13:18, 30 May 2011

Marking new again. Seems fine on ci now?

#Comment by Tim Starling (talk | contribs)   11:05, 14 September 2011

MessageCache::parse() is not tolerant of $wgTitle being null, which was one of the main complaints in bug 28532. Compare with Parser::transformMsg():

		if ( !$title ) {
			global $wgTitle;
			$title = $wgTitle;
		}
		if ( !$title ) {
			# It's not uncommon having a null $wgTitle in scripts. See [[Special:Code/MediaWiki/80898|r80898]]
			# Create a ghost title in such case
			$title = Title::newFromText( 'Dwimmerlaik' );
		}

We need something like this in MessageCache::parse().

#Comment by Tim Starling (talk | contribs)   03:44, 2 March 2012

You called ParserOptions::setInterfaceMessage() conditionally on the cached object without cloning it, so $interface=true leaks from one call to the next. I'm fixing it.

Status & tagging log