summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php295
1 files changed, 295 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php b/www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php
new file mode 100644
index 00000000..954b048a
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Exporter/ExpResourceMapper.php
@@ -0,0 +1,295 @@
+<?php
+
+namespace SMW\Exporter;
+
+use RuntimeException;
+use SMW\DataValueFactory;
+use SMW\DIProperty;
+use SMW\DIWikiPage;
+use SMW\Exporter\Element\ExpNsResource;
+use SMW\Exporter\Element\ExpResource;
+use SMW\InMemoryPoolCache;
+use SMW\Store;
+use SMWDataItem as DataItem;
+use SMWExporter as Exporter;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.2
+ *
+ * @author mwjames
+ * @author Markus Krötzsch
+ */
+class ExpResourceMapper {
+
+ /**
+ * Identifies auxiliary data (helper values)
+ */
+ const AUX_MARKER = 'aux';
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var DataValueFactory
+ */
+ private $dataValueFactory;
+
+ /**
+ * @var InMemoryPoolCache
+ */
+ private $inMemoryPoolCache;
+
+ /**
+ * @note Legacy setting expected to vanish with 3.0
+ *
+ * @var boolean
+ */
+ private $bcAuxiliaryUse = true;
+
+ /**
+ * @var boolean
+ */
+ private $seekImportVocabulary = true;
+
+ /**
+ * @since 2.2
+ *
+ * @param Store $store
+ */
+ public function __construct( Store $store ) {
+ $this->store = $store;
+ $this->dataValueFactory = DataValueFactory::getInstance();
+ $this->inMemoryPoolCache = InMemoryPoolCache::getInstance();
+ }
+
+ /**
+ * @since 2.3
+ */
+ public function reset() {
+ $this->inMemoryPoolCache->resetPoolCacheById( 'exporter.expresource.mapper' );
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param boolean $bcAuxiliaryUse
+ */
+ public function setBCAuxiliaryUse( $bcAuxiliaryUse ) {
+ $this->bcAuxiliaryUse = (bool)$bcAuxiliaryUse;
+ }
+
+ /**
+ * @since 2.2
+ *
+ * @param DIWikiPage $subject
+ */
+ public function invalidateCache( DIWikiPage $subject ) {
+
+ $hash = $subject->getHash();
+
+ $poolCache = $this->inMemoryPoolCache->getPoolCacheById(
+ 'exporter.expresource.mapper'
+ );
+
+ foreach ( [ $hash, $hash . self::AUX_MARKER . $this->seekImportVocabulary ] as $key ) {
+ $poolCache->delete( $key );
+ }
+ }
+
+ /**
+ * Create an ExpElement for some internal resource, given by an
+ * DIProperty object.
+ *
+ * This code is only applied to user-defined properties, since the
+ * code for special properties in
+ * Exporter::getSpecialPropertyResource may require information
+ * about the namespace in which some special property is used.
+ *
+ * @note $useAuxiliaryModifier is to determine whether an auxiliary
+ * property resource is to store a helper value
+ * (see Exporter::getDataItemHelperExpElement) should be generated
+ *
+ * @param DIProperty $property
+ * @param boolean $useAuxiliaryModifier
+ * @param boolean $seekImportVocabulary
+ *
+ * @return ExpResource
+ * @throws RuntimeException
+ */
+ public function mapPropertyToResourceElement( DIProperty $property, $useAuxiliaryModifier = false, $seekImportVocabulary = true ) {
+
+ // We want the a canonical representation to ensure that resources
+ // are language independent
+ $this->seekImportVocabulary = $seekImportVocabulary;
+ $diWikiPage = $property->getCanonicalDiWikiPage();
+
+ if ( $diWikiPage === null ) {
+ throw new RuntimeException( 'Only non-inverse, user-defined properties are permitted.' );
+ }
+
+ // No need for any aux properties besides those listed here
+ if ( !$this->bcAuxiliaryUse && $property->findPropertyTypeID() !== '_dat' && $property->findPropertyTypeID() !== '_geo' ) {
+ $useAuxiliaryModifier = false;
+ }
+
+ $expResource = $this->mapWikiPageToResourceElement( $diWikiPage, $useAuxiliaryModifier );
+ $this->seekImportVocabulary = true;
+
+ return $expResource;
+ }
+
+ /**
+ * Create an ExpElement for some internal resource, given by an
+ * DIWikiPage object. This is the one place in the code where URIs
+ * of wiki pages and user-defined properties are determined. A modifier
+ * can be given to make variants of a URI, typically done for
+ * auxiliary properties. In this case, the URI is modiied by appending
+ * "-23$modifier" where "-23" is the URI encoding of "#" (a symbol not
+ * occurring in MW titles).
+ *
+ * @param DIWikiPage $diWikiPage
+ * @param boolean $useAuxiliaryModifier
+ *
+ * @return ExpResource
+ */
+ public function mapWikiPageToResourceElement( DIWikiPage $diWikiPage, $useAuxiliaryModifier = false ) {
+
+ $modifier = $useAuxiliaryModifier ? self::AUX_MARKER : '';
+
+ $hash = $diWikiPage->getHash() . $modifier . $this->seekImportVocabulary;
+
+ $poolCache = $this->inMemoryPoolCache->getPoolCacheById( 'exporter.expresource.mapper' );
+
+ if ( $poolCache->contains( $hash ) ) {
+ return $poolCache->fetch( $hash );
+ }
+
+ if ( $diWikiPage->getSubobjectName() !== '' ) {
+ $modifier = $diWikiPage->getSubobjectName();
+ }
+
+ $resource = $this->newExpNsResource(
+ $diWikiPage,
+ $modifier
+ );
+
+ $poolCache->save(
+ $hash,
+ $resource
+ );
+
+ return $resource;
+ }
+
+ private function newExpNsResource( $diWikiPage, $modifier ) {
+
+ $importDataItem = $this->findImportDataItem( $diWikiPage, $modifier );
+
+ if ( $this->seekImportVocabulary && $importDataItem instanceof DataItem ) {
+ list( $localName, $namespace, $namespaceId ) = $this->defineElementsForImportDataItem( $importDataItem );
+ } else {
+ list( $localName, $namespace, $namespaceId ) = $this->defineElementsForDiWikiPage( $diWikiPage, $modifier );
+ }
+
+ $resource = new ExpNsResource(
+ $localName,
+ $namespace,
+ $namespaceId,
+ $diWikiPage
+ );
+
+ $resource->isImported = $importDataItem instanceof DataItem;
+ $dbKey = $diWikiPage->getDBkey();
+
+ if ( $diWikiPage->getNamespace() === SMW_NS_PROPERTY && $dbKey !== '' && $dbKey{0} !== '-' ) {
+ $resource->isUserDefined = DIProperty::newFromUserLabel( $diWikiPage->getDBkey() )->isUserDefined();
+ }
+
+ return $resource;
+ }
+
+ private function defineElementsForImportDataItem( DataItem $dataItem ) {
+
+ $importValue = $this->dataValueFactory->newDataValueByItem(
+ $dataItem,
+ new DIProperty( '_IMPO' )
+ );
+
+ return [
+ $importValue->getLocalName(),
+ $importValue->getNS(),
+ $importValue->getNSID()
+ ];
+ }
+
+ private function defineElementsForDiWikiPage( DIWikiPage $diWikiPage, $modifier ) {
+
+ $localName = '';
+ $hasFixedNamespace = false;
+
+ if ( $diWikiPage->getNamespace() === NS_CATEGORY ) {
+ $namespace = Exporter::getInstance()->getNamespaceUri( 'category' );
+ $namespaceId = 'category';
+ $localName = Escaper::encodeUri( $diWikiPage->getDBkey() );
+ $hasFixedNamespace = true;
+ }
+
+ if ( $diWikiPage->getNamespace() === SMW_NS_PROPERTY ) {
+ $namespace = Exporter::getInstance()->getNamespaceUri( 'property' );
+ $namespaceId = 'property';
+ $localName = Escaper::encodeUri( $diWikiPage->getDBkey() );
+ $hasFixedNamespace = true;
+ }
+
+ if ( ( $localName === '' ) ||
+ ( in_array( $localName{0}, [ '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] ) ) ||
+ ( $hasFixedNamespace && strpos( $localName, '/' ) !== false )
+ ) {
+ $namespace = Exporter::getInstance()->getNamespaceUri( 'wiki' );
+ $namespaceId = 'wiki';
+ $localName = Escaper::encodePage( $diWikiPage );
+ }
+
+ if ( $hasFixedNamespace && strpos( $localName, '/' ) !== false ) {
+ $namespace = Exporter::getInstance()->getNamespaceUri( 'wiki' );
+ $namespaceId = 'wiki';
+ $localName = Escaper::armorChars( Escaper::encodePage( $diWikiPage ) );
+ }
+
+ // "-23$modifier" where "-23" is the URI encoding of "#" (a symbol not
+ // occurring in MW titles).
+ if ( $modifier !== '' ) {
+ $localName .= '-23' . Escaper::encodeUri( $modifier );
+ }
+
+ return [
+ $localName,
+ $namespace,
+ $namespaceId
+ ];
+ }
+
+ private function findImportDataItem( DIWikiPage $diWikiPage, $modifier ) {
+
+ $importDataItems = null;
+
+ // Only try to find an import vocab for a matchable entity
+ if ( $this->seekImportVocabulary && $diWikiPage->getNamespace() === NS_CATEGORY || $diWikiPage->getNamespace() === SMW_NS_PROPERTY ) {
+ $importDataItems = $this->store->getPropertyValues(
+ $diWikiPage,
+ new DIProperty( '_IMPO' )
+ );
+ }
+
+ if ( $importDataItems !== null && $importDataItems !== [] ) {
+ $importDataItems = current( $importDataItems );
+ }
+
+ return $importDataItems;
+ }
+
+}