Hoo man has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/304162

Change subject: Add Wikibase item links into the toolbox on article placeholders
......................................................................

Add Wikibase item links into the toolbox on article placeholders

Bug: T126873
Change-Id: I3ac0c78e6fd05cc042757a874e93cb6b8b614b17
---
M extension.json
A includes/BaseTemplateToolboxHookHandler.php
A tests/phpunit/includes/BaseTemplateToolboxHookHandlerTest.php
3 files changed, 356 insertions(+), 0 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ArticlePlaceholder 
refs/changes/62/304162/1

diff --git a/extension.json b/extension.json
index d9dd0ba..75ebe1f 100644
--- a/extension.json
+++ b/extension.json
@@ -62,6 +62,9 @@
                "remoteExtPath": "ArticlePlaceholder/modules"
        },
        "Hooks": {
+               "BaseTemplateToolbox": [
+                       
"ArticlePlaceholder\\BaseTemplateToolboxHookHandler::onBaseTemplateToolbox"
+               ],
                "ScribuntoExternalLibraries": [
                        
"ArticlePlaceholder\\Hooks::onScribuntoExternalLibraries"
                ],
diff --git a/includes/BaseTemplateToolboxHookHandler.php 
b/includes/BaseTemplateToolboxHookHandler.php
new file mode 100644
index 0000000..42a962b
--- /dev/null
+++ b/includes/BaseTemplateToolboxHookHandler.php
@@ -0,0 +1,142 @@
+<?php
+
+namespace ArticlePlaceholder;
+
+use BaseTemplate;
+use Exception;
+use SpecialPage;
+use SpecialPageFactory;
+use Title;
+use WebRequest;
+use Wikibase\Client\RepoLinker;
+use Wikibase\Client\WikibaseClient;
+use Wikibase\DataModel\Entity\EntityIdParser;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Services\Lookup\EntityLookup;
+
+/**
+ * Add Wikibase item link in toolbox for placeholders: Handler for the 
"BaseTemplateToolbox" hook.
+ *
+ * @license GPL-2.0+
+ * @author Marius Hoch < h...@online.de >
+ */
+class BaseTemplateToolboxHookHandler {
+
+       /**
+        * @var EntityIdParser
+        */
+       private $entityIdParser;
+
+       /**
+        * @var RepoLinker
+        */
+       private $repoLinker;
+
+       /**
+        * @var EntityLookup
+        */
+       private $entityLookup;
+
+       /**
+        * @param SpecialPage $specialPage
+        *
+        * @return self
+        */
+       private static function newFromGlobalState() {
+               $wikibaseClient = WikibaseClient::getDefaultInstance();
+
+               return new self(
+                       $wikibaseClient->getEntityIdParser(),
+                       $wikibaseClient->newRepoLinker(),
+                       $wikibaseClient->getStore()->getEntityLookup()
+               );
+       }
+
+       /**
+        * @param EntityIdParser $entityIdParser
+        * @param RepoLinker $repoLinker
+        * @param EntityLookup $entityLookup
+        */
+       public function __construct(
+               EntityIdParser $entityIdParser,
+               RepoLinker $repoLinker,
+               EntityLookup $entityLookup
+       ) {
+               $this->entityIdParser = $entityIdParser;
+               $this->repoLinker = $repoLinker;
+               $this->entityLookup = $entityLookup;
+       }
+
+       /**
+        * @param BaseTemplate $baseTemplate
+        * @param array &$toolbox
+        */
+       public static function onBaseTemplateToolbox( BaseTemplate 
$baseTemplate, array &$toolbox ) {
+               // Return early (for performance reasons) in case we're not on
+               // Special:AboutTopic (even before calling newFromGlobalState)
+               $title = $baseTemplate->getSkin()->getTitle();
+
+               if ( $title->getNamespace() !== NS_SPECIAL ) {
+                       return;
+               }
+
+               $canonicalSpecialPageName = SpecialPageFactory::resolveAlias( 
$title->getText() )[0];
+               if ( $canonicalSpecialPageName !== 'AboutTopic' ) {
+                       return;
+               }
+
+               $self = self::newFromGlobalState();
+               $self->doBaseTemplateToolbox( $baseTemplate, $toolbox );
+       }
+
+       /**
+        * @param BaseTemplate $baseTemplate
+        * @param array &$toolbox
+        */
+       public function doBaseTemplateToolbox( BaseTemplate $baseTemplate, 
array &$toolbox ) {
+               $itemId = $this->getItemId(
+                       $baseTemplate->getSkin()->getTitle(),
+                       $baseTemplate->getSkin()->getRequest()
+               );
+
+               if ( $itemId && $this->entityLookup->hasEntity( $itemId ) ) {
+                       // Duplicated from 
Wikibase\ClientHooks::onBaseTemplateToolbox
+                       $toolbox['wikibase'] = array(
+                               'text' => $baseTemplate->getMsg( 
'wikibase-dataitem' )->text(),
+                               'href' => $this->repoLinker->getEntityUrl( 
$itemId ),
+                               'id' => 't-wikibase'
+                       );
+               }
+       }
+
+       /**
+        * @param Title $title
+        * @param WebRequest $webRequest
+        *
+        * @return ItemId
+        */
+       private function getItemId( Title $title, WebRequest $webRequest ) {
+               $idSerialization = $webRequest->getText(
+                       'entityid',
+                       SpecialPageFactory::resolveAlias( $title->getText() )[1]
+               );
+
+               if ( !$idSerialization ) {
+                       return null;
+               }
+
+               try {
+                       $id = $this->entityIdParser->parse( $idSerialization );
+                       if ( !( $id instanceof ItemId ) ) {
+                               return null;
+                       }
+
+                       return $id;
+               } catch ( Exception $ex ) {
+                       // Ignore
+               }
+
+               return null;
+       }
+
+}
diff --git a/tests/phpunit/includes/BaseTemplateToolboxHookHandlerTest.php 
b/tests/phpunit/includes/BaseTemplateToolboxHookHandlerTest.php
new file mode 100644
index 0000000..88a5991
--- /dev/null
+++ b/tests/phpunit/includes/BaseTemplateToolboxHookHandlerTest.php
@@ -0,0 +1,211 @@
+<?php
+
+namespace ArticlePlaceholder\Tests;
+
+use ArticlePlaceholder\BaseTemplateToolboxHookHandler;
+use BaseTemplate;
+use MediaWikiTestCase;
+use Skin;
+use Title;
+use WebRequest;
+use Wikibase\Client\WikibaseClient;
+use Wikibase\DataModel\Entity\Item;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\Test\MockClientStore;
+
+/**
+ * @group ArticlePlaceholder
+ *
+ * @covers ArticlePlaceholder\BaseTemplateToolboxHookHandler
+ *
+ * @license GPL-2.0+
+ * @author Marius Hoch < h...@online.de >
+ */
+class BaseTemplateToolboxHookHandlerTest extends MediaWikiTestCase {
+
+       public function setUp() {
+               parent::setUp();
+
+               $clientStore = new MockClientStore();
+               $wikibaseClient = WikibaseClient::getDefaultInstance();
+               $wikibaseClient->overrideStore( $clientStore );
+
+               $mockRepository = $clientStore->getEntityRevisionLookup();
+               $item = new Item( new ItemId( 'Q2013' ) );
+
+               $mockRepository->putEntity( $item );
+       }
+
+       public function tearDown() {
+               parent::tearDown();
+
+               WikibaseClient::getDefaultInstance( 'reset' );
+       }
+
+       public function testOnBaseTemplateToolbox_wrongNamespace() {
+               $title = $this->getMock( Title::class );
+               $title->expects( $this->once() )
+                       ->method( 'getNamespace' )
+                       ->will( $this->returnValue( 2 ) );
+
+               // We abort early, before Title::getText is ever called
+               $title->expects( $this->never() )
+                       ->method( 'getText' );
+
+               $baseTemplate = $this->getBaseTemplate( $title );
+
+               $arr = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $arr );
+
+               $this->assertSame( [], $arr );
+       }
+
+       public function testOnBaseTemplateToolbox_wrongSpecialPageName() {
+               $title = $this->getMock( Title::class );
+               $title->expects( $this->once() )
+                       ->method( 'getNamespace' )
+                       ->will( $this->returnValue( NS_SPECIAL ) );
+
+               // Title::getText is only called once, because we abort after 
checking the name
+               $title->expects( $this->once() )
+                       ->method( 'getText' )
+                       ->will( $this->returnValue( 'Preferences' ) );
+
+               $baseTemplate = $this->getBaseTemplate( $title );
+
+               $arr = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $arr );
+
+               $this->assertSame( [], $arr );
+       }
+
+       public function testOnBaseTemplateToolbox_invalidItemId() {
+               $title = $this->getAboutTopicTitle( 'not-an-item-id' );
+
+               $baseTemplate = $this->getBaseTemplate( $title );
+
+               $arr = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $arr );
+
+               $this->assertSame( [], $arr );
+       }
+
+       public function testOnBaseTemplateToolbox_unknownItemId() {
+               $title = $this->getAboutTopicTitle( 'Q42' );
+
+               $baseTemplate = $this->getBaseTemplate( $title );
+
+               $arr = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $arr );
+
+               $this->assertSame( [], $arr );
+       }
+
+       public function testOnBaseTemplateToolbox_subPage() {
+               $title = $this->getAboutTopicTitle( 'Q2013' );
+
+               $baseTemplate = $this->getBaseTemplate( $title );
+
+               $toolbox = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $toolbox );
+
+               $this->assertAmendedToolbox( $toolbox );
+       }
+
+       public function testOnBaseTemplateToolbox_entityidParam() {
+               $title = $this->getAboutTopicTitle();
+
+               $baseTemplate = $this->getBaseTemplate( $title, 'Q2013' );
+
+               $toolbox = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $toolbox );
+
+               $this->assertAmendedToolbox( $toolbox );
+       }
+
+       public function 
testOnBaseTemplateToolbox_entityidParamOverridesSubPage() {
+               // This matches the special page's behaviour.
+               $title = $this->getAboutTopicTitle( 'Q123' );
+
+               $baseTemplate = $this->getBaseTemplate( $title, 'Q2013' );
+
+               $toolbox = [];
+               BaseTemplateToolboxHookHandler::onBaseTemplateToolbox( 
$baseTemplate, $toolbox );
+
+               $this->assertAmendedToolbox( $toolbox );
+       }
+
+       private function assertAmendedToolbox( $toolbox ) {
+               $itemId = new ItemId( 'Q2013' );
+               $text = wfMessage( 'wikibase-dataitem' )->text();
+               $href = 
WikibaseClient::getDefaultInstance()->newRepoLinker()->getEntityUrl( $itemId );
+
+               $this->assertSame(
+                       [
+                               'wikibase' => [
+                                       'text' => $text,
+                                       'href' => $href,
+                                       'id' => 't-wikibase'
+                               ]
+                       ],
+                       $toolbox
+               );
+       }
+
+       private function getAboutTopicTitle( $subPage = null ) {
+               $titleText = 'AboutTopic';
+
+               if ( $subPage ) {
+                       $titleText .= '/' . $subPage;
+               }
+
+               $title = $this->getMock( Title::class );
+               $title->expects( $this->once() )
+                       ->method( 'getNamespace' )
+                       ->will( $this->returnValue( NS_SPECIAL ) );
+
+               $title->expects( $this->exactly( 2 ) )
+                       ->method( 'getText' )
+                       ->will( $this->returnValue( $titleText ) );
+
+               return $title;
+       }
+
+       private function getBaseTemplate( Title $title, $itemIdParam = null ) {
+               $request = $this->getMock( WebRequest::class );
+               $request->expects( $this->any() )
+                       ->method( 'getText' )
+                       ->will( $this->returnCallback( function( $name, 
$default ) use ( $itemIdParam ) {
+                               $this->assertSame( 'entityid', $name );
+
+                               return $itemIdParam ?: $default;
+                       } ) );
+
+               $skin = $this->getMockBuilder( Skin::class )
+                       ->setMethods( [ 'getTitle', 'getRequest' ] )
+                       ->getMockForAbstractClass();
+
+               $skin->expects( $this->any() )
+                       ->method( 'getTitle' )
+                       ->will( $this->returnValue( $title ) );
+
+               $skin->expects( $this->any() )
+                       ->method( 'getRequest' )
+                       ->will( $this->returnValue( $request ) );
+
+               $skin->expects( $this->any() )
+                       ->method( 'getRequest' )
+                       ->will( $this->returnValue( $request ) );
+
+               $baseTemplate = $this->getMockBuilder( BaseTemplate::class )
+                       ->setMethods( [ 'getSkin' ] )
+                       ->getMockForAbstractClass();
+
+               $baseTemplate->expects( $this->any() )
+                       ->method( 'getSkin' )
+                       ->will( $this->returnValue( $skin ) );
+
+               return $baseTemplate;
+       }
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/304162
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I3ac0c78e6fd05cc042757a874e93cb6b8b614b17
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ArticlePlaceholder
Gerrit-Branch: master
Gerrit-Owner: Hoo man <h...@online.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to