Parser: Refactor parsing of [[File:...|link=...]] syntax for reusability
Change-Id: I91467297de4b7c532448a4c20b9a0dc8216c7200
This commit is contained in:
parent
66351c7f1b
commit
1c9664d18a
2 changed files with 131 additions and 32 deletions
|
|
@ -5143,24 +5143,18 @@ class Parser {
|
||||||
break;
|
break;
|
||||||
case 'gallery-internal-link':
|
case 'gallery-internal-link':
|
||||||
$linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
|
$linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
|
||||||
$chars = self::EXT_LINK_URL_CLASS;
|
|
||||||
$addr = self::EXT_LINK_ADDR;
|
|
||||||
$prots = $this->mUrlProtocols;
|
|
||||||
// check to see if link matches an absolute url, if not then it must be a wiki link.
|
|
||||||
if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
|
if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
|
||||||
// Result of LanguageConverter::markNoConversion
|
// Result of LanguageConverter::markNoConversion
|
||||||
// invoked on an external link.
|
// invoked on an external link.
|
||||||
$linkValue = substr( $linkValue, 4, -2 );
|
$linkValue = substr( $linkValue, 4, -2 );
|
||||||
}
|
}
|
||||||
if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
|
list( $type, $target ) = $this->parseLinkParameter( $linkValue );
|
||||||
$link = $linkValue;
|
if ( $type === 'link-url' ) {
|
||||||
$this->mOutput->addExternalLink( $link );
|
$link = $target;
|
||||||
} else {
|
$this->mOutput->addExternalLink( $target );
|
||||||
$localLinkTitle = Title::newFromText( $linkValue );
|
} elseif ( $type === 'link-title' ) {
|
||||||
if ( $localLinkTitle !== null ) {
|
$link = $target->getLinkURL();
|
||||||
$this->mOutput->addLink( $localLinkTitle );
|
$this->mOutput->addLink( $target );
|
||||||
$link = $localLinkTitle->getLinkURL();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -5342,29 +5336,16 @@ class Parser {
|
||||||
$value = $this->stripAltText( $value, $holders );
|
$value = $this->stripAltText( $value, $holders );
|
||||||
break;
|
break;
|
||||||
case 'link':
|
case 'link':
|
||||||
$chars = self::EXT_LINK_URL_CLASS;
|
list( $paramName, $value ) = $this->parseLinkParameter( $value );
|
||||||
$addr = self::EXT_LINK_ADDR;
|
if ( $paramName ) {
|
||||||
$prots = $this->mUrlProtocols;
|
|
||||||
if ( $value === '' ) {
|
|
||||||
$paramName = 'no-link';
|
|
||||||
$value = true;
|
|
||||||
$validated = true;
|
$validated = true;
|
||||||
} elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
|
if ( $paramName === 'no-link' ) {
|
||||||
if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
|
$value = true;
|
||||||
$paramName = 'link-url';
|
}
|
||||||
$this->mOutput->addExternalLink( $value );
|
if ( $paramName === 'link-url' ) {
|
||||||
if ( $this->mOptions->getExternalLinkTarget() ) {
|
if ( $this->mOptions->getExternalLinkTarget() ) {
|
||||||
$params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
|
$params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
|
||||||
}
|
}
|
||||||
$validated = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$linkTitle = Title::newFromText( $value );
|
|
||||||
if ( $linkTitle ) {
|
|
||||||
$paramName = 'link-title';
|
|
||||||
$value = $linkTitle;
|
|
||||||
$this->mOutput->addLink( $linkTitle );
|
|
||||||
$validated = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -5459,6 +5440,48 @@ class Parser {
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the value of 'link' parameter in image syntax (`[[File:Foo.jpg|link=<value>]]`).
|
||||||
|
*
|
||||||
|
* Adds an entry to appropriate link tables.
|
||||||
|
*
|
||||||
|
* @since 1.32
|
||||||
|
* @return array of `[ type, target ]`, where:
|
||||||
|
* - `type` is one of:
|
||||||
|
* - `null`: Given value is not a valid link target, use default
|
||||||
|
* - `'no-link'`: Given value is empty, do not generate a link
|
||||||
|
* - `'link-url'`: Given value is a valid external link
|
||||||
|
* - `'link-title'`: Given value is a valid internal link
|
||||||
|
* - `target` is:
|
||||||
|
* - When `type` is `null` or `'no-link'`: `false`
|
||||||
|
* - When `type` is `'link-url'`: URL string corresponding to given value
|
||||||
|
* - When `type` is `'link-title'`: Title object corresponding to given value
|
||||||
|
*/
|
||||||
|
public function parseLinkParameter( $value ) {
|
||||||
|
$chars = self::EXT_LINK_URL_CLASS;
|
||||||
|
$addr = self::EXT_LINK_ADDR;
|
||||||
|
$prots = $this->mUrlProtocols;
|
||||||
|
$type = null;
|
||||||
|
$target = false;
|
||||||
|
if ( $value === '' ) {
|
||||||
|
$type = 'no-link';
|
||||||
|
} elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
|
||||||
|
if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
|
||||||
|
$this->mOutput->addExternalLink( $value );
|
||||||
|
$type = 'link-url';
|
||||||
|
$target = $value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$linkTitle = Title::newFromText( $value );
|
||||||
|
if ( $linkTitle ) {
|
||||||
|
$this->mOutput->addLink( $linkTitle );
|
||||||
|
$type = 'link-title';
|
||||||
|
$target = $linkTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [ $type, $target ];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $caption
|
* @param string $caption
|
||||||
* @param LinkHolderArray|bool $holders
|
* @param LinkHolderArray|bool $holders
|
||||||
|
|
|
||||||
|
|
@ -215,4 +215,80 @@ class ExtraParserTest extends MediaWikiTestCase {
|
||||||
$result = $parserOutput->getCategoryLinks();
|
$result = $parserOutput->getCategoryLinks();
|
||||||
$this->assertEmpty( $result );
|
$this->assertEmpty( $result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers Parser::parseLinkParameter
|
||||||
|
* @dataProvider provideParseLinkParameter
|
||||||
|
*/
|
||||||
|
public function testParseLinkParameter( $input, $expected, $expectedLinks, $desc ) {
|
||||||
|
$this->parser->startExternalParse( Title::newFromText( __FUNCTION__ ),
|
||||||
|
$this->options, Parser::OT_HTML );
|
||||||
|
$output = $this->parser->parseLinkParameter( $input );
|
||||||
|
|
||||||
|
$this->assertEquals( $expected[0], $output[0], "$desc (type)" );
|
||||||
|
|
||||||
|
if ( $expected[0] === 'link-title' ) {
|
||||||
|
$this->assertTrue( $expected[1]->equals( $output[1] ), "$desc (target)" );
|
||||||
|
} else {
|
||||||
|
$this->assertEquals( $expected[1], $output[1], "$desc (target)" );
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $expectedLinks as $func => $expected ) {
|
||||||
|
$output = $this->parser->getOutput()->$func();
|
||||||
|
$this->assertEquals( $expected, $output, "$desc ($func)" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideParseLinkParameter() {
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
'',
|
||||||
|
[ 'no-link', false ],
|
||||||
|
[],
|
||||||
|
'Return no link when requested',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'https://example.com/',
|
||||||
|
[ 'link-url', 'https://example.com/' ],
|
||||||
|
[ 'getExternalLinks' => [ 'https://example.com/' => 1 ] ],
|
||||||
|
'External link',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'//example.com/',
|
||||||
|
[ 'link-url', '//example.com/' ],
|
||||||
|
[ 'getExternalLinks' => [ '//example.com/' => 1 ] ],
|
||||||
|
'External link',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Test',
|
||||||
|
[ 'link-title', Title::newFromText( 'Test' ) ],
|
||||||
|
[ 'getLinks' => [ 0 => [ 'Test' => 0 ] ] ],
|
||||||
|
'Internal link',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'mw:Test',
|
||||||
|
[ 'link-title', Title::newFromText( 'mw:Test' ) ],
|
||||||
|
[ 'getInterwikiLinks' => [ 'mw' => [ 'Test' => 1 ] ] ],
|
||||||
|
'Internal link (interwiki)',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'https://',
|
||||||
|
[ null, false ],
|
||||||
|
[],
|
||||||
|
'Invalid link target',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'<>',
|
||||||
|
[ null, false ],
|
||||||
|
[],
|
||||||
|
'Invalid link target',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
' ',
|
||||||
|
[ null, false ],
|
||||||
|
[],
|
||||||
|
'Invalid link target',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue