From 6067e1ea8b0c5b025df33715201e0d8c145c1eb4 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 9 Jan 2008 07:13:54 +0000 Subject: [PATCH] Added {{#tag:}}: generic adaptor from parser function syntax to XML-style extension tag. Allows any extension tag (including nowiki and pre) to be called with input given by a template expansion. Inspired by [[Extension:TagParser]]. --- includes/CoreParserFunctions.php | 51 +++++++++++++++++++++++++++++++ includes/Parser.php | 19 +++++++----- languages/messages/MessagesEn.php | 4 +++ 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/includes/CoreParserFunctions.php b/includes/CoreParserFunctions.php index 4f7b840f94..3f455f6ee7 100644 --- a/includes/CoreParserFunctions.php +++ b/includes/CoreParserFunctions.php @@ -211,5 +211,56 @@ class CoreParserFunctions { return ''; } } + + /** + * Parser function to extension tag adaptor + */ + public static function tagObj( $parser, $frame, $args ) { + $xpath = false; + if ( !count( $args ) ) { + return ''; + } + $tagName = strtolower( trim( $frame->expand( array_shift( $args ) ) ) ); + $stripList = $parser->getStripList(); + if ( !in_array( $tagName, $stripList ) ) { + return '' . + wfMsg( 'unknown_extension_tag', $tagName ) . + ''; + } + + $lastNumberedNode = false; + $attributes = array(); + foreach ( $args as $arg ) { + if ( !$xpath ) { + $xpath = new DOMXPath( $arg->ownerDocument ); + } + $names = $xpath->query( 'name', $arg ); + if ( $names->item( 0 )->hasAttributes() ) { + $lastNumberedNode = $arg; + } else { + $name = $frame->expand( $names->item( 0 ), PPFrame::STRIP_COMMENTS ); + if ( preg_match( '/^\d+$/', $name ) ) { + // For = suppression syntax {{#tag|thing|1=2=3=4}} + $lastNumberedNode = $arg; + } else { + $values = $xpath->query( 'value', $arg ); + $attributes[$name] = trim( $frame->expand( $values->item( 0 ) ) ); + } + } + } + + if ( !$lastNumberedNode ) { + $inner = null; + } else { + $values = $xpath->query( 'value', $lastNumberedNode ); + $inner = $frame->expand( $values->item( 0 ) ); + } + $params = array( + 'name' => $tagName, + 'inner' => $inner, + 'attributes' => $attributes + ); + return $parser->extensionSubstitution( $params, $frame ); + } } diff --git a/includes/Parser.php b/includes/Parser.php index ea02a6e619..0e220cd538 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -166,6 +166,7 @@ class Parser $this->setFunctionHook( 'special', array( 'CoreParserFunctions', 'special' ) ); $this->setFunctionHook( 'defaultsort', array( 'CoreParserFunctions', 'defaultsort' ), SFH_NO_HASH ); $this->setFunctionHook( 'filepath', array( 'CoreParserFunctions', 'filepath' ), SFH_NO_HASH ); + $this->setFunctionHook( 'tag', array( 'CoreParserFunctions', 'tagObj' ), SFH_OBJECT_ARGS ); if ( $wgAllowDisplayTitle ) { $this->setFunctionHook( 'displaytitle', array( 'CoreParserFunctions', 'displaytitle' ), SFH_NO_HASH ); @@ -3661,7 +3662,8 @@ class Parser * * @param array $params Associative array of parameters: * name DOMNode for the tag name - * attrText DOMNode for unparsed text where tag attributes are thought to be + * attr DOMNode for unparsed text where tag attributes are thought to be + * attributes Optional associative array of parsed attributes * inner Contents of extension element * noClose Original text did not have a close tag * @param PPFrame $frame @@ -3671,15 +3673,18 @@ class Parser static $n = 1; $name = $frame->expand( $params['name'] ); - $attrText = is_null( $params['attr'] ) ? null : $frame->expand( $params['attr'] ); - $content = is_null( $params['inner'] ) ? null : $frame->expand( $params['inner'] ); + $attrText = !isset( $params['attr'] ) ? null : $frame->expand( $params['attr'] ); + $content = !isset( $params['inner'] ) ? null : $frame->expand( $params['inner'] ); $marker = "{$this->mUniqPrefix}-$name-" . sprintf('%08X', $n++) . $this->mMarkerSuffix; if ( $this->ot['html'] ) { $name = strtolower( $name ); - $params = Sanitizer::decodeTagAttributes( $attrText ); + $attributes = Sanitizer::decodeTagAttributes( $attrText ); + if ( isset( $params['attributes'] ) ) { + $attributes = $attributes + $params['attributes']; + } switch ( $name ) { case 'html': if( $wgRawHtml ) { @@ -3693,15 +3698,15 @@ class Parser break; case 'math': $output = $wgContLang->armourMath( - MathRenderer::renderMath( $content, $params ) ); + MathRenderer::renderMath( $content, $attributes ) ); break; case 'gallery': - $output = $this->renderImageGallery( $content, $params ); + $output = $this->renderImageGallery( $content, $attributes ); break; default: if( isset( $this->mTagHooks[$name] ) ) { $output = call_user_func_array( $this->mTagHooks[$name], - array( $content, $params, $this ) ); + array( $content, $attributes, $this ) ); } else { throw new MWException( "Invalid call hook $name" ); } diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 1e311fce2b..ec6737baa2 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -335,6 +335,7 @@ $magicWords = array( 'special' => array( 0, 'special', ), 'defaultsort' => array( 1, 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ), 'filepath' => array( 0, 'FILEPATH:' ), + 'tag' => array( 0, 'tag' ), ); /** @@ -3115,4 +3116,7 @@ $1', 'signature' => '[[{{ns:user}}:$1|$2]]', # don't translate or duplicate this message to other languages 'signature-anon' => '[[{{#special:Contributions}}/$1|$2]]', # don't translate or duplicate this message to other languages +# CoreParserFunctions +'unknown_extension_tag' => 'Unknown extension tag "$1"', + ); -- 2.20.1