Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/BoardMover.php
<?php

namespace Flow;

use DatabaseBase;
use Flow\Data\BufferedCache;
use Flow\Data\ManagerGroup;
use Flow\Exception\FlowException;
use Flow\Model\Header;
use Flow\Model\Workflow;
use Title;
use User;

class BoardMover {
	/**
	 * @var DbFactory
	 */
	protected $dbFactory;

	/**
	 * @var ManagerGroup
	 */
	protected $storage;

	/**
	 * @var User
	 */
	protected $nullEditUser;

	/**
	 * @var DatabaseBase|null
	 */
	protected $dbw;

	public function __construct( DbFactory $dbFactory, BufferedCache $cache, ManagerGroup $storage, User $nullEditUser ) {
		$this->dbFactory = $dbFactory;
		$this->cache = $cache;
		$this->storage = $storage;
		$this->nullEditUser = $nullEditUser;
	}

	/**
	 * Starts a transaction on the Flow database.
	 */
	protected function begin() {
		// All reads must go through master to help ensure consistency
		$this->dbFactory->forceMaster();

		// Open a transaction, this will be closed from self::commit.
		$this->dbw = $this->dbFactory->getDB( DB_MASTER );
		$this->dbw->startAtomic( __CLASS__ );
		$this->cache->begin();
	}

	/**
	 * Collects the workflow and header (if it exists) and puts them into the database. Does
	 * not commit yet. It is intended for begin to be called at the beginning of the
	 * transaction, move to be called for each move, and commit to be called at the end
	 * the core transaction, via a hook.
	 *
	 * @param int $oldPageId Page ID before move/change
	 * @param Title $newPage Page after move/change
	 * @throws Exception\DataModelException
	 * @throws FlowException
	 */
	public function move( $oldPageId, Title $newPage ) {
		if ( $this->dbw === null ) {
			$this->begin();
		}

		// @todo this loads every topic workflow this board has ever seen,
		// would prefer to update db directly but that won't work due to
		// the caching layer not getting updated.  After dropping Flow\Data\Index\*
		// revisit this.
		/** @var Workflow[] $found */
		$found = $this->storage->find( 'Workflow', array(
			'workflow_wiki' => wfWikiID(),
			'workflow_page_id' => $oldPageId,
		) );
		if ( !$found ) {
			throw new FlowException( "Could not locate workflow for $oldPageId" );
		}

		$discussionWorkflow = null;
		foreach ( $found as $workflow ) {
			if ( $workflow->getType() === 'discussion' ) {
				$discussionWorkflow = $workflow;
			}
			$workflow->updateFromPageId( $oldPageId, $newPage );
			$this->storage->put( $workflow, array() );
		}
		if ( $discussionWorkflow === null ) {
			throw new FlowException( "Main discussion workflow for $oldPageId not found" );
		}

		/** @var Header[] $found */
		$found = $this->storage->find(
			'Header',
			array( 'rev_type_id' => $discussionWorkflow->getId() ),
			array( 'sort' => 'rev_id', 'order' => 'DESC', 'limit' => 1 )
		);

		if ( $found ) {
			$header = reset( $found );
			$nextHeader = $header->newNextRevision(
				$this->nullEditUser,
				$header->getContentRaw(),
				$header->getContentFormat(),
				'edit-header',
				$newPage
			);
			if ( $header !== $nextHeader ) {
				$this->storage->put( $nextHeader, array(
					'workflow' => $discussionWorkflow,
				) );
			}
		}
	}

	/**
	 * @throws Exception\FlowException
	 */
	public function commit() {
		if ( $this->dbw === null ) {
			return;
		}

		try {
			$this->dbw->endAtomic( __CLASS__ );
			$this->cache->commit();
		} catch ( \Exception $e ) {
			$this->dbw->rollback( __METHOD__ );
			$this->cache->rollback();
			throw $e;
		}

		// reset dbw (which is used to check if a move transaction is already in
		// progress, which is no longer the case)
		$this->dbw = null;
	}
}