Matthias Mullie has submitted this change and it was merged. Change subject: Remove flow_text table ......................................................................
Remove flow_text table Merged flow_text into flow_revision, it only exists in core for historical reasons. Any wiki that expects a reasonable amount of content should set $wgFlowExternalStore to keep the bulk of content outside the revision table. To allow storage classes to assign auto-ids the WritableObjectStorage::insert method now returns an array representing the final storage state. ObjectMapper::fromStorageRow has received an additional nullable param, $object, which allows us to push those changes from insert back into the object. Revision content compression happens in AbstractRevision::setContent, decompression is handled in AbstractRevision::getContent so we lazily decompres only the content the content that is needed. Change-Id: I5cf3fe8ef0f6edb4328f4355a4abe5bec439446e --- M flow.sql M includes/Data/ObjectManager.php M includes/Data/RevisionStorage.php M includes/Model/AbstractRevision.php M includes/Model/Definition.php M includes/Model/PostRevision.php M includes/Model/Summary.php M includes/Model/TopicListEntry.php M includes/Model/Workflow.php M includes/Repository/TreeRepository.php 10 files changed, 228 insertions(+), 171 deletions(-) Approvals: Matthias Mullie: Verified; Looks good to me, approved diff --git a/flow.sql b/flow.sql index 22aa4af..caad08b 100644 --- a/flow.sql +++ b/flow.sql @@ -106,28 +106,18 @@ rev_user_text varchar(255) binary not null default '', -- rev_id of parent or null if no previous revision rev_parent_id binary(16), - + -- comma separated set of ascii flags. + rev_flags tinyblob not null, -- content of the revision - rev_text_id int unsigned not null, + rev_content mediumblob not null, -- comment attached to revision's flag change rev_comment varchar(255) binary null, - PRIMARY KEY (rev_id) ) /*$wgDBTableOptions*/; -- Prevents inconsistency, but perhaps will hurt inserts? CREATE UNIQUE INDEX /*i*/flow_revision_unique_parent ON /*_*/flow_revision (rev_parent_id); - -CREATE TABLE /*_*/flow_text ( - -- undecided on uuid, or if table is even neccessary - -- large wiki should just use external store to distribute - -- content - text_id int(10) unsigned not null auto_increment, - text_content mediumblob not null, - text_flags tinyblob not null, - PRIMARY KEY (text_id) -) /*$wgDBTableOptions*/; -- Closure table implementation of tree storage in sql -- We may be able to go simpler than this diff --git a/includes/Data/ObjectManager.php b/includes/Data/ObjectManager.php index 3d1d999..d5b2f0a 100644 --- a/includes/Data/ObjectManager.php +++ b/includes/Data/ObjectManager.php @@ -50,6 +50,9 @@ // Note that while ObjectLocator implements the above ObjectStorage interface, ObjectManger // cant use this interface because backing stores deal in rows, and OM deals in objects. interface WritableObjectStorage extends ObjectStorage { + /** + * @return array The resulting $row including any auto-assigned ids or false on failure + */ function insert( array $row ); function update( array $old, array $new ); function remove( array $row ); @@ -62,9 +65,15 @@ function toStorageRow( $object ); /** - * Convert a db row to its domain model. + * Convert a db row to its domain model. Object passing is intended for + * updating the object to match a changed storage representation. + * + * @param array $row assoc array representing the domain model + * @param object|null $object The domain model to populate, creates when null + * @return object The domain model populated with $row + * @throws Exception When object is the wrong class for the mapper */ - function fromStorageRow( array $row ); + function fromStorageRow( array $row, $object = null ); } // An Index is just a store that receives updates via handler. @@ -330,12 +339,17 @@ protected function insert( $object ) { try { - $new = $this->mapper->toStorageRow( $object ); - $this->storage->insert( $new ); - foreach ( $this->lifecycleHandlers as $handler ) { - $handler->onAfterInsert( $object, $new ); + $row = $this->mapper->toStorageRow( $object ); + $stored = $this->storage->insert( $row ); + if ( !$stored ) { + throw new \Exception( 'failed insert' ); } - $this->loaded[$object] = $new; + // propogate auto-id's and such back into $object + $this->mapper->fromStorageRow( $stored, $object ); + foreach ( $this->lifecycleHandlers as $handler ) { + $handler->onAfterInsert( $object, $stored ); + } + $this->loaded[$object] = $stored; } catch ( \Exception $e ) { throw new PersistenceException( 'failed insert', null, $e ); } @@ -449,12 +463,18 @@ public function toStorageRow( $object ) { return call_user_func( $this->toStorageRow, $object ); } - public function fromStorageRow( array $row ) { - return call_user_func( $this->fromStorageRow, $row ); + public function fromStorageRow( array $row, $object = null ) { + return call_user_func( $this->fromStorageRow, $row, $object ); } } -// Doesn't support updating primary key value yet +/** + * Standard backing store for data model with no special cases which is stored + * in a single table in mysql. + * + * Doesn't support updating primary key value yet + * Doesn't support auto-increment pk yet + */ class BasicDbStorage implements WritableObjectStorage { public function __construct( DbFactory $dbFactory, $table, array $primaryKey ) { if ( !$primaryKey ) { @@ -465,13 +485,19 @@ $this->primaryKey = $primaryKey; } + // Does not support auto-increment id yet public function insert( array $row ) { // insert returns boolean true/false - return $this->dbFactory->getDB( DB_MASTER )->insert( + $res = $this->dbFactory->getDB( DB_MASTER )->insert( $this->table, $row, __METHOD__ ); + if ( $res ) { + return $row; + } else { + return false; + } } public function update( array $old, array $new ) { diff --git a/includes/Data/RevisionStorage.php b/includes/Data/RevisionStorage.php index aa05ce4..b50eb0f 100644 --- a/includes/Data/RevisionStorage.php +++ b/includes/Data/RevisionStorage.php @@ -10,7 +10,7 @@ use User; abstract class RevisionStorage implements WritableObjectStorage { - static protected $allowedUpdateColumns = array( 'text_flags' ); + static protected $allowedUpdateColumns = array( 'rev_flags' ); protected $dbFactory; protected $externalStores; @@ -18,7 +18,7 @@ abstract protected function relatedPk(); abstract protected function joinField(); - abstract protected function insertRelated( array $rev, array $related ); + abstract protected function insertRelated( array $row, array $related ); abstract protected function updateRelated( array $rev, array $related ); abstract protected function removeRelated( array $row ); @@ -40,15 +40,12 @@ protected function findInternal( array $attributes, array $options = array() ) { $dbr = $this->dbFactory->getDB( DB_MASTER ); $res = $dbr->select( - array( $this->joinTable(), 'rev' => 'flow_revision', 'text' => 'flow_text' ), + array( $this->joinTable(), 'rev' => 'flow_revision' ), '*', UUID::convertUUIDs( $attributes ), __METHOD__, $options, - array( - 'rev' => array( 'JOIN', $this->joinField() . ' = rev_id' ), - 'text' => array( 'JOIN', "text_id = rev_text_id" ), - ) + array( 'rev' => array( 'JOIN', $this->joinField() . ' = rev_id' ) ) ); if ( !$res ) { return null; @@ -66,23 +63,8 @@ } else { $res = $this->findMultiInternal( $queries, $options ); } - if ( $this->externalStore ) { - $res = Merger::mergeMulti( - $res, - 'text_content', - array( 'ExternalStore', 'batchFetchFromURLs' ) - ); - } - - // decompress content - foreach ( $res as &$record ) { - foreach ( $record as $id => &$row ) { - $flags = explode( ',', $row['text_flags'] ); - $row['text_content'] = \Revision::decompressRevisionText( $row['text_content'], $flags ); - } - } - - return $res; + // Fetches content for all revisions flagged 'external' + return $this->mergeExternalContent( $res ); } protected function fallbackFindMulti( array $queries, array $options ) { @@ -167,16 +149,12 @@ // JOIN flow_revision ON tree_rev_id = rev_id // WHERE tree_rev_id IN (...) $res = $dbr->select( - array( 'flow_revision', 'text' => 'flow_text', 'rev' => $this->joinTable() ), + array( 'flow_revision', 'rev' => $this->joinTable() ), '*', array( 'rev_id' => $revisionIds ), __METHOD__, array(), - array( - 'rev' => array( 'JOIN', "rev_id = $joinField" ), - // not efficient, likely to pull same content multiple times. - 'text' => array( 'JOIN', "text_id = rev_text_id" ), - ) + array( 'rev' => array( 'JOIN', "rev_id = $joinField" ) ) ); if ( !$res ) { // TODO: dont fail, but dont end up caching bad result either @@ -190,6 +168,37 @@ } return $duplicator->getResult(); + } + + /** + * Handle the injection of externalstore data into a revision + * row. All rows exiting this method will have rev_content_url + * set to either null or the external url. The rev_content + * field will be the final content (possibly compressed still) + * + * @param array $cacheResult 2d array of rows + * @return array 2d array of rows with content merged and rev_content_url populated + */ + protected function mergeExternalContent( array $cacheResult ) { + foreach ( $cacheResult as &$source ) { + foreach ( $source as &$row ) { + $flags = explode( ',', $row['rev_flags'] ); + if ( in_array( 'external', $flags ) ) { + $row['rev_content_url'] = $row['rev_content']; + $row['rev_content'] = ''; + } else { + $row['rev_content_url'] = null; + } + } + } + + return Merger::mergeMulti( + $cacheResult, + /* fromKey = */ 'rev_content_url', + /* callable = */ array( 'ExternalStore', 'batchFetchFromURLs' ), + /* name = */ 'rev_content', + /* default = */ '' + ); } protected function buildCompositeInCondition( DatabaseBase $dbr, array $queries ) { @@ -214,11 +223,18 @@ } public function insert( array $row ) { - if ( !isset( $row['rev_text_id'] ) ) { - $row['rev_text_id'] = $this->insertContent( $row['text_content'], $row['text_flags'] ); + // Check if we need to insert new content + if ( $this->externalStore && !isset( $row['rev_content_url'] ) ) { + $row = $this->insertExternalStore( $row ); } - unset( $row['text_content'], $row['text_flags'] ); list( $rev, $related ) = $this->splitUpdate( $row ); + // If a content url is available store that in the db + // instead of real content. + if ( isset( $rev['rev_content_url'] ) ) { + $rev['rev_content'] = $rev['rev_content_url']; + } + unset( $rev['rev_content_url'] ); + $dbw = $this->dbFactory->getDB( DB_MASTER ); $res = $dbw->insert( 'flow_revision', @@ -230,33 +246,22 @@ return false; } - return $this->insertRelated( $rev, $related ); + return $this->insertRelated( $row, $related ); } - protected function insertContent( $data, $flags = '' ) { - $compressionFlags = \Revision::compressRevisionText( $data ); - $flags = array_merge( explode( ',', $flags ), explode( ',', $compressionFlags ) ); - $flags = array_filter( $flags ); - - if ( $this->externalStore ) { - // Store and get the URL - $data = ExternalStore::insertWithFallback( $this->externalStore, $data ); - if ( !$data ) { - throw new \MWException( "Unable to store text to external storage" ); - } - $flags[] = 'external'; + protected function insertExternalStore( array $row ) { + $url = ExternalStore::insertWithFallback( $this->externalStore, $row['rev_content'] ); + if ( !$url ) { + throw new \MWException( "Unable to store text to external storage" ); + } + $row['rev_content_url'] = $url; + if ( $row['rev_flags'] ) { + $row['rev_flags'] .= ',external'; + } else { + $row['rev_flags'] = 'external'; } - $dbw = $this->dbFactory->getDB( DB_MASTER ); - $dbw->insert( - 'flow_text', - array( - 'text_content' => $data, - 'text_flags' => implode( ',', array_unique( $flags ) ), - ), - __METHOD__ - ); - return $dbw->insertId(); + return $row; } // This is to *UPDATE* a revision. It should hardly ever be used. @@ -357,20 +362,21 @@ UUID::convertUUIDs( $tree ), __METHOD__ ); - if ( !$res ) { - return false; - } // If this is a brand new root revision it needs to be added to the tree // If it has a rev_parent_id then its already a part of the tree - if ( $row['rev_parent_id'] === null ) { - return (bool) $this->treeRepo->insert( + if ( $res && $row['rev_parent_id'] === null ) { + $res = (bool) $this->treeRepo->insert( UUID::create( $tree['tree_rev_descendant_id'] ), UUID::create( $tree['tree_parent_id'] ) ); } - return true; + if ( !$res ) { + return false; + } + + return $row; } // Topic split will primarily be done through the TreeRepository directly, but @@ -407,12 +413,16 @@ return 'summary_rev_id'; } - protected function insertRelated( array $rev, array $summary ) { - return (bool) $this->dbFactory->getDB( DB_MASTER )->insert( + protected function insertRelated( array $row, array $summary ) { + $res = $this->dbFactory->getDB( DB_MASTER )->insert( $this->joinTable(), $summary, __METHOD__ ); + if ( !$res ) { + return false; + } + return $row; } // There is changable data in the summary half, it just points to the correct workflow @@ -443,14 +453,22 @@ * @param callable $callable Callable receiving array of foreign keys returning map * from foreign key to its value * @param string $name Name to merge loaded foreign data as. If null uses $fromKey. + * @param string $default Value to use when no matching foreign value can be located * @return array $source array with all found foreign key values merged */ - static public function merge( array $source, $fromKey, $callable, $name = null ) { + static public function merge( array $source, $fromKey, $callable, $name = null, $default = '' ) { if ( $name === null ) { $name = $fromKey; } + $ids = array(); foreach ( $source as $row ) { - $ids[] = $row[$fromKey]; + $id = $row[$fromKey]; + if ( $id !== null ) { + $ids[] = $id; + } + } + if ( !$ids ) { + return $source; } $res = call_user_func( $callable, $ids ); if ( $res === false ) { @@ -458,9 +476,10 @@ } foreach ( $source as $idx => $row ) { $id = $row[$fromKey]; - if ( isset( $res[$id] ) ) { - $source[$idx][$name] = $res[$id]; + if ( $id === null ) { + continue; } + $source[$idx][$name] = isset( $res[$id] ) ? $res[$id] : $default; } return $source; } @@ -468,14 +487,21 @@ /** * Same as self::merge, but for 3-dimensional source arrays */ - static public function mergeMulti( array $multiSource, $fromKey, $callable, $name = null ) { + static public function mergeMulti( array $multiSource, $fromKey, $callable, $name = null, $default = '' ) { if ( $name === null ) { $name = $fromKey; } + $ids = array(); foreach ( $multiSource as $source ) { foreach ( $source as $row ) { - $ids[] = $row[$fromKey]; + $id = $row[$fromKey]; + if ( $id !== null ) { + $ids[] = $id; + } } + } + if ( !$ids ) { + return $multiSource; } $res = call_user_func( $callable, array_unique( $ids ) ); if ( $res === false ) { @@ -484,9 +510,10 @@ foreach ( $multiSource as $i => $source ) { foreach ( $source as $j => $row ) { $id = $row[$fromKey]; - if ( isset( $res[$id] ) ) { - $multiSource[$i][$j][$name] = $res[$id]; + if ( $id === null ) { + continue; } + $multiSource[$i][$j][$name] = isset( $res[$id] ) ? $res[$id] : $default; } } return $multiSource; diff --git a/includes/Model/AbstractRevision.php b/includes/Model/AbstractRevision.php index c0fedcd..b2517bf 100644 --- a/includes/Model/AbstractRevision.php +++ b/includes/Model/AbstractRevision.php @@ -6,7 +6,6 @@ abstract class AbstractRevision { protected $revId; - protected $textId; protected $userId; protected $userText; protected $flags = array(); @@ -17,28 +16,28 @@ protected $prevRevision; // content - protected $contentModel; - protected $contentFormat; protected $content; + // Only populated when external store is in use + protected $contentUrl; + // This is decompressed on-demand from $this->content in self::getContent() + protected $decompressedContent; - static public function fromStorageRow( array $row ) { - $obj = new static; - if ( $row['rev_type'] !== $obj->getRevisionType() ) { - throw new \MWException( sprintf( - "Wrong revision type, expected '%s' but received '%s'", - $obj->getRevisionType(), - $row['rev_type'] - ) ); + static public function fromStorageRow( array $row, $obj = null ) { + if ( $obj === null ) { + $obj = new static; + } elseif ( !$obj instanceof static ) { + throw new \Exception( 'wrong object type' ); } $obj->revId = UUID::create( $row['rev_id'] ); $obj->userId = $row['rev_user_id']; $obj->userText = $row['rev_user_text']; $obj->prevRevision = UUID::create( $row['rev_parent_id'] ); $obj->comment = $row['rev_comment']; - - $obj->textId = $row['rev_text_id']; - $obj->content = $row['text_content']; - $obj->flags = explode( ',', $row['text_flags'] ); + $obj->flags = array_filter( explode( ',', $row['rev_flags'] ) ); + $obj->content = $row['rev_content']; + // null if external store is not being used + $obj->contentUrl = $row['rev_content_url']; + $obj->decompressedContent = null; return $obj; } @@ -49,11 +48,11 @@ 'rev_user_text' => $obj->userText, 'rev_parent_id' => $obj->prevRevision ? $obj->prevRevision->getBinary() : null, 'rev_comment' => $obj->comment, - 'rev_text_id' => $obj->textId, 'rev_type' => $obj->getRevisionType(), - 'text_content' => $obj->content, - 'text_flags' => implode( ',', $obj->flags ), + 'rev_content' => $obj->content, + 'rev_content_url' => $obj->contentUrl, + 'rev_flags' => implode( ',', $obj->flags ), ); } @@ -70,11 +69,7 @@ public function newNextRevision( User $user, $content ) { $obj = $this->newNullRevision( $user ); - $obj->flags = array(); - if ( $content !== $obj->content ) { - $obj->content = $content; - $obj->textId = null; - } + $obj->setContent( $content ); return $obj; } @@ -83,14 +78,19 @@ } public function getContent() { - if ( $this->content === null ) { - throw new \MWException( 'Content not loaded' ); + if ( $this->decompressedContent === null ) { + $this->decompressedContent = \Revision::decompressRevisionText( $this->content, $this->flags ); } - return $this->content; + return $this->decompressedContent; } - public function getTextId() { - return $this->textId; // not available on creation + protected function setContent( $content ) { + if ( $content !== $this->getContent() ) { + $this->content = $this->decompressedContent = $content; + $this->contentUrl = null; + // should this only remove a subset of flags? + $this->flags = array_filter( explode( ',', \Revision::compressRevisionText( $this->content ) ) ); + } } public function getPrevRevisionId() { diff --git a/includes/Model/Definition.php b/includes/Model/Definition.php index fda4791..325f5db 100644 --- a/includes/Model/Definition.php +++ b/includes/Model/Definition.php @@ -10,11 +10,15 @@ protected $name; protected $options = array(); - static public function fromStorageRow( array $row ) { - $obj = new self; + static public function fromStorageRow( array $row, $obj = null ) { if ( ! $row['definition_wiki'] ) { throw new \MWException( "No definition_wiki" ); } + if ( $obj === null ) { + $obj = new self; + } elseif ( !$obj instanceof self ) { + throw new \Exception( 'Wrong obj type: ' . get_class( $obj ) ); + } $obj->id = UUID::create( $row['definition_id'] ); $obj->type = $row['definition_type']; $obj->wiki = $row['definition_wiki']; diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php index 1617faa..0ab36d7 100644 --- a/includes/Model/PostRevision.php +++ b/includes/Model/PostRevision.php @@ -24,21 +24,22 @@ $obj = new self; $obj->revId = UUID::create(); $obj->postId = $topic->getId(); - $obj->content = $content; $obj->origUserId = $obj->userId = $topic->getUserId(); $obj->origUserText = $obj->userText = $topic->getUserText(); $obj->origCreateTime = wfTimestampNow(); $obj->replyToId = null; // not a reply to anything $obj->prevRevId = null; // no parent revision $obj->comment = 'flow-rev-message-new-post'; + $obj->setContent( $content ); + return $obj; } - static public function fromStorageRow( array $row ) { + static public function fromStorageRow( array $row, $obj = null ) { if ( $row['rev_id'] !== $row['tree_rev_id'] ) { throw new \MWException( 'tree revision doesn\'t match provided revision' ); } - $obj = parent::fromStorageRow( $row ); + $obj = parent::fromStorageRow( $row, $obj ); $obj->replyToId = UUID::create( $row['tree_parent_id'] ); $obj->postId = UUID::create( $row['tree_rev_descendant_id'] ); @@ -68,7 +69,7 @@ $reply->userId = $reply->origUserId = $user->getId(); $reply->userText = $reply->origUserText = $user->getName(); $reply->origCreateTime = wfTimestampNow(); - $reply->content = $content; + $reply->setContent( $content ); $reply->replyToId = $this->postId; $reply->comment = 'flow-rev-message-reply'; return $reply; diff --git a/includes/Model/Summary.php b/includes/Model/Summary.php index 238a874..ffb65a1 100644 --- a/includes/Model/Summary.php +++ b/includes/Model/Summary.php @@ -11,15 +11,15 @@ $obj = new self; $obj->revId = UUID::create(); $obj->workflowId = $workflow->getId(); - $obj->content = $content; $obj->userId = $user->getId(); $obj->userText = $user->getName(); $obj->prevRevision = null; // no prior revision + $obj->setContent( $content ); return $obj; } - static public function fromStorageRow( array $row ) { - $obj = parent::fromStorageRow( $row ); + static public function fromStorageRow( array $row, $obj = null ) { + $obj = parent::fromStorageRow( $row, $obj ); $obj->workflowId = UUID::create( $row['summary_workflow_id'] ); return $obj; } diff --git a/includes/Model/TopicListEntry.php b/includes/Model/TopicListEntry.php index 6d07f16..0521d89 100644 --- a/includes/Model/TopicListEntry.php +++ b/includes/Model/TopicListEntry.php @@ -4,40 +4,44 @@ // TODO: We shouldn't need this class class TopicListEntry { - protected $topicListId; - protected $topicId; + protected $topicListId; + protected $topicId; - static public function create( Workflow $topicList, Workflow $topic ) { - // die( var_dump( array( - // 'topicList' => $topicList, - // 'topic' => $topic, - // ))); + static public function create( Workflow $topicList, Workflow $topic ) { + // die( var_dump( array( + // 'topicList' => $topicList, + // 'topic' => $topic, + // ))); + $obj = new self; + $obj->topicListId = $topicList->getId(); + $obj->topicId = $topic->getId(); + return $obj; + } + + static public function fromStorageRow( array $row, $obj = null ) { + if ( $obj === null ) { $obj = new self; - $obj->topicListId = $topicList->getId(); - $obj->topicId = $topic->getId(); - return $obj; + } elseif ( !$obj instanceof self ) { + throw new \Exception( 'Wrong obj type: ' . get_class( $obj ) ); } + $obj->topicListId = UUID::create( $row['topic_list_id'] ); + $obj->topicId = UUID::create( $row['topic_id'] ); + return $obj; + } - static public function fromStorageRow( array $row ) { - $obj = new self; - $obj->topicListId = UUID::create( $row['topic_list_id'] ); - $obj->topicId = UUID::create( $row['topic_id'] ); - return $obj; - } + static public function toStorageRow( TopicListEntry $obj ) { + return array( + 'topic_list_id' => $obj->topicListId->getBinary(), + 'topic_id' => $obj->topicId->getBinary(), + ); + } - static public function toStorageRow( TopicListEntry $obj ) { - return array( - 'topic_list_id' => $obj->topicListId->getBinary(), - 'topic_id' => $obj->topicId->getBinary(), - ); - } + public function getId() { + return $this->topicId; + } - public function getId() { - return $this->topicId; - } - - public function getListId() { - return $this-topicListId; - } + public function getListId() { + return $this-topicListId; + } } diff --git a/includes/Model/Workflow.php b/includes/Model/Workflow.php index 0b0ad54..c16efa2 100644 --- a/includes/Model/Workflow.php +++ b/includes/Model/Workflow.php @@ -8,6 +8,7 @@ class Workflow { protected $id; + // @var boolean false before writing to storage protected $isNew; protected $wiki; protected $pageId; @@ -20,9 +21,14 @@ protected $lockState; protected $definitionId; - static public function fromStorageRow( array $row ) { - $obj = new self; + static public function fromStorageRow( array $row, $obj = null ) { + if ( $obj === null ) { + $obj = new self; + } elseif ( !$obj instanceof self ) { + throw new \Exception( 'Wrong obj type: ' . get_class( $obj ) ); + } $obj->id = UUID::create( $row['workflow_id'] ); + $obj->isNew = false; $obj->wiki = $row['workflow_wiki']; $obj->pageId = $row['workflow_page_id']; $obj->namespace = (int) $row['workflow_namespace']; @@ -50,20 +56,19 @@ static public function create( Definition $definition, User $user, Title $title ) { if ( $title->isLocal() ) { - if ( $definition->getWiki() !== wfWikiId() ) { - throw new \Exception( 'Title and Definition are from separate wikis' ); - } + $wiki = wfWikiId(); } else { - if ( $definition->getWiki() !== $title->getTransWikiID() ) { + $wiki = $title->getTransWikiID(); + } + if ( $definition->getWiki() !== $wiki ) { throw new \Exception( 'Title and Definition are from separate wikis' ); - } } $obj = new self; // Probably unnecessary to create id up front? // simpler in prototype to give everything an id up front? $obj->id = UUID::create(); - $obj->isNew = true; // new as of this request + $obj->isNew = true; // has not been persisted $obj->wiki = $definition->getWiki(); $obj->pageId = $title->getArticleID(); $obj->namespace = $title->getNamespace(); diff --git a/includes/Repository/TreeRepository.php b/includes/Repository/TreeRepository.php index d88bd94..6c91115 100644 --- a/includes/Repository/TreeRepository.php +++ b/includes/Repository/TreeRepository.php @@ -94,8 +94,8 @@ $this->cache->del( $pathKey ); throw new MWEception( 'Failed inserting new tree node' ); } - $this->appendToSubtreeCache( $descendant, $path ); + return true; } protected function appendToSubtreeCache( UUID $descendant, array $rootPath ) { -- To view, visit https://gerrit.wikimedia.org/r/78313 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I5cf3fe8ef0f6edb4328f4355a4abe5bec439446e Gerrit-PatchSet: 5 Gerrit-Project: mediawiki/extensions/Flow Gerrit-Branch: master Gerrit-Owner: EBernhardson (WMF) <ebernhard...@wikimedia.org> Gerrit-Reviewer: EBernhardson (WMF) <ebernhard...@wikimedia.org> Gerrit-Reviewer: Matthias Mullie <mmul...@wikimedia.org> Gerrit-Reviewer: Werdna <agarr...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits