summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php274
1 files changed, 274 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php b/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php
new file mode 100644
index 00000000..11065976
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/SQLStore/RedirectStore.php
@@ -0,0 +1,274 @@
+<?php
+
+namespace SMW\SQLStore;
+
+use Onoi\Cache\Cache;
+use SMW\HashBuilder;
+use SMW\InMemoryPoolCache;
+use SMW\MediaWiki\Jobs\UpdateJob;
+use SMW\SQLStore\TableBuilder\FieldType;
+use SMW\Store;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.1
+ *
+ * @author mwjames
+ */
+class RedirectStore {
+
+ const TABLE_NAME = 'smw_fpt_redi';
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var Cache
+ */
+ private $cache;
+
+ /**
+ * @var boolean
+ */
+ private $hasEqualitySupport = false;
+
+ /**
+ * @since 2.1
+ *
+ * @param Store $store
+ * @param Cache|null $cache
+ */
+ public function __construct( Store $store, Cache $cache = null ) {
+ $this->store = $store;
+ $this->cache = $cache;
+
+ if ( $this->cache === null ) {
+ $this->cache = InMemoryPoolCache::getInstance()->getPoolCacheById( 'sql.store.redirect.infostore' );
+ }
+
+ $this->setEqualitySupportFlag( $GLOBALS['smwgQEqualitySupport'] );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param integer $equalitySupport
+ */
+ public function setEqualitySupportFlag( $equalitySupport ) {
+ $this->hasEqualitySupport = $equalitySupport != SMW_EQ_NONE;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $title DB key
+ * @param integer $namespace
+ *
+ * @return boolean
+ */
+ public function isRedirect( $title, $namespace ) {
+ return $this->findRedirect( $title, $namespace ) != 0;
+ }
+
+ /**
+ * Returns an id for a redirect if no redirect is found 0 is returned
+ *
+ * @since 2.1
+ *
+ * @param string $title DB key
+ * @param integer $namespace
+ *
+ * @return integer
+ */
+ public function findRedirect( $title, $namespace ) {
+
+ $hash = HashBuilder::createHashIdFromSegments(
+ $title,
+ $namespace
+ );
+
+ if ( $this->cache->contains( $hash ) ) {
+ return $this->cache->fetch( $hash );
+ }
+
+ $id = $this->select( $title, $namespace );
+
+ $this->cache->save( $hash, $id );
+
+ return $id;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param integer $id
+ * @param string $title
+ * @param integer $namespace
+ */
+ public function addRedirect( $id, $title, $namespace ) {
+
+ $this->insert( $id, $title, $namespace );
+
+ $hash = HashBuilder::createHashIdFromSegments(
+ $title,
+ $namespace
+ );
+
+ $this->cache->save( $hash, $id );
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param string $id
+ * @param string $title
+ * @param integer $namespace
+ */
+ public function updateRedirect( $id, $title, $namespace ) {
+
+ $this->deleteRedirect( $title, $namespace );
+
+ if ( !$this->canCreateUpdateJobs() || !$this->hasEqualitySupport ) {
+ return;
+ }
+
+ // Entries that refer to old target may in fact refer to subject,
+ // but we don't know which: schedule affected pages for update
+ $propertyTables = $this->store->getPropertyTables();
+ $connection = $this->store->getConnection( 'mw.db' );
+ $jobs = [];
+
+ foreach ( $propertyTables as $proptable ) {
+
+ // Can be skipped safely
+ if ( $proptable->getName() == self::TABLE_NAME ) {
+ continue;
+ }
+
+ $query = [
+ 'from' => '',
+ 'fields' => ''
+ ];
+
+ $query['condition'] = [ 'p_id' => $id ];
+
+ if ( $proptable->usesIdSubject() ) {
+ $query['from'] .= $connection->tableName( $proptable->getName() );
+ $query['from'] .= ' INNER JOIN ';
+ $query['from'] .= $connection->tableName( SQLStore::ID_TABLE ) . ' ON s_id=smw_id';
+ $query['fields'] = 'DISTINCT smw_title AS t,smw_namespace AS ns';
+ } else {
+ $query['from'] = $connection->tableName( $proptable->getName() );
+ $query['fields'] = 'DISTINCT s_title AS t,s_namespace AS ns';
+ }
+
+ if ( $namespace === SMW_NS_PROPERTY && !$proptable->isFixedPropertyTable() ) {
+ $this->findUpdateJobs( $connection, $query, $jobs );
+ }
+
+ foreach ( $proptable->getFields( $this->store ) as $fieldName => $fieldType ) {
+
+ if ( $fieldType !== FieldType::FIELD_ID ) {
+ continue;
+ }
+
+ $query['condition'] = [ $fieldName => $id ];
+ $this->findUpdateJobs( $connection, $query, $jobs );
+ }
+ }
+
+ foreach ( $jobs as $job ) {
+ $job->insert();
+ }
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param string $title
+ * @param integer $namespace
+ */
+ public function deleteRedirect( $title, $namespace ) {
+
+ $this->delete( $title, $namespace );
+
+ $hash = HashBuilder::createHashIdFromSegments(
+ $title,
+ $namespace
+ );
+
+ $this->cache->delete( $hash );
+ }
+
+ private function select( $title, $namespace ) {
+
+ $connection = $this->store->getConnection( 'mw.db' );
+
+ $row = $connection->selectRow(
+ self::TABLE_NAME,
+ 'o_id',
+ [
+ 's_title' => $title,
+ 's_namespace' => $namespace
+ ],
+ __METHOD__
+ );
+
+ return $row !== false && isset( $row->o_id ) ? (int)$row->o_id : 0;
+ }
+
+ private function insert( $id, $title, $namespace ) {
+
+ $connection = $this->store->getConnection( 'mw.db' );
+
+ $connection->insert(
+ self::TABLE_NAME,
+ [
+ 's_title' => $title,
+ 's_namespace' => $namespace,
+ 'o_id' => $id ],
+ __METHOD__
+ );
+ }
+
+ private function delete( $title, $namespace ) {
+
+ $connection = $this->store->getConnection( 'mw.db' );
+
+ $connection->delete(
+ self::TABLE_NAME,
+ [
+ 's_title' => $title,
+ 's_namespace' => $namespace ],
+ __METHOD__
+ );
+ }
+
+ private function canCreateUpdateJobs() {
+ return $this->store->getOption( Store::OPT_CREATE_UPDATE_JOB, true ) && $this->store->getOption( 'smwgEnableUpdateJobs' );
+ }
+
+ private function findUpdateJobs( $connection, $query, &$jobs ) {
+
+ $res = $connection->select(
+ $query['from'],
+ $query['fields'],
+ $query['condition'],
+ __METHOD__
+ );
+
+ foreach ( $res as $row ) {
+ $title = Title::makeTitleSafe( $row->ns, $row->t );
+
+ if ( $title !== null ) {
+ $jobs[] = new UpdateJob( $title );
+ }
+ }
+
+ $connection->freeResult( $res );
+ }
+
+}