diff --git a/composer.json b/composer.json index ea07357..6040038 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "professional-wiki/semantic-wikibase", + "name": "baillyk/semantic-wikibase", "type": "mediawiki-extension", "description": "MediaWiki extension that makes Wikibase data available in Semantic MediaWiki", "keywords": [ @@ -12,7 +12,7 @@ "semantic web", "wikidata" ], - "homepage": "https://professional.wiki/en/extension/semantic-wikibase", + "homepage": "https://github.com/baillyk/SemanticWikibase", "license": "GPL-2.0-or-later", "authors": [ { diff --git a/extension.json b/extension.json index 93814aa..4ad02c3 100644 --- a/extension.json +++ b/extension.json @@ -38,9 +38,11 @@ "callback": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onExtensionRegistration", "Hooks": { + "ParserFirstCallInit":"MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onParserFirstCallInit", "SMW::Property::initProperties": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onSmwInitProperties", "SMW::SQLStore::AddCustomFixedPropertyTables": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onSmwAddCustomFixedPropertyTables", - "SMWStore::updateDataBefore": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onSmwUpdateDataBefore" + "SMW::SQLStore::BeforeDataUpdateComplete": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onSmwUpdateDataBefore", + "MultiContentSave": "MediaWiki\\Extension\\SemanticWikibase\\EntryPoints\\HookHandlers::onMultiContentSave" }, "config": { diff --git a/src/EntryPoints/HookHandlers.php b/src/EntryPoints/HookHandlers.php index 8ab1ec3..508f4a8 100644 --- a/src/EntryPoints/HookHandlers.php +++ b/src/EntryPoints/HookHandlers.php @@ -4,11 +4,22 @@ namespace MediaWiki\Extension\SemanticWikibase\EntryPoints; +use MediaWiki\Revision\RenderedRevision; +use MediaWiki\User\UserIdentity; +use CommentStoreComment; +use Status; +use MediaWiki\MediaWikiServices; +use MediaWiki\TitleFactory; use MediaWiki\Extension\SemanticWikibase\SemanticWikibase; +use SMW\Services\ServicesFactory as ApplicationFactory; use SMW\PropertyRegistry; use SMW\SemanticData; +use SMW\DIWikiPage; +use SMW\StoreFactory; use SMW\Store; +use Parser; + class HookHandlers { public static function onExtensionRegistration(): void { @@ -17,18 +28,52 @@ public static function onExtensionRegistration(): void { $smwgNamespacesWithSemanticLinks[WB_NS_PROPERTY] = true; } + public static function onParserFirstCallInit( Parser $parser ) { + # getInstance() will call initProperties() which aktivates existing hook onSmwInitProperties() + wfDebug( __METHOD__ . "SWB: onParserFirstCallInit" ); + PropertyRegistry::getInstance(); + } + public static function onSmwInitProperties( PropertyRegistry $propertyRegistry ): void { - SemanticWikibase::getGlobalInstance()->registerProperties( $propertyRegistry ); + wfDebug( __METHOD__ . "SWB: onSmwInitProperties..." ); + SemanticWikibase::getGlobalInstance()->registerProperties( $propertyRegistry ); } public static function onSmwAddCustomFixedPropertyTables( array &$customFixedProperties, array &$fixedPropertyTablePrefix ): void { + wfDebug( __METHOD__ . "SWB: onSmwAddCustomFixedPropertyTables" ); SemanticWikibase::getGlobalInstance()->getFixedProperties() ->registerFixedTables( $customFixedProperties, $fixedPropertyTablePrefix ); } public static function onSmwUpdateDataBefore( Store $store, SemanticData $semanticData ): void { + wfDebug( __METHOD__ . "SWB: onSmwUpdateDataBefore" ); SemanticWikibase::getGlobalInstance()->getSemanticDataUpdate() ->run( $semanticData ); + } + public static function onPageSaveComplete( WikiPage $wikiPage, MediaWiki\User\UserIdentity $user, string $summary, int $flags, MediaWiki\Revision\RevisionRecord $revisionRecord, MediaWiki\Storage\EditResult $editResult ) { + wfDebug( __METHOD__ . "SWB: onPageSaveComplete" ); + // Access the semantic data of the page via the Semantic MediaWiki API + $semanticData = \SMW\MediaWiki\Hooks\ParserHooks::getSemanticDataForPage($wikiPage); + + onSmwUpdateDataBefore(null, $semanticData); + } + + public static function onMultiContentSave( RenderedRevision $renderedRevision, UserIdentity $user, CommentStoreComment $summary, $flags, Status $hookStatus ) { + wfDebug( __METHOD__ . "SWB: onMultiContentSave" ); + $revision = $renderedRevision->getRevision(); + + $titleFactory = MediaWikiServices::getInstance()->getTitleFactory(); + $title = $titleFactory->newFromLinkTarget($revision->getPageAsLinkTarget()); + wfDebug( __METHOD__ . "SWB: onMultiContentSave...title:".$title ); + $subject = DIWikiPage::newFromTitle( $title ); + #$new_content = $revision->getContent(SlotRecord::MAIN, RevisionRecord::RAW)->getNativeData(); + $semanticData = StoreFactory::getStore()->getSemanticData( DIWikiPage::newFromTitle( $title ) ); + wfDebug( __METHOD__ . "SWB: onMultiContentSave: ".json_encode($semanticData) ); + SemanticWikibase::getGlobalInstance()->getSemanticDataUpdate()->run( $semanticData ); + + return true; + } + } diff --git a/src/SMW/SemanticEntity.php b/src/SMW/SemanticEntity.php index 1c0e2ad..7255562 100644 --- a/src/SMW/SemanticEntity.php +++ b/src/SMW/SemanticEntity.php @@ -8,28 +8,34 @@ use SMW\DIWikiPage; use SMW\SemanticData; use SMWDataItem; +use SMW\Subobject; class SemanticEntity { private array $dataItemsPerProperty = []; + private array $subObjectsPerProperty=[]; - public function addPropertyValue( string $propertyId, SMWDataItem $dataItem ) { - $this->dataItemsPerProperty[$propertyId][] = $dataItem; + public function addPropertyValue( string $NumericPropertyId, SMWDataItem $dataItem ) { + $this->dataItemsPerProperty[$NumericPropertyId][] = $dataItem; + } + + public function addSubobject( string $NumericPropertyId, SubObject $subobject ){ + $this->subObjectsPerProperty[$NumericPropertyId][] = $subobject; } /** - * @param string $propertyId + * @param string $NumericPropertyId * @return SMWDataItem[] */ - public function getDataItemsForProperty( string $propertyId ): array { - return $this->dataItemsPerProperty[$propertyId] ?? []; + public function getDataItemsForProperty( string $NumericPropertyId ): array { + return $this->dataItemsPerProperty[$NumericPropertyId] ?? []; } public function toSemanticData( DIWikiPage $subject ): SemanticData { $semanticData = new SemanticData( $subject ); - foreach ( $this->dataItemsPerProperty as $propertyId => $dataItems ) { - $property = new DIProperty( $propertyId ); + foreach ( $this->dataItemsPerProperty as $NumericPropertyId => $dataItems ) { + $property = new DIProperty( $NumericPropertyId ); foreach ( $dataItems as $dataItem ) { $semanticData->addPropertyObjectValue( @@ -39,6 +45,14 @@ public function toSemanticData( DIWikiPage $subject ): SemanticData { } } + foreach ( $this->subObjectsPerProperty as $NumericPropertyId => $subobjects ) { + $property = new DIProperty( $NumericPropertyId ); + + foreach ( $subobjects as $subobject ) { + $semanticData->addSubobject($subobject); + } + } + return $semanticData; } @@ -52,9 +66,9 @@ public function functionalMerge( self $entity ): self { } public function add( self $entity ): void { - foreach ( $entity->dataItemsPerProperty as $propertyId => $dataItems ) { + foreach ( $entity->dataItemsPerProperty as $NumericPropertyId => $dataItems ) { foreach ( $dataItems as $dataItem ) { - $this->addPropertyValue( $propertyId, $dataItem ); + $this->addPropertyValue( $NumericPropertyId, $dataItem ); } } } diff --git a/src/SemanticDataUpdate.php b/src/SemanticDataUpdate.php index 0de6f59..e182b2e 100644 --- a/src/SemanticDataUpdate.php +++ b/src/SemanticDataUpdate.php @@ -12,7 +12,7 @@ use SMW\SemanticData; use Title; use Wikibase\DataModel\Entity\ItemId; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Services\Lookup\ItemLookup; use Wikibase\DataModel\Services\Lookup\PropertyLookup; @@ -63,8 +63,13 @@ private function newItemTranslator( Title $title ): ItemTranslator { } private function getSemanticEntityForPropertyTitle( Title $title ): SemanticEntity { + wfDebug(__METHOD__. "swb: getSemanticEntity:".json_encode($title)); + wfDebug(__METHOD__. "swb: getSemanticEntity:".json_encode($title->getText())); + wfDebug(__METHOD__. "swb: getSemanticEntity:".json_encode(new NumericPropertyId( $title->getText() ))); + wfDebug(__METHOD__. "swb: getSemanticEntity:".json_encode($this->propertyLookup->getPropertyForId( new NumericPropertyId( $title->getText() ) ))); + return $this->newPropertyTranslator( $title )->translateProperty( - $this->propertyLookup->getPropertyForId( new PropertyId( $title->getText() ) ) + $this->propertyLookup->getPropertyForId( new NumericPropertyId( $title->getText() ) ) ); } diff --git a/src/SemanticWikibase.php b/src/SemanticWikibase.php index 05c728c..1cc2a7f 100644 --- a/src/SemanticWikibase.php +++ b/src/SemanticWikibase.php @@ -62,15 +62,18 @@ protected function getPropertyTypeLookup(): PropertyDataTypeLookup { } public function registerProperties( PropertyRegistry $propertyRegistry ) { + wfDebug("SWB: register properties ".json_encode($this->getAllProperties())); foreach ( $this->getAllProperties() as $property ) { $propertyRegistry->registerProperty( $property->getId(), $property->getType(), $property->getLabel(), - true, - false + true, #is_visible + true, #is_annotable + false #is_declarative ); - + wfDebug("SWB: register property ".$property->getId()); + wfDebug("SWB: register property ".$property->getType()); foreach ( $property->getAliases() as $alias ) { $propertyRegistry->registerPropertyAlias( $property->getId(), $alias ); } diff --git a/src/Translation/DataValueTranslator.php b/src/Translation/DataValueTranslator.php index 23a2a3b..c82023c 100644 --- a/src/Translation/DataValueTranslator.php +++ b/src/Translation/DataValueTranslator.php @@ -19,14 +19,33 @@ use Wikibase\DataModel\Entity\EntityId; use Wikibase\DataModel\Entity\EntityIdValue; use Wikibase\DataModel\Entity\ItemId; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; +use Wikibase\EDTF\Services\TimeValueBuilder; +use Wikibase\EDTF\EdtfValue; +use MediaWiki\Logger\LoggerFactory; +use EDTF\EdtfFactory; +use EDTF\Model\ExtDate; +use EDTF\Model\ExtDateTime; +use EDTF\Model\Interval; class DataValueTranslator { public function translate( TypedDataValue $typedValue ): SMWDataItem { + + $value = $typedValue->getValue(); - + $propertyType = $typedValue->getPropertyType(); + if( $value != null) { + wfDebug( 'swb: translate: '.get_class( $value ).' ptype: '.$propertyType ); + } + if ( $value instanceof StringValue ) { + wfDebug( 'swb: translate: '. $typedValue->getValue()->getValue() ); + if( $propertyType == 'edtf') { + return $this->translateEDTF("".$value->getValue()); + }else if ($propertyType == 'localMedia') { + return $this->translateLocalMedia("".$value->getValue()); + } return $this->translateStringValue( $typedValue ); } if ( $value instanceof BooleanValue ) { @@ -44,10 +63,13 @@ public function translate( TypedDataValue $typedValue ): SMWDataItem { if ( $value instanceof GlobeCoordinateValue ) { return $this->translateGlobeCoordinateValue( $value ); } + if ( $value instanceof TimeValue ) { + wfDebug( 'swb: translate time: '. $$value.toString() ); return $this->translateTimeValue( $value ); } - + + throw new \RuntimeException( 'Support for DataValue type "' . get_class( $value ) . '" not implemented' ); } @@ -66,6 +88,12 @@ private function translateGlobeCoordinateValue( GlobeCoordinateValue $globeValue ); } + private function translateLocalMedia( String $imagePage): SMWDataItem { + return new DIWikiPage( + $imagePage, + NS_FILE + ); + } private function translateEntityIdValue( EntityIdValue $idValue ): SMWDataItem { return new DIWikiPage( $idValue->getEntityId()->getSerialization(), @@ -78,7 +106,7 @@ private function entityIdToNamespaceId( EntityId $idValue ): int { return WB_NS_ITEM; } - if ( $idValue instanceof PropertyId ) { + if ( $idValue instanceof NumericPropertyId ) { return WB_NS_PROPERTY; } @@ -89,6 +117,59 @@ public function translateDecimalValue( DecimalValue $value ): SMWDataItem { return new \SMWDINumber( $value->getValueFloat() ); } + private function translateEDTF( String $value ): \SMWDITime { + wfDebug( 'swb: translate edtf' ); + $tvb = new TimeValueBuilder( EdtfFactory::newParser() ); + $tvArr = $tvb->edtfToTimeValues( $value ); + $parser = \EDTF\EdtfFactory::newParser(); + $parsingResult = $parser->parse($value); + wfDebug($parsingResult->isValid()); // true + $edtfValue = $parsingResult->getEdtfValue(); // \EDTF\EdtfValue + $humanizer = \EDTF\EdtfFactory::newHumanizerForLanguage( 'en' ); + wfDebug($humanizer->humanize($edtfValue)); // string + wfDebug(get_class($edtfValue)); // string + $result = null; + + if ( $edtfValue instanceof Interval ) { + if($edtfValue->hasStartDate()){ + $edtfValue = $edtfValue->getStartDate(); + } else if ($edtfValue->hasEndDate()){ + $edtfValue = $edtfValue->getEndDate(); + } else { + wfDebug('ERROR: unable to translate empty edtf interval to smw date'); + return null; + } + } + + if( $edtfValue instanceof ExtDate ) { + $result = new \SMWDITime( + SMWDITime::CM_GREGORIAN, + $edtfValue->getYear(), + $edtfValue->getMonth(), + $edtfValue->getDay() + ); + + } else if ( $edtfValue instanceof ExtDateTime ) { + $result = new \SMWDITime( + SMWDITime::CM_GREGORIAN, + $edtfValue->getYear(), + $edtfValue->getMonth(), + $edtfValue->getDay(), + $edtfValue->getHour(), + $edtfValue->getMinute(), + $edtfValue->getSecond() + ); + } else { + $result = new \SMWDITime( + SMWDITime::CM_GREGORIAN, + 1970 + ); + + } + + return $result; + } + private function translateTimeValue( TimeValue $value ): \SMWDITime { $components = ( new TimeValueParser() )->parse( $value->getTime() ); diff --git a/src/Translation/ItemTranslator.php b/src/Translation/ItemTranslator.php index ebc877f..4b5d5f7 100644 --- a/src/Translation/ItemTranslator.php +++ b/src/Translation/ItemTranslator.php @@ -18,10 +18,10 @@ public function __construct( FingerprintTranslator $fingerprintTranslator, State $this->statementListTranslator = $statementListTranslator; } - public function translateItem( Item $item ): SemanticEntity { + public function translateItem( ?Item $item ): SemanticEntity { $semanticEntity = new SemanticEntity(); - if ( $item->getId() === null ) { + if ( $item === null || $item->getId() === null ) { return $semanticEntity; } diff --git a/src/Translation/PropertyTranslator.php b/src/Translation/PropertyTranslator.php index d134b5c..1bc3ac6 100644 --- a/src/Translation/PropertyTranslator.php +++ b/src/Translation/PropertyTranslator.php @@ -6,7 +6,7 @@ use MediaWiki\Extension\SemanticWikibase\SMW\SemanticEntity; use Wikibase\DataModel\Entity\Property; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; class PropertyTranslator { @@ -18,10 +18,10 @@ public function __construct( FingerprintTranslator $fingerprintTranslator, State $this->statementListTranslator = $statementListTranslator; } - public function translateProperty( Property $property ): SemanticEntity { + public function translateProperty( ?Property $property ): SemanticEntity { $semanticEntity = new SemanticEntity(); - if ( $property->getId() === null ) { + if ( $property === null || $property->getId() === null ) { return $semanticEntity; } @@ -32,7 +32,7 @@ public function translateProperty( Property $property ): SemanticEntity { return $semanticEntity; } - private function addId( SemanticEntity $semanticEntity, PropertyId $itemId ): void { + private function addId( SemanticEntity $semanticEntity, NumericPropertyId $itemId ): void { $semanticEntity->addPropertyValue( FixedProperties::ID, new \SMWDIBlob( $itemId->getSerialization() ) diff --git a/src/Translation/PropertyTypeTranslator.php b/src/Translation/PropertyTypeTranslator.php index 37676ae..49521f1 100644 --- a/src/Translation/PropertyTypeTranslator.php +++ b/src/Translation/PropertyTypeTranslator.php @@ -38,10 +38,12 @@ private function getMap(): array { 'tabular-data' => null, // TODO 'entity-schema' => null, // TODO 'time' => SMWTimeValue::TYPE_ID, + 'edtf' => SMWTimeValue::TYPE_ID, 'url' => '_uri', 'external-id' => ExternalIdentifierValue::TYPE_ID, 'wikibase-item' => '_wpg', 'wikibase-property' => '_wpg', + 'localMedia' => '_wpg' ]; if ( class_exists( CoordinateValue::class ) ) { diff --git a/src/Translation/StatementListTranslator.php b/src/Translation/StatementListTranslator.php index f45edcc..dcee94f 100644 --- a/src/Translation/StatementListTranslator.php +++ b/src/Translation/StatementListTranslator.php @@ -9,6 +9,11 @@ use SMW\DIWikiPage; use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Statement\StatementList; +use MWException; +use SMW\PropertyRegistry; +use SMW\Subobject; +use SMW\StoreFactory; +use SMW\Store; class StatementListTranslator { @@ -23,36 +28,63 @@ public function __construct( StatementTranslator $statementTranslator, DIWikiPag public function translateStatements( StatementList $statements ): SemanticEntity { $semanticEntity = new SemanticEntity(); + $i = 1; foreach ( $statements->getBestStatements()->getByRank( [ Statement::RANK_PREFERRED, Statement::RANK_NORMAL ] ) as $statement ) { - $this->addStatement( $semanticEntity, $statement ); + $this->addStatement( $semanticEntity, $statement, $i ); + $i++; } return $semanticEntity; } - private function addStatement( SemanticEntity $semanticEntity, Statement $statement ): void { - $dataItem = $this->statementTranslator->statementToDataItem( $statement, $this->subject ); + private function addStatement( SemanticEntity $semanticEntity, Statement $statement, $statementNr ): void { + $mainSnakDataItem = $this->statementTranslator->statementToDataItem( $statement, $this->subject ); - if ( $dataItem !== null ) { + if ( $mainSnakDataItem !== null ) { + // first link the statement value directly via property name // TODO: belongs in statement translator - if ( $dataItem instanceof \SMWDIContainer ) { - $semanticEntity->addPropertyValue( DIProperty::TYPE_SUBOBJECT, $dataItem ); + if ( $mainSnakDataItem instanceof \SMWDIContainer ) { + $semanticEntity->addPropertyValue( DIProperty::TYPE_SUBOBJECT, $mainSnakDataItem ); $semanticEntity->addPropertyValue( - $this->propertyIdForStatement( $statement ), - $dataItem->getSemanticData()->getSubject() + $this->NumericPropertyIdForStatement( $statement ), + $mainSnakDataItem->getSemanticData()->getSubject() ); } else { $semanticEntity->addPropertyValue( - $this->propertyIdForStatement( $statement ), - $dataItem + $this->NumericPropertyIdForStatement( $statement ), + $mainSnakDataItem ); } + + // for complex data e.g. using qualifiers, we add the statement additionally as a subobject + $subObjs = $this->statementTranslator->statementToSubobjects($statement, $this->subject, $statementNr); + foreach($subObjs as $subObject ){ + $semanticEntity->addPropertyValue( DIProperty::TYPE_SUBOBJECT, $subObject->getContainer() ); + } + //$semanticEntity->addPropertyValue( 'STATEMENTS', $subObject->getContainer() ); + + // now process qualifiers + /* + $qualifiers = $statement->getQualifiers(); + $i = 1; + foreach( $qualifiers as $actQualifier) { + $actQualifierDataItem = $this->statementTranslator->snakToDataItem($actQualifier, $statement, $this->subject); + + // TODO: do we need to handle type SMWDIContainer here? + //throw new MWException(json_encode($actQualifier->getDataValue())); + $newPropId = $statement->getPropertyId()->getSerialization()."hasQualifier".$actQualifier->getPropertyId(); + $semanticEntity->addPropertyValue( + $newPropId, + $actQualifierDataItem + ); + $i++; + }*/ } } - private function propertyIdForStatement( Statement $statement ): string { + private function NumericPropertyIdForStatement( Statement $statement ): string { return UserDefinedProperties::idFromWikibaseProperty( $statement->getPropertyId() ); } diff --git a/src/Translation/StatementTranslator.php b/src/Translation/StatementTranslator.php index a58ee90..4669202 100644 --- a/src/Translation/StatementTranslator.php +++ b/src/Translation/StatementTranslator.php @@ -5,11 +5,16 @@ namespace MediaWiki\Extension\SemanticWikibase\Translation; use MediaWiki\Extension\SemanticWikibase\Wikibase\TypedDataValue; -use SMW\DIWikiPage; -use SMWDataItem; use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup; use Wikibase\DataModel\Snak\PropertyValueSnak; use Wikibase\DataModel\Statement\Statement; +use SMW\DIWikiPage; +use SMWDataItem; +use SMW\Subobject; +use SMW\DataValueFactory; +use SMW\DIProperty; +use MediaWiki\MediaWikiServices; +use SMWDITime; class StatementTranslator { @@ -25,8 +30,21 @@ public function __construct( DataValueTranslator $dataValueTranslator, Container public function statementToDataItem( Statement $statement, DIWikiPage $subject ): ?SMWDataItem { $mainSnak = $statement->getMainSnak(); + return $this->snakToDataItem($mainSnak, $statement, $subject); + } + + public function statementToQualifiersDataItemList( Statement $statement, DIWikiPage $subject ): array { + $qualifiers = $statement->getQualifiers(); + $result = []; + foreach( $qualifiers as $actQualifier) { + $result[] = $this->snakToDataItem($actQualifier, $statement, $subject); + } - if ( !( $mainSnak instanceof PropertyValueSnak ) ) { + return $result; + } + + public function snakToDataItem( PropertyValueSnak $snak, Statement $statement, DIWikiPage $subject ): ?SMWDataItem { + if ( !( $snak instanceof PropertyValueSnak ) ) { return null; } @@ -34,7 +52,7 @@ public function statementToDataItem( Statement $statement, DIWikiPage $subject ) return $this->containerValueTranslator->statementToDataItem( $statement, $subject ); } - return $this->snakWithSimpleDataValueToDataItem( $mainSnak ); + return $this->snakWithSimpleDataValueToDataItem( $snak ); } private function snakWithSimpleDataValueToDataItem( PropertyValueSnak $snak ): SMWDataItem { @@ -46,4 +64,81 @@ private function snakWithSimpleDataValueToDataItem( PropertyValueSnak $snak ): S ); } + public function statementToSubobjects( Statement $statement, DIWikiPage $subject , $statementNr): array { + $result = []; + $wbPropertyNamespaceName = MediaWikiServices::getInstance()->getNamespaceInfo()->getCanonicalName( WB_NS_PROPERTY ); + $smwPropertyNamespaceName = MediaWikiServices::getInstance()->getNamespaceInfo()->getCanonicalName( SMW_NS_PROPERTY ); + + $mainSnak = $statement->getMainSnak(); + $qualifiers = $statement->getQualifiers(); + $mainSnakDI = $this->snakToDataItem($mainSnak, $statement, $subject); + // create a smw semantic subobject for the statement + $statementProperty = $mainSnak->getPropertyId()->getLocalPart(); + $statementValue = StatementTranslator::valueDIToString($mainSnakDI); + + $statementObj = new Subobject($subject->getTitle()); + $statementObj->setEmptyContainerForId("statement".$statementNr); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('subObjectType', 'statement', false, $subject) ); + //$statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('item', $subject->getTitle(), false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_name', $statementProperty, false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_wb', $wbPropertyNamespaceName.":".$statementProperty, false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_smw', $smwPropertyNamespaceName.":".$statementProperty, false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('value', $statementValue, false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText($statementProperty, $statementValue, false, $subject) ); + #$prop = DIProperty::newFromUserLabel($mainSnak->getPropertyId()->getLocalPart()); + $prop = new DIProperty( 'semanticProperty:value'); + wfDebug('swb: prop: '.$prop); + $propertyDV = DataValueFactory::getInstance()->newPropertyValueByLabel("value"); + $propertyDI = $propertyDV->getDataItem(); + #$statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByItem($mainSnakDI, $propertyDI)); + $result[] = $statementObj; + $qNr = 1; + $statementPage = $subject->getTitle()."#statement".$statementNr; + foreach( $qualifiers as $actQualifier){ + $qualifierProperty = $actQualifier->getPropertyId()->getLocalPart(); + $qualifierId = "statement".$statementNr."-qualifier".$qNr; + $qualifierObj = new Subobject($subject->getTitle()); + $qualifierObj->setEmptyContainerForId($qualifierId); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('subObjectType', 'qualifier', false, $subject) ); + //$qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('item', $subject->getTitle(), false, $subject) ); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('statement', $statementPage, false, $subject) ); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_name', $qualifierProperty, false, $subject) ); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_wb', $wbPropertyNamespaceName.":".$qualifierProperty, false, $subject) ); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('property_smw', $smwPropertyNamespaceName.":".$qualifierProperty, false, $subject) ); + $qualifierDI = $this->snakToDataItem($actQualifier, $statement, $subject); + $qualifierValue = StatementTranslator::valueDIToString($qualifierDI); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('value', $qualifierValue, false, $subject) ); + $qualifierObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText($qualifierProperty, $qualifierValue, false, $subject) ); + + // set reference in statement obj + $qualifierPage = $subject->getTitle()."#".$qualifierId; + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText('qualifier', $qualifierPage, false, $subject) ); + $statementObj->addDataValue( DataValueFactory::getInstance()->newDataValueByText($statementProperty.$statementValue, $qualifierPage, false, $subject) ); + + + $qNr++; + $result[] = $qualifierObj; + } + + return $result; + + } + + + + private static function valueDIToString($di) : string { + wfDebug('smw: translate DI: '.get_class($di)); + if( $di instanceof DIWikiPage ) { + return $di->getTitle()->getText().""; + } else if ( $di instanceof SMWDITime){ + wfDebug('time:'.$di->getSerialization()); + return $di->asDateTime()->format( 'Y-m-d H:i:s' ); + #return "01.01.1700"; + } + wfdebug('default'); + return $di.""; + + } + } + diff --git a/src/Translation/UserDefinedProperties.php b/src/Translation/UserDefinedProperties.php index 13205b0..f887a74 100644 --- a/src/Translation/UserDefinedProperties.php +++ b/src/Translation/UserDefinedProperties.php @@ -5,7 +5,7 @@ namespace MediaWiki\Extension\SemanticWikibase\Translation; use MediaWiki\Extension\SemanticWikibase\SMW\SemanticProperty; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Services\Lookup\TermLookup; use Wikibase\Lib\Store\PropertyInfoLookup; use Wikibase\Lib\Store\StorageException; @@ -40,10 +40,12 @@ public function getAll(): array { $this->propertyTypeTranslator->translate( $propertyInfo['type'] ), $id, $this->termLookup->getLabel( - new PropertyId( $id ), + new NumericPropertyId( $id ), $this->labelLanguageCode ) ); + }else{ + wfDebug("swb: cannot translate ".$propertyInfo['type']); } } @@ -59,11 +61,11 @@ public function getAllPropertyInfo(): array { } } - private static function idFromWikibaseString( string $propertyId ): string { - return '___SWB_' . $propertyId; + private static function idFromWikibaseString( string $NumericPropertyId ): string { + return '___SWB_' . $NumericPropertyId; } - public static function idFromWikibaseProperty( PropertyId $id ): string { + public static function idFromWikibaseProperty( NumericPropertyId $id ): string { return self::idFromWikibaseString( $id->getSerialization() ); } diff --git a/tests/TestFactory.php b/tests/TestFactory.php index c09410b..d9acf5d 100644 --- a/tests/TestFactory.php +++ b/tests/TestFactory.php @@ -10,7 +10,7 @@ use MediaWiki\Extension\SemanticWikibase\Translation\MonoTextTranslator; use MediaWiki\Extension\SemanticWikibase\Translation\StatementTranslator; use SMW\DIWikiPage; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Services\Lookup\InMemoryDataTypeLookup; use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup; @@ -36,7 +36,7 @@ private function initialize(): void { private function newPropertyTypeLookup(): InMemoryDataTypeLookup { $lookup = new InMemoryDataTypeLookup(); - $lookup->setDataTypeForProperty( new PropertyId( 'P1' ), 'string' ); + $lookup->setDataTypeForProperty( new NumericPropertyId( 'P1' ), 'string' ); return $lookup; } diff --git a/tests/Unit/Translation/ContainerValueTranslatorTest.php b/tests/Unit/Translation/ContainerValueTranslatorTest.php index 9383020..a5804c4 100644 --- a/tests/Unit/Translation/ContainerValueTranslatorTest.php +++ b/tests/Unit/Translation/ContainerValueTranslatorTest.php @@ -15,7 +15,7 @@ use SMW\DIProperty; use SMW\DIWikiPage; use SMWDIContainer; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Snak\PropertySomeValueSnak; use Wikibase\DataModel\Snak\PropertyValueSnak; use Wikibase\DataModel\Statement\Statement; @@ -32,7 +32,7 @@ public function testTranslateBoundedQuantity() { $container = $this->translate( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new QuantityValue( new DecimalValue( 42 ), 'mega awesome', @@ -70,7 +70,7 @@ public function testTranslateUnboundedQuantity() { $container = $this->translate( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new UnboundedQuantityValue( new DecimalValue( 42 ), 'mega awesome' @@ -111,7 +111,7 @@ public function testSupportsQuantityStatements() { $this->assertTrue( $this->newTranslator()->supportsStatement( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new UnboundedQuantityValue( new DecimalValue( 42 ), 'mega awesome' @@ -125,7 +125,7 @@ public function testDoesNotSupportNonValueStatements() { $this->assertFalse( $this->newTranslator()->supportsStatement( new Statement( new PropertySomeValueSnak( - new PropertyId( 'P1' ) + new NumericPropertyId( 'P1' ) ) ) ) ); @@ -135,7 +135,7 @@ public function testDoesNotSupportBooleanValueStatements() { $this->assertFalse( $this->newTranslator()->supportsStatement( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new BooleanValue( true ) ) ) diff --git a/tests/Unit/Translation/DataValueTranslatorTest.php b/tests/Unit/Translation/DataValueTranslatorTest.php index 35be23e..315dadd 100644 --- a/tests/Unit/Translation/DataValueTranslatorTest.php +++ b/tests/Unit/Translation/DataValueTranslatorTest.php @@ -20,7 +20,7 @@ use SMWDIUri; use Wikibase\DataModel\Entity\EntityIdValue; use Wikibase\DataModel\Entity\ItemId; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; /** * @covers \MediaWiki\Extension\SemanticWikibase\Translation\DataValueTranslator @@ -70,7 +70,7 @@ public function testTranslateEntityId() { $this->assertEquals( new DIWikiPage( 'P42', WB_NS_PROPERTY ), - $this->translate( new EntityIdValue( new PropertyId( 'P42' ) ) ) + $this->translate( new EntityIdValue( new NumericPropertyId( 'P42' ) ) ) ); } diff --git a/tests/Unit/Translation/ItemTranslatorTest.php b/tests/Unit/Translation/ItemTranslatorTest.php index 90429e0..8a66007 100644 --- a/tests/Unit/Translation/ItemTranslatorTest.php +++ b/tests/Unit/Translation/ItemTranslatorTest.php @@ -17,7 +17,7 @@ use SMWDIContainer; use Wikibase\DataModel\Entity\Item; use Wikibase\DataModel\Entity\ItemId; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Snak\PropertyNoValueSnak; use Wikibase\DataModel\Snak\PropertySomeValueSnak; use Wikibase\DataModel\Snak\PropertyValueSnak; @@ -54,7 +54,7 @@ public function testItemIdIsTranslated() { public function testStatementMainSnakValueIsTranslated() { $item = new Item( new ItemId( 'Q1' ) ); $item->getStatements()->addNewStatement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new StringValue( 'Hello there' ) ) ); @@ -68,12 +68,12 @@ public function testMultipleStatementsForOneProperty() { $item = new Item( new ItemId( 'Q1' ) ); $item->getStatements()->addNewStatement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new StringValue( 'Hello there' ) ) ); $item->getStatements()->addNewStatement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new StringValue( 'fellow sentient' ) ) ); @@ -89,8 +89,8 @@ public function testMultipleStatementsForOneProperty() { public function testOnlyPropertyValueSnaksGetAdded() { $item = new Item( new ItemId( 'Q1' ) ); - $item->getStatements()->addNewStatement( new PropertyNoValueSnak( new PropertyId( 'P1' ) ) ); - $item->getStatements()->addNewStatement( new PropertySomeValueSnak( new PropertyId( 'P1' ) ) ); + $item->getStatements()->addNewStatement( new PropertyNoValueSnak( new NumericPropertyId( 'P1' ) ) ); + $item->getStatements()->addNewStatement( new PropertySomeValueSnak( new NumericPropertyId( 'P1' ) ) ); $this->assertSame( [], @@ -103,7 +103,7 @@ public function testTranslationToSubobject() { $item->getStatements()->addNewStatement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new UnboundedQuantityValue( new DecimalValue( 42 ), 'mega awesome' @@ -135,7 +135,7 @@ public function testTranslationToSubobject() { ); } - private function assertHasSubobjectWithPropertyValue( SemanticEntity $semanticEntity, string $propertyId, \SMWDataItem $expectedDataItem ) { + private function assertHasSubobjectWithPropertyValue( SemanticEntity $semanticEntity, string $NumericPropertyId, \SMWDataItem $expectedDataItem ) { /** * @var SMWDIContainer $container */ @@ -143,7 +143,7 @@ private function assertHasSubobjectWithPropertyValue( SemanticEntity $semanticEn $this->assertEquals( [ $expectedDataItem ], - $container->getSemanticData()->getPropertyValues( new DIProperty( $propertyId ) ) + $container->getSemanticData()->getPropertyValues( new DIProperty( $NumericPropertyId ) ) ); } diff --git a/tests/Unit/Translation/PropertyTranslatorTest.php b/tests/Unit/Translation/PropertyTranslatorTest.php index efa738b..d66a613 100644 --- a/tests/Unit/Translation/PropertyTranslatorTest.php +++ b/tests/Unit/Translation/PropertyTranslatorTest.php @@ -11,7 +11,7 @@ use MediaWiki\Extension\SemanticWikibase\Translation\FixedProperties; use SMW\DIWikiPage; use Wikibase\DataModel\Entity\Property; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; /** * @covers \MediaWiki\Extension\SemanticWikibase\Translation\PropertyTranslator @@ -30,7 +30,7 @@ public function testIdIsTranslated() { private function newProperty(): Property { return new Property( - new PropertyId( self::ID ), + new NumericPropertyId( self::ID ), null, self::TYPE ); diff --git a/tests/Unit/Translation/StatementTranslatorTest.php b/tests/Unit/Translation/StatementTranslatorTest.php index 681f293..00c4281 100644 --- a/tests/Unit/Translation/StatementTranslatorTest.php +++ b/tests/Unit/Translation/StatementTranslatorTest.php @@ -13,7 +13,7 @@ use PHPUnit\Framework\TestCase; use SMW\DIProperty; use SMW\DIWikiPage; -use Wikibase\DataModel\Entity\PropertyId; +use Wikibase\DataModel\Entity\NumericPropertyId; use Wikibase\DataModel\Snak\PropertyValueSnak; use Wikibase\DataModel\Statement\Statement; @@ -32,7 +32,7 @@ public function testTranslateSimpleValue() { $this->newTranslator()->statementToDataItem( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new StringValue( 'Kittens' ) ) ), @@ -45,7 +45,7 @@ public function testTranslateContainerValue() { $container = $this->newTranslator()->statementToDataItem( new Statement( new PropertyValueSnak( - new PropertyId( 'P1' ), + new NumericPropertyId( 'P1' ), new UnboundedQuantityValue( new DecimalValue( 42 ), 'mega awesome'