* @return LinkTarget
*/
public function createFragmentTarget( $fragment );
+
+ /**
+ * Whether this LinkTarget has an interwiki component
+ *
+ * @return bool
+ */
+ public function isExternal();
+
+ /**
+ * The interwiki component of this LinkTarget
+ *
+ * @return string
+ */
+ public function getInterwiki();
}
* @param string $text The page title. Should be valid. Only minimal normalization is applied.
* Underscores will be replaced.
* @param string $fragment The fragment name (may be empty).
+ * @param string $interwiki The interwiki name (may be empty).
*
* @throws InvalidArgumentException If the namespace is invalid
* @return string
*/
- public function formatTitle( $namespace, $text, $fragment = '' ) {
+ public function formatTitle( $namespace, $text, $fragment = '', $interwiki = '' ) {
if ( $namespace !== false ) {
$namespace = $this->getNamespaceName( $namespace, $text );
$text = $text . '#' . $fragment;
}
+ if ( $interwiki !== '' ) {
+ $text = $interwiki . ':' . $text;
+ }
+
$text = str_replace( '_', ' ', $text );
return $text;
// be refactored to avoid this.
$parts = $this->splitTitleString( $text, $defaultNamespace );
- // Interwiki links are not supported by TitleValue
- if ( $parts['interwiki'] !== '' ) {
- throw new MalformedTitleException( 'title-invalid-interwiki', $text );
- }
-
// Relative fragment links are not supported by TitleValue
if ( $parts['dbkey'] === '' ) {
throw new MalformedTitleException( 'title-invalid-empty', $text );
}
- return new TitleValue( $parts['namespace'], $parts['dbkey'], $parts['fragment'] );
+ return new TitleValue(
+ $parts['namespace'],
+ $parts['dbkey'],
+ $parts['fragment'],
+ $parts['interwiki']
+ );
}
/**
* @return string
*/
public function getPrefixedText( LinkTarget $title ) {
- return $this->formatTitle( $title->getNamespace(), $title->getText(), '' );
+ return $this->formatTitle(
+ $title->getNamespace(),
+ $title->getText(),
+ '',
+ $title->getInterwiki()
+ );
}
/**
* @return string
*/
public function getFullText( LinkTarget $title ) {
- return $this->formatTitle( $title->getNamespace(), $title->getText(), $title->getFragment() );
+ return $this->formatTitle(
+ $title->getNamespace(),
+ $title->getText(),
+ $title->getFragment(),
+ $title->getInterwiki()
+ );
}
/**
* @param int|bool $namespace The namespace ID (or false, if the namespace should be ignored)
* @param string $text The page title
* @param string $fragment The fragment name (may be empty).
+ * @param string $interwiki The interwiki prefix (may be empty).
*
* @return string
*/
- public function formatTitle( $namespace, $text, $fragment = '' );
+ public function formatTitle( $namespace, $text, $fragment = '', $interwiki = '' );
/**
* Returns the title text formatted for display, without namespace of fragment.
* @note In contrast to Title, this is designed to be a plain value object. That is,
* it is immutable, does not use global state, and causes no side effects.
*
- * @note TitleValue represents the title of a local page (or fragment of a page).
- * It does not represent a link, and does not support interwiki prefixes etc.
- *
* @see https://www.mediawiki.org/wiki/Requests_for_comment/TitleValue
* @since 1.23
*/
*/
protected $fragment;
+ /**
+ * @var string
+ */
+ protected $interwiki;
+
/**
* Constructs a TitleValue.
*
* @param string $dbkey The page title in valid DBkey form. No normalization is applied.
* @param string $fragment The fragment title. Use '' to represent the whole page.
* No validation or normalization is applied.
+ * @param string $interwiki The interwiki component
*
* @throws InvalidArgumentException
*/
- public function __construct( $namespace, $dbkey, $fragment = '' ) {
+ public function __construct( $namespace, $dbkey, $fragment = '', $interwiki = '' ) {
Assert::parameterType( 'integer', $namespace, '$namespace' );
Assert::parameterType( 'string', $dbkey, '$dbkey' );
Assert::parameterType( 'string', $fragment, '$fragment' );
+ Assert::parameterType( 'string', $interwiki, '$interwiki' );
// Sanity check, no full validation or normalization applied here!
Assert::parameter( !preg_match( '/^_|[ \r\n\t]|_$/', $dbkey ), '$dbkey', 'invalid DB key' );
$this->namespace = $namespace;
$this->dbkey = $dbkey;
$this->fragment = $fragment;
+ $this->interwiki = $interwiki;
}
/**
* @return TitleValue
*/
public function createFragmentTarget( $fragment ) {
- return new TitleValue( $this->namespace, $this->dbkey, $fragment );
+ return new TitleValue(
+ $this->namespace,
+ $this->dbkey,
+ $fragment,
+ $this->interwiki
+ );
+ }
+
+ /**
+ * Whether it has an interwiki part
+ *
+ * @since 1.27
+ * @return bool
+ */
+ public function isExternal() {
+ return $this->interwiki !== '';
+ }
+
+ /**
+ * Returns the interwiki part
+ *
+ * @since 1.27
+ * @return string
+ */
+ public function getInterwiki() {
+ return $this->interwiki;
}
/**
$name .= '#' . $this->fragment;
}
+ if ( $this->interwiki !== '' ) {
+ $name = $this->interwiki . ':' . $name;
+ }
+
return $name;
}
}
public static function provideFormat() {
return [
- [ NS_MAIN, 'Foo_Bar', '', 'en', 'Foo Bar' ],
- [ NS_USER, 'Hansi_Maier', 'stuff_and_so_on', 'en', 'User:Hansi Maier#stuff and so on' ],
- [ false, 'Hansi_Maier', '', 'en', 'Hansi Maier' ],
+ [ NS_MAIN, 'Foo_Bar', '', '', 'en', 'Foo Bar' ],
+ [ NS_USER, 'Hansi_Maier', 'stuff_and_so_on', '', 'en', 'User:Hansi Maier#stuff and so on' ],
+ [ false, 'Hansi_Maier', '', '', 'en', 'Hansi Maier' ],
[
NS_USER_TALK,
'hansi__maier',
'',
+ '',
'en',
'User talk:hansi maier',
'User talk:Hansi maier'
// getGenderCache() provides a mock that considers first
// names ending in "a" to be female.
- [ NS_USER, 'Lisa_Müller', '', 'de', 'Benutzerin:Lisa Müller' ],
+ [ NS_USER, 'Lisa_Müller', '', '', 'de', 'Benutzerin:Lisa Müller' ],
+ [ NS_MAIN, 'FooBar', '', 'remotetestiw', 'en', 'remotetestiw:FooBar' ],
];
}
/**
* @dataProvider provideFormat
*/
- public function testFormat( $namespace, $text, $fragment, $lang, $expected, $normalized = null ) {
+ public function testFormat( $namespace, $text, $fragment, $interwiki, $lang, $expected,
+ $normalized = null
+ ) {
if ( $normalized === null ) {
$normalized = $expected;
}
$codec = $this->makeCodec( $lang );
- $actual = $codec->formatTitle( $namespace, $text, $fragment );
+ $actual = $codec->formatTitle( $namespace, $text, $fragment, $interwiki );
$this->assertEquals( $expected, $actual, 'formatted' );
$actual2 = $codec->formatTitle(
$parsed->getNamespace(),
$parsed->getText(),
- $parsed->getFragment()
+ $parsed->getFragment(),
+ $parsed->getInterwiki()
);
$this->assertEquals( $normalized, $actual2, 'normalized after round trip' );
[ 'Talk:File:Foo.jpg' ],
[ 'Talk:localtestiw:Foo' ],
- [ 'remotetestiw:Foo' ],
[ '::1' ], // only valid in user namespace
[ 'User::x' ], // leading ":" in a user name is only valid of IPv6 addresses
public function goodConstructorProvider() {
return [
- [ NS_USER, 'TestThis', 'stuff', true ],
- [ NS_USER, 'TestThis', '', false ],
+ [ NS_USER, 'TestThis', 'stuff', '', true, false ],
+ [ NS_USER, 'TestThis', '', 'baz', false, true ],
];
}
/**
* @dataProvider goodConstructorProvider
*/
- public function testConstruction( $ns, $text, $fragment, $hasFragment ) {
- $title = new TitleValue( $ns, $text, $fragment );
+ public function testConstruction( $ns, $text, $fragment, $interwiki, $hasFragment,
+ $hasInterwiki
+ ) {
+ $title = new TitleValue( $ns, $text, $fragment, $interwiki );
$this->assertEquals( $ns, $title->getNamespace() );
$this->assertEquals( $text, $title->getText() );
$this->assertEquals( $fragment, $title->getFragment() );
$this->assertEquals( $hasFragment, $title->hasFragment() );
+ $this->assertEquals( $interwiki, $title->getInterwiki() );
+ $this->assertEquals( $hasInterwiki, $title->isExternal() );
}
public function badConstructorProvider() {
return [
- [ 'foo', 'title', 'fragment' ],
- [ null, 'title', 'fragment' ],
- [ 2.3, 'title', 'fragment' ],
+ [ 'foo', 'title', 'fragment', '' ],
+ [ null, 'title', 'fragment', '' ],
+ [ 2.3, 'title', 'fragment', '' ],
- [ NS_MAIN, 5, 'fragment' ],
- [ NS_MAIN, null, 'fragment' ],
- [ NS_MAIN, '', 'fragment' ],
- [ NS_MAIN, 'foo bar', '' ],
- [ NS_MAIN, 'bar_', '' ],
- [ NS_MAIN, '_foo', '' ],
- [ NS_MAIN, ' eek ', '' ],
+ [ NS_MAIN, 5, 'fragment', '' ],
+ [ NS_MAIN, null, 'fragment', '' ],
+ [ NS_MAIN, '', 'fragment', '' ],
+ [ NS_MAIN, 'foo bar', '', '' ],
+ [ NS_MAIN, 'bar_', '', '' ],
+ [ NS_MAIN, '_foo', '', '' ],
+ [ NS_MAIN, ' eek ', '', '' ],
- [ NS_MAIN, 'title', 5 ],
- [ NS_MAIN, 'title', null ],
- [ NS_MAIN, 'title', [] ],
+ [ NS_MAIN, 'title', 5, '' ],
+ [ NS_MAIN, 'title', null, '' ],
+ [ NS_MAIN, 'title', [], '' ],
+
+ [ NS_MAIN, 'title', '', 5 ],
+ [ NS_MAIN, 'title', null, 5 ],
+ [ NS_MAIN, 'title', [], 5 ],
];
}
/**
* @dataProvider badConstructorProvider
*/
- public function testConstructionErrors( $ns, $text, $fragment ) {
+ public function testConstructionErrors( $ns, $text, $fragment, $interwiki ) {
$this->setExpectedException( 'InvalidArgumentException' );
- new TitleValue( $ns, $text, $fragment );
+ new TitleValue( $ns, $text, $fragment, $interwiki );
}
public function fragmentTitleProvider() {