Anja Jentzsch has uploaded a new change for review.
https://gerrit.wikimedia.org/r/54839
Change subject: (bug 45037) show edit link only if we have repo links
......................................................................
(bug 45037) show edit link only if we have repo links
This also fixes bug 44536 to have Q### links instead of link via
Special:ItemByTitle
This patch adds parser output and output page properties that indicate:
1) wikibase_item: the associated prefixed item id
This is used by the skin in constructing the "edit links" link directly to the
Q### page,
or to know if a page is connected to the wikibase repo.
Then it's easier and more efficient for the code to determine whether or not to
add "edit links" link and build the link to the associated item.
Change-Id: I97cc9378477953bddebd04840871964f31ef1b7f
---
M client/WikibaseClient.hooks.php
M client/WikibaseClient.php
D client/includes/ClientUtils.php
A client/includes/EntityIdPropertyUpdater.php
M client/includes/LangLinkHandler.php
A client/includes/RepoLinker.php
M client/includes/recentchanges/ExternalChangesLine.php
D client/tests/phpunit/includes/ClientUtilsTest.php
M client/tests/phpunit/includes/LangLinkHandlerTest.php
A client/tests/phpunit/includes/RepoLinkerTest.php
M lib/tests/phpunit/MockRepository.php
11 files changed, 783 insertions(+), 231 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase
refs/changes/39/54839/1
diff --git a/client/WikibaseClient.hooks.php b/client/WikibaseClient.hooks.php
index 1396a58..fe85a76 100644
--- a/client/WikibaseClient.hooks.php
+++ b/client/WikibaseClient.hooks.php
@@ -80,7 +80,7 @@
'includes/CachedEntity',
'includes/ChangeHandler',
- 'includes/ClientUtils',
+ 'includes/RepoLinker',
'includes/EntityCacheUpdater',
'includes/api/ApiClientInfo',
@@ -380,8 +380,15 @@
);
if ( $itemId !== false ) {
- $itemByTitle = 'Special:ItemByTitle/' . $globalId . '/'
. wfUrlencode( $oldTitle->getPrefixedDBkey() );
- $itemByTitleLink = ClientUtils::repoArticleUrl(
$itemByTitle );
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ $itemByTitle = 'Special:ItemByTitle/' . $globalId . '/'
. $oldTitle->getPrefixedDBkey();
+ $itemByTitleLink = $repoLinker->repoArticleUrl(
$itemByTitle );
$out = $movePage->getOutput();
$out->addModules( 'wikibase.client.page-move' );
$out->addHTML(
@@ -619,12 +626,43 @@
}
/**
+ * Add output page property if repo links are suppressed, and property
for item id
+ *
+ * @since 0.4
+ *
+ * @param \OutputPage &$out
+ * @param \ParserOutput $pout
+ *
+ * @return bool
+ */
+ public static function onOutputPageParserOutput( \OutputPage &$out,
\ParserOutput $pout ) {
+ $langLinkHandler = new LangLinkHandler(
+ Settings::get( 'siteGlobalID' ),
+ Settings::get( 'namespaces' ),
+ Settings::get( 'excludeNamespaces' ),
+ ClientStoreFactory::getStore()->newSiteLinkTable(),
+ \Sites::singleton() );
+
+ $noExternalLangLinks =
$langLinkHandler->getNoExternalLangLinks( $pout );
+ if ( $noExternalLangLinks !== array() ) {
+ $out->setProperty( 'noexternallanglinks',
$noExternalLangLinks );
+ }
+
+ $itemId = $pout->getProperty( 'wikibase_item' );
+ if ( $itemId !== false ) {
+ $out->setProperty( 'wikibase_item', $itemId );
+ }
+
+ return true;
+ }
+
+ /**
* Displays a list of links to pages on the central wiki at the end of
the language box.
+ *
+ * @since 0.1
*
* @param \Skin $skin
* @param \QuickTemplate $template
- *
- * @since 0.1
*
* @return bool
*/
@@ -632,34 +670,45 @@
wfProfileIn( __METHOD__ );
$title = $skin->getContext()->getTitle();
- if ( !in_array( $title->getNamespace(), Settings::get(
'excludeNamespaces' ) ) && $title->exists() ) {
+ $namespaceChecker = new NamespaceChecker(
+ Settings::get( 'excludeNamespaces' ),
+ Settings::get( 'namespaces' )
+ );
+ if ( $title->exists() && $namespaceChecker->isWikibaseEnabled(
$title->getNamespace() ) ) {
if ( empty( $template->data['language_urls'] ) &&
\Action::getActionName( $skin->getContext() ) === 'view' ) {
- // Placeholder in case the page doesn't have
any langlinks yet
- // self::onBeforePageDisplay adds the
JavaScript module which will overwrite this with a link
- $template->data['language_urls'][] = array(
- 'text' => '',
- 'id' => 'wbc-linkToItem',
- 'class' => 'wbc-editpage
wbc-nolanglinks',
- );
+ // if property is not set, it will return null
+ $noExternalLangLinks =
$skin->getOutput()->getProperty( 'noexternallanglinks' );
+
+ if ( $noExternalLangLinks === null ||
!in_array( '*', $noExternalLangLinks ) ) {
+ // Placeholder in case the page doesn't
have any langlinks yet
+ // self::onBeforePageDisplay adds the
JavaScript module which will overwrite this with a link
+ $template->data['language_urls'][] =
array(
+ 'text' => '',
+ 'id' => 'wbc-linkToItem',
+ 'class' => 'wbc-editpage
wbc-nolanglinks',
+ );
+ }
wfProfileOut( __METHOD__ );
return true;
}
- $title = $skin->getContext()->getTitle();
+ $prefixedId = $skin->getOutput()->getProperty(
'wikibase_item' );
- // gets the main part of the title, no underscores used
in this db table
- // TODO: use the item id from the page props when they
are available
- $titleText = $title->getPrefixedText();
- $siteId = Settings::get( 'siteGlobalID' );
+ if ( $prefixedId !== null ) {
+ $entityId = EntityId::newFromPrefixedId(
$prefixedId );
- $itemId =
ClientStoreFactory::getStore()->newSiteLinkTable()->getItemIdForLink( $siteId,
$titleText );
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
- if ( $itemId ) {
// links to the special page
$template->data['language_urls'][] = array(
- 'href' => ClientUtils::repoArticleUrl(
"Special:ItemByTitle/$siteId/" . wfUrlencode( $title->getPrefixedDBkey() ) ),
+ 'href' => $repoLinker->repoItemUrl(
$entityId ),
'text' => wfMessage(
'wikibase-editlinks' )->text(),
'title' => wfMessage(
'wikibase-editlinkstitle' )->text(),
'class' => 'wbc-editpage',
diff --git a/client/WikibaseClient.php b/client/WikibaseClient.php
index 59dd8bf..2d9f39d 100644
--- a/client/WikibaseClient.php
+++ b/client/WikibaseClient.php
@@ -59,12 +59,13 @@
$wgAutoloadClasses['Wikibase\ClientHooks'] = $dir .
'WikibaseClient.hooks.php';
$wgAutoloadClasses['Wikibase\CachedEntity'] = $dir .
'includes/CachedEntity.php';
-$wgAutoloadClasses['Wikibase\ClientUtils'] = $dir .
'includes/ClientUtils.php';
$wgAutoloadClasses['Wikibase\EntityCacheUpdater'] = $dir .
'includes/EntityCacheUpdater.php';
+$wgAutoloadClasses['Wikibase\EntityIdPropertyUpdater'] = $dir .
'includes/EntityIdPropertyUpdater.php';
$wgAutoloadClasses['Wikibase\InterwikiSorter'] = $dir .
'includes/InterwikiSorter.php';
$wgAutoloadClasses['Wikibase\LangLinkHandler'] = $dir .
'includes/LangLinkHandler.php';
$wgAutoloadClasses['Wikibase\ChangeHandler'] = $dir .
'includes/ChangeHandler.php';
$wgAutoloadClasses['Wikibase\NamespaceChecker'] = $dir .
'includes/NamespaceChecker.php';
+$wgAutoloadClasses['Wikibase\RepoLinker'] = $dir .
'includes/RepoLinker.php';
$wgAutoloadClasses['Scribunto_LuaWikibaseLibrary'] = $dir .
'includes/WikibaseLibrary.php';
// includes/api
@@ -99,6 +100,7 @@
$wgHooks['UnitTestsList'][] =
'\Wikibase\ClientHooks::registerUnitTests';
$wgHooks['LoadExtensionSchemaUpdates'][] =
'\Wikibase\ClientHooks::onSchemaUpdate';
$wgHooks['OldChangesListRecentChangesLine'][] =
'\Wikibase\ClientHooks::onOldChangesListRecentChangesLine';
+$wgHooks['OutputPageParserOutput'][] =
'\Wikibase\ClientHooks::onOutputPageParserOutput';
$wgHooks['ParserAfterParse'][] =
'\Wikibase\ClientHooks::onParserAfterParse';
$wgHooks['ParserFirstCallInit'][] =
'\Wikibase\ClientHooks::onParserFirstCallInit';
$wgHooks['MagicWordwgVariableIDs'][] =
'\Wikibase\ClientHooks::onMagicWordwgVariableIDs';
diff --git a/client/includes/ClientUtils.php b/client/includes/ClientUtils.php
deleted file mode 100644
index 3fe1f73..0000000
--- a/client/includes/ClientUtils.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-namespace Wikibase;
-
-/**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @since 0.2
- *
- * @file
- * @ingroup WikibaseClient
- *
- * @licence GNU GPL v2+
- * @author Katie Filbert < [email protected] >
- */
-final class ClientUtils {
-
- /**
- * @since 0.2
- *
- * @return string
- */
- public static function baseUrl() {
- $baseUrl = Settings::get( 'repoUrl' );
- $baseUrl = rtrim( $baseUrl, '/' );
- return wfExpandUrl( $baseUrl, PROTO_RELATIVE );
- }
-
- /**
- * @since 0.3
- *
- * @param string $target
- *
- * @return string
- */
- public static function repoArticleUrl( $target ) {
- return self::baseUrl() . str_replace( '$1', $target,
Settings::get( 'repoArticlePath' ) );
- }
-
- /**
- * @since 0.3
- *
- * @param string $target
- * @param string $text
- * @param array $attribs
- *
- * @return string
- */
- public static function repoLink( $target, $text, $attribs = array() ) {
- $baseUrl = self::baseUrl();
-
- if ( array_key_exists( 'query', $attribs ) && is_array(
$attribs['query'] ) ) {
- $repoScriptPath = Settings::get( 'repoScriptPath' );
- if ( $attribs['query']['type'] === 'index' ) {
- $url = $baseUrl . $repoScriptPath .
'/index.php';
- } else if ( $attribs['query']['type'] === 'api' ) {
- $url = $baseUrl . $repoScriptPath . '/api.php';
- } else {
- throw new \MWException( 'Invalid query type' );
- }
- $url = wfAppendQuery( $url, wfArrayToCgi(
$attribs['query']['params'] ) );
- unset( $attribs['query'] );
- } else {
- $url = self::repoArticleUrl( $target );
- }
-
- if ( $url === null ) {
- throw new \MWException( 'Could not build a repoLink
url.' );
- }
-
- $class = 'plainlinks';
- if ( array_key_exists( 'class', $attribs ) ) {
- $class .= ' ' . $attribs['class'];
- }
-
- $attribs['class'] = $class;
- $attribs['href'] = $url;
-
- return \Html::element( 'a', $attribs, $text );
- }
-
-}
diff --git a/client/includes/EntityIdPropertyUpdater.php
b/client/includes/EntityIdPropertyUpdater.php
new file mode 100644
index 0000000..f1e1968
--- /dev/null
+++ b/client/includes/EntityIdPropertyUpdater.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * Handles wikibase_item page and parser output property
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @file
+ * @ingroup WikibaseClient
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert
+ */
+class EntityIdPropertyUpdater {
+
+ /* @var SiteLinkLookup */
+ protected $siteLinkLookup;
+
+ /* @var Site */
+ protected $site;
+
+ /**
+ * @since 0.4
+ *
+ * @param SiteLinkLookup $siteLinkLookup
+ * @param \Site $site
+ */
+ public function __construct( SiteLinkLookup $siteLinkLookup, \Site
$site ) {
+ $this->siteLinkLookup = $siteLinkLookup;
+ $this->site = $site;
+ }
+
+ /**
+ * Set parser output property with item id
+ *
+ * @since 0.4
+ *
+ * @param \ParserOutput $out
+ * @param Title $title
+ */
+ public function updateItemIdProperty( \ParserOutput $out, \Title $title
) {
+ $siteLink = new SiteLink(
+ $this->site,
+ $title->getFullText()
+ );
+
+ // todo: do we really want to fetch item id twice during
parsing?
+ $itemId = $this->siteLinkLookup->getEntityIdForSiteLink(
$siteLink );
+
+ if ( $itemId instanceof EntityId ) {
+ // @todo get prefixed id in nicer way, or maybe we want
it to be numeric id
+ $out->setProperty( 'wikibase_item',
$itemId->getPrefixedId() );
+ } else {
+ // unset property, if it was set
+ $this->unsetProperty( $out, 'wikibase_item' );
+
+ wfDebugLog( __CLASS__, __FUNCTION__ . 'Trying to set
wikibase_item property for '
+ . $siteLink->getSite()->getGlobalId() . ':' .
$siteLink->getPage()
+ . ' but $itemId is not an EntityId object.' );
+ }
+ }
+
+ /**
+ * Unsets the wikibase_item property
+ * @todo: should use functionality in core, and if not exists, add it
there.
+ *
+ * @since 0.4
+ *
+ * @param ParserOutput $out
+ */
+ protected function unsetProperty( \ParserOutput $out, $propertyName ) {
+ // unset property, if it was set
+ $properties = $out->getProperties();
+
+ if ( array_key_exists( $propertyName, $properties ) ) {
+ unset( $properties[$propertyName] );
+ $out->mProperties = $properties;
+ }
+ }
+}
diff --git a/client/includes/LangLinkHandler.php
b/client/includes/LangLinkHandler.php
index 0cf009d..4b85ffb 100644
--- a/client/includes/LangLinkHandler.php
+++ b/client/includes/LangLinkHandler.php
@@ -2,6 +2,7 @@
namespace Wikibase;
use SiteStore;
+use Sites;
use Site;
use Title;
use ParserOutput;
@@ -80,18 +81,21 @@
wfProfileIn( __METHOD__ );
wfDebugLog( __CLASS__, __FUNCTION__ . ": Looking for sitelinks
defined by the corresponding item on the wikibase repo." );
- $itemId = $this->siteLinksLookup->getItemIdForLink(
- $this->siteId,
- $title->getFullText()
- );
+ $links = array();
- $links = array();
+ $site = $this->sites->getSite( $this->siteId );
- if ( $itemId !== false ) {
- wfDebugLog( __CLASS__, __FUNCTION__ . ": Item ID for "
. $title->getFullText() . " is " . $itemId );
+ if ( $site === null ) {
+ wfWarn( 'Site not found for ' . $this->siteId );
+ return $links;
+ }
- $links = $this->siteLinksLookup->getSiteLinksForItem(
- new EntityId( Item::ENTITY_TYPE, $itemId ) );
+ $siteLink = new SiteLink( $site, $title->getFullText() );
+ $itemId = $this->siteLinksLookup->getEntityIdForSiteLink(
$siteLink );
+
+ if ( $itemId !== null ) {
+ wfDebugLog( __CLASS__, __FUNCTION__ . ": Item ID for "
. $title->getFullText() . " is " . $itemId->getPrefixedId() );
+ $links = $this->siteLinksLookup->getSiteLinksForItem(
$itemId );
} else {
wfDebugLog( __CLASS__, __FUNCTION__ . ": No
corresponding item found for " . $title->getFullText() );
}
@@ -124,7 +128,7 @@
);
// use repoLinks in only the namespaces specified in settings
- if ( $namespaceChecker->isWikibaseEnabled(
$title->getNamespace() ) ) {
+ if ( $namespaceChecker->isWikibaseEnabled(
$title->getNamespace() ) === true ) {
$nel = self::getNoExternalLangLinks( $out );
if( in_array( '*', $nel ) ) {
@@ -203,6 +207,7 @@
*/
public function getNoExternalLangLinks( ParserOutput $out ) {
wfProfileIn( __METHOD__ );
+
$property = $out->getProperty( 'noexternallanglinks' );
$nel = is_string( $property ) ? unserialize( $property ) :
array();
@@ -352,6 +357,7 @@
$onPageLinks = $this->localLinksToArray( $onPageLinks );
$repoLinks = $this->getEntityLinks( $title );
+
$repoLinks = $this->repoLinksToArray( $repoLinks );
$repoLinks = $this->suppressRepoLinks( $out, $repoLinks );
@@ -376,17 +382,23 @@
public function addLinksFromRepository( Title $title, ParserOutput $out
) {
wfProfileIn( __METHOD__ );
+ $site = $this->sites->getSite( $this->siteId );
+
+ if ( $site === null ) {
+ wfWarn( 'Site not found for ' . $this->siteId . '.
Cannot add links from repository.' );
+ return;
+ }
+
$repoLinks = $this->getEffectiveRepoLinks( $title, $out );
foreach ( $repoLinks as $wiki => $page ) {
- $site = $this->sites->getSite( $wiki );
-
- if ( !$site ) {
+ $targetSite = $this->sites->getSite( $wiki );
+ if ( !$targetSite ) {
trigger_error( "Unknown wiki '$wiki' used as
sitelink target", E_USER_WARNING );
continue;
}
- $nav = $site->getNavigationIds();
+ $nav = $targetSite->getNavigationIds();
$nav = array_values( $nav );
if ( isset( $nav[0] ) ) {
@@ -399,6 +411,9 @@
}
}
+ $propertyHandler = new EntityIdPropertyUpdater(
$this->siteLinksLookup, $site );
+ $propertyHandler->updateItemIdProperty( $out, $title );
+
wfProfileOut( __METHOD__ );
}
}
diff --git a/client/includes/RepoLinker.php b/client/includes/RepoLinker.php
new file mode 100644
index 0000000..183dedd
--- /dev/null
+++ b/client/includes/RepoLinker.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.2
+ *
+ * @file
+ * @ingroup WikibaseClient
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < [email protected] >
+ */
+class RepoLinker {
+
+ protected $baseUrl;
+
+ protected $articlePath;
+
+ protected $scriptPath;
+
+ protected $namespaces;
+
+ public function __construct( $baseUrl, $articlePath, $scriptPath, array
$namespaces ) {
+ $this->baseUrl = $baseUrl;
+ $this->articlePath = $articlePath;
+ $this->scriptPath = $scriptPath;
+ $this->namespaces = $namespaces;
+ }
+
+ /**
+ * @since 0.2
+ *
+ * @return string
+ */
+ public function baseUrl() {
+ return rtrim( $this->baseUrl, '/' );
+ }
+
+ /**
+ * @since 0.3
+ *
+ * @param string $target
+ *
+ * @return string
+ */
+ public function repoArticleUrl( $target ) {
+ $encodedPage = $this->encodePage( $target );
+ return $this->baseUrl() . str_replace( '$1', $encodedPage,
$this->articlePath );
+ }
+
+ /**
+ * Encode a page title
+ *
+ * @since 0.4
+ *
+ * @param string $page
+ *
+ * @return string
+ */
+ protected function encodePage( $page ) {
+ if ( !is_string( $page ) ) {
+ trigger_error( __CLASS__ . ' : Trying to encode a page
but $page is not a string.', E_USER_WARNING );
+ return '';
+ }
+ return is_string( $page ) ? wfUrlencode( str_replace( ' ', '_',
$page ) ) : '';
+ }
+
+ /**
+ * Returns a url to the item page on the repo
+ * @todo support all types of entities
+ *
+ * @since 0.4
+ *
+ * @param EntityId $entityId
+ *
+ * @return string
+ */
+ public function repoItemUrl( EntityId $entityId ) {
+ $prefixedId = $entityId->getPrefixedId();
+
+ $itemNamespace = $this->getNamespace( Item::ENTITY_TYPE );
+
+ $formattedNamespace = is_string( $itemNamespace ) && !empty(
$itemNamespace ) ?
+ $itemNamespace . ':' : $itemNamespace;
+
+ return $this->repoArticleUrl( $formattedNamespace . strtoupper(
$prefixedId ) );
+ }
+
+ /**
+ * Get namespace of an entity in string format
+ *
+ * @since 0.2
+ *
+ * @param string $entityType
+ *
+ * @return string
+ */
+ public function getNamespace( $entityType ) {
+ $nsList = $this->namespaces;
+ $ns = null;
+
+ $contentType = 'wikibase-' . $entityType;
+ if ( is_array( $nsList ) && array_key_exists( $contentType,
$nsList ) ) {
+ $ns = $nsList[$contentType];
+ } else {
+ // todo: support queries and better error handling here
+ return false;
+ }
+
+ return $ns;
+ }
+
+ /**
+ * @since 0.3
+ * @todo could be made nicer
+ *
+ * @param string|null $target - needed only for /wiki/$1 type links
+ * @param string $text - what goes inside the <a> tag
+ * @param array $attribs - optional, used only for query string urls,
and both
+ * url formats to insert additional css classes; example:
+ * $attribs = array(
+ * 'query' =>
+ * 'params' => array(
+ * 'action' => 'query',
+ * 'meta' => 'siteinfo
+ * ),
+ * 'type' => 'api' // or 'index' for index.php
+ * ),
+ * 'class' => 'wikibase-link item' // string
+ * );
+ *
+ * @throws \MWException
+ *
+ * @return string
+ */
+ public function repoLink( $target, $text, $attribs = array() ) {
+ if ( array_key_exists( 'query', $attribs ) && is_array(
$attribs['query'] ) ) {
+ if ( $attribs['query']['type'] === 'index' ) {
+ $url = $this->baseUrl() . $this->scriptPath .
'/index.php';
+ } else if ( $attribs['query']['type'] === 'api' ) {
+ $url = $this->baseUrl() . $this->scriptPath .
'/api.php';
+ } else {
+ throw new \MWException( 'Invalid query type' );
+ }
+ $url = wfAppendQuery( $url, wfArrayToCgi(
$attribs['query']['params'] ) );
+ unset( $attribs['query'] );
+ } else {
+ // should not happen, but just in case...
+ if ( !is_string( $target ) ) {
+ throw new \MWException( 'repoLink requires a
$target to contruct an article url.' );
+ }
+ $url = $this->repoArticleUrl( $target );
+ }
+
+ if ( $url === null ) {
+ throw new \MWException( 'Could not build a repoLink
url.' );
+ }
+
+ $class = 'plainlinks';
+ // @todo more validation and maybe accept array instead
+ if ( array_key_exists( 'class', $attribs ) ) {
+ $class .= ' ' . $attribs['class'];
+ }
+
+ $attribs['class'] = $class;
+ $attribs['href'] = $url;
+
+ return \Html::element( 'a', $attribs, $text );
+ }
+
+}
diff --git a/client/includes/recentchanges/ExternalChangesLine.php
b/client/includes/recentchanges/ExternalChangesLine.php
index 617b272..4131c3d 100644
--- a/client/includes/recentchanges/ExternalChangesLine.php
+++ b/client/includes/recentchanges/ExternalChangesLine.php
@@ -3,6 +3,8 @@
namespace Wikibase;
/**
+ * @todo remove static stuff and refactor
+ *
* Generates a changes line for including changes from the Wikibase repo in
* the client's recent changes, watchlist and related changes special pages.
*
@@ -70,7 +72,14 @@
$line = '';
if ( in_array( $changeType, array( 'remove', 'restore' ) ) ) {
- $deletionLog = ClientUtils::repoLink(
'Special:Log/delete', wfMessage( 'dellogpage' )->text() );
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ $deletionLog = $repoLinker->repoLink(
'Special:Log/delete', wfMessage( 'dellogpage' )->text() );
$line .= wfMessage( 'parentheses' )->rawParams(
$deletionLog );
} else if ( in_array( $changeType, array( 'add', 'update' ) ) )
{
@@ -210,7 +219,14 @@
* @return string
*/
protected static function diffLink( $titleText, $entityData, $rc ) {
- return ClientUtils::repoLink(
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ return $repoLinker->repoLink(
null,
wfMessage( 'diff' )->text(),
array(
@@ -238,7 +254,14 @@
* @return string
*/
protected static function historyLink( $titleText, $entityData ) {
- $link = ClientUtils::repoLink(
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ $link = $repoLinker->repoLink(
null,
wfMessage( 'hist' )->text(),
array(
@@ -283,12 +306,19 @@
* @return string
*/
protected static function userLink( $userName ) {
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
// @todo: localise this once namespaces are localised on the
repo
$link = "User:$userName";
$attribs = array(
'class' => 'mw-userlink'
);
- return ClientUtils::repoLink( $link, $userName, $attribs );
+ return $repoLinker->repoLink( $link, $userName, $attribs );
}
/**
@@ -306,7 +336,15 @@
if ( $text === null ) {
$text = wfMessage( 'contribslink' );
}
- return ClientUtils::repoLink( $link, $text );
+
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ return $repoLinker->repoLink( $link, $text );
}
/**
@@ -317,10 +355,17 @@
* @return string
*/
protected static function userTalkLink( $userName ) {
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
// @todo: localize this once we can localize namespaces on the
repo
$link = "User_talk:$userName";
$text = wfMessage( 'talkpagelinktext' )->text();
- return ClientUtils::repoLink( $link, $text );
+ return $repoLinker->repoLink( $link, $text );
}
/**
@@ -366,41 +411,14 @@
return false;
}
- return ClientUtils::repoLink( $entityText, $entityId, array(
'class' => 'wb-entity-link' ) );
- }
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
- /**
- * TODO: returning a string as namespace like this is odd.
- * Returning the namespace ID would make more sense.
- * If the result of this is not handled to a Title object
- * we miss out on proper localization and stuff.
- *
- * @since 0.2
- *
- * @param array $entityData
- *
- * @return string
- */
- protected static function getNamespace( $entityData ) {
- $nsList = Settings::get( 'repoNamespaces' );
- $ns = null;
-
- switch( $entityData['entity_type'] ) {
- case 'item':
- $ns = $nsList['wikibase-item'];
- break;
- case 'property':
- $ns = $nsList['wikibase-property'];
- break;
- default:
- // invalid entity type
- // todo: query data type
- return false;
- }
- if ( ! empty( $ns ) ) {
- $ns = $ns . ':';
- }
- return $ns;
+ return $repoLinker->repoLink( $entityText, $entityId, array(
'class' => 'wb-entity-link' ) );
}
/**
@@ -416,6 +434,7 @@
$id = $entityData['object_id'];
if ( ctype_digit( $id ) || is_numeric( $id ) ) {
+ // @deprecated
// FIXME: this is evil; we seem to have lost
all encapsulation at this point,
// so some refactoring is needed to have sane
access to the info here.
$entityType = explode( '-',
$entityData['entity_type'], 2 );
@@ -426,12 +445,20 @@
$entityId = EntityId::newFromPrefixedId( $id );
}
- // TODO: ideally the uppercasing would be handled by a
Title object
- $titleText = $entityId ? strtoupper(
$entityId->getPrefixedId() ) : $id;
+ $titleText = strtoupper( $entityId->getPrefixedId() );
if ( $includeNamespace ) {
- $ns = self::getNamespace( $entityData );
- $titleText = $ns . $titleText;
+ $repoLinker = new RepoLinker(
+ Settings::get( 'repoUrl' ),
+ Settings::get( 'repoArticlePath' ),
+ Settings::get( 'repoScriptPath' ),
+ Settings::get( 'repoNamespaces' )
+ );
+
+ $ns = $repoLinker->getNamespace( $entityId );
+ if ( !empty( $ns ) ) {
+ $titleText = $ns . ':' . $titleText;
+ }
}
return $titleText;
diff --git a/client/tests/phpunit/includes/ClientUtilsTest.php
b/client/tests/phpunit/includes/ClientUtilsTest.php
deleted file mode 100644
index 515e2a7..0000000
--- a/client/tests/phpunit/includes/ClientUtilsTest.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-namespace Wikibase\Test;
-
-/**
- * Tests for the Wikibase\ClientUtils class.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @since 0.3
- *
- * @ingroup WikibaseClient
- * @ingroup Test
- *
- * @group WikibaseClient
- * @group ClientUtilsTest
- *
- * @licence GNU GPL v2+
- * @author Jeroen De Dauw < [email protected] >
- */
-class ClientUtilsTest extends \MediaWikiTestCase {
-
- public function testBaseUrl() {
- $this->assertInternalType( 'string',
\Wikibase\ClientUtils::baseUrl() );
- }
-
-}
diff --git a/client/tests/phpunit/includes/LangLinkHandlerTest.php
b/client/tests/phpunit/includes/LangLinkHandlerTest.php
index e7e945c..0ec3516 100644
--- a/client/tests/phpunit/includes/LangLinkHandlerTest.php
+++ b/client/tests/phpunit/includes/LangLinkHandlerTest.php
@@ -49,18 +49,18 @@
'id' => 1,
'label' => array( 'en' => 'Foo' ),
'links' => array(
- 'testwiki' => 'Foo',
'dewiki' => 'Foo_de',
'enwiki' => 'Foo_en',
+ 'srwiki' => 'Foo_sr',
)
),
array( // matches, but not in a namespace with external
langlinks enabled
'id' => 2,
'label' => array( 'en' => 'Talk:Foo' ),
'links' => array(
- 'testwiki' => 'Talk:Foo',
'dewiki' => 'Talk:Foo_de',
'enwiki' => 'Talk:Foo_en',
+ 'srwiki' => 'Talk:Foo_sr',
)
)
);
@@ -84,9 +84,9 @@
}
$this->langLinkHandler = new \Wikibase\LangLinkHandler(
- 'testwiki',
- array( NS_MAIN ),
+ 'srwiki',
array(),
+ array( NS_TALK ),
$this->mockRepo,
\SiteSQLStore::newInstance()
);
@@ -99,11 +99,11 @@
array() // expected links
),
array( // #1
- 'Foo', // page
+ 'Foo_sr', // page
array( // expected links
- 'testwiki' => 'Foo',
'dewiki' => 'Foo_de',
'enwiki' => 'Foo_en',
+ 'srwiki' => 'Foo_sr',
)
),
);
@@ -201,22 +201,22 @@
public static function provideUseRepoLinks() {
return array(
array( // #0
- 'Foo',
+ 'Foo_sr',
array(),
true
),
array( // #1
- 'Foo',
+ 'Foo_sr',
array( '*' ),
false
),
array( // #2
- 'Foo',
+ 'Foo_sr',
array( 'de' ),
true
),
array( // #3
- 'Talk:Foo',
+ 'Talk:Foo_sr',
array(),
false
),
@@ -229,6 +229,7 @@
public function testUseRepoLinks( $title, $noexternallanglinks,
$expected ) {
if ( is_string( $title ) ) {
$title = \Title::newFromText( $title );
+ $title->resetArticleID( 1 );
}
$out = $this->makeParserOutput( array(), $noexternallanglinks );
@@ -241,7 +242,7 @@
public static function provideGetEffectiveRepoLinks() {
return array(
array( // #0: local overrides remote
- 'Foo', // title
+ 'Foo_sr', // title
array( // langlinks
'de' => 'Xoo_de',
'nl' => 'Foo_nl',
@@ -253,7 +254,7 @@
)
),
array( // #1: namespace not covered
- 'Talk:Foo', // title
+ 'Talk:Foo_sr', // title
array( // langlinks
'de' => 'Talk:Foo_de',
'nl' => 'Talk:Foo_nl',
@@ -264,7 +265,7 @@
)
),
array( // #2: disabled
- 'Foo', // title
+ 'Foo_sr', // title
array( // langlinks
'de' => 'Foo_de',
'nl' => 'Foo_nl',
@@ -276,7 +277,7 @@
)
),
array( // #3: suppressed
- 'Foo', // title
+ 'Foo_sr', // title
array( // langlinks
'de' => 'Foo_de',
'nl' => 'Foo_nl',
@@ -288,7 +289,7 @@
)
),
array( // #4: suppressed redundantly
- 'Foo', // title
+ 'Foo_sr', // title
array( // langlinks
'de' => 'Foo_de',
'nl' => 'Foo_nl',
diff --git a/client/tests/phpunit/includes/RepoLinkerTest.php
b/client/tests/phpunit/includes/RepoLinkerTest.php
new file mode 100644
index 0000000..9d1e1a6
--- /dev/null
+++ b/client/tests/phpunit/includes/RepoLinkerTest.php
@@ -0,0 +1,290 @@
+<?php
+
+namespace Wikibase\Test;
+use Wikibase\RepoLinker;
+use Wikibase\EntityId;
+use Wikibase\Item;
+
+/**
+ * Tests for the Wikibase\RepoLinker class.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseClient
+ * @ingroup Test
+ *
+ * @group WikibaseClient
+ * @group RepoLinkerTest
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < [email protected] >
+ */
+class RepoLinkerTest extends \MediaWikiTestCase {
+
+ public function getRepoSettings() {
+ return array(
+ array(
+ 'baseUrl' => '//www.example.com',
+ 'articlePath' => '/wiki/$1',
+ 'scriptPath' => '',
+ 'repoNamespaces' => array(
+ 'wikibase-item' => '',
+ 'wikibase-property' => 'Property'
+ )
+ ),
+ array(
+ 'baseUrl' => '//example.com',
+ 'articlePath' => '/wiki/$1',
+ 'scriptPath' => '',
+ 'repoNamespaces' => array(
+ 'wikibase-item' => '',
+ 'wikibase-property' => 'Property'
+ )
+ ),
+ array(
+ 'baseUrl' => 'http://www.example.com',
+ 'articlePath' => '/wiki/$1',
+ 'scriptPath' => '/w',
+ 'repoNamespaces' => array(
+ 'wikibase-item' => 'Item',
+ 'wikibase-property' => 'Property'
+ )
+ )
+ );
+ }
+
+ public function baseUrlProvider() {
+ $settings = $this->getRepoSettings();
+
+ return array(
+ array(
+ '//www.example.com',
+ $settings[0]
+ ),
+ array(
+ '//example.com',
+ $settings[1]
+ ),
+ array(
+ 'http://www.example.com',
+ $settings[2]
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider baseUrlProvider
+ */
+ public function testBaseUrl( $expected, array $settings ) {
+ $repoLinker = new RepoLinker(
+ $settings['baseUrl'],
+ $settings['articlePath'],
+ $settings['scriptPath'],
+ $settings['repoNamespaces']
+ );
+
+ $baseUrl = $repoLinker->baseUrl();
+ $this->assertEquals( $expected, $baseUrl );
+ }
+
+ public function repoArticleUrlProvider() {
+ $settings = $this->getRepoSettings();
+
+ return array(
+ array(
+ '//www.example.com/wiki/Rome',
+ $settings[0],
+ 'Rome'
+ ),
+ array(
+ '//example.com/wiki/Rome',
+ $settings[1],
+ 'Rome'
+ ),
+ array(
+ '//www.example.com/wiki/Hall_%26_Oates',
+ $settings[0],
+ 'Hall & Oates'
+ ),
+ array(
+ 'http://www.example.com/wiki/Why%3F_(film)',
+ $settings[2],
+ 'Why? (film)'
+ )
+ );
+ }
+
+ /**
+ * @dataProvider repoArticleUrlProvider
+ */
+ public function testRepoArticleUrl( $expected, array $settings, $page
) {
+ $repoLinker = new RepoLinker(
+ $settings['baseUrl'],
+ $settings['articlePath'],
+ $settings['scriptPath'],
+ $settings['repoNamespaces']
+ );
+
+ $repoUrl = $repoLinker->repoArticleUrl( $page );
+
+ $this->assertEquals( $expected, $repoUrl );
+ }
+
+ public function repoItemUrlProvider() {
+ $settings = $this->getRepoSettings();
+
+ return array(
+ array(
+ '//www.example.com/wiki/Q4',
+ $settings[0],
+ new EntityId( Item::ENTITY_TYPE, 4 )
+ ),
+ array(
+ '//example.com/wiki/Q100',
+ $settings[1],
+ new EntityId( Item::ENTITY_TYPE, 100 )
+ ),
+ array(
+ 'http://www.example.com/wiki/Item:Q100',
+ $settings[2],
+ new EntityId( Item::ENTITY_TYPE, 100 )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider repoItemUrlProvider
+ */
+ public function testRepoItemUrl( $expected, array $settings, EntityId
$entityId ) {
+ $repoLinker = new RepoLinker(
+ $settings['baseUrl'],
+ $settings['articlePath'],
+ $settings['scriptPath'],
+ $settings['repoNamespaces']
+ );
+
+ $itemUrl = $repoLinker->repoItemUrl( $entityId );
+
+ $this->assertEquals( $expected, $itemUrl );
+ }
+
+ public function namespaceProvider() {
+ $settings = $this->getRepoSettings();
+
+ return array(
+ array(
+ '',
+ $settings[0],
+ 'item'
+ ),
+ array(
+ 'Property',
+ $settings[1],
+ 'property'
+ ),
+ array(
+ 'Item',
+ $settings[2],
+ 'item'
+ )
+ );
+ }
+
+ /**
+ * @dataProvider namespaceProvider
+ */
+ public function testGetNamespace( $expected, array $settings,
$entityType ) {
+ $repoLinker = new RepoLinker(
+ $settings['baseUrl'],
+ $settings['articlePath'],
+ $settings['scriptPath'],
+ $settings['repoNamespaces']
+ );
+
+ $namespace = $repoLinker->getNamespace( $entityType );
+
+ $this->assertEquals( $expected, $namespace );
+ }
+
+ public function repoLinkProvider() {
+ $settings = $this->getRepoSettings();
+
+ return array(
+ array(
+ '<a class="plainlinks"
href="//www.example.com/api.php?action=query&meta=siteinfo">api query</a>',
+ $settings[0],
+ array(
+ 'target' => null,
+ 'text' => 'api query',
+ 'params' => array(
+ 'query' => array(
+ 'params' => array(
+ 'action' =>
'query',
+ 'meta' =>
'siteinfo'
+ ),
+ 'type' => 'api'
+ )
+ )
+ )
+ ),
+ array(
+ '<a class="plainlinks"
href="//example.com/index.php?title=Rome">Roma</a>',
+ $settings[1],
+ array(
+ 'target' => 'Rome',
+ 'text' => 'Roma',
+ 'params' => array(
+ 'query' => array(
+ 'params' => array(
+ 'title' =>
'Rome'
+ ),
+ 'type' => 'index'
+ )
+ )
+ )
+ ),
+ array(
+ '<a class="plainlinks"
href="http://www.example.com/wiki/Rome">Rome</a>',
+ $settings[2],
+ array(
+ 'target' => 'Rome',
+ 'text' => 'Rome',
+ 'params' => array()
+ )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider repoLinkProvider
+ */
+ public function testRepoLink( $expected, $settings, $params ) {
+ $repoLinker = new RepoLinker(
+ $settings['baseUrl'],
+ $settings['articlePath'],
+ $settings['scriptPath'],
+ $settings['repoNamespaces']
+ );
+
+ $repoLink = $repoLinker->repoLink( $params['target'],
$params['text'], $params['params'] );
+
+ $this->assertEquals( $expected, $repoLink );
+ }
+
+}
diff --git a/lib/tests/phpunit/MockRepository.php
b/lib/tests/phpunit/MockRepository.php
index f4f9710..f4e33a2 100644
--- a/lib/tests/phpunit/MockRepository.php
+++ b/lib/tests/phpunit/MockRepository.php
@@ -143,6 +143,26 @@
}
/**
+ * Gets an EntityId for a SiteLink
+ *
+ * @since 0.4
+ *
+ * @param SiteLink $siteLink
+ *
+ * @return EntityId
+ */
+ public function getEntityIdForSiteLink( SiteLink $siteLink ) {
+ $globalSiteId = $siteLink->getSite()->getGlobalId();
+
+ // @todo: fix test data to use titles with underscores, like
the site link table does it
+ $title = \Title::newFromText( $siteLink->getPage() );
+ $pageTitle = $title->getDBkey();
+
+ $numericItemId = $this->getItemIdForLink( $globalSiteId,
$pageTitle );
+ return is_int( $numericItemId ) ? new EntityId(
Item::ENTITY_TYPE, $numericItemId ) : null;
+ }
+
+ /**
* Registers the sitelinsk of the given Item so they can later be found
with getLinks, etc
*
* @param \Wikibase\Item $item
--
To view, visit https://gerrit.wikimedia.org/r/54839
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I97cc9378477953bddebd04840871964f31ef1b7f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: mw1.21-wmf12
Gerrit-Owner: Anja Jentzsch <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits