diff options
Diffstat (limited to 'www/wiki/includes/Storage/MutableRevisionRecord.php')
-rw-r--r-- | www/wiki/includes/Storage/MutableRevisionRecord.php | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/www/wiki/includes/Storage/MutableRevisionRecord.php b/www/wiki/includes/Storage/MutableRevisionRecord.php new file mode 100644 index 00000000..a259ae0b --- /dev/null +++ b/www/wiki/includes/Storage/MutableRevisionRecord.php @@ -0,0 +1,328 @@ +<?php +/** + * Mutable RevisionRecord implementation, for building new revision entries programmatically. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + */ + +namespace MediaWiki\Storage; + +use CommentStoreComment; +use Content; +use InvalidArgumentException; +use MediaWiki\User\UserIdentity; +use MWException; +use Title; +use Wikimedia\Assert\Assert; + +/** + * Mutable RevisionRecord implementation, for building new revision entries programmatically. + * Provides setters for all fields. + * + * @since 1.31 + */ +class MutableRevisionRecord extends RevisionRecord { + + /** + * Returns an incomplete MutableRevisionRecord which uses $parent as its + * parent revision, and inherits all slots form it. If saved unchanged, + * the new revision will act as a null-revision. + * + * @param RevisionRecord $parent + * @param CommentStoreComment $comment + * @param UserIdentity $user + * @param string $timestamp + * + * @return MutableRevisionRecord + */ + public static function newFromParentRevision( + RevisionRecord $parent, + CommentStoreComment $comment, + UserIdentity $user, + $timestamp + ) { + // TODO: ideally, we wouldn't need a Title here + $title = Title::newFromLinkTarget( $parent->getPageAsLinkTarget() ); + $rev = new MutableRevisionRecord( $title, $parent->getWikiId() ); + + $rev->setComment( $comment ); + $rev->setUser( $user ); + $rev->setTimestamp( $timestamp ); + + foreach ( $parent->getSlotRoles() as $role ) { + $slot = $parent->getSlot( $role, self::RAW ); + $rev->inheritSlot( $slot ); + } + + $rev->setPageId( $parent->getPageId() ); + $rev->setParentId( $parent->getId() ); + + return $rev; + } + + /** + * @note Avoid calling this constructor directly. Use the appropriate methods + * in RevisionStore instead. + * + * @param Title $title The title of the page this Revision is associated with. + * @param bool|string $wikiId the wiki ID of the site this Revision belongs to, + * or false for the local site. + * + * @throws MWException + */ + function __construct( Title $title, $wikiId = false ) { + $slots = new MutableRevisionSlots(); + + parent::__construct( $title, $slots, $wikiId ); + + $this->mSlots = $slots; // redundant, but nice for static analysis + } + + /** + * @param int $parentId + */ + public function setParentId( $parentId ) { + Assert::parameterType( 'integer', $parentId, '$parentId' ); + + $this->mParentId = $parentId; + } + + /** + * Sets the given slot. If a slot with the same role is already present in the revision, + * it is replaced. + * + * @note This can only be used with a fresh "unattached" SlotRecord. Calling code that has a + * SlotRecord from another revision should use inheritSlot(). Calling code that has access to + * a Content object can use setContent(). + * + * @note This may cause the slot meta-data for the revision to be lazy-loaded. + * + * @note Calling this method will cause the revision size and hash to be re-calculated upon + * the next call to getSize() and getSha1(), respectively. + * + * @param SlotRecord $slot + */ + public function setSlot( SlotRecord $slot ) { + if ( $slot->hasRevision() && $slot->getRevision() !== $this->getId() ) { + throw new InvalidArgumentException( + 'The given slot must be an unsaved, unattached one. ' + . 'This slot is already attached to revision ' . $slot->getRevision() . '. ' + . 'Use inheritSlot() instead to preserve a slot from a previous revision.' + ); + } + + $this->mSlots->setSlot( $slot ); + $this->resetAggregateValues(); + } + + /** + * "Inherits" the given slot's content. + * + * If a slot with the same role is already present in the revision, it is replaced. + * + * @note This may cause the slot meta-data for the revision to be lazy-loaded. + * + * @param SlotRecord $parentSlot + */ + public function inheritSlot( SlotRecord $parentSlot ) { + $slot = SlotRecord::newInherited( $parentSlot ); + $this->setSlot( $slot ); + } + + /** + * Sets the content for the slot with the given role. + * + * If a slot with the same role is already present in the revision, it is replaced. + * Calling code that has access to a SlotRecord can use inheritSlot() instead. + * + * @note This may cause the slot meta-data for the revision to be lazy-loaded. + * + * @note Calling this method will cause the revision size and hash to be re-calculated upon + * the next call to getSize() and getSha1(), respectively. + * + * @param string $role + * @param Content $content + */ + public function setContent( $role, Content $content ) { + $this->mSlots->setContent( $role, $content ); + $this->resetAggregateValues(); + } + + /** + * Removes the slot with the given role from this revision. + * This effectively ends the "stream" with that role on the revision's page. + * Future revisions will no longer inherit this slot, unless it is added back explicitly. + * + * @note This may cause the slot meta-data for the revision to be lazy-loaded. + * + * @note Calling this method will cause the revision size and hash to be re-calculated upon + * the next call to getSize() and getSha1(), respectively. + * + * @param string $role + */ + public function removeSlot( $role ) { + $this->mSlots->removeSlot( $role ); + $this->resetAggregateValues(); + } + + /** + * @param CommentStoreComment $comment + */ + public function setComment( CommentStoreComment $comment ) { + $this->mComment = $comment; + } + + /** + * Set revision hash, for optimization. Prevents getSha1() from re-calculating the hash. + * + * @note This should only be used if the calling code is sure that the given hash is correct + * for the revision's content, and there is no chance of the content being manipulated + * later. When in doubt, this method should not be called. + * + * @param string $sha1 SHA1 hash as a base36 string. + */ + public function setSha1( $sha1 ) { + Assert::parameterType( 'string', $sha1, '$sha1' ); + + $this->mSha1 = $sha1; + } + + /** + * Set nominal revision size, for optimization. Prevents getSize() from re-calculating the size. + * + * @note This should only be used if the calling code is sure that the given size is correct + * for the revision's content, and there is no chance of the content being manipulated + * later. When in doubt, this method should not be called. + * + * @param int $size nominal size in bogo-bytes + */ + public function setSize( $size ) { + Assert::parameterType( 'integer', $size, '$size' ); + + $this->mSize = $size; + } + + /** + * @param int $visibility + */ + public function setVisibility( $visibility ) { + Assert::parameterType( 'integer', $visibility, '$visibility' ); + + $this->mDeleted = $visibility; + } + + /** + * @param string $timestamp A timestamp understood by wfTimestamp + */ + public function setTimestamp( $timestamp ) { + Assert::parameterType( 'string', $timestamp, '$timestamp' ); + + $this->mTimestamp = wfTimestamp( TS_MW, $timestamp ); + } + + /** + * @param bool $minorEdit + */ + public function setMinorEdit( $minorEdit ) { + Assert::parameterType( 'boolean', $minorEdit, '$minorEdit' ); + + $this->mMinorEdit = $minorEdit; + } + + /** + * Set the revision ID. + * + * MCR migration note: this replaces Revision::setId() + * + * @warning Use this with care, especially when preparing a revision for insertion + * into the database! The revision ID should only be fixed in special cases + * like preserving the original ID when restoring a revision. + * + * @param int $id + */ + public function setId( $id ) { + Assert::parameterType( 'integer', $id, '$id' ); + + $this->mId = $id; + } + + /** + * Sets the user identity associated with the revision + * + * @param UserIdentity $user + */ + public function setUser( UserIdentity $user ) { + $this->mUser = $user; + } + + /** + * @param int $pageId + */ + public function setPageId( $pageId ) { + Assert::parameterType( 'integer', $pageId, '$pageId' ); + + if ( $this->mTitle->exists() && $pageId !== $this->mTitle->getArticleID() ) { + throw new InvalidArgumentException( + 'The given Title does not belong to page ID ' . $this->mPageId + ); + } + + $this->mPageId = $pageId; + } + + /** + * Returns the nominal size of this revision. + * + * MCR migration note: this replaces Revision::getSize + * + * @return int The nominal size, may be computed on the fly if not yet known. + */ + public function getSize() { + // If not known, re-calculate and remember. Will be reset when slots change. + if ( $this->mSize === null ) { + $this->mSize = $this->mSlots->computeSize(); + } + + return $this->mSize; + } + + /** + * Returns the base36 sha1 of this revision. + * + * MCR migration note: this replaces Revision::getSha1 + * + * @return string The revision hash, may be computed on the fly if not yet known. + */ + public function getSha1() { + // If not known, re-calculate and remember. Will be reset when slots change. + if ( $this->mSha1 === null ) { + $this->mSha1 = $this->mSlots->computeSha1(); + } + + return $this->mSha1; + } + + /** + * Invalidate cached aggregate values such as hash and size. + */ + private function resetAggregateValues() { + $this->mSize = null; + $this->mSha1 = null; + } + +} |