jenkins-bot has submitted this change and it was merged.

Change subject: Create a new special page to list properties by data type
......................................................................


Create a new special page to list properties by data type

The new special page is called Special:ListProperties.
Queries can be done via the form or in the format
Special:ListProperties/dataType, eg Special:ListProperties/url.

Note: Split into Id9775659

Bug: T55618
Change-Id: I79a08ec87bf76adba869d4b7eb22098b41fbdb72
---
M repo/Wikibase.i18n.alias.php
M repo/Wikibase.php
M repo/i18n/en.json
M repo/i18n/qqq.json
M repo/includes/DataTypeSelector.php
M repo/includes/WikibaseRepo.php
A repo/includes/specials/SpecialListProperties.php
A repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
8 files changed, 455 insertions(+), 13 deletions(-)

Approvals:
  Aude: Looks good to me, but someone else must approve
  Daniel Kinzler: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/repo/Wikibase.i18n.alias.php b/repo/Wikibase.i18n.alias.php
index a449b40..be8a5bc 100644
--- a/repo/Wikibase.i18n.alias.php
+++ b/repo/Wikibase.i18n.alias.php
@@ -22,6 +22,7 @@
        'GoToLinkedPage' => array( 'GoToLinkedPage' ),
        'ItemDisambiguation' => array( 'ItemDisambiguation' ),
        'ListDatatypes' => array( 'ListDatatypes' ),
+       'ListProperties' => array( 'ListProperties' ),
        'SetLabel' => array( 'SetLabel' ),
        'SetDescription' => array( 'SetDescription' ),
        'SetAliases' => array( 'SetAliases' ),
diff --git a/repo/Wikibase.php b/repo/Wikibase.php
index 6509446..411b17e 100644
--- a/repo/Wikibase.php
+++ b/repo/Wikibase.php
@@ -180,6 +180,7 @@
        $wgSpecialPages['EntitiesWithoutLabel']                         = 
array( 'Wikibase\Repo\Specials\SpecialEntitiesWithoutPageFactory', 
'newSpecialEntitiesWithoutLabel' );
        $wgSpecialPages['EntitiesWithoutDescription']           = array( 
'Wikibase\Repo\Specials\SpecialEntitiesWithoutPageFactory', 
'newSpecialEntitiesWithoutDescription' );
        $wgSpecialPages['ListDatatypes']                                        
= 'Wikibase\Repo\Specials\SpecialListDatatypes';
+       $wgSpecialPages['ListProperties']                                       
= 'Wikibase\Repo\Specials\SpecialListProperties';
        $wgSpecialPages['DispatchStats']                                        
= 'Wikibase\Repo\Specials\SpecialDispatchStats';
        $wgSpecialPages['EntityData']                                           
= 'Wikibase\Repo\Specials\SpecialEntityData';
        $wgSpecialPages['MyLanguageFallbackChain']                      = 
'Wikibase\Repo\Specials\SpecialMyLanguageFallbackChain';
diff --git a/repo/i18n/en.json b/repo/i18n/en.json
index 8ca930e..14c0b70 100644
--- a/repo/i18n/en.json
+++ b/repo/i18n/en.json
@@ -242,6 +242,12 @@
        "wikibase-listdatatypes-intro": "This is a list of all data types 
available on this installation:",
        "wikibase-history-title-with-label": "Revision history of \"$2\" ($1)",
        "wikibase-history-title-without-label": "Revision history of ($1)",
+       "special-listproperties": "List of properties",
+       "wikibase-listproperties-legend": "Get a list of properties by data 
type",
+       "wikibase-listproperties-datatype": "Data type:",
+       "wikibase-listproperties-all": "All data types",
+       "wikibase-listproperties-submit": "Find",
+       "wikibase-listproperties-invalid-datatype": "\"$1\" is not a valid data 
type.",
        "special-entitieswithoutdescription": "Entities without description",
        "wikibase-entitieswithoutdescription-legend": "Get list of entities 
without description",
        "special-entitieswithoutlabel": "Entities without label",
diff --git a/repo/i18n/qqq.json b/repo/i18n/qqq.json
index fb7ee41..d36e48d 100644
--- a/repo/i18n/qqq.json
+++ b/repo/i18n/qqq.json
@@ -270,6 +270,12 @@
        "wikibase-listdatatypes-intro": "Intro text for the ListDatatypes 
special page.",
        "wikibase-history-title-with-label": "The title of the history page 
with label and prefixed id. Parameters:\n* $1 - the prefixed id, the id is 
usually in parenthesis\n* $2 - the localized label, it is usually in quotes",
        "wikibase-history-title-without-label": "The title of the history page 
with only a prefixed id. Parameters:\n* $1 - the prefixed id, the id is usually 
in parenthesis",
+       "special-listproperties": "{{doc-special|ListProperties}}\nThis special 
page returns a list of properties for a given datatype (such as commonsMedia)",
+       "wikibase-listproperties-legend": "Legend for the ListProperties 
special page.",
+       "wikibase-listproperties-datatype": "Label for the datatype 
dropdown.\n{{Identical|Data type}}",
+       "wikibase-listproperties-all": "Option to select that properties with 
all data types should be shown.",
+       "wikibase-listproperties-submit": "Label for the button that activates 
the action.\n{{Identical|Find}}",
+       "wikibase-listproperties-invalid-datatype": "Error message shown when 
the data type passed in parameter is invalid.\n\nParameters:\n* $1 - data type",
        "special-entitieswithoutdescription": 
"{{doc-special|EntitiesWithoutDescription}}\nThis special page returns a list 
of entities without description for a given language",
        "wikibase-entitieswithoutdescription-legend": "Legend of the form that 
allow to change the language.",
        "special-entitieswithoutlabel": 
"{{doc-special|EntitiesWithoutLabel}}\nThis special page returns a list of 
entities without label for a given language",
diff --git a/repo/includes/DataTypeSelector.php 
b/repo/includes/DataTypeSelector.php
index f0ae7fa..5e89dad 100644
--- a/repo/includes/DataTypeSelector.php
+++ b/repo/includes/DataTypeSelector.php
@@ -1,6 +1,7 @@
 <?php
 
 namespace Wikibase;
+
 use DataTypes\DataType;
 use Html;
 use MWException;
@@ -55,10 +56,36 @@
         *
         * @param string $id
         * @param string $name
+        * @param string $selectedTypeId
         *
         * @return string
         */
-       public function getHtml( $id = 'datatype', $name = 'datatype' ) {
+       public function getHtml( $id = 'datatype', $name = 'datatype', 
$selectedTypeId = '' ) {
+               $options = $this->getOptionsHtml( $selectedTypeId );
+
+               $html = Html::rawElement(
+                       'select',
+                       array(
+                               'name' => $name,
+                               'id' => $id,
+                               'class' => 'wb-select'
+                       ),
+                       $options
+               );
+
+               return $html;
+       }
+
+       /**
+        * Builds and returns the html for the options of the DataType selector.
+        *
+        * @since 0.5
+        *
+        * @param string $selectedTypeId
+        *
+        * @return string
+        */
+       public function getOptionsHtml( $selectedTypeId = '' ) {
                $dataTypes = array();
 
                foreach ( $this->dataTypes as $dataType ) {
@@ -72,20 +99,13 @@
                foreach ( $dataTypes as $typeId => $typeLabel ) {
                        $html .= Html::element(
                                'option',
-                               array( 'value' => $typeId ),
+                               array(
+                                       'value' => $typeId,
+                                       'selected' => $typeId === 
$selectedTypeId
+                               ),
                                $typeLabel
                        );
                }
-
-               $html = Html::rawElement(
-                       'select',
-                       array(
-                               'name' => $name,
-                               'id' => $id,
-                               'class' => 'wb-select'
-                       ),
-                       $html
-               );
 
                return $html;
        }
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 54574b7..9f37b90 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -1002,7 +1002,10 @@
                return $this->entityNamespaceLookup;
        }
 
-       private function getEntityIdHtmlLinkFormatterFactory() {
+       /**
+        * @return EntityIdHtmlLinkFormatterFactory
+        */
+       public function getEntityIdHtmlLinkFormatterFactory() {
                return new EntityIdHtmlLinkFormatterFactory(
                        $this->getEntityTitleLookup(),
                        new LanguageNameLookup()
diff --git a/repo/includes/specials/SpecialListProperties.php 
b/repo/includes/specials/SpecialListProperties.php
new file mode 100644
index 0000000..2732232
--- /dev/null
+++ b/repo/includes/specials/SpecialListProperties.php
@@ -0,0 +1,246 @@
+<?php
+
+namespace Wikibase\Repo\Specials;
+
+use DataTypes\DataTypeFactory;
+use Html;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataTypeSelector;
+use Wikibase\LanguageFallbackChainFactory;
+use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookup;
+use Wikibase\Lib\Store\TermLookup;
+use Wikibase\PropertyInfoStore;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Store\TermBuffer;
+use Wikibase\View\EntityIdFormatterFactory;
+
+/**
+ * Special page to list properties by data type
+ *
+ * @since 0.5
+ * @licence GNU GPL v2+
+ * @author Bene* < benestar.wikime...@gmail.com >
+ */
+class SpecialListProperties extends SpecialWikibasePage {
+
+       /**
+        * Max server side caching time in seconds.
+        *
+        * @type integer
+        */
+       const CACHE_TTL_IN_SECONDS = 30;
+
+       /**
+        * @var DataTypeFactory
+        */
+       private $dataTypeFactory;
+
+       /**
+        * @var PropertyInfoStore
+        */
+       private $propertyInfoStore;
+
+       /**
+        * @var LanguageFallbackChainFactory
+        */
+       private $languageFallbackChainFactory;
+
+       /**
+        * @var TermLookup
+        */
+       private $termLookup;
+
+       /**
+        * @var TermBuffer
+        */
+       private $termBuffer;
+
+       /**
+        * @var EntityIdFormatterFactory
+        */
+       private $entityIdFormatterFactory;
+
+       /**
+        * @var string
+        */
+       private $dataType;
+
+       public function __construct() {
+               parent::__construct( 'ListProperties' );
+
+               $this->initServices(
+                       
WikibaseRepo::getDefaultInstance()->getDataTypeFactory(),
+                       
WikibaseRepo::getDefaultInstance()->getStore()->getPropertyInfoStore(),
+                       
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory(),
+                       WikibaseRepo::getDefaultInstance()->getTermLookup(),
+                       WikibaseRepo::getDefaultInstance()->getTermBuffer(),
+                       
WikibaseRepo::getDefaultInstance()->getEntityIdHtmlLinkFormatterFactory()
+               );
+       }
+
+       /**
+        * Set service objects to use. Unit tests may call this to substitute 
mock
+        * services.
+        */
+       public function initServices(
+               DataTypeFactory $dataTypeFactory,
+               PropertyInfoStore $propertyInfoStore,
+               LanguageFallbackChainFactory $languageFallbackChainFactory,
+               TermLookup $termLookup,
+               TermBuffer $termBuffer,
+               EntityIdFormatterFactory $entityIdFormatterFactory
+       ) {
+               $this->dataTypeFactory = $dataTypeFactory;
+               $this->propertyInfoStore = $propertyInfoStore;
+               $this->languageFallbackChainFactory = 
$languageFallbackChainFactory;
+               $this->termLookup = $termLookup;
+               $this->termBuffer = $termBuffer;
+               $this->entityIdFormatterFactory = $entityIdFormatterFactory;
+       }
+
+       /**
+        * @see SpecialWikibasePage::execute
+        *
+        * @since 0.5
+        *
+        * @param string|null $subPage
+        */
+       public function execute( $subPage ) {
+               parent::execute( $subPage );
+
+               $output = $this->getOutput();
+               $output->setSquidMaxage( static::CACHE_TTL_IN_SECONDS );
+
+               $this->prepareArguments( $subPage );
+               $this->showForm();
+
+               if ( $this->dataType !== null ) {
+                       $this->showQuery();
+               }
+       }
+
+       private function prepareArguments( $subPage ) {
+               $request = $this->getRequest();
+
+               $this->dataType = $request->getText( 'datatype', $subPage );
+               if ( $this->dataType !== '' && !in_array( $this->dataType, 
$this->dataTypeFactory->getTypeIds() ) ) {
+                       $this->showErrorHTML( $this->msg( 
'wikibase-listproperties-invalid-datatype', $this->dataType )->escaped() );
+                       $this->dataType = null;
+               }
+       }
+
+       private function showForm() {
+               $dataTypeSelect = new DataTypeSelector(
+                       $this->dataTypeFactory->getTypes() + array( 'all' ),
+                       $this->getLanguage()->getCode()
+               );
+
+               $this->getOutput()->addHTML(
+                       Html::openElement(
+                               'form',
+                               array(
+                                       'action' => 
$this->getPageTitle()->getLocalURL(),
+                                       'name' => 'listproperties',
+                                       'id' => 'wb-listproperties-form'
+                               )
+                       ) .
+                       Html::openElement( 'fieldset' ) .
+                       Html::element(
+                               'legend',
+                               array(),
+                               $this->msg( 'wikibase-listproperties-legend' 
)->text()
+                       ) .
+                       Html::openElement( 'p' ) .
+                       Html::element(
+                               'label',
+                               array(
+                                       'for' => 'wb-listproperties-datatype'
+                               ),
+                               $this->msg( 'wikibase-listproperties-datatype' 
)->text()
+                       ) . ' ' .
+                       Html::rawElement(
+                               'select',
+                               array(
+                                       'name' => 'datatype',
+                                       'id' => 'wb-listproperties-datatype',
+                                       'class' => 'wb-select'
+                               ),
+                               Html::element(
+                                       'option',
+                                       array(
+                                               'value' => '',
+                                               'selected' => $this->dataType 
=== ''
+                                       ),
+                                       $this->msg( 
'wikibase-listproperties-all' )->text()
+                               ) .
+                               $dataTypeSelect->getOptionsHtml( 
$this->dataType )
+                       ) . ' ' .
+                       Html::input(
+                               '',
+                               $this->msg( 'wikibase-listproperties-submit' 
)->text(),
+                               'submit',
+                               array(
+                                       'id' => 
'wikibase-listproperties-submit',
+                                       'class' => 'wb-input-button'
+                               )
+                       ) .
+                       Html::closeElement( 'p' ) .
+                       Html::closeElement( 'fieldset' ) .
+                       Html::closeElement( 'form' )
+               );
+       }
+
+       private function showQuery() {
+               $propertyIds = $this->getPropertyIds();
+
+               if ( empty( $propertyIds ) ) {
+                       $this->getOutput()->addWikiMsg( 'specialpage-empty' );
+                       return;
+               }
+
+               $languageFallbackChain = 
$this->languageFallbackChainFactory->newFromLanguage(
+                       $this->getLanguage(),
+                       LanguageFallbackChainFactory::FALLBACK_SELF
+                               | 
LanguageFallbackChainFactory::FALLBACK_VARIANTS
+                               | LanguageFallbackChainFactory::FALLBACK_OTHERS
+               );
+               $languages = $languageFallbackChain->getFetchLanguageCodes();
+               $labelDescriptionLookup = new 
LanguageFallbackLabelDescriptionLookup(
+                       $this->termLookup,
+                       $languageFallbackChain
+               );
+               $formatter = 
$this->entityIdFormatterFactory->getEntityIdFormater( $labelDescriptionLookup );
+
+               $this->termBuffer->prefetchTerms( $propertyIds, array( 'label' 
), $languages );
+
+               $html = Html::openElement( 'ul' );
+
+               foreach ( $propertyIds as $propertyId ) {
+                       $html .= Html::rawElement( 'li', array(), 
$formatter->formatEntityId( $propertyId ) );
+               }
+
+               $html .= Html::closeElement( 'ul' );
+               $this->getOutput()->addHTML( $html );
+       }
+
+       /**
+        * @return PropertyId[]
+        */
+       private function getPropertyIds() {
+               if ( $this->dataType === '' ) {
+                       $propertyInfoForDataType = 
$this->propertyInfoStore->getAllPropertyInfo();
+               } else {
+                       $propertyInfoForDataType = 
$this->propertyInfoStore->getPropertyInfoForDataType( $this->dataType );
+               }
+
+               $propertyIds = array();
+
+               foreach ( $propertyInfoForDataType as $numericId => $info ) {
+                       $propertyIds[] = PropertyId::newFromNumber( $numericId 
);
+               }
+
+               return $propertyIds;
+       }
+
+}
+
diff --git a/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php 
b/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
new file mode 100644
index 0000000..4297813
--- /dev/null
+++ b/repo/tests/phpunit/includes/specials/SpecialListPropertiesTest.php
@@ -0,0 +1,159 @@
+<?php
+
+namespace Wikibase\Test;
+
+use DataTypes\DataType;
+use DataTypes\DataTypeFactory;
+use Language;
+use Title;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\LanguageFallbackChainFactory;
+use Wikibase\Lib\LanguageNameLookup;
+use Wikibase\PropertyInfoStore;
+use Wikibase\Repo\EntityIdHtmlLinkFormatterFactory;
+use Wikibase\Repo\Specials\SpecialListProperties;
+use Wikibase\Test\SpecialPageTestBase;
+
+/**
+ * @covers Wikibase\Repo\Specials\SpecialListProperties
+ *
+ * @group Wikibase
+ * @group WikibaseRepo
+ * @group SpecialPage
+ * @group WikibaseSpecialPage
+ *
+ * @licence GNU GPL v2+
+ * @author Bene* < benestar.wikime...@gmail.com >
+ */
+class SpecialListPropertiesTest extends SpecialPageTestBase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgContLang' => Language::factory( 'qqx' )
+               ) );
+       }
+
+       private function getDataTypeFactory() {
+               $dataTypeFactory = DataTypeFactory::newFromTypes( array(
+                       new DataType( 'wikibase-item', 'wikibase-item', array() 
),
+                       new DataType( 'string', 'string', array() ),
+                       new DataType( 'quantity', 'quantity', array() )
+               ) );
+
+               return $dataTypeFactory;
+       }
+
+       private function getPropertyInfoStore() {
+               $propertyInfoStore = new MockPropertyInfoStore();
+
+               $propertyInfoStore->setPropertyInfo(
+                       new PropertyId( 'P123' ),
+                       array( PropertyInfoStore::KEY_DATA_TYPE => 
'wikibase-item' )
+               );
+
+               $propertyInfoStore->setPropertyInfo(
+                       new PropertyId( 'P456' ),
+                       array( PropertyInfoStore::KEY_DATA_TYPE => 
'wikibase-item' )
+               );
+
+               $propertyInfoStore->setPropertyInfo(
+                       new PropertyId( 'P789' ),
+                       array( PropertyInfoStore::KEY_DATA_TYPE => 'string' )
+               );
+
+               return $propertyInfoStore;
+       }
+
+       private function getTermLookup() {
+               $termLookup = $this->getMock( 'Wikibase\Lib\Store\TermLookup' );
+               $termLookup->expects( $this->any() )
+                       ->method( 'getLabels' )
+                       ->will( $this->returnCallback( function( PropertyId 
$propertyId ) {
+                               return array( 'en' => 'Property with label ' . 
$propertyId->getSerialization() );
+                       } ) );
+
+               return $termLookup;
+       }
+
+       private function getTermBuffer() {
+               $termBuffer = $this->getMock( 'Wikibase\Store\TermBuffer' );
+               $termBuffer->expects( $this->any() )
+                       ->method( 'prefetchTerms' );
+
+               return $termBuffer;
+       }
+
+       private function getEntityTitleLookup() {
+               $entityTitleLookup = $this->getMock( 
'Wikibase\Lib\Store\EntityTitleLookup' );
+               $entityTitleLookup->expects( $this->any() )
+                       ->method( 'getTitleForId' )
+                       ->will( $this->returnCallback(
+                               function ( EntityId $id ) {
+                                       return Title::makeTitle( NS_MAIN, 
$id->getSerialization() );
+                               }
+                       ) );
+
+               return $entityTitleLookup;
+       }
+
+       protected function newSpecialPage() {
+               $specialPage = new SpecialListProperties();
+
+               $specialPage->initServices(
+                       $this->getDataTypeFactory(),
+                       $this->getPropertyInfoStore(),
+                       new LanguageFallbackChainFactory(),
+                       $this->getTermLookup(),
+                       $this->getTermBuffer(),
+                       new EntityIdHtmlLinkFormatterFactory( 
$this->getEntityTitleLookup(), new LanguageNameLookup() )
+               );
+
+               return $specialPage;
+       }
+
+       public function testExecute() {
+               // This also tests that there is no fatal error, that the 
restriction handling is working
+               // and doesn't block. That is, the default should let the user 
execute the page.
+               list( $output, ) = $this->executeSpecialPage( '' );
+
+               $this->assertInternalType( 'string', $output );
+               $this->assertContains( 'wikibase-listproperties-summary', 
$output );
+               $this->assertContains( 'wikibase-listproperties-legend', 
$output );
+               $this->assertNotContains( 
'wikibase-listproperties-invalid-datatype', $output );
+       }
+
+       public function testExecute_empty() {
+               list( $output, ) = $this->executeSpecialPage( 'quantity' );
+
+               $this->assertContains( 'specialpage-empty', $output );
+       }
+
+       public function testExecute_error() {
+               list( $output, ) = $this->executeSpecialPage( 'test<>' );
+
+               $this->assertContains( 
'wikibase-listproperties-invalid-datatype', $output );
+               $this->assertContains( 'test&lt;&gt;', $output );
+       }
+
+       public function testExecute_wikibase_item() {
+               // Use en-gb as language to test language fallback
+               list( $output, ) = $this->executeSpecialPage( 'wikibase-item', 
null, 'en-gb' );
+
+               $this->assertContains( 'Property with label P123', $output );
+               $this->assertContains( 'Property with label P456', $output );
+               $this->assertNotContains( 'P789', $output );
+       }
+
+       public function testExecute_string() {
+               list( $output, ) = $this->executeSpecialPage( 'string', null, 
'en-gb' );
+
+               $this->assertNotContains( 'P123', $output );
+               $this->assertNotContains( 'P456', $output );
+               $this->assertContains( 'Property with label P789', $output );
+       }
+
+}
+

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I79a08ec87bf76adba869d4b7eb22098b41fbdb72
Gerrit-PatchSet: 13
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Bene <benestar.wikime...@gmail.com>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Bene <benestar.wikime...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Hoo man <h...@online.de>
Gerrit-Reviewer: Jeroen De Dauw <jeroended...@gmail.com>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: Lydia Pintscher <lydia.pintsc...@wikimedia.de>
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

Reply via email to