Mwjames has uploaded a new change for review.
https://gerrit.wikimedia.org/r/89098
Change subject: \SMW\SemanticDataSerializer
......................................................................
\SMW\SemanticDataSerializer
A full qualified serialization of a SemanticData container. Tests include
rountrips for various scenarios. The data model is being decribed in
/serializer/README.md.
The serializer is used in the experimantal MongoStore implementation which
uses this class for on-the-fly SemanticData serialization from/to the
MongoDB.
Change-Id: Ief0648e3ca70f9f815139e51528a1bc695bad1fc
---
M SemanticMediaWiki.classes.php
A includes/serializer/README.md
A includes/serializer/SemanticDataSerializer.php
A includes/serializer/Serializable.php
A includes/serializer/Serializer.php
A tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
6 files changed, 815 insertions(+), 0 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SemanticMediaWiki
refs/changes/98/89098/1
diff --git a/SemanticMediaWiki.classes.php b/SemanticMediaWiki.classes.php
index 9fb5bbf..faaee16 100644
--- a/SemanticMediaWiki.classes.php
+++ b/SemanticMediaWiki.classes.php
@@ -97,6 +97,11 @@
'SMW\Configurable' => 'includes/Configurable.php',
'SMW\StoreAccess' => 'includes/StoreAccess.php',
+ // Serializer
+ 'SMW\Serializer' =>
'includes/serializer/Serializer.php',
+ 'SMW\Serializable' =>
'includes/serializer/Serializable.php',
+ 'SMW\SemanticDataSerializer' =>
'includes/serializer/SemanticDataSerializer.php',
+
// Cache
'SMW\CacheHandler' => 'includes/cache/CacheHandler.php',
'SMW\CacheableResultMapper' =>
'includes/cache/CacheableResultMapper.php',
diff --git a/includes/serializer/README.md b/includes/serializer/README.md
new file mode 100644
index 0000000..65f995b
--- /dev/null
+++ b/includes/serializer/README.md
@@ -0,0 +1,142 @@
+This document contains information about Semantic MediaWiki serializers.
+
+## Serializer
+
+### SemanticDataSerializer
+SemanticDataSerializer provides full serialization and un-serialization
support for a SemanticData container including its subobjects.
+
+#### Data model
+A serialized record has a reference to the generator class which will
automatically be used during un-serialization and each record includes a
version number to compare the data model used and enable a consistency check
before an attempt to un-serialize a record.
+
+```php
+[subject] -> DIWikiPage serialization
+[data] -> array container
+ [property] -> DIProperty serialization
+ [dataitem] -> DataItem serialization
+ ...
+[sobj] -> array container
+ [subject] -> Subobject DIWikiPage serialization
+ [data] -> array container
+ [property] -> DIProperty serialization
+ [dataitem] -> DataItem serialization
+ ...
+[serializer] -> Class of the generator and entry point for the un-serializer
+[version] -> Provides a number to allows to compare structural integrity
between serialization and un-serialization
+```
+#### Example
+For a page called "Foo" that contains <code>[[Has property::Bar]]</code>,
<code>{{#subobject:|Has subobjects=Bam}}</code>, <code>{{#ask:Has
subobjects::Bam}}</code>, the Serializer will output:
+
+```php
+[subject] => Foo#0#
+[data] => Array (
+ [0] => Array (
+ [property] => Has_property
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 9
+ [item] => Bar#0#
+ )
+ )
+ )
+ [1] => Array (
+ [property] => _ASK
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 9
+ [item] =>
Foo#0##_QUERYc8606da8f325fc05aa8e8b958821c3b4
+ [sobj] => _QUERYc8606da8f325fc05aa8e8b958821c3b4
+ )
+ )
+ )
+ [2] => Array (
+ [property] => _MDAT
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 6
+ [item] => 1/2013/10/10/14/55/40
+ )
+ )
+ )
+ [3] => Array (
+ [property] => _SKEY
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 2
+ [item] => Foo
+ )
+ )
+ )
+ [4] => Array (
+ [property] => _SOBJ
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 9
+ [item] =>
Foo#0##_fc4b104aabf80eb06429e946aa8f7070
+ [sobj] => _fc4b104aabf80eb06429e946aa8f7070
+ )
+ )
+ )
+)
+[sobj] => Array (
+ [0] => Array (
+ [subject] => Foo#0##_fc4b104aabf80eb06429e946aa8f7070
+ [data] => Array (
+ [0] => Array (
+ [property] => Has_subobjects
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 9
+ [item] => Bam#0#
+ )
+ )
+ )
+ )
+ )
+ [1] => Array (
+ [subject] => Foo#0##_QUERYc8606da8f325fc05aa8e8b958821c3b4
+ [data] => Array (
+ [0] => Array (
+ [property] => _ASKDE
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 1
+ [item] => 1
+ )
+ )
+ )
+ [1] => Array (
+ [property] => _ASKFO
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 2
+ [item] => list
+ )
+ )
+ )
+ [2] => Array (
+ [property] => _ASKSI
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 1
+ [item] => 2
+ )
+ )
+ )
+ [3] => Array (
+ [property] => _ASKST
+ [dataitem] => Array (
+ [0] => Array (
+ [type] => 2
+ [item] => [[Has
subobjects::Bam]]
+ )
+ )
+ )
+ )
+ )
+)
+[serializer] => SMW\SemanticDataSerializer
+[version] => 0.3
+```
+
+### QueryResultSerializer
+N/A (see \SMW\DISerializer)
diff --git a/includes/serializer/SemanticDataSerializer.php
b/includes/serializer/SemanticDataSerializer.php
new file mode 100644
index 0000000..b47eb23
--- /dev/null
+++ b/includes/serializer/SemanticDataSerializer.php
@@ -0,0 +1,299 @@
+<?php
+
+namespace SMW;
+
+use SMWContainerSemanticData;
+use SMWDIContainer as DIContainer;
+use SMWDataItem as DataItem;
+use SMWErrorValue as ErrorValue;
+
+use OutOfBoundsException;
+
+/**
+ * SemanticData serializer / un-serializer
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * SemanticData serializer
+ *
+ * @ingroup SMW
+ */
+class SemanticDataSerializer implements Serializable {
+
+ /**
+ * The version number reflects the need for consistency among
serialized data
+ * and therefore be aware of any change that is done in the serializer
class.
+ *
+ * The un-serializer will raise an exception if the version of the
incoming
+ * data does not match with the version number found in this class.
+ */
+ const VERSION = 0.3;
+
+ /**
+ * Cache for already processed Id's to minimize lock-up performance
during
+ * un-serialization
+ *
+ * @var array
+ */
+ protected $dataItemTypeIdCache = array();
+
+ /**
+ * Initiates serialization of a SemanticData object
+ *
+ * @since 1.9
+ *
+ * @return array
+ * @throws OutOfBoundsException
+ */
+ public function serialize( $semanticData ) {
+
+ if ( !( $semanticData instanceOf SemanticData ) ) {
+ throw new OutOfBoundsException( 'Object was not
identified as a SemanticData instance' );
+ }
+
+ return $this->serializeSemanticData( $semanticData ) + array(
'serializer' => __CLASS__, 'version' => self::VERSION );
+ }
+
+ /**
+ * Initiates un-serialization of an object
+ *
+ * @since 1.9
+ *
+ * @return SemanticData
+ * @throws OutOfBoundsException
+ */
+ public function unserialize( $data ) {
+
+ $semanticData = null;
+
+ if ( isset( $data['version'] ) && $data['version'] !==
self::VERSION ) {
+ throw new OutOfBoundsException(
'Serializer/Unserializer version do not match, please update your data' );
+ }
+
+ if ( isset( $data['subject'] ) ) {
+ $semanticData = new SemanticData(
DIWikiPage::doUnserialize( $data['subject'] ) );
+ }
+
+ if ( !( $semanticData instanceOf SemanticData ) ) {
+ throw new OutOfBoundsException( 'SemanticData could not
be created probably due to a missing subject' );
+ }
+
+ $this->unserializeSemanticData( $data, $semanticData );
+
+ return $semanticData;
+ }
+
+ /**
+ * Returns serialized SemanticData
+ *
+ * @return array
+ */
+ protected function serializeSemanticData( SemanticData $semanticData ) {
+
+ $output = array();
+
+ $output['subject'] =
$semanticData->getSubject()->getSerialization();
+
+ /**
+ * Build property and dataItem serialization record
+ */
+ foreach ( $semanticData->getProperties() as $key => $property )
{
+
+ $prop = array();
+
+ $prop['property'] = $property->getSerialization();
+
+ foreach ( $semanticData->getPropertyValues( $property )
as $dataItem ) {
+ $prop['dataitem'][] = $this->serializeDataItem(
$dataItem );
+ }
+
+ $output['data'][] = $prop;
+
+ }
+
+ $this->serializeSubobject( $semanticData->getSubSemanticData(),
$output );
+
+ return $output;
+ }
+
+ /**
+ * Returns DataItem serialization
+ *
+ * @note 'type' is added to ensure that during un-serialization the type
+ * definition of the requested data is in alignment with the definition
found
+ * in the system (type changes that can occur during the time between
+ * serialization and un-serialization)
+ *
+ * @note 'sobj' is only added for when a subobject is present
+ *
+ * @return array
+ */
+ protected function serializeDataItem( DataItem $dataItem ) {
+
+ $di = array(
+ 'type' => $dataItem->getDIType(),
+ 'item' => $dataItem->getSerialization()
+ );
+
+ if ( $dataItem->getDIType() === DataItem::TYPE_WIKIPAGE &&
$dataItem->getSubobjectName() ) {
+ $di += array( 'sobj' => $dataItem->getSubobjectName() );
+ }
+
+ return $di;
+ }
+
+ /**
+ * Returns all subobjects of a SemanticData instance
+ *
+ * @note The subobject name is used as reference key as it is the only
+ * reliable unique key to allow a performable lookup during
un-serialization
+ *
+ * @return array
+ */
+ protected function serializeSubobject( $subSemanticData, &$output ) {
+
+ foreach ( $subSemanticData as $semanticData ) {
+ $output['sobj'][] = $this->serializeSemanticData(
$semanticData );
+ }
+
+ }
+
+ /**
+ * @return
+ */
+ protected function unserializeSemanticData( $data, &$semanticData ) {
+
+ $property = null;
+
+ if ( !isset( $data['data'] ) ) {
+ return;
+ }
+
+ foreach ( $data['data'] as $values ) {
+
+ if ( is_array( $values ) ) {
+
+ foreach ( $values as $key => $value ) {
+
+ /**
+ * @var DIProperty $property
+ */
+ if ( $key === 'property' ) {
+ $property =
DIProperty::doUnserialize( $value );
+ }
+
+ /**
+ * @var DataItem
+ */
+ if ( $key === 'dataitem' ) {
+ foreach ( $value as $val ) {
+
$this->unserializeDataItem( $property, $data, $val, $semanticData );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return DataItem
+ */
+ protected function unserializeDataItem( $property, $data, $value,
$semanticData ) {
+
+ $dataItem = null;
+
+ $type = $this->getDataItemId( $property );
+
+ // Verify that the current property type definition and the
type of the
+ // property during serialization do match, throw an error value
to avoid that
+ // the DataItem object will complain about the mismatch of data
definitions
+ if ( $type === $value['type'] ) {
+ $dataItem = DataItem::newFromSerialization(
$value['type'], $value['item'] );
+ } else {
+ $dataItem = $property->getDiWikiPage();
+ $property = new DIProperty( DIProperty::TYPE_ERROR );
+
+ $semanticData->addError( array(
+ new ErrorValue( $type, 'type mismatch',
$property->getLabel() )
+ ) );
+
+ }
+
+ // Check whether the current dataItem has a subobject reference
+ if ( isset( $value['sobj'] ) && $value['sobj'] !== null ) {
+
+ $dataItem = $this->unserializeSubobject(
+ $data,
+ $value['item'],
+ new SMWContainerSemanticData( $dataItem )
+ );
+
+ }
+
+ // Ensure that errors are collected from a subobject level as
well and
+ // made available at the top
+ if ( $dataItem instanceOf DIContainer ) {
+ $semanticData->addError(
$dataItem->getSemanticData()->getErrors() );
+ }
+
+ if ( $property !== null ) {
+ $semanticData->addPropertyObjectValue( $property,
$dataItem );
+ }
+
+ }
+
+ /**
+ * Resolves properties and dataitems assigned to a subobject recursively
+ *
+ * @return DIContainer
+ */
+ protected function unserializeSubobject( $data, $id, $semanticData ) {
+
+ foreach ( $data['sobj'] as $subobject ) {
+
+ if ( $subobject['subject'] === $id ) {
+ $this->unserializeSemanticData( $subobject,
$semanticData );
+ }
+
+ }
+
+ return new DIContainer( $semanticData );
+ }
+
+ /**
+ * Returns DataItemId for a property
+ *
+ * @note Not sure why matching can only be done with the help of
DataValueFactory
+ * because it is the only place the holds both definitions
+ *
+ * Word of caution, findPropertyTypeID is calling the Store to find the
+ * typeId reference this is costly but at the moment there is no other
+ * way to determine the typeId without the Store being involved
+ *
+ * Reason for this check is to ensure that during un-serialization the
+ * correct item in terms of its definition is being sought otherwise
+ * inconsistencies can occur due to type changes of a property between
+ * the time of serialization and its un-serialization (e.g for when the
+ * serialization object is stored in cache, DB etc.)
+ *
+ * @return integer
+ */
+ protected function getDataItemId( DIProperty $property ) {
+
+ if ( isset( $this->dataItemTypeIdCache[ $property->getKey() ] )
) {
+ return $this->dataItemTypeIdCache[ $property->getKey()
];
+ }
+
+ $this->dataItemTypeIdCache[ $property->getKey() ] =
DataValueFactory::getDataItemId( $property->findPropertyTypeID() );
+
+ return $this->dataItemTypeIdCache[ $property->getKey() ];
+ }
+
+}
diff --git a/includes/serializer/Serializable.php
b/includes/serializer/Serializable.php
new file mode 100644
index 0000000..0f829aa
--- /dev/null
+++ b/includes/serializer/Serializable.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace SMW;
+
+/**
+ * Serializer and serializable objects
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * Common interface to access a serializable object
+ *
+ * @ingroup SMW
+ */
+interface Serializable {
+
+ /**
+ * Initiates serialization of an arbitrary object
+ *
+ * @since 1.9
+ *
+ * @param mixed $object
+ *
+ * @return array
+ */
+ public function serialize( $object );
+
+ /**
+ * Initiates un-serialization of an arbitrary object
+ *
+ * @since 1.9
+ *
+ * @param array $object
+ *
+ * @return mixed
+ */
+ public function unserialize( $object );
+
+}
diff --git a/includes/serializer/Serializer.php
b/includes/serializer/Serializer.php
new file mode 100644
index 0000000..9cf6671
--- /dev/null
+++ b/includes/serializer/Serializer.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace SMW;
+
+use OutOfBoundsException;
+
+/**
+ * Serializer handler for a serializable object
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * Serializer handler
+ *
+ * @ingroup Utility
+ */
+class Serializer {
+
+ /**
+ * Initiates serialization of an object
+ *
+ * @since 1.9
+ *
+ * @param mixed $object
+ *
+ * @return array
+ */
+ public static function serialize( $object ) {
+
+ $serializer = null;
+
+ if ( $object instanceof SemanticData ) {
+ $serializer = new SemanticDataSerializer;
+ }
+
+ if ( !( $serializer instanceof Serializable ) ) {
+ throw new OutOfBoundsException( "For the invoked object
no serializer has been registered" );
+ }
+
+ return $serializer->serialize( $object );
+ }
+
+ /**
+ * Initiates un-serialization of an object
+ *
+ * @note Each object is expected to hold the serializer/un-serializer
reference
+ * class within in its records otherwise an exception is raised
+ *
+ * @since 1.9
+ *
+ * @param array $object
+ *
+ * @return mixed
+ */
+ public static function unserialize( array $object ) {
+
+ $serializer = null;
+
+ if ( isset( $object['serializer'] ) && $object['serializer']
!== '' ) {
+ $serializer = new $object['serializer'];
+ }
+
+ if ( !( $serializer instanceof Serializable ) ) {
+ throw new OutOfBoundsException( "For the invoked object
no un-serializer has been assigned" );
+ }
+
+ return $serializer->unserialize( $object );
+ }
+
+}
diff --git a/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
b/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
new file mode 100644
index 0000000..0b4dc66
--- /dev/null
+++ b/tests/phpunit/includes/serializer/SemanticDataSerializerTest.php
@@ -0,0 +1,248 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\SemanticDataSerializer;
+use SMW\DataValueFactory;
+use SMw\SemanticData;
+use SMW\Serializer;
+use SMW\DIWikiPage;
+use SMW\Subobject;
+
+/**
+ * Tests for the SemanticDataSerializer class
+ *
+ * @file
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+
+/**
+ * @covers \SMW\SemanticDataSerializer
+ * @covers \SMW\Serializer
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class SemanticDataSerializerTest extends SemanticMediaWikiTestCase {
+
+ /**
+ * Returns the name of the class to be tested
+ *
+ * @return string|false
+ */
+ public function getClass() {
+ return '\SMW\SemanticDataSerializer';
+ }
+
+ /**
+ * Helper method that returns a SemanticDataSerializer object
+ *
+ * @since 1.9
+ *
+ * @param $data
+ *
+ * @return SemanticDataSerializer
+ */
+ private function newInstance() {
+ return new SemanticDataSerializer();
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testConstructor() {
+ $this->assertInstanceOf( $this->getClass(),
$this->newInstance() );
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testSerializeOutOfBoundsException() {
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance = $this->newInstance();
+ $instance->serialize( 'Foo' );
+
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testUnserializeInvalidVersionOutOfBoundsException() {
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance = $this->newInstance();
+ $instance->unserialize( array( 'version' => 'Foo' ) );
+
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testUnserializeInvalidSubjectDataItemException() {
+
+ $this->setExpectedException( '\SMW\DataItemException' );
+
+ $instance = $this->newInstance();
+ $instance->unserialize( array( 'subject' => '--#Foo' ) );
+
+ }
+
+ /**
+ * @since 1.9
+ */
+ public function testUnserializeMissingSubjectOutOfBoundsException() {
+
+ $this->setExpectedException( 'OutOfBoundsException' );
+
+ $instance = $this->newInstance();
+ $instance->unserialize( array() );
+
+ }
+
+ /**
+ * @dataProvider semanticDataProvider
+ *
+ * @since 1.9
+ */
+ public function testSerializerUnserializerRountrip( $data ) {
+
+ $serialized = Serializer::serialize( $data );
+
+ $this->assertEquals(
+ $serialized,
+ Serializer::serialize( Serializer::unserialize(
$serialized ) ),
+ 'Asserts that the intial serialized container is equal
to a container after roundtrip'
+ );
+
+
+ $this->assertEquals(
+ $data->getHash(),
+ Serializer::unserialize( $serialized )->getHash(),
+ 'Asserts that the hash of the orginal SemanticData
container equals that of the serialized-un-serialized container'
+ );
+ }
+
+ /**
+ * @dataProvider typeChangeSemanticDataProvider
+ * @since 1.9
+ */
+ public function testForcedTypeErrorDuringRountrip( $data, $type ) {
+
+ $instance = $this->newInstance();
+ $serialized = Serializer::serialize( $data );
+
+ // Inject the cache with differen type to cause an error
+ $reflector = $this->newReflector();
+ $property = $reflector->getProperty( 'dataItemTypeIdCache' );
+ $property->setAccessible( true );
+ $property->setValue( $instance, array( $type => 2 ) );
+
+ $unserialized = $instance->unserialize( $serialized );
+
+ $this->assertInstanceOf(
+ 'SMW\SemanticData',
+ $unserialized,
+ 'Asserts the instance'
+ );
+
+ $this->assertNotEmpty(
+ $unserialized->getErrors(),
+ 'Asserts that the getErrors() is not empty'
+ );
+
+ }
+
+ /**
+ * @return array
+ */
+ public function semanticDataProvider() {
+
+ $provider = array();
+ $title = $this->newTitle( NS_MAIN, 'Foo' );
+
+ // #0 Empty container
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $provider[] = array( $foo );
+
+ // #1 Single entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
fooQuex', 'Bar' ) );
+ $provider[] = array( $foo );
+
+ // #2 Single + single subobject entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
fooQuex', 'Bar' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::newPropertyValue(
'Has subobjects', 'Bam' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(),
$subobject->getContainer() );
+
+ $provider[] = array( $foo );
+
+ // #3 Multiple entries
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
fooQuex', 'Bar' ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
queez', 'Xeey' ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::newPropertyValue(
'Has subobjects', 'Bam' ) );
+ $subobject->addDataValue( DataValueFactory::newPropertyValue(
'Has fooQuex', 'Fuz' ) );
+
+ $subobject->setSemanticData( 'Bar' );
+ $subobject->addDataValue( DataValueFactory::newPropertyValue(
'Has fooQuex', 'Fuz' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(),
$subobject->getContainer() );
+
+ $provider[] = array( $foo );
+
+ return $provider;
+ }
+
+ /**
+ * @return array
+ */
+ public function typeChangeSemanticDataProvider() {
+
+ $provider = array();
+ $title = $this->newTitle( NS_MAIN, 'Foo' );
+
+ // #0
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
fooQuex', 'Bar' ) );
+
+ $provider[] = array( $foo, 'Has_fooQuex' );
+
+ // #1 single subobject entry
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+
+ $subobject = new Subobject( $title );
+ $subobject->setSemanticData( 'Foo' );
+ $subobject->addDataValue( DataValueFactory::newPropertyValue(
'Has fomQuex', 'Bam' ) );
+
+ $foo->addPropertyObjectValue( $subobject->getProperty(),
$subobject->getContainer() );
+
+ $provider[] = array( $foo, 'Has_fomQuex' );
+
+ // #2 combined
+ $foo = new SemanticData( DIWikiPage::newFromTitle( $title ) );
+ $foo->addDataValue( DataValueFactory::newPropertyValue( 'Has
fooQuex', 'Bar' ) );
+ $foo->addPropertyObjectValue( $subobject->getProperty(),
$subobject->getContainer() );
+
+ $provider[] = array( $foo, 'Has_fomQuex' );
+
+ return $provider;
+ }
+
+}
--
To view, visit https://gerrit.wikimedia.org/r/89098
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ief0648e3ca70f9f815139e51528a1bc695bad1fc
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits