Daniel Werner has uploaded a new change for review.

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


Change subject: (bug 55593) use jQuery.wikibase.snakview on Special:SimpleQuery
......................................................................

(bug 55593) use jQuery.wikibase.snakview on Special:SimpleQuery

Introduces more convenient input method for defining property and value of the 
simple query.
Results into wikibase.repo.fetchedEntities being filled with the entities used 
in the simple query
when the page gets loaded again after clicking the execution button.

REQUIRES Ief559fc, Id6ddb49 and I7e10544 in the Wikibase repo.

Change-Id: I5c089e8af1f3d1859e0c2f14d1dfcda4df171cd2
---
M Tests/Unit/Setup/ExtensionSetupTest.php
A WikibaseQuery.resources.php
M src/Wikibase/Query/Setup/ExtensionSetup.php
A src/Wikibase/Query/Specials/SimpleQuery.js
M src/Wikibase/Query/Specials/SimpleQuery.php
5 files changed, 255 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseQuery 
refs/changes/17/89117/1

diff --git a/Tests/Unit/Setup/ExtensionSetupTest.php 
b/Tests/Unit/Setup/ExtensionSetupTest.php
index b27e985..eefecb7 100644
--- a/Tests/Unit/Setup/ExtensionSetupTest.php
+++ b/Tests/Unit/Setup/ExtensionSetupTest.php
@@ -23,7 +23,7 @@
                parent::setUp();
 
                $this->globalVars = array( 'wgHooks' => array() );
-               $this->rootDir = __DIR__;
+               $this->rootDir = __DIR__ . '/../../..';
                $this->dicRegistrant = function() {};
        }
 
@@ -67,4 +67,13 @@
                $this->assertArrayHasKey( 'WikibaseQueryAliases', 
$this->globalVars['wgExtensionMessagesFiles'] );
        }
 
+       public function testResourceLoaderModulesAreRegistered() {
+               $this->runSetup();
+               $this->assertResourceLoaderModulesAreRegistered();
+       }
+
+       protected function assertResourceLoaderModulesAreRegistered() {
+               $this->assertNotEmpty( $this->globalVars['wgResourceModules'] );
+       }
+
 }
diff --git a/WikibaseQuery.resources.php b/WikibaseQuery.resources.php
new file mode 100644
index 0000000..3cdad1f
--- /dev/null
+++ b/WikibaseQuery.resources.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Definition of "WikibaseQuery" resourceloader modules.
+ *
+ * @since 0.1
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ *
+ * @codeCoverageIgnoreStart
+ */
+return call_user_func( function() {
+
+       $moduleTemplate = array(
+               'localBasePath' => __DIR__ . '/src/Wikibase/Query',
+               'remoteExtPath' =>  'WikibaseQuery/src/Wikibase/Query',
+       );
+
+       return array(
+               'wikibase.query.special.simpleQuery' => $moduleTemplate + array(
+                       'scripts' => array(
+                               'Specials/SimpleQuery.js'
+                       ),
+                       'dependencies' => array(
+                               'jquery.ui.suggester',
+                               'jquery.wikibase.snakview',
+                               'wikibase.serialization.fetchedcontent',
+                               'wikibase.serialization.entities',
+                               
'mw.ext.wikibase.repo.fetchedEntitiesFromMwConfig',
+                       ),
+               ),
+       );
+
+} );
+// @codeCoverageIgnoreEnd
diff --git a/src/Wikibase/Query/Setup/ExtensionSetup.php 
b/src/Wikibase/Query/Setup/ExtensionSetup.php
index 4e6ace8..cc44db8 100644
--- a/src/Wikibase/Query/Setup/ExtensionSetup.php
+++ b/src/Wikibase/Query/Setup/ExtensionSetup.php
@@ -35,6 +35,7 @@
                $this->registerInternationalization();
                $this->registerWebAPI();
                $this->registerSpecialPages();
+               $this->registerResourceLoaderModules();
        }
 
        protected function registerDic() {
@@ -80,4 +81,11 @@
                $this->globalVars['wgSpecialPageGroups']['SimpleQuery'] = 
'wikibaserepo';
        }
 
+       protected function registerResourceLoaderModules() {
+               $modules = include( $this->rootDirectory . 
'/WikibaseQuery.resources.php' );
+
+               foreach( $modules as $moduleName => $module ) {
+                       $this->globalVars['wgResourceModules'][ $moduleName ] = 
$module;
+               }
+       }
 }
diff --git a/src/Wikibase/Query/Specials/SimpleQuery.js 
b/src/Wikibase/Query/Specials/SimpleQuery.js
new file mode 100644
index 0000000..33c11b8
--- /dev/null
+++ b/src/Wikibase/Query/Specials/SimpleQuery.js
@@ -0,0 +1,98 @@
+/**
+ * JavaScript for "SimpleQuery" special page. Initializes widgets for better 
user experience on
+ * top of the special page.
+ *
+ * @since 0.1
+ * @licence GNU GPL v2+
+ * @author Daniel Werner < daniel.wer...@wikimedia.de >
+ */
+( function( $ ) {
+       'use strict';
+
+       $( document ).ready( function() {
+               // TODO: Split this function up a little.
+
+               var $form = $( '#wb-SimpleQuery-form' );
+               var $formMembers = $form.children( 'fieldset' ).children();
+               var $legend = $formMembers.filter( 'legend' );
+               var $button = $formMembers.filter( '.wb-input-button' );
+
+               var propertyId = $formMembers.find( 
'#wb-specialsimplequery-property' ).val() || null;
+               var valueJsonString = $formMembers.find( 
'#wb-specialsimplequery-valuejson' ).val();
+               var dataValue;
+
+               try{
+                       var valueJson = $.secureEvalJSON( valueJsonString ) || 
null;
+                       dataValue = valueJson && dataValues.newDataValue( 
valueJson.type, valueJson.value );
+               } catch( error ) {
+                       dataValue = null;
+               }
+
+               var $snakview = $( '<div/>' ).snakview( {
+                       value: {
+                               property: propertyId,
+                               // Only supports property-value paris right 
now, basically PropertyValueSnaks, ...
+                               snaktype: wb.PropertyValueSnak.TYPE,
+                               datavalue: dataValue
+                       },
+                       locked: {
+                               snaktype: true // ...so prevent user from 
choosing different snak types.
+                       }
+               } );
+               var snakview = $snakview.data( 'snakview' );
+               snakview.startEditing();
+
+               // TODO: (Bug 54021) Hack to prevent from leaving edit mode on 
Enter/ESC.
+               snakview.stopEditing = $.noop;
+
+               function setButtonState() {
+                       $button.prop( 'disabled', !snakview.snak() );
+                       return true;
+               }
+
+               $formMembers.not( $legend.add( $button ) ).remove();
+               $legend.after( $snakview );
+
+               // TODO: Implement a snakview.focus which focuses the property 
input or the variation if
+               //  the property has been chosen already.
+               snakview.$property.find( 'input' ).focus();
+
+               $snakview.on( 'snakviewchange', setButtonState );
+               setButtonState();
+
+               $form.on( 'submit', function( event ) {
+                       var snakviewValue = snakview.value();
+                       var $hiddenFields =
+                               buildHiddenFormFields( snakviewValue.property, 
snakviewValue.datavalue );
+
+                       $form.append( $hiddenFields );
+               } );
+       } );
+
+       /**
+        * Creates the hidden fields to be injected into the form before being 
sent so the request
+        * represents the property and value chosen by the user via the 
snakview.
+        */
+       function buildHiddenFormFields( property, dataValue ) {
+               var fullValueJson = {
+                       type: dataValue.getType(),
+                       value: dataValue.toJSON()
+               };
+
+               var $propertyField = $( '<input>', {
+                       type: 'hidden',
+                       name: 'property',
+                       value: property,
+                       id: 'wb-specialsimplequery-property'
+               } );
+               var $valueField = $( '<input>', {
+                       type: 'hidden',
+                       name: 'valuejson',
+                       value: $.toJSON( fullValueJson ),
+                       id: 'wb-specialsimplequery-valuejson'
+               } );
+
+               return $propertyField.add( $valueField );
+       }
+
+}( jQuery ) );
diff --git a/src/Wikibase/Query/Specials/SimpleQuery.php 
b/src/Wikibase/Query/Specials/SimpleQuery.php
index e4fec08..e142ed8 100644
--- a/src/Wikibase/Query/Specials/SimpleQuery.php
+++ b/src/Wikibase/Query/Specials/SimpleQuery.php
@@ -2,9 +2,18 @@
 
 namespace Wikibase\Query\Specials;
 
-use Wikibase\Query\DIC\ExtensionAccess;
-use Wikibase\Lib\Specials\SpecialWikibaseQueryPage;
+use Exception;
 use Html;
+use FormatJson;
+use Wikibase\Query\DIC\ExtensionAccess;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Lib\Specials\SpecialWikibaseQueryPage;
+use Wikibase\WikiPageEntityLookup;
+use Wikibase\EntityContentFactory;
+use Wikibase\ReferencedEntitiesFinder;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\Serializers\EntityRevisionSerializer;
 
 /**
  * Special page that allows for querying for all entities with at least one 
PropertySnak using a
@@ -46,8 +55,80 @@
                        ) )
                );
 
+               $this->addFrontendEntityStoreData();
+               $output->addModules( 'wikibase.query.special.simpleQuery' );
+
                $this->showQuery();
                return true;
+       }
+
+       /**
+        * Adds the information required for frontend widgets to display labels 
of used entities
+        * properly.
+        *
+        * @since 0.5
+        */
+       protected function addFrontendEntityStoreData() {
+               $usedEntities = $this->getReferencedEntitiesFromDataValueJson( 
$this->valueJson );
+               try{
+                       $usedEntities[] = new PropertyId( $this->propertyId );
+               } catch( Exception $e ) {}
+
+               $basicEntityInfo = $this->getUsedEntitiesSerializations( 
$usedEntities );
+
+               $this->getOutput()->addJsConfigVars(
+                       'wbUsedEntities',
+                       FormatJson::encode( $basicEntityInfo )
+               );
+       }
+
+       /**
+        * Gets the referenced entities from a serialized value JSON string.
+        *
+        * @since 0.5
+        *
+        * @param string $valueJson
+        * @return EntityId[]
+        */
+       protected function getReferencedEntitiesFromDataValueJson( $valueJson ) 
{
+               $dataValueFactory = 
WikibaseRepo::getDefaultInstance()->getDataValueFactory();
+
+               $valueJson = json_decode( $valueJson, true );
+               if( !is_array( $valueJson ) ) {
+                       return array();
+               }
+               try {
+                       $dataValue = $dataValueFactory->newFromArray( 
$valueJson );
+               } catch( Exception $e ) {
+                       return array();
+               }
+
+               $entityFinder = new ReferencedEntitiesFinder();
+               return $entityFinder->findDataValueLinks( $dataValue );
+       }
+
+       /**
+        * @param EntityId[] $entityIds
+        *
+        * @return array
+        */
+       protected function getUsedEntitiesSerializations( $entityIds ) {
+               $entityInfo = array();
+
+               $entityTitleLookup = 
WikibaseRepo::getDefaultInstance()->getEntityContentFactory();
+               $entityRevisionLookup = new WikiPageEntityLookup( false, false 
);
+
+               $langCode = $this->getLanguage()->getCode();
+               $serializer = EntityRevisionSerializer::newForFrontendStore( 
$entityTitleLookup, $langCode );
+
+               foreach( $entityIds as $entityId ) {
+                       $entityRevision = 
$entityRevisionLookup->getEntityRevision( $entityId );
+                       if( $entityRevision !== null ) {
+                               $serialization = $serializer->getSerialized( 
$entityRevision );
+                               $entityInfo[ $entityId->getPrefixedId() ] = 
$serialization;
+                       }
+               }
+               return $entityInfo;
        }
 
        /**
@@ -69,12 +150,34 @@
                        //  class had to be refactored and more specific 
exception implementations would be
                        //  useful as well.
                        return array();
+               } catch( \Exception $e ) {
+                       // Catch whatever could possibly go wrong.
+                       return array();
                }
 
                return $entityIds;
        }
 
        /**
+        * @param EntityId[] $ids
+        *
+        * @return (EntityRevision|null)[] A map from IDs to the respective 
entities.
+        *         If no entity is found for a given ID, the respective entry 
in the map will be null.
+        */
+       private function getEntityRevisions( array $ids ) {
+               $entityRevisionLookup = new WikiPageEntityLookup( false, false 
);
+               $revisions = array();
+
+               foreach ( $ids as $id ) {
+                       $key = $id->getPrefixedId();
+                       $revision = $entityRevisionLookup->getEntityRevision( 
$id );
+                       $revisions[$key] = $revision;
+               }
+
+               return $revisions;
+       }
+
+       /**
         * Creates HTML for a search form suitable for the special page's 
purpose.
         *
         * @since 0.1

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5c089e8af1f3d1859e0c2f14d1dfcda4df171cd2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikibaseQuery
Gerrit-Branch: master
Gerrit-Owner: Daniel Werner <daniel.wer...@wikimedia.de>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Daniel Werner <daniel.wer...@wikimedia.de>
Gerrit-Reviewer: Henning Snater <henning.sna...@wikimedia.de>
Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@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