mirror of
				https://github.com/diocloid/LinkTitles.git
				synced 2025-10-22 05:42:32 +02:00 
			
		
		
		
	Prefix links with namespace if needed.
- Fix: Links to other namespaces were not prefixed properly.
This commit is contained in:
		@@ -35,15 +35,16 @@ class Linker {
 | 
			
		||||
	public $config;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The string representation of the title object for the potential target page
 | 
			
		||||
	 * that is currently being processed.
 | 
			
		||||
	 * The link value of the target page that is currently being evaluated.
 | 
			
		||||
	 * This may be either the page name or the page name prefixed with the
 | 
			
		||||
	 * name space if the target's name space is not NS_MAIN.
 | 
			
		||||
	 *
 | 
			
		||||
	 * This is an instance variable (rather than a local method variable) so it
 | 
			
		||||
	 * can be accessed in the preg_replace_callback callbacks.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @var String $targetTitleString
 | 
			
		||||
	 * @var String $linkValue
 | 
			
		||||
	 */
 | 
			
		||||
	private $targetTitleText;
 | 
			
		||||
	private $linkValue;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Constructs a new instance of the Linker class.
 | 
			
		||||
@@ -101,7 +102,7 @@ class Linker {
 | 
			
		||||
			$count = 0;
 | 
			
		||||
 | 
			
		||||
			// Cache the target title text for the regex callbacks
 | 
			
		||||
			$this->targetTitleText = $target->getTitleText();
 | 
			
		||||
			$this->linkValue = $target->getPrefixedTitleText();
 | 
			
		||||
 | 
			
		||||
			// Even indexes will point to sections of the text that may be linked
 | 
			
		||||
			for ( $i = 0; $i < count( $arr ); $i += 2 ) {
 | 
			
		||||
@@ -147,7 +148,13 @@ class Linker {
 | 
			
		||||
	 * @return string Target page title with or without link markup
 | 
			
		||||
	 */
 | 
			
		||||
	private function simpleModeCallback( array $matches ) {
 | 
			
		||||
		return '[[' . $matches[0] . ']]';
 | 
			
		||||
		// If the link value is longer than the match, it must be prefixed with
 | 
			
		||||
		// a namespace. In this case, we build a piped link.
 | 
			
		||||
		if ( strlen( $this->linkValue ) > strlen( $matches[0] ) ) {
 | 
			
		||||
			return '[[' . $this->linkValue . '|' . $matches[0] . ']]';
 | 
			
		||||
		} else {
 | 
			
		||||
			return '[[' . $matches[0] . ']]';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -163,28 +170,20 @@ class Linker {
 | 
			
		||||
	 * @return string Target page title with or without link markup
 | 
			
		||||
	 */
 | 
			
		||||
	private function smartModeCallback( array $matches ) {
 | 
			
		||||
		// If cases of the target page title and the actual occurrence in the text
 | 
			
		||||
		// are not identical, we need to build a piped link.
 | 
			
		||||
		// How case-identity is determined depends on the $wgCapitalLinks setting:
 | 
			
		||||
		// with $wgCapitalLinks = true, the case of first letter of the title is
 | 
			
		||||
		// not significant.
 | 
			
		||||
		if ( $this->config->capitalLinks ) {
 | 
			
		||||
			// With $wgCapitalLinks set to true we have a slightly more
 | 
			
		||||
			// complicated version of the callback than if it were false;
 | 
			
		||||
			// we need to ignore the first letter of the page titles, as
 | 
			
		||||
			// it does not matter for linking.
 | 
			
		||||
			if ( strcmp( substr( $this->targetTitleText, 1 ), substr( $matches[ 0 ], 1) ) == 0 ) {
 | 
			
		||||
				// Case-sensitive match: no need to build piped link.
 | 
			
		||||
				return '[[' . $matches[ 0 ]  . ']]';
 | 
			
		||||
			} else  {
 | 
			
		||||
				// Case-insensitive match: build piped link.
 | 
			
		||||
				return '[[' . $this->targetTitleText . '|' . $matches[ 0 ] . ']]';
 | 
			
		||||
			}
 | 
			
		||||
			$needPipe = strcmp( substr( $this->linkValue, 1 ), substr( $matches[ 0 ], 1 ) ) != 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			// If $wgCapitalLinks is false, we can use the simple variant
 | 
			
		||||
			// of the callback function.
 | 
			
		||||
			if ( strcmp( $this->targetTitleText, $matches[ 0 ] ) == 0 ) {
 | 
			
		||||
				// Case-sensitive match: no need to build piped link.
 | 
			
		||||
				return '[[' . $matches[ 0 ] . ']]';
 | 
			
		||||
			} else  {
 | 
			
		||||
				// Case-insensitive match: build piped link.
 | 
			
		||||
				return '[[' . $this->targetTitleText . '|' . $matches[ 0 ] . ']]';
 | 
			
		||||
			}
 | 
			
		||||
			$needPipe = strcmp( $this->linkValue, $matches[ 0 ] ) != 0;
 | 
			
		||||
		}
 | 
			
		||||
		if ( $needPipe ) {
 | 
			
		||||
			return '[[' . $this->linkValue . '|' . $matches[ 0 ] . ']]';
 | 
			
		||||
		} else  {
 | 
			
		||||
			return '[[' . $matches[ 0 ]  . ']]';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,8 @@ class Target {
 | 
			
		||||
 | 
			
		||||
	private $caseSensitiveLinkValueRegex;
 | 
			
		||||
 | 
			
		||||
	private $nsText;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Constructs a new Target object
 | 
			
		||||
	 *
 | 
			
		||||
@@ -71,6 +73,7 @@ class Target {
 | 
			
		||||
	 * @param String &$title Title of the target page
 | 
			
		||||
	 */
 | 
			
		||||
	public function __construct( $nameSpace, $title, Config &$config ) {
 | 
			
		||||
		// print "\n>>>nameSpace=$nameSpace;title=$title<<<\n";
 | 
			
		||||
		$this->title = \Title::makeTitleSafe( $nameSpace, $title );
 | 
			
		||||
		$this->titleValue = $this->title->getTitleValue();
 | 
			
		||||
		$this->config = $config;
 | 
			
		||||
@@ -91,6 +94,32 @@ class Target {
 | 
			
		||||
		return $this->title->getText();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function getPrefixedTitleText() {
 | 
			
		||||
		return $this->getNsPrefix() . $this->getTitleText();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Gets the string representation of the target's namespace.
 | 
			
		||||
	 *
 | 
			
		||||
	 * May be false if the namespace is NS_MAIN. The value is cached.
 | 
			
		||||
	 * @return String|bool Target's namespace
 | 
			
		||||
	 */
 | 
			
		||||
	public function getNsText() {
 | 
			
		||||
		if ( $this->nsText === null ) {
 | 
			
		||||
			$this->nsText = $this->title->getNsText();
 | 
			
		||||
		}
 | 
			
		||||
		return $this->nsText;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Gets the namespace prefix. This is the namespace text followed by a colon,
 | 
			
		||||
	 * or an empty string if the namespace text evaluates to false (e.g. NS_MAIN).
 | 
			
		||||
	 * @return String namespace prefix
 | 
			
		||||
	 */
 | 
			
		||||
	public function getNsPrefix() {
 | 
			
		||||
		return $this->getNsText() ? $this->getNsText() . ':' : '';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Gets the title string with certain characters escaped that may interfere
 | 
			
		||||
	 * with regular expressions.
 | 
			
		||||
 
 | 
			
		||||
@@ -111,8 +111,8 @@ class LinkTitlesLinkerTest extends LinkTitles\TestCase {
 | 
			
		||||
			[
 | 
			
		||||
				true, // wgCapitalLinks
 | 
			
		||||
				true, // smartMode
 | 
			
		||||
				'With smart mode on and $wgCapitalLinks = true, this page should link to Link Target',
 | 
			
		||||
				'With smart mode on and $wgCapitalLinks = true, this page should link to [[Link target|Link Target]]'
 | 
			
		||||
				'With smart mode on and $wgCapitalLinks = true, this page should link to Link target',
 | 
			
		||||
				'With smart mode on and $wgCapitalLinks = true, this page should link to [[Link target]]'
 | 
			
		||||
			],
 | 
			
		||||
			[
 | 
			
		||||
				true, // wgCapitalLinks
 | 
			
		||||
@@ -203,34 +203,43 @@ class LinkTitlesLinkerTest extends LinkTitles\TestCase {
 | 
			
		||||
		$this->assertSame( $text, $linker->linkContent( $this->title, $text ) );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @dataProvider provideLinkContentNameSpacesData
 | 
			
		||||
	 */
 | 
			
		||||
	public function testLinkContentNameSpaces( $nameSpaces, $input, $expectedOutput ) {
 | 
			
		||||
		$ns = 3000;
 | 
			
		||||
		$this->setMwGlobals( [
 | 
			
		||||
			"wgExtraNameSpaces[$ns]" => 'custom_namespace'
 | 
			
		||||
		] );
 | 
			
		||||
		$this->insertPage(  'in custom namespace', 'This is a page in a custom namespace', $ns );
 | 
			
		||||
		$config = new LinkTitles\Config();
 | 
			
		||||
		$config->nameSpaces = $nameSpaces;
 | 
			
		||||
		$linker = new LinkTitles\Linker( $config );
 | 
			
		||||
		$this->assertSame( $expectedOutput, $linker->linkContent( $this->title, $input ));
 | 
			
		||||
	}
 | 
			
		||||
	// Tests for namespace handling are commented out until I find a way to add
 | 
			
		||||
	// a custom namespace during testing. (The assertTrue assertion below fails.)
 | 
			
		||||
 | 
			
		||||
	public function provideLinkContentNameSpacesData() {
 | 
			
		||||
		return [
 | 
			
		||||
			[
 | 
			
		||||
				[], // nameSpaces
 | 
			
		||||
				'With nameSpaces = [], page in custom namespace should not be linked',
 | 
			
		||||
				'With nameSpaces = [], page in custom namespace should not be linked'
 | 
			
		||||
			],
 | 
			
		||||
			[
 | 
			
		||||
				[ 3000 ], // nameSpaces
 | 
			
		||||
				'With nameSpaces = 3000, page in custom namespace should be linked',
 | 
			
		||||
				'With nameSpaces = 3000, page [[custom_namespace:in custom namespace]] should be linked'
 | 
			
		||||
			],
 | 
			
		||||
		];
 | 
			
		||||
	}
 | 
			
		||||
	// /**
 | 
			
		||||
	//  * @dataProvider provideLinkContentNameSpacesData
 | 
			
		||||
	//  */
 | 
			
		||||
	// public function testLinkContentNameSpaces( $nameSpaces, $input, $expectedOutput ) {
 | 
			
		||||
	// 	$ns = 4000;
 | 
			
		||||
	// 	$this->setMwGlobals( [
 | 
			
		||||
	// 		"wgExtraNamespaces[$ns]" => 'custom_namespace'
 | 
			
		||||
	// 	] );
 | 
			
		||||
	// 	// global $wgExtraNamespaces;
 | 
			
		||||
	// 	// global $wgContentNamespaces;
 | 
			
		||||
	// 	// $wgContentNamespaces[] = $ns;
 | 
			
		||||
	// 	// $wgExtraNamespaces[$ns] = 'custom_adsf';
 | 
			
		||||
	// 	$this->insertPage( 'in custom namespace', 'This is a page in a custom namespace', $ns );
 | 
			
		||||
	// 	$this->assertTrue( MWNamespace::exists( $ns ), "The name space with id $ns should exist!" );
 | 
			
		||||
	// 	LinKTitles\Targets::invalidate();
 | 
			
		||||
	// 	$config = new LinkTitles\Config();
 | 
			
		||||
	// 	$config->nameSpaces = $nameSpaces;
 | 
			
		||||
	// 	$linker = new LinkTitles\Linker( $config );
 | 
			
		||||
	// 	$this->assertSame( $expectedOutput, $linker->linkContent( $this->title, $input ));
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	// public function provideLinkContentNameSpacesData() {
 | 
			
		||||
	// 	return [
 | 
			
		||||
	// 		[
 | 
			
		||||
	// 			[], // nameSpaces
 | 
			
		||||
	// 			'With nameSpaces = [], page in custom namespace should not be linked',
 | 
			
		||||
	// 			'With nameSpaces = [], page in custom namespace should not be linked'
 | 
			
		||||
	// 		],
 | 
			
		||||
	// 		[
 | 
			
		||||
	// 			[ 4000 ], // nameSpaces
 | 
			
		||||
	// 			'With nameSpaces = [ 4000 ], page in custom namespace should be linked',
 | 
			
		||||
	// 			'With nameSpaces = [ 4000 ], page [[custom_namespace:in custom namespace]] should be linked'
 | 
			
		||||
	// 		],
 | 
			
		||||
	// 	];
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user