jenkins-bot has submitted this change and it was merged. Change subject: Introduce Special:EntityUsage/Q# ......................................................................
Introduce Special:EntityUsage/Q# Bug: T144923 Change-Id: Ib93d0b5aa6e9326e9845ba08ce0528fbbb36076b --- M client/WikibaseClient.hooks.php M client/WikibaseClient.i18n.alias.php M client/WikibaseClient.php M client/i18n/en.json M client/i18n/qqq.json A client/includes/Specials/SpecialEntityUsage.php A client/tests/phpunit/includes/Specials/SpecialEntityUsageTest.php 7 files changed, 317 insertions(+), 0 deletions(-) Approvals: Daniel Kinzler: Looks good to me, approved jenkins-bot: Verified diff --git a/client/WikibaseClient.hooks.php b/client/WikibaseClient.hooks.php index 3e74593..476e209 100644 --- a/client/WikibaseClient.hooks.php +++ b/client/WikibaseClient.hooks.php @@ -27,6 +27,7 @@ use Wikibase\Client\RecentChanges\ExternalChangeFactory; use Wikibase\Client\Specials\SpecialPagesWithBadges; use Wikibase\Client\Specials\SpecialUnconnectedPages; +use Wikibase\Client\Specials\SpecialEntityUsage; use Wikibase\Client\WikibaseClient; use Wikibase\DataModel\Entity\EntityId; use Wikibase\Lib\AutoCommentFormatter; @@ -473,6 +474,7 @@ public static function onwgQueryPages( &$queryPages ) { $queryPages[] = array( SpecialUnconnectedPages::class, 'UnconnectedPages' ); $queryPages[] = array( SpecialPagesWithBadges::class, 'PagesWithBadges' ); + $queryPages[] = array( SpecialEntityUsage::class, 'EntityUsage' ); return true; } diff --git a/client/WikibaseClient.i18n.alias.php b/client/WikibaseClient.i18n.alias.php index 9feeb67..893baf6 100644 --- a/client/WikibaseClient.i18n.alias.php +++ b/client/WikibaseClient.i18n.alias.php @@ -14,6 +14,7 @@ /** English (English) */ $specialPageAliases['en'] = array( + 'EntityUsage' => array( 'EntityUsage', 'EntityUsageData' ), 'PagesWithBadges' => array( 'PagesWithBadges', 'QueryBadges' ), 'UnconnectedPages' => array( 'UnconnectedPages', 'WithoutConnection', 'WithoutSitelinks' ), ); diff --git a/client/WikibaseClient.php b/client/WikibaseClient.php index dab1b05..a29f57e 100644 --- a/client/WikibaseClient.php +++ b/client/WikibaseClient.php @@ -208,6 +208,7 @@ // Special page registration $wgSpecialPages['UnconnectedPages'] = 'Wikibase\Client\Specials\SpecialUnconnectedPages'; $wgSpecialPages['PagesWithBadges'] = 'Wikibase\Client\Specials\SpecialPagesWithBadges'; + $wgSpecialPages['EntityUsage'] = 'Wikibase\Client\Specials\SpecialEntityUsage'; $wgHooks['wgQueryPages'][] = 'Wikibase\ClientHooks::onwgQueryPages'; // Resource loader modules diff --git a/client/i18n/en.json b/client/i18n/en.json index bb20403..d806555 100644 --- a/client/i18n/en.json +++ b/client/i18n/en.json @@ -82,6 +82,12 @@ "wikibase-pageswithbadges-legend": "List of pages with a given badge", "wikibase-pageswithbadges-badge": "Badge:", "wikibase-pageswithbadges-submit": "Show pages", + "entityusage": "Entity Usage", + "entityusage-summary": "This page lists pages that use the given entity (e.g. Q42). The list is sorted by descending page ID, so that newer pages are listed first.", + "wikibase-entityusage-invalid-id": "$1 is not a valid item ID", + "wikibase-entityusage-legend": "List of pages that use a given entity", + "wikibase-entityusage-entity": "Entity:", + "wikibase-entityusage-submit": "Show pages", "wikibase-pageinfo-entity-id": "{{WBREPONAME}} item ID", "wikibase-pageinfo-entity-id-none": "None", "wikibase-pageinfo-entity-usage": "{{WBREPONAME}} entities used in this page", diff --git a/client/i18n/qqq.json b/client/i18n/qqq.json index d93e514..917c245 100644 --- a/client/i18n/qqq.json +++ b/client/i18n/qqq.json @@ -93,6 +93,12 @@ "wikibase-pageswithbadges-legend": "Legend for the PagesWithBadges special page", "wikibase-pageswithbadges-badge": "Label for the input field to select the badge to filter by.\n{{Identical|Badge}}", "wikibase-pageswithbadges-submit": "Label for the button that activates the action", + "entityusage": "{{doc-special|EntityUsage}}", + "entityusage-summary": "Introductory text used on Special:EntityUsage.", + "wikibase-entityusage-invalid-id": "Error message when an invalid id is passed to the special page. Parameters:\n* $1 - the invalid ID", + "wikibase-entityusage-legend": "Legend for the EntityUsage special page", + "wikibase-entityusage-entity": "Label for the input field to select the entity to show.", + "wikibase-entityusage-submit": "Label for the button that activates the action", "wikibase-pageinfo-entity-id": "A link to the corresponding Wikibase Item", "wikibase-pageinfo-entity-id-none": "The page is not linked with a wikibase item.\n{{Identical|None}}", "wikibase-pageinfo-entity-usage": "Desciption in action=info about entities used in the page", diff --git a/client/includes/Specials/SpecialEntityUsage.php b/client/includes/Specials/SpecialEntityUsage.php new file mode 100644 index 0000000..496427c --- /dev/null +++ b/client/includes/Specials/SpecialEntityUsage.php @@ -0,0 +1,216 @@ +<?php + +namespace Wikibase\Client\Specials; + +use HTMLForm; +use Html; +use InvalidArgumentException; +use Linker; +use QueryPage; +use Skin; +use Title; +use Wikibase\Client\WikibaseClient; +use Wikibase\Client\Usage\EntityUsage; +use Wikibase\DataModel\Entity\ItemId; + +/** + * Get usage of any given entity. + * + * @since 0.5 + * + * @license GPL-2.0+ + * @author Amir Sarabadani (ladsgr...@gmail.com) + */ +class SpecialEntityUsage extends QueryPage { + + /** + * @var ItemId|null + */ + private $entityId; + + /** + * @see SpecialPage::__construct + * + * @param string $name + */ + public function __construct( $name = 'EntityUsage' ) { + parent::__construct( $name ); + } + + /** + * @see QueryPage::execute + * + * @param string $subPage + */ + public function execute( $subPage ) { + $this->prepareParams( $subPage ); + + if ( $this->entityId !== null ) { + parent::execute( $subPage ); + } else { + $this->setHeaders(); + $this->outputHeader(); + $this->getOutput()->addHTML( $this->getPageHeader() ); + } + } + + private function prepareParams( $subPage ) { + $entity = $this->getRequest()->getText( 'entity', $subPage ); + + if ( $entity ) { + try { + $this->entityId = new ItemId( $entity ); + } catch ( InvalidArgumentException $ex ) { + $this->getOutput()->addHTML( + Html::element( + 'p', + [ + 'class' => 'error' + ], + $this->msg( 'wikibase-entityusage-invalid-id', $entity ) + ) + ); + } + } + } + + /** + * @see QueryPage::getPageHeader + * + * @return string + */ + public function getPageHeader() { + $formDescriptor = [ + 'entity' => [ + 'name' => 'entity', + 'type' => 'text', + 'id' => 'wb-entityusage-entity', + 'label-message' => 'wikibase-entityusage-entity', + ], + 'submit' => [ + 'name' => '', + 'type' => 'submit', + 'id' => 'wikibase-entityusage-submit', + 'default' => $this->msg( 'wikibase-entityusage-submit' )->text() + ] + ]; + + if ( $this->entityId !== null ) { + $formDescriptor['entity']['default'] = $this->entityId->getSerialization(); + } + + return HTMLForm::factory( 'inline', $formDescriptor, $this->getContext() ) + ->setMethod( 'get' ) + ->setWrapperLegendMsg( 'wikibase-entityusage-legend' ) + ->suppressDefaultSubmit() + ->prepareForm() + ->getHTML( '' ); + } + + /** + * @see QueryPage::getQueryInfo + * + * @return array[] + */ + public function getQueryInfo() { + $joinConds = [ 'wbc_entity_usage' => [ 'JOIN', [ 'page_id = eu_page_id' ] ] ]; + $conds = [ 'eu_entity_id' => $this->entityId->getSerialization() ]; + $groupConcat = wfGetDB( DB_REPLICA ) + ->buildGroupConcatField( '|', 'wbc_entity_usage', + 'eu_aspect', $conds, $joinConds + ); + + return [ + 'tables' => [ + 'page', + 'wbc_entity_usage' + ], + 'fields' => [ + 'value' => 'page_id', + 'namespace' => 'page_namespace', + 'title' => 'page_title', + 'aspects' => $groupConcat, + 'eu_page_id', + ], + 'conds' => $conds, + 'options' => ['GROUP BY' => 'eu_page_id' ], + 'join_conds' => $joinConds + ]; + } + + /** + * @see QueryPage::formatResult + * + * @param Skin $skin + * @param object $result + * + * @return string + */ + public function formatResult( $skin, $row ) { + global $wgContLang; + + $title = Title::makeTitleSafe( $row->namespace, $row->title ); + $aspects = $this->formatAspects( $row->aspects ); + if ( $title instanceof Title ) { + $text = $wgContLang->convert( $title->getPrefixedText() ); + return Linker::link( $title, htmlspecialchars( $text ) ) . ': ' . $aspects; + } else { + return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ], + Linker::getInvalidTitleDescription( $this->getContext(), $row->namespace, $row->title ) ); + } + } + + /** + * @param string $rowAspects + * @return string + */ + public function formatAspects( $rowAspects ) { + $rowAspects = explode( '|', $rowAspects ); + $aspects = []; + + foreach ( $rowAspects as $aspect ) { + $aspect = EntityUsage::splitAspectKey( $aspect ); + $aspects[] = $this->getContext()->msg( + 'wikibase-pageinfo-entity-usage-' . $aspect[0], $aspect[1] )->parse(); + } + + return $this->getContext()->getLanguage()->commaList( $aspects ); + } + + /** + * @see QueryPage::isSyndicated + * + * @return bool + */ + public function isSyndicated() { + return false; + } + + /** + * @see QueryPage::isCacheable + * + * @return bool + */ + public function isCacheable() { + return false; + } + + /** + * @see QueryPage::linkParameters + * + * @return array + */ + public function linkParameters() { + return [ 'entity' => $this->entityId->getSerialization() ]; + } + + /** + * @see SpecialPage::getGroupName + * + * @return string + */ + protected function getGroupName() { + return 'pages'; + } + +} diff --git a/client/tests/phpunit/includes/Specials/SpecialEntityUsageTest.php b/client/tests/phpunit/includes/Specials/SpecialEntityUsageTest.php new file mode 100644 index 0000000..320962e --- /dev/null +++ b/client/tests/phpunit/includes/Specials/SpecialEntityUsageTest.php @@ -0,0 +1,85 @@ +<?php + +namespace Wikibase\Client\Tests\Specials; + +use FakeResultWrapper; +use SpecialPageFactory; +use SpecialPageTestBase; +use Title; +use WikiPage; +use Wikibase\Client\Specials\SpecialEntityUsage; +use Wikibase\DataModel\Entity\ItemId; +use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup; +use Wikibase\DataModel\Term\Term; +use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory; + +/** + * @covers Wikibase\Client\Specials\SpecialEntityUsage + * + * @group WikibaseClient + * @group SpecialPage + * @group WikibaseSpecialPage + * @group Wikibase + * + * @license GPL-2.0+ + * @author Amir Sarabadani <ladsgr...@gmail.com> + */ +class SpecialEntityUsageTest extends SpecialPageTestBase { + + protected function setUp() { + parent::setUp(); + } + + public function reallyDoQueryMock() { + $rows = [ + (object)[ + 'value' => 11, + 'namespace' => 0, + 'title' => 'Tehran', + 'aspects' => 'S|O|L.fa', + 'eu_page_id' => 11, + 'eu_entity_id' => 'Q3', + ], + ]; + $res = new FakeResultWrapper( $rows ); + return $res; + } + + protected function newSpecialPage() { + $specialPage = $this->getMockBuilder( SpecialEntityUsage::class ) + ->setMethods( [ 'reallyDoQuery' ] ) + ->getMock(); + + $specialPage->expects( $this->any() ) + ->method( 'reallyDoQuery' ) + ->will( $this->returnValue( $this->reallyDoQueryMock() ) ); + + return $specialPage; + } + + public function testExecuteWithValidParam() { + list( $result, ) = $this->executeSpecialPage( 'Q3' ); + $aspects = [ + wfMessage( 'wikibase-pageinfo-entity-usage-S' )->parse(), + wfMessage( 'wikibase-pageinfo-entity-usage-O' )->parse(), + wfMessage( 'wikibase-pageinfo-entity-usage-L', 'fa' )->parse(), + ]; + + $this->assertContains( 'Tehran', $result ); + $this->assertNotContains( '<p class="error"', $result ); + $expected = SpecialPageFactory::getLocalNameFor( 'EntityUsage', 'Q3' ); + $this->assertContains( $expected, $result ); + $this->assertContains( implode( ", ", $aspects ), $result ); + } + + public function testExecuteWithInvalidParam() { + list( $result, ) = $this->executeSpecialPage( 'FooBar' ); + + $this->assertContains( '<p class="error"', $result ); + $this->assertContains( + wfMessage( 'wikibase-entityusage-invalid-id', 'FooBar' )->text(), + $result + ); + } + +} -- To view, visit https://gerrit.wikimedia.org/r/310580 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ib93d0b5aa6e9326e9845ba08ce0528fbbb36076b Gerrit-PatchSet: 7 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Ladsgroup <ladsgr...@gmail.com> Gerrit-Reviewer: Addshore <addshorew...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> Gerrit-Reviewer: Hoo man <h...@online.de> Gerrit-Reviewer: Ladsgroup <ladsgr...@gmail.com> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits