jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/361498 )

Change subject: Dynamic experts' registration
......................................................................


Dynamic experts' registration

Bug: T167964
Change-Id: I0252d16ec531b4aee65e51029fee3051b37f872e
Depends-On: I1ef5de1b6a49bcc1b0b4d1992143b16bc3a1f4c2
---
M .eslintrc.json
M composer.json
M lib/includes/DataTypeDefinitions.php
M lib/tests/phpunit/DataTypeDefinitionsTest.php
M repo/WikibaseRepo.datatypes.php
A repo/includes/Modules/PropertyValueExpertsModule.php
M repo/includes/WikibaseRepo.php
M repo/resources/Resources.php
M repo/resources/experts/Item.js
M repo/resources/experts/Property.js
M repo/resources/experts/getStore.js
M repo/resources/experts/resources.php
A view/tests/qunit/experts/wikibase.experts.modules.tests.js
M view/tests/qunit/resources.php
14 files changed, 196 insertions(+), 22 deletions(-)

Approvals:
  WMDE-leszek: Checked; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/.eslintrc.json b/.eslintrc.json
index caa1719..de4c388 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -6,6 +6,7 @@
        },
        "globals": {
                "mediaWiki": false,
+               "module": false,
                "dataTypes": false,
                "dataValues": false,
                "OO": false,
diff --git a/composer.json b/composer.json
index c3d5d66..82efc07 100644
--- a/composer.json
+++ b/composer.json
@@ -31,7 +31,7 @@
                "data-values/data-types": "^1.0.0",
                "data-values/serialization": "^1.2.1",
                "data-values/javascript": "^0.8.3",
-               "data-values/value-view": "^0.19.1",
+               "data-values/value-view": "^0.19.2",
                "wikibase/data-model": "^7.0.0",
                "wikibase/data-model-serialization": "^2.1.0",
                "wikibase/internal-serialization": "^2.2.0",
diff --git a/lib/includes/DataTypeDefinitions.php 
b/lib/includes/DataTypeDefinitions.php
index 9651626..2891bdb 100644
--- a/lib/includes/DataTypeDefinitions.php
+++ b/lib/includes/DataTypeDefinitions.php
@@ -142,6 +142,23 @@
                return array_keys( $ptDefinitions );
        }
 
+       public function getExpertModules() {
+               $ptDefinitions = $this->getFilteredByPrefix( 
$this->dataTypeDefinitions, 'PT:' );
+
+               $result = [];
+               foreach ( $ptDefinitions as $typeId => $definition ) {
+                       if ( empty( $definition['expert-module'] ) ) {
+                               throw new \UnexpectedValueException(
+                                       "Type definition for '{$typeId}' 
doesn't contain 'expert-module' property"
+                               );
+                       }
+
+                       $result[$typeId] = $definition['expert-module'];
+               }
+
+               return $result;
+       }
+
        /**
         * @param string $field
         *
diff --git a/lib/tests/phpunit/DataTypeDefinitionsTest.php 
b/lib/tests/phpunit/DataTypeDefinitionsTest.php
index 58fd032..6e7ebc2 100644
--- a/lib/tests/phpunit/DataTypeDefinitionsTest.php
+++ b/lib/tests/phpunit/DataTypeDefinitionsTest.php
@@ -154,4 +154,41 @@
                );
        }
 
+       public function 
test_getExpertModules_GivenPropertyType_ReturnsMapFromTypeIdToExpertModule() {
+               $definitions = [
+                       'PT:some-type' => [
+                               'expert-module' => 'some-expert-module',
+                       ]
+               ];
+               $dataTypeDefinitions = new DataTypeDefinitions( $definitions );
+
+               $this->assertEquals(
+                       [ 'some-type' => 'some-expert-module' ],
+                       $dataTypeDefinitions->getExpertModules()
+               );
+       }
+
+       public function 
test_getExpertModules_GivenPropertyTypeWithoutExpertModule_ThrowsAnException() {
+               $definitions = [
+                       'PT:some-type' => [
+                               'expert-module' => '',
+                       ]
+               ];
+               $dataTypeDefinitions = new DataTypeDefinitions( $definitions );
+
+               $this->setExpectedException( \Exception::class );
+               $dataTypeDefinitions->getExpertModules();
+       }
+
+       public function 
test_getExpertModules_GivenValueTypeWithExpertModuleProperty_IgnoresIt() {
+               $definitions = [
+                       'VT:some-type' => [
+                               'expert-module' => '',
+                       ]
+               ];
+               $dataTypeDefinitions = new DataTypeDefinitions( $definitions );
+
+               $this->assertEquals( [], 
$dataTypeDefinitions->getExpertModules() );
+       }
+
 }
diff --git a/repo/WikibaseRepo.datatypes.php b/repo/WikibaseRepo.datatypes.php
index 97c898c..16deeb2 100644
--- a/repo/WikibaseRepo.datatypes.php
+++ b/repo/WikibaseRepo.datatypes.php
@@ -89,6 +89,7 @@
                        }
                ),
                'PT:commonsMedia' => array(
+                       'expert-module' => 
'jquery.valueview.experts.CommonsMediaType',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                // Don't go for commons during unit tests.
@@ -112,6 +113,7 @@
                        },
                ),
                'PT:geo-shape' => array(
+                       'expert-module' => 'jquery.valueview.experts.GeoShape',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                // Don't go for commons during unit tests.
@@ -135,6 +137,7 @@
                        },
                ),
                'PT:tabular-data' => array(
+                       'expert-module' => 
'jquery.valueview.experts.TabularData',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                // Don't go for commons during unit tests.
@@ -279,6 +282,7 @@
                        },
                ),
                'PT:url' => array(
+                       'expert-module' => 
'jquery.valueview.experts.StringValue',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                return $factory->buildUrlValidators();
@@ -299,6 +303,7 @@
                        },
                ),
                'PT:external-id' => array(
+                       'expert-module' => 
'jquery.valueview.experts.StringValue',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                return $factory->buildStringValidators();
@@ -331,13 +336,30 @@
                                return new EntityIdRdfBuilder( $vocab, $tracker 
);
                        },
                ),
+               'PT:globe-coordinate'  => array(
+                       'expert-module' => 
'jquery.valueview.experts.GlobeCoordinateInput',
+               ),
+               'PT:monolingualtext'   => array(
+                       'expert-module' => 
'jquery.valueview.experts.MonolingualText',
+               ),
+               'PT:quantity'          => array(
+                       'expert-module' => 
'jquery.valueview.experts.QuantityInput',
+               ),
+               'PT:string'            => array(
+                       'expert-module' => 
'jquery.valueview.experts.StringValue',
+               ),
+               'PT:time'              => array(
+                       'expert-module' => 'jquery.valueview.experts.TimeInput',
+               ),
                'PT:wikibase-item' => array(
+                       'expert-module' => 'wikibase.experts.Item',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                return $factory->buildItemValidators();
                        },
                ),
                'PT:wikibase-property' => array(
+                       'expert-module' => 'wikibase.experts.Property',
                        'validator-factory-callback' => function() {
                                $factory = 
WikibaseRepo::getDefaultValidatorBuilders();
                                return $factory->buildPropertyValidators();
diff --git a/repo/includes/Modules/PropertyValueExpertsModule.php 
b/repo/includes/Modules/PropertyValueExpertsModule.php
new file mode 100644
index 0000000..063c9a5
--- /dev/null
+++ b/repo/includes/Modules/PropertyValueExpertsModule.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Wikibase\Repo\Modules;
+
+use ResourceLoaderContext;
+use Wikibase\Lib\DataTypeDefinitions;
+
+/**
+ * Module exporting map from property type to expert module name handling this 
type
+ *
+ * @note Tested via wikibase.experts.modules.tests.js
+ */
+class PropertyValueExpertsModule extends \ResourceLoaderModule {
+
+       /**
+        * @var DataTypeDefinitions
+        */
+       private $dataTypeDefinitions;
+
+       public function __construct( DataTypeDefinitions $dataTypeDefinitions ) 
{
+               $this->dataTypeDefinitions = $dataTypeDefinitions;
+       }
+
+       public function getScript( ResourceLoaderContext $context ) {
+               $expertModuleMap = \XML::encodeJsVar( 
$this->dataTypeDefinitions->getExpertModules() );
+
+               $js = <<<JS
+module.exports = ( function () {
+       'use strict';
+       return $expertModuleMap;
+}() );
+JS;
+
+               return $js;
+       }
+
+       public function getDependencies( ResourceLoaderContext $context = null 
) {
+               return array_values( 
$this->dataTypeDefinitions->getExpertModules() );
+       }
+
+}
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 967768f..21b8de5 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -85,6 +85,7 @@
 use Wikibase\Lib\Store\EntityRevisionLookup;
 use Wikibase\Lib\Store\EntityStore;
 use Wikibase\Lib\Store\EntityStoreWatcher;
+use Wikibase\Repo\Modules\PropertyValueExpertsModule;
 use Wikibase\Repo\Modules\SettingsValueProvider;
 use Wikibase\Rdf\EntityRdfBuilderFactory;
 use Wikibase\Repo\ChangeOp\Deserialization\ChangeOpDeserializerFactory;
@@ -1983,4 +1984,8 @@
                return $this->repositoryDefinitions->getConceptBaseUris();
        }
 
+       public function getPropertyValueExpertsModule() {
+               return new PropertyValueExpertsModule( 
$this->getDataTypeDefinitions() );
+       }
+
 }
diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php
index 89940bf..3bbee5c 100644
--- a/repo/resources/Resources.php
+++ b/repo/resources/Resources.php
@@ -2,6 +2,7 @@
 
 use DataTypes\Modules\DataTypesModule;
 use Wikibase\Repo\Modules\MediaWikiConfigModule;
+use Wikibase\Repo\Modules\PropertyValueExpertsModule;
 use Wikibase\Repo\WikibaseRepo;
 
 /**
@@ -172,6 +173,12 @@
                        ),
                ),
 
+               'wikibase.experts.modules' => $moduleTemplate + [
+                               'factory' => function () {
+                                       return 
WikibaseRepo::getDefaultInstance()->getPropertyValueExpertsModule();
+                               }
+               ],
+
        );
 
        return array_merge(
diff --git a/repo/resources/experts/Item.js b/repo/resources/experts/Item.js
index f29df7b..8b3c987 100644
--- a/repo/resources/experts/Item.js
+++ b/repo/resources/experts/Item.js
@@ -1,4 +1,4 @@
-( function ( wb, vv ) {
+module.exports = ( function ( wb, vv ) {
        'use strict';
 
        var MODULE = wb.experts,
@@ -28,4 +28,6 @@
         */
        SELF.TYPE = 'item';
 
+       return SELF;
+
 }( wikibase, jQuery.valueview ) );
diff --git a/repo/resources/experts/Property.js 
b/repo/resources/experts/Property.js
index 9814f07..c4c2b01 100644
--- a/repo/resources/experts/Property.js
+++ b/repo/resources/experts/Property.js
@@ -1,4 +1,4 @@
-( function ( wb, vv ) {
+module.exports = ( function ( wb, vv ) {
        'use strict';
 
        var MODULE = wb.experts,
@@ -28,4 +28,6 @@
         */
        SELF.TYPE = 'property';
 
+       return SELF;
+
 }( wikibase, jQuery.valueview ) );
diff --git a/repo/resources/experts/getStore.js 
b/repo/resources/experts/getStore.js
index a786913..c7e4f52 100644
--- a/repo/resources/experts/getStore.js
+++ b/repo/resources/experts/getStore.js
@@ -5,6 +5,11 @@
 ( function ( wb, vv, dv ) {
        'use strict';
 
+       /**
+        * @type {object} Map from property type to expert module name
+        */
+       var registeredExperts = require( 'wikibase.experts.modules' );
+
        var MODULE = wb.experts;
 
        /**
@@ -41,16 +46,7 @@
                // Register experts for data types defined in Wikibase. Since 
those data types are defined by a
                // setting, it needs to be checked whether they are actually 
defined.
 
-               var dataTypeIdToExpertConstructor = {
-                       commonsMedia: vv.experts.CommonsMediaType,
-                       'geo-shape': vv.experts.GeoShape,
-                       'tabular-data': vv.experts.TabularData,
-                       'external-id': vv.experts.StringValue,
-                       monolingualtext: vv.experts.MonolingualText,
-                       url: vv.experts.StringValue,
-                       'wikibase-item': wb.experts.Item,
-                       'wikibase-property': wb.experts.Property
-               };
+               var dataTypeIdToExpertConstructor = resolveExpertModules( 
registeredExperts );
 
                for ( var dataTypeId in dataTypeIdToExpertConstructor ) {
                        var dataType = dataTypeStore.getDataType( dataTypeId );
@@ -66,4 +62,15 @@
 
        };
 
+       function resolveExpertModules( registeredExperts ) {
+               var constructors = {};
+               for ( var dataType in registeredExperts ) {
+                       if ( registeredExperts.hasOwnProperty( dataType ) ) {
+                               constructors[ dataType ] = require( 
registeredExperts[ dataType ] );
+                       }
+               }
+
+               return constructors;
+       }
+
 }( wikibase, jQuery.valueview, dataValues ) );
diff --git a/repo/resources/experts/resources.php 
b/repo/resources/experts/resources.php
index fe1c8e3..a589be1 100644
--- a/repo/resources/experts/resources.php
+++ b/repo/resources/experts/resources.php
@@ -30,22 +30,15 @@
                                'getStore.js',
                        ),
                        'dependencies' => array(
+                               'wikibase.experts.modules',
                                'dataValues.values',
                                'jquery.valueview.ExpertStore',
-                               'jquery.valueview.experts.CommonsMediaType',
-                               'jquery.valueview.experts.GeoShape',
                                'jquery.valueview.experts.GlobeCoordinateInput',
-                               'jquery.valueview.experts.MonolingualText',
                                'jquery.valueview.experts.QuantityInput',
                                'jquery.valueview.experts.StringValue',
-                               'jquery.valueview.experts.TabularData',
                                'jquery.valueview.experts.TimeInput',
                                
'jquery.valueview.experts.UnDeserializableValue',
                                'jquery.valueview.experts.UnsupportedValue',
-                               'wikibase.datamodel.EntityId',
-                               'wikibase.experts.__namespace',
-                               'wikibase.experts.Item',
-                               'wikibase.experts.Property',
                        ),
                ),
 
diff --git a/view/tests/qunit/experts/wikibase.experts.modules.tests.js 
b/view/tests/qunit/experts/wikibase.experts.modules.tests.js
new file mode 100644
index 0000000..a991be3
--- /dev/null
+++ b/view/tests/qunit/experts/wikibase.experts.modules.tests.js
@@ -0,0 +1,34 @@
+( function () {
+       'use strict';
+       QUnit.module( 'wikibase.experts.modules' );
+
+       QUnit.test(
+               'module has correct dependencies and every registered property 
type exports expert',
+               function ( assert ) {
+                       var modules = require( 'wikibase.experts.modules' );
+
+                       for ( var propertyType in modules ) {
+                               if ( modules.hasOwnProperty( propertyType ) ) {
+                                       var caughtError = null;
+
+                                       try {
+                                               var module = require( modules[ 
propertyType ] );
+                                               assert.equal(
+                                                       typeof module,
+                                                       'function',
+                                                       'Property type "' + 
propertyType + '" exports a constructor'
+                                               );
+                                       } catch ( e ) {
+                                               caughtError = e;
+                                       }
+
+                                       assert.notOk(
+                                               caughtError,
+                                               'Property type "' + 
propertyType + '" expert is added as a dependency'
+                                       );
+                               }
+                       }
+
+               }
+       );
+}() );
diff --git a/view/tests/qunit/resources.php b/view/tests/qunit/resources.php
index 204c4bf..08c98c2 100644
--- a/view/tests/qunit/resources.php
+++ b/view/tests/qunit/resources.php
@@ -19,7 +19,13 @@
                        'jquery.wikibase.listview',
                        'wikibase.tests',
                )
-       )
+       ),
+       'wikibase.experts.modules.tests' => $moduleBase + [
+               'scripts' => 'experts/wikibase.experts.modules.tests.js',
+               'dependencies' => [
+                       'wikibase.experts.modules'
+               ]
+       ],
 );
 
 return array_merge(

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I0252d16ec531b4aee65e51029fee3051b37f872e
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Aleksey Bekh-Ivanov (WMDE) <[email protected]>
Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <[email protected]>
Gerrit-Reviewer: Jonas Kress (WMDE) <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: WMDE-leszek <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to