Current File : /home/jvzmxxx/wiki/extensions/Flow/maintenance/FlowUpdateWorkflowPageId.php
<?php

use Flow\Container;
use Flow\Model\UUID;
use Flow\Model\Workflow;
use Flow\OccupationController;

$IP = getenv( 'MW_INSTALL_PATH' );
if ( $IP === false ) {
	$IP = dirname( __FILE__ ) . '/../../..';
}
require_once( "$IP/maintenance/Maintenance.php" );
require_once( "$IP/includes/utils/RowUpdateGenerator.php" );

/**
 * In some cases we have created workflow instances before the related Title
 * has an ArticleID assigned to it.  This goes through and sets that value
 *
 * @ingroup Maintenance
 */
class FlowUpdateWorkflowPageId extends LoggedUpdateMaintenance {
	public function __construct() {
		parent::__construct();
		$this->mDescription = "Update workflow_page_id with the page id of its specified ns/title";
		$this->setBatchSize( 300 );
	}

	/**
	 * Assembles the update components, runs them, and reports
	 * on what they did
	 */
	public function doDbUpdates() {
		global $wgFlowCluster, $wgLang;

		$dbw = Container::get( 'db.factory' )->getDB( DB_MASTER );

		$it = new BatchRowIterator(
			$dbw,
			'flow_workflow',
			'workflow_id',
			$this->mBatchSize
		);
		$it->setFetchColumns( array( '*' ) );
		$it->addConditions( array(
			'workflow_wiki' => wfWikiID(),
		) );

		$gen = new WorkflowPageIdUpdateGenerator( $wgLang );
		$writer = new BatchRowWriter( $dbw, 'flow_workflow', $wgFlowCluster );
		$updater = new BatchRowUpdate( $it, $writer, $gen );

		$updater->execute();

		$this->output( $gen->report() );

		return true;
	}

	protected function getUpdateKey() {
		return __CLASS__;
	}
}

/**
 * Looks at rows from the flow_workflow table and returns an update
 * for the workflow_page_id field if necessary.
 */
class WorkflowPageIdUpdateGenerator implements RowUpdateGenerator {
	/**
	 * @var Language|StubUserLang
	 */
	protected $lang;
	protected $fixedCount = 0;
	protected $failures = array();
	protected $warnings = array();

	/**
	 * @param Language|StubUserLang $lang
	 */
	public function __construct( $lang ) {
		$this->lang = $lang;
	}

	public function update( $row ) {
		$title = Title::makeTitleSafe( $row->workflow_namespace, $row->workflow_title_text );
		if ( $title === null ) {
			throw new Exception( sprintf(
				'Could not create title for %s at %s:%s',
				UUID::create( $row->workflow_id )->getAlphadecimal(),
				$this->lang->getNsText( $row->workflow_namespace ) ?: $row->workflow_namespace,
				$row->workflow_title_text
			) );
		}

		// at some point, we failed to create page entries for new workflows: only
		// create that page if the workflow was stored with a 0 page id (otherwise,
		// we could mistake the $title for a deleted page)
		if ( (int) $row->workflow_page_id === 0 && $title->getArticleID() === 0 ) {
			$workflow = Workflow::fromStorageRow( (array) $row );
			$status = $this->createPage( $title, $workflow );
			if ( !$status->isGood() ) {
				// just warn when we failed to create the page, but keep this code
				// going and see if we manage to associate the workflow anyways
				// (or if that fails, we'll also get an error there)
				$this->warnings[] = $status->getMessage()->text();
			}
		}

		// re-associate the workflow with the correct page; only if a page exists
		if ( $title->getArticleID() !== 0 && $title->getArticleID() !== (int) $row->workflow_page_id ) {
			// This makes the assumption the page has not moved or been deleted?
			++$this->fixedCount;
			return array(
				'workflow_page_id' => $title->getArticleID(),
			);
		} elseif ( !$row->workflow_page_id ) {
			// No id exists for this workflow? (reason should likely show up in $this->warnings)
			$this->failures[] = $row;
		}

		return array();
	}

	/**
	 * @param Title $title
	 * @param Workflow $workflow
	 * @return Status
	 */
	protected function createPage( Title $title, $workflow ) {
		/** @var OccupationController $occupationController */
		$occupationController = Container::get( 'occupation_controller' );

		try {
			$status = $occupationController->safeAllowCreation( $title, $occupationController->getTalkpageManager() );
			$status2 = $occupationController->ensureFlowRevision( new Article( $title ), $workflow );

			$status->merge( $status2 );
		} catch ( \Exception $e ) {
			// "convert" exception into Status
			$message = new RawMessage( $e->getMessage() );
			$status = Status::newFatal( $message );
		}

		if ( $status->isGood() ) {
			// force article id to be refetched from db
			$title->getArticleID( Title::GAID_FOR_UPDATE );
		}

		return $status;
	}

	public function report() {
		return "Updated {$this->fixedCount}  workflows\n\n" .
			"Warnings: " . count( $this->warnings ) . "\n" . print_r( $this->warnings, true ) . "\n\n" .
			"Failed: " . count( $this->failures ) . "\n" . print_r( $this->failures, true );
	}
}

$maintClass = "FlowUpdateWorkflowPageId";
require_once( DO_MAINTENANCE );