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;
|
||||
case 'gallery-internal-link':
|
||||
$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 ) ) {
|
||||
// Result of LanguageConverter::markNoConversion
|
||||
// invoked on an external link.
|
||||
$linkValue = substr( $linkValue, 4, -2 );
|
||||
}
|
||||
if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
|
||||
$link = $linkValue;
|
||||
$this->mOutput->addExternalLink( $link );
|
||||
} else {
|
||||
$localLinkTitle = Title::newFromText( $linkValue );
|
||||
if ( $localLinkTitle !== null ) {
|
||||
$this->mOutput->addLink( $localLinkTitle );
|
||||
$link = $localLinkTitle->getLinkURL();
|
||||
}
|
||||
list( $type, $target ) = $this->parseLinkParameter( $linkValue );
|
||||
if ( $type === 'link-url' ) {
|
||||
$link = $target;
|
||||
$this->mOutput->addExternalLink( $target );
|
||||
} elseif ( $type === 'link-title' ) {
|
||||
$link = $target->getLinkURL();
|
||||
$this->mOutput->addLink( $target );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -5342,29 +5336,16 @@ class Parser {
|
|||
$value = $this->stripAltText( $value, $holders );
|
||||
break;
|
||||
case 'link':
|
||||
$chars = self::EXT_LINK_URL_CLASS;
|
||||
$addr = self::EXT_LINK_ADDR;
|
||||
$prots = $this->mUrlProtocols;
|
||||
if ( $value === '' ) {
|
||||
$paramName = 'no-link';
|
||||
$value = true;
|
||||
list( $paramName, $value ) = $this->parseLinkParameter( $value );
|
||||
if ( $paramName ) {
|
||||
$validated = true;
|
||||
} elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
|
||||
if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
|
||||
$paramName = 'link-url';
|
||||
$this->mOutput->addExternalLink( $value );
|
||||
if ( $paramName === 'no-link' ) {
|
||||
$value = true;
|
||||
}
|
||||
if ( $paramName === 'link-url' ) {
|
||||
if ( $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;
|
||||
|
|
@ -5459,6 +5440,48 @@ class Parser {
|
|||
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 LinkHolderArray|bool $holders
|
||||
|
|
|
|||
|
|
@ -215,4 +215,80 @@ class ExtraParserTest extends MediaWikiTestCase {
|
|||
$result = $parserOutput->getCategoryLinks();
|
||||
$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