Tobias Gritschacher has uploaded a new change for review. https://gerrit.wikimedia.org/r/52040
Change subject: Make use of new data model constructors all over the UI now ...................................................................... Make use of new data model constructors all over the UI now * replaced wb.entities with wb.fetchedEntities, holding wb.FetchedContent now instead of wb.Entity instances. Includes some tests. * wb.entity is a wb.Entity object representing the site's entity now. * for unserializing JSON in entityViewInit we now use the wikibase.serialization module. * wb.entityview is expecting a wb.Entity object instead of a loose data structure now. * removed/changed some todos Change-Id: I40bcc945610fe6f32e89fc12ea3b0def3126317a --- M lib/resources/jquery.valueview.views/wikibaseItem.js M lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js M lib/resources/jquery.wikibase/jquery.wikibase.claimview.js M lib/resources/jquery.wikibase/jquery.wikibase.entityview.js M lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js M lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.variations.Value.js M lib/resources/wikibase.js M lib/resources/wikibase.utilities/wikibase.utilities.ui.js M lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js M repo/includes/EntityView.php M repo/resources/Resources.php M repo/resources/wikibase.ui.entityViewInit.js 12 files changed, 114 insertions(+), 86 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/40/52040/1 diff --git a/lib/resources/jquery.valueview.views/wikibaseItem.js b/lib/resources/jquery.valueview.views/wikibaseItem.js index 5e4140b..3bd4f26 100644 --- a/lib/resources/jquery.valueview.views/wikibaseItem.js +++ b/lib/resources/jquery.valueview.views/wikibaseItem.js @@ -72,14 +72,20 @@ $( this ).data( 'entityselector' ).repositionMenu(); } ) .on( 'entityselectorselect', function( e, ui ) { + var itemData = { + id: ui.item.id, + label: {} + }; + itemData.label[ language ] = ui.item.label; + // update local store with newest information about selected item // TODO: create more sophisticated local store interface rather than accessing - // wb.entities directly - wb.entities[ ui.item.id ] = { - id: ui.item.id, - label: ui.item.label, - url: ui.item.url - }; + // wb.fetchedEntities directly + wb.fetchedEntities[ ui.item.id ] = new wb.store.FetchedContent( { + // TODO: *terrible* solution to use regex, entityselector should provide title + title: new mw.Title( ui.item.url.match( /[^\/]+$/ )[0] ), + content: new wb.Item( itemData ) + } ); } ) .on( // "aftersetentity": When setting the entity programmatically (editing an existing @@ -101,20 +107,22 @@ _displayValue: function( value ) { if( this.$input ) { var entityId = value === null ? null : value.getPrefixedId( WB_ENTITIES_PREFIXMAP ), - entity = entityId ? wb.entities[ entityId ] : null, + fetchedEntity = entityId ? wb.fetchedEntities[ entityId ] : null, simpleEntity = null; - if( entity ) { + if( fetchedEntity ) { // entity selector requires very basic data only, but ID has to be set which is - // not the case in the wb.entities entity store. + // not the case in the wb.fetchedEntities entity store. simpleEntity = { - label: entity.label, + label: fetchedEntity.getContent().getLabel(), id: entityId }; } // in edit mode: this.$input.data( 'entityselector' ).selectedEntity( simpleEntity ); + // TODO: entityselector should just be able to handle wb.Entity without making it a + // dependency there. } else { // in static mode: PARENT.prototype._displayValue.call( this, value ); @@ -129,8 +137,8 @@ return ''; } var itemId = value.getPrefixedId( WB_ENTITIES_PREFIXMAP ), - item = wb.entities[ itemId ], - url = item ? item.url : false; + fetchedItem = wb.fetchedEntities[ itemId ], + url = fetchedItem ? fetchedItem.getTitle().getUrl() : false; return url || ''; }, @@ -143,19 +151,21 @@ return ''; } var itemId = value.getPrefixedId( WB_ENTITIES_PREFIXMAP ), - item = wb.entities[ itemId ]; + fetchedItem = wb.fetchedEntities[ itemId ]; - if( !item ) { + if( !fetchedItem ) { return itemId; } - if( !item.label ) { + var label = fetchedItem.getContent().getLabel(); + + if( !label ) { return $( document.createTextNode( itemId + ' ' ) ).add( $( '<span/>' ).text( '(' + mw.msg( 'wikibase-label-empty' ) + ')' ) ); } - return item.label; + return label; }, /** diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js index 48d9901..b84a6d1 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimlistview.js @@ -254,11 +254,11 @@ var $section = this.$claims.children( '.wb-claim-section-' + mainSnakPropertyId ).first(); if( $section.length === 0 ) { - var property = wb.entities[ mainSnakPropertyId ], + var fetchedProperty = wb.fetchedEntities[ mainSnakPropertyId ], $addClaim, self = this; - if( !property ) { + if( !fetchedProperty ) { // Property info not in local store. // This should not ever happen if used properly, but make sure! throw new Error( 'Information for Property "' + mainSnakPropertyId + '" not found ' @@ -276,7 +276,9 @@ // create new section for first Claim in this section $section = mw.template( 'wb-claim-section', mainSnakPropertyId, // main Snak's property ID - wb.utilities.ui.buildEntityLink( property ), // property name + wb.utilities.ui.buildLinkToEntityPage( // property name + fetchedProperty.getContent(), + fetchedProperty.getTitle().getUrl() ), $addClaim // claim ).appendTo( this.$claims ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js index 4e23194..6b18103 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.claimview.js @@ -171,12 +171,11 @@ } ); if ( this._claim || this.options.predefined.mainSnak ) { - var propertyName; - if ( this._claim ) { - propertyName = wb.entities[this.mainSnak().getPropertyId()].label; - } else { - propertyName = wb.entities[this.options.predefined.mainSnak.property].label; - } + var property = this._claim + ? this.mainSnak().getPropertyId() + : this.options.predefined.mainSnak.property; + + var propertyName = wb.fetchedEntities[ property ].getContent().getLabel(); this.options.helpMessage = mw.msg( 'wikibase-claimview-snak-tooltip', propertyName ); } }, diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js index a7818ae..de592af 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.entityview.js @@ -40,12 +40,13 @@ _create: function() { this.element.empty(); - var $claimsHeading = - $( mw.template( 'wb-section-heading', mw.msg( 'wikibase-statements' ) ) ); + var entity = this.option( 'value' ), + $claimsHeading = + $( mw.template( 'wb-section-heading', mw.msg( 'wikibase-statements' ) ) ); this.$claims = $( '<div/>' ).claimlistview( { - value: this.option( 'value' ).claims, - entityId: this.option( 'value' ).id, + value: entity.getClaims(), + entityId: entity.getId(), listMembersWidget: $.wikibase.statementview } ); diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js index 878c348..e504b6b 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.js @@ -219,13 +219,12 @@ // update local store with newest information about selected property // TODO: create more sophisticated local store interface rather than accessing - // wb.entities directly - wb.entities[ entityId ] = { - id: entityId, - label: entity.getLabel(), - datatype: entity.getDataType().getId(), - url: ui.item.url - }; + // wb.fetchedEntities directly + wb.fetchedEntities[ entityId ] = new wb.store.FetchedContent( { + // TODO: *terrible* solution to use regex, entityselector should provide title + title: new mw.Title( ui.item.url.match( /[^\/]+$/ )[0] ), + content: entity + } ); self.propertyId( entityId ); @@ -706,19 +705,20 @@ drawProperty: function() { var $propertyDom, propertyId = this._propertyId, - property = propertyId ? wb.entities[ propertyId ] : null; + fetchedProperty = propertyId ? wb.fetchedEntities[ propertyId ] : null, + property = fetchedProperty ? fetchedProperty.getContent() : null; if( this.options.locked.property || !this.isInEditMode() ) { // property set and can't be changed afterwards, only display label $propertyDom = property - ? wb.utilities.ui.buildEntityLink( property ) + ? wb.utilities.ui.buildLinkToEntityPage( + property, fetchedProperty.getTitle().getUrl() ) // shouldn't usually happen, only in non-edit mode, while no Snak is set: : $( document.createTextNode( '' ) ); - // TODO: display nice label with link here, just like claimlistview } else { // no property set for this Snak, serve edit view to specify it: var propertySelector = this._getPropertySelector(), - propertyLabel = property && ( property.label || propertyId ) || ''; + propertyLabel = property && ( property.getLabel() || propertyId ) || ''; // TODO: use selectedEntity() or other command to set selected entity in both cases! if( propertySelector ) { diff --git a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.variations.Value.js b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.variations.Value.js index 73cb093..1c8716e 100644 --- a/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.variations.Value.js +++ b/lib/resources/jquery.wikibase/jquery.wikibase.snakview/snakview.variations.Value.js @@ -86,7 +86,7 @@ // directly (also by user interaction) are always rendered immediately if( newValue !== false ) { var propertyId = this._viewState.propertyId(), - dataType = dt.getDataType( wb.entities[ propertyId ].datatype ); + dataType = wb.fetchedEntities[ propertyId ].getContent().getDataType(); // if the new value's type is not the data value type used by the Snak's property // data type, something is very wrong. Display warning! diff --git a/lib/resources/wikibase.js b/lib/resources/wikibase.js index 26f91df..e0ed59f 100644 --- a/lib/resources/wikibase.js +++ b/lib/resources/wikibase.js @@ -61,11 +61,19 @@ /** * Holds very basic information about all entities used in the pages entity view. Entity IDs - * are used as keys for many inner hashes where each has 'id', 'url' and 'label' fields. In case - * of property entities also a 'datatype' field. + * are used as keys for many inner hashes where each is an instance of wb.FetchedContent. + * Each of those wb.FetchedContent instances holds an instance of wb.Entity as its content. This + * entity data might be incomplete though, it is guaranteed that ID, and label are provided, + * for wb.Property instances it is also guaranteed that the datatype is provided. + * + * TODO: This should vanish from here (since its global) and will be replaced with a proper + * store interface which will be injected into each jQuery.wikibase.entityview + * + * @since 0.4 + * * @type {Object} */ - this.entities = {}; + this.fetchedEntities = {}; /** * Will hold a list of all the sites after getSites() was called. This will cache the result. diff --git a/lib/resources/wikibase.utilities/wikibase.utilities.ui.js b/lib/resources/wikibase.utilities/wikibase.utilities.ui.js index 12148fa..f60846e 100644 --- a/lib/resources/wikibase.utilities/wikibase.utilities.ui.js +++ b/lib/resources/wikibase.utilities/wikibase.utilities.ui.js @@ -101,30 +101,31 @@ }; /** - * Creates a pretty link to a entity's page. Expects information about the Entity as a plain - * Object with 'id', 'url' and 'label' fields. If the label is not set or empty, then the link - * will show the entity's ID and some explanatory text describing that the label hast not been - * set yet. + * Creates a pretty link to an entity's page. If the label is not yet set, then the link will + * show the entity's ID and some explanatory text describing that the label hast not been set + * yet. Requires an URL to the wikipage or equivalent, on which the Entity is represented. * * @since 0.4 * - * @param {Object} entityData Requires 'url', 'id' and optionally 'label' fields - * @return jQuery 'a' element + * @param {wb.Entity} entity + * @param {string} url + * @return {jQuery} An 'a' element */ - wb.utilities.ui.buildEntityLink = function( entityData ) { - var $propertyLink = $( '<a/>', { - href: entityData.url, - text: entityData.label || entityData.id + wb.utilities.ui.buildLinkToEntityPage = function( entity, url ) { + var label = entity.getLabel(); + var $entityLink = $( '<a/>', { + href: url, + text: label || entity.getId() } ); - if( !entityData.label ) { - $propertyLink.append( $( '<span/>', { + if( !label ) { + $entityLink.append( $( '<span/>', { 'class': 'wb-entity-undefinedinfo', 'text': ' (' + mw.msg( 'wikibase-label-empty' ) + ')' } ) ); } - return $propertyLink; + return $entityLink; }; /** diff --git a/lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js b/lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js index 137d9b7..cb06eac 100644 --- a/lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js +++ b/lib/tests/qunit/wikibase.datamodel/Wikibase.snak.tests.js @@ -57,7 +57,7 @@ deobjectifiedSnak.equals( snak ) && snak.equals( deobjectifiedSnak ), 'Newly constructed Snak from json is equal to original Snak' ); - } + }; $.each( snakInfo, function( i, info ) { var snakConstructor = info[0], diff --git a/repo/includes/EntityView.php b/repo/includes/EntityView.php index 3cf483e..1efb24e 100644 --- a/repo/includes/EntityView.php +++ b/repo/includes/EntityView.php @@ -760,23 +760,29 @@ protected static function getBasicEntityInfo( EntityLookup $entityLoader, array $entityIds, $langCode ) { wfProfileIn( __METHOD__ ); + $entityContentFactory = EntityContentFactory::singleton(); $entities = $entityLoader->getEntities( $entityIds ); $entityInfo = array(); + + $serializerFactory = new SerializerFactory(); + $serializationOptions = new \Wikibase\Lib\Serializers\EntitySerializationOptions(); + $serializationOptions->setProps( array( 'labels', 'descriptions', 'datatype' ) ); + + $serializationOptions->setLanguages( array( $langCode ) ); foreach( $entities as $prefixedId => $entity ) { if( $entity === null ) { continue; } - $entities[ $prefixedId ] = $entity->getLabel( $langCode ); + $serializer = $serializerFactory->newSerializerForObject( $entity, $serializationOptions ); + $entityInfo[ $prefixedId ] = $serializer->getSerialized( $entity ); - $entityInfo[ $prefixedId ] = array( - 'label' => $entity->getLabel( $langCode ), - 'url' => EntityContentFactory::singleton()->getTitleForId( $entity->getId() )->getFullUrl() - ); + $entityContent = $entityContentFactory->getFromId( $entity->getId() ); - if( $entity instanceof Property ) { - $entityInfo[ $prefixedId ]['datatype'] = $entity->getDataType()->getId(); - } + // TODO: should perhaps implement and use a EntityContentSerializer since this is mixed, + // serialized Entity and EntityContent data because of adding the URL: + $entityInfo[ $prefixedId ]['title'] = $entityContent->getTitle()->getPrefixedText(); + $entityInfo[ $prefixedId ]['lastrevid'] = $entityContent->getWikiPage()->getRevision()->getId(); } wfProfileOut( __METHOD__ ); diff --git a/repo/resources/Resources.php b/repo/resources/Resources.php index dac0f07..ed41942 100644 --- a/repo/resources/Resources.php +++ b/repo/resources/Resources.php @@ -48,6 +48,8 @@ 'wikibase.datamodel', 'jquery.json', 'jquery.cookie', + 'wikibase.serialization.entities', + 'wikibase.serialization.fetchedcontent' ), 'messages' => array( 'wikibase-sitelinks', diff --git a/repo/resources/wikibase.ui.entityViewInit.js b/repo/resources/wikibase.ui.entityViewInit.js index 4bd2836..f8044aa 100644 --- a/repo/resources/wikibase.ui.entityViewInit.js +++ b/repo/resources/wikibase.ui.entityViewInit.js @@ -74,13 +74,29 @@ if( mw.config.get( 'wbEntity' ) !== null ) { var entityJSON = $.evalJSON( mw.config.get( 'wbEntity' ) ), - usedEntitiesJSON = $.evalJSON( mw.config.get( 'wbUsedEntities' ) ); + usedEntitiesJSON = $.evalJSON( mw.config.get( 'wbUsedEntities' ) ), + unserializerFactory = new wb.serialization.SerializerFactory(), + entityUnserializer = unserializerFactory.newUnserializerFor( wb.Entity ); + + // unserializer for fetched content whose content is a wb.Entity: + var fetchedEntityUnserializer = unserializerFactory.newUnserializerFor( + wb.store.FetchedContent, { + contentUnserializer: entityUnserializer + } + ); + + wb.entity = entityUnserializer.unserialize( entityJSON ); + entityJSON = null; + + $.each( usedEntitiesJSON, function( id, fetchedEntityJSON ) { + wb.fetchedEntities[ id ] = fetchedEntityUnserializer.unserialize( fetchedEntityJSON ); + } ); // if there are no aliases yet, the DOM structure for creating new ones is created manually since it is not // needed for running the page without JS $( '.wb-aliases-empty' ) .each( function() { - $( this ).replaceWith( wikibase.ui.AliasesEditTool.getEmptyStructure() ); + $( this ).replaceWith( wb.ui.AliasesEditTool.getEmptyStructure() ); } ); // edit tool for aliases: @@ -88,29 +104,12 @@ new wb.ui.AliasesEditTool( this ); } ); - // Information about used properties: - $.each( usedEntitiesJSON, function( id, entity ) { - entity.id = id; // we don't get that in the JSON but it is essential for wb.entities - wb.entities[ id ] = entity; - } ); - - // Definition of the views entity: - if ( entityJSON.claims !== undefined ) { - $.each( entityJSON.claims, function( propertyId, claims ) { - $.each( claims, function( i, claim ) { - wb.entity.claims.push( wb.Claim.newFromJSON( claim ) ); - } ); - } ); - } - wb.entity.id = entityJSON.id; - wb.entity.type = entityJSON.type; - $( '.wb-section-heading' ).remove(); // BUILD CLAIMS VIEW: // Note: $.entityview() only works for claims right now, the goal is to use it for more var $claims = $( '.wb-claims' ).entityview( { - value: wb.entity // only holds the claims of an entity page right now + value: wb.entity } ); // removing site links heading to rebuild it with value counter -- To view, visit https://gerrit.wikimedia.org/r/52040 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I40bcc945610fe6f32e89fc12ea3b0def3126317a Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: mw1.21-wmf11 Gerrit-Owner: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: Daniel Werner <daniel.wer...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits