From 4a4bfbd7defe0cceaeaff5be45750dcc4de9518f Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Tue, 8 Nov 2016 06:19:49 +0100 Subject: [PATCH 1/6] Fix formatting in README.md. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1814aae..d2ac176 100644 --- a/README.md +++ b/README.md @@ -18,5 +18,5 @@ If you wish to contribute, please issue pull requests against the `develop` bran Contributors ------------ -Daniel Kraus (@bovender), main developer -Ulrich Strauss (@c0nnex), namespaces +- Daniel Kraus (@bovender), main developer +- Ulrich Strauss (@c0nnex), namespaces From e899f6a5cd0197cd5e5fb5968790d6e146f9bc69 Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Wed, 9 Nov 2016 17:08:57 +0100 Subject: [PATCH 2/6] Fix namespace of \Title class in maintenance script. - FIX: Removed a fatal bug in the LinkTitles_Maintenance script. --- LinkTitles_Maintenance.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LinkTitles_Maintenance.php b/LinkTitles_Maintenance.php index fccbf29..f38adbc 100755 --- a/LinkTitles_Maintenance.php +++ b/LinkTitles_Maintenance.php @@ -143,7 +143,7 @@ class Cli extends \Maintenance { // Iterate through the pages; break if a time limit is exceeded. foreach ( $res as $row ) { $index += 1; - $curTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title); + $curTitle = \Title::makeTitleSafe( $row->page_namespace, $row->page_title); $this->output( sprintf("\rPage #%d (%02.0f%%)", $index, $index / $numPages * 100) ); From feda14e833037c49f98f7025689b22506d01361a Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Wed, 9 Nov 2016 22:40:28 +0100 Subject: [PATCH 3/6] Fix namespaces support. --- includes/LinkTitles_Extension.php | 93 +++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/includes/LinkTitles_Extension.php b/includes/LinkTitles_Extension.php index 88259e1..5646077 100644 --- a/includes/LinkTitles_Extension.php +++ b/includes/LinkTitles_Extension.php @@ -35,6 +35,9 @@ class Extension { /// A Title object for the target page currently being examined. private static $targetTitle; + + // The TitleValue object of the target page + private static $targetTitleValue; /// The content object for the currently processed target page. /// This variable is necessary to be able to prevent loading the target @@ -53,6 +56,9 @@ class Extension { private static $wordStartDelim; private static $wordEndDelim; + public static $ltConsoleOutput; + public static $ltConsoleOutputDebug; + /// Setup method public static function setup() { self::BuildDelimiters(); @@ -62,14 +68,21 @@ class Extension { public static function onPageContentSave( &$wikiPage, &$user, &$content, &$summary, $isMinor, $isWatch, $section, &$flags, &$status ) { global $wgLinkTitlesParseOnEdit; - if (!$wgLinkTitlesParseOnEdit) return true; + global $wgLinkTitlesNamespaces; + if ( !$wgLinkTitlesParseOnEdit ) return true; - if ( !$isMinor && !\MagicWord::get('MAG_LINKTITLES_NOAUTOLINKS')->match( $text ) ) { + if ( !$isMinor && !\MagicWord::get( 'MAG_LINKTITLES_NOAUTOLINKS' )->match( $text ) ) { $title = $wikiPage->getTitle(); - $text = $content->getContentHandler()->serializeContent($content); - $newText = self::parseContent( $title, $text ); - if ( $newText != $text ) { - $content = $content->getContentHandler()->unserializeContent( $newText ); + + // Only process if page is in one of our namespaces we want to link + // Fixes ugly autolinking of sidebar pages + if ( in_array( $title->getNamespace(), $wgLinkTitlesNamespaces )) + { + $text = $content->getContentHandler()->serializeContent( $content ); + $newText = self::parseContent( $title, $text ); + if ( $newText != $text ) { + $content = $content->getContentHandler()->unserializeContent( $newText ); + } } }; return true; @@ -81,10 +94,13 @@ class Extension { public static function onInternalParseBeforeLinks( \Parser &$parser, &$text ) { global $wgLinkTitlesParseOnRender; if (!$wgLinkTitlesParseOnRender) return true; + global $wgLinkTitlesNamespaces; + $title = $parser->getTitle(); // If the page contains the magic word '__NOAUTOLINKS__', do not parse it. - if ( !isset($parser->mDoubleUnderScores[$text] )) { - $text = self::parseContent( $parser->getTitle(), $text ); + // Only process if page is in one of our namespaces we want to link + if ( !isset( $parser->mDoubleUnderScores[$text] ) && in_array( $title->getNamespace(), $wgLinkTitlesNamespaces ) ) { + $text = self::parseContent( $title, $text ); } return true; } @@ -102,6 +118,7 @@ class Extension { global $wgLinkTitlesFirstOnly; global $wgLinkTitlesSmartMode; global $wgCapitalLinks; + global $wgLinkTitlesNamespaces; ( $wgLinkTitlesPreferShortTitles ) ? $sort_order = 'ASC' : $sort_order = 'DESC'; ( $wgLinkTitlesFirstOnly ) ? $limit = 1 : $limit = -1; @@ -115,6 +132,22 @@ class Extension { '("' . implode( '", "',$wgLinkTitlesBlackList ) . '", "' . addslashes( self::$currentTitle->getDbKey() ) . '")' ); + $currentNamespace[] = $title->getNamespace(); + + // Build our weight list. Make sure current namespace is first element + $namespaces = array_diff($wgLinkTitlesNamespaces, $currentNamespace); + array_unshift($namespaces, $currentNamespace[0] ); + + // No need for sanitiy check. we are sure that we have at least one element in the array + $weightSelect = "CASE page_namespace "; + $currentWeight = 0; + foreach ($namespaces as &$namspacevalue) { + $currentWeight = $currentWeight + 100; + $weightSelect = $weightSelect . " WHEN " . $namspacevalue . " THEN " . $currentWeight . PHP_EOL; + } + $weightSelect = $weightSelect . " END "; + $namespacesClause = str_replace( '_', ' ','(' . implode( ', ',$namespaces ) . ')' ); + // Build an SQL query and fetch all page titles ordered by length from // shortest to longest. Only titles from 'normal' pages (namespace uid // = 0) are returned. Since the db may be sqlite, we need a try..catch @@ -123,9 +156,9 @@ class Extension { try { $res = $dbr->select( 'page', - 'page_title', + array( 'page_title', 'page_namespace' , "weight" => $weightSelect), array( - 'page_namespace = 0', + 'page_namespace IN ' . $namespacesClause, 'CHAR_LENGTH(page_title) >= ' . $wgLinkTitlesMinimumTitleLength, 'page_title NOT IN ' . $blackList, ), @@ -135,9 +168,9 @@ class Extension { } catch (Exception $e) { $res = $dbr->select( 'page', - 'page_title', + array( 'page_title', 'page_namespace' , "weight" => $weightSelect ), array( - 'page_namespace = 0', + 'page_namespace IN ' . $namespacesClause, 'LENGTH(page_title) >= ' . $wgLinkTitlesMinimumTitleLength, 'page_title NOT IN ' . $blackList, ), @@ -150,6 +183,8 @@ class Extension { foreach( $res as $row ) { self::newTarget( $row->page_title ); + LinkTitles::newTarget( $row->page_namespace, $row->page_title ); + // split the page content by [[...]] groups // credits to inhan @ StackOverflow for suggesting preg_split // see http://stackoverflow.com/questions/10672286 @@ -159,6 +194,9 @@ class Extension { // regexp compilation errors self::$targetTitleText = self::$targetTitle->getText(); $quotedTitle = preg_quote(self::$targetTitleText, '/'); + + LinkTitles::ltDebugLog('TargetTitle='. LinkTitles::$targetTitleText,"private"); + LinkTitles::ltDebugLog('TargetTitleQuoted='. $quotedTitle,"private"); // Depending on the global configuration setting $wgCapitalLinks, // the title has to be searched for either in a strictly case-sensitive @@ -214,8 +252,8 @@ class Extension { /// to obtain such an object. /// @returns undefined public static function processPage( $title, \RequestContext $context ) { - // TODO: make this namespace-aware $titleObj = \Title::makeTitle(0, $title); + LinkTitles::ltLog('Processing '. $titleObj->getPrefixedText()); $page = \WikiPage::factory($titleObj); $content = $page->getContent(); $text = $content->getContentHandler()->serializeContent($content); @@ -244,6 +282,7 @@ class Extension { // Build an anonymous callback function to be used in simple mode. private static function simpleModeCallback( array $matches ) { if ( self::checkTargetPage() ) { + self::ltLog( "Linking '$matches[0]' to '" . self::$targetTitle . "'" ); return '[[' . $matches[0] . ']]'; } else @@ -268,6 +307,7 @@ class Extension { // we need to ignore the first letter of the page titles, as // it does not matter for linking. if ( self::checkTargetPage() ) { + LinkTitles::ltLog( "Linking (smart) '$matches[0]' to '" . LinkTitles::$targetTitle . "'" ); if ( strcmp(substr(self::$targetTitleText, 1), substr($matches[0], 1)) == 0 ) { // Case-sensitive match: no need to bulid piped link. return '[[' . $matches[0] . ']]'; @@ -284,6 +324,7 @@ class Extension { // If $wgCapitalLinks is false, we can use the simple variant // of the callback function. if ( self::checkTargetPage() ) { + LinkTitles::ltLog( "Linking (smart) '$matches[0]' to '" . LinkTitles::$targetTitle . "'" ); if ( strcmp(self::$targetTitleText, $matches[0]) == 0 ) { // Case-sensitive match: no need to bulid piped link. return '[[' . $matches[0] . ']]'; @@ -300,9 +341,11 @@ class Extension { } /// Sets member variables for the current target page. - private static function newTarget( $title ) { - // @todo Make this wiki namespace aware. - self::$targetTitle = \Title::makeTitle( NS_MAIN, $title); + private static function newTarget( $ns, $title ) { + self::$targetTitle = \Title::makeTitleSafe( $ns, $title ); + self::ltDebugLog( 'newtarget='. self::$targetTitle->getText(), "private" ); + self::$targetTitleValue = self::$targetTitle->getTitleValue(); + self::ltDebugLog( 'altTarget='. self::$targetTitleValue->getText(), "private" ); self::$targetContent = null; } @@ -409,6 +452,24 @@ private static function BuildDelimiters() { '(?<=\b)\S+\@(?:\S+\.)+\S+(?=\b)' . // email addresses ')/ismS'; } + + /// Local Debugging output function which can send output to console as well + public static function ltDebugLog($text) { + if (LinkTitles::$ltConsoleOutputDebug) + { + print $text . "\n"; + } + wfDebugLog('LinkTitles', $text , 'private'); + } + + /// Local Logging output function which can send output to console as well + public static function ltLog($text) { + if (LinkTitles::$ltConsoleOutput) + { + print $text . "\n"; + } + wfDebugLog('LinkTitles', $text , 'private'); + } } // vim: ts=2:sw=2:noet:comments^=\:/// From c67a428dde350d0b24d1ae09c49e0374af4aae67 Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Wed, 9 Nov 2016 22:45:44 +0100 Subject: [PATCH 4/6] Fix PHP namespace errors. --- LinkTitles_Maintenance.php | 6 +++--- includes/LinkTitles_Extension.php | 18 ++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/LinkTitles_Maintenance.php b/LinkTitles_Maintenance.php index f38adbc..96b6f93 100755 --- a/LinkTitles_Maintenance.php +++ b/LinkTitles_Maintenance.php @@ -101,11 +101,11 @@ class Cli extends \Maintenance { if ($this->hasOption('log')) { - LinkTitles::$ltConsoleOutput = true; + Extension::$ltConsoleOutput = true; } if ($this->hasOption('debug')) { - LinkTitles::$ltConsoleOutputDebug = true; + Extension::$ltConsoleOutputDebug = true; } $pagename = strval($this->getOption('page')); @@ -145,7 +145,7 @@ class Cli extends \Maintenance { $index += 1; $curTitle = \Title::makeTitleSafe( $row->page_namespace, $row->page_title); $this->output( - sprintf("\rPage #%d (%02.0f%%)", $index, $index / $numPages * 100) + sprintf("\rPage #%d (%02.0f%%) ", $index, $index / $numPages * 100) ); Extension::processPage($curTitle, $context); } diff --git a/includes/LinkTitles_Extension.php b/includes/LinkTitles_Extension.php index 5646077..09ae694 100644 --- a/includes/LinkTitles_Extension.php +++ b/includes/LinkTitles_Extension.php @@ -181,9 +181,7 @@ class Extension { // Iterate through the page titles foreach( $res as $row ) { - self::newTarget( $row->page_title ); - - LinkTitles::newTarget( $row->page_namespace, $row->page_title ); + self::newTarget( $row->page_namespace, $row->page_title ); // split the page content by [[...]] groups // credits to inhan @ StackOverflow for suggesting preg_split @@ -195,8 +193,8 @@ class Extension { self::$targetTitleText = self::$targetTitle->getText(); $quotedTitle = preg_quote(self::$targetTitleText, '/'); - LinkTitles::ltDebugLog('TargetTitle='. LinkTitles::$targetTitleText,"private"); - LinkTitles::ltDebugLog('TargetTitleQuoted='. $quotedTitle,"private"); + self::ltDebugLog('TargetTitle='. self::$targetTitleText,"private"); + self::ltDebugLog('TargetTitleQuoted='. $quotedTitle,"private"); // Depending on the global configuration setting $wgCapitalLinks, // the title has to be searched for either in a strictly case-sensitive @@ -253,7 +251,7 @@ class Extension { /// @returns undefined public static function processPage( $title, \RequestContext $context ) { $titleObj = \Title::makeTitle(0, $title); - LinkTitles::ltLog('Processing '. $titleObj->getPrefixedText()); + self::ltLog('Processing '. $titleObj->getPrefixedText()); $page = \WikiPage::factory($titleObj); $content = $page->getContent(); $text = $content->getContentHandler()->serializeContent($content); @@ -307,7 +305,7 @@ class Extension { // we need to ignore the first letter of the page titles, as // it does not matter for linking. if ( self::checkTargetPage() ) { - LinkTitles::ltLog( "Linking (smart) '$matches[0]' to '" . LinkTitles::$targetTitle . "'" ); + self::ltLog( "Linking (smart) '$matches[0]' to '" . self::$targetTitle . "'" ); if ( strcmp(substr(self::$targetTitleText, 1), substr($matches[0], 1)) == 0 ) { // Case-sensitive match: no need to bulid piped link. return '[[' . $matches[0] . ']]'; @@ -324,7 +322,7 @@ class Extension { // If $wgCapitalLinks is false, we can use the simple variant // of the callback function. if ( self::checkTargetPage() ) { - LinkTitles::ltLog( "Linking (smart) '$matches[0]' to '" . LinkTitles::$targetTitle . "'" ); + self::ltLog( "Linking (smart) '$matches[0]' to '" . self::$targetTitle . "'" ); if ( strcmp(self::$targetTitleText, $matches[0]) == 0 ) { // Case-sensitive match: no need to bulid piped link. return '[[' . $matches[0] . ']]'; @@ -455,7 +453,7 @@ private static function BuildDelimiters() { /// Local Debugging output function which can send output to console as well public static function ltDebugLog($text) { - if (LinkTitles::$ltConsoleOutputDebug) + if (self::$ltConsoleOutputDebug) { print $text . "\n"; } @@ -464,7 +462,7 @@ private static function BuildDelimiters() { /// Local Logging output function which can send output to console as well public static function ltLog($text) { - if (LinkTitles::$ltConsoleOutput) + if (self::$ltConsoleOutput) { print $text . "\n"; } From d6a7f69c4d9eb1e332c88b7dbd3ca8ea6f08b29d Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Wed, 9 Nov 2016 22:48:49 +0100 Subject: [PATCH 5/6] Bump version. - FIX: Repaired severely broken namespaces support. --- extension.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension.json b/extension.json index 5f57b44..ce5bff0 100644 --- a/extension.json +++ b/extension.json @@ -6,7 +6,7 @@ ], "type": "parserhook", "url": "https://www.mediawiki.org/wiki/Extension:LinkTitles", - "version": "4.0.1", + "version": "4.0.2", "license-name": "GPL-2.0+", "descriptionmsg": "linktitles-desc", "requires": { From fa323ec6932519724121d309d0cd9479f671a6c4 Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Wed, 9 Nov 2016 22:49:57 +0100 Subject: [PATCH 6/6] Write history, write docs. --- NEWS | 9 +++++++++ gh-pages | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b464a05..a51447d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Version 4.0.2 (2016-11-09) +------------------------------------------------------------------------ + +- FIX: Removed a fatal bug in the LinkTitles_Maintenance script. +- FIX: Repaired severely broken namespaces support. + +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + Version 4.0.1 (2016-11-08) ------------------------------------------------------------------------ diff --git a/gh-pages b/gh-pages index a19a8d5..28e9c04 160000 --- a/gh-pages +++ b/gh-pages @@ -1 +1 @@ -Subproject commit a19a8d5737feac3bab26dd99383e51928eb56af4 +Subproject commit 28e9c0416e0793b797d09d567fc87a510074c911