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

namespace Flow\Formatter;

use Flow\Data\ManagerGroup;
use Flow\Data\Listener\RecentChangesListener;
use Flow\Exception\FlowException;
use Flow\FlowActions;
use Flow\Model\UUID;
use Flow\Repository\TreeRepository;
use MediaWiki\Logger\LoggerFactory;
use RecentChange;

class ChangesListQuery extends AbstractQuery {

	/**
	 * Check if the most recent action for an entity has been displayed already
	 *
	 * @var array
	 */
	protected $displayStatus = array();

	/**
	 * @var FlowActions
	 */
	protected $actions;

	/**
	 * @var bool
	 */
	protected $extendWatchlist = false;

	public function __construct( ManagerGroup $storage, TreeRepository $treeRepo, FlowActions $actions ) {
		parent::__construct( $storage, $treeRepo );
		$this->actions = $actions;
	}

	/**
	 * @param bool $extend
	 */
	public function setExtendWatchlist( $extend ) {
		$this->extendWatchlist = (bool)$extend;
	}

	/**
	 * @param \stdClass[] $rows List of recentchange database rows
	 * @param bool $isWatchlist
	 */
	public function loadMetadataBatch( $rows, $isWatchlist = false ) {
		$needed = array();
		foreach ( $rows as $row ) {
			if ( !isset( $row->rc_source ) || $row->rc_source !== RecentChangesListener::SRC_FLOW ) {
				continue;
			}
			if ( !isset( $row->rc_params ) ) {
				wfDebugLog( 'Flow', __METHOD__ . ': Bad row without rc_params passed in $rows' );
				continue;
			}
			$params = unserialize( $row->rc_params );
			if ( !$params ) {
				wfDebugLog( 'Flow', __METHOD__ . ": rc_params does not contain serialized content: {$row->rc_params}" );
				continue;
			}
			$changeData = $params['flow-workflow-change'];
			/**
			 * Check to make sure revision_type exists, this is to make sure corrupted
			 * flow recent change data doesn't throw error on the page.
			 * See bug 59106 for more detail
			 */
			if ( !isset( $changeData['revision_type'] ) ) {
				continue;
			}
			if ( $this->excludeFromChangesList( $isWatchlist, $changeData['action'] ) ) {
				continue;
			}
			if ( $isWatchlist && $this->isRecordHidden( $changeData ) ) {
				continue;
			}
			$revisionType = $changeData['revision_type'];
			$needed[$revisionType][] = UUID::create( $changeData['revision'] );
		}

		$found = array();
		foreach ( $needed as $type => $uids ) {
			$found[] = $this->storage->getMulti( $type, $uids );
		}

		$found = array_filter( $found );
		$count = count( $found );
		if ( $count === 0 ) {
			$results = array();
		} elseif ( $count === 1 ) {
			$results = reset( $found );
		} else {
			$results = call_user_func_array( 'array_merge', $found );
		}

		if ( $results ) {
			parent::loadMetadataBatch( $results );
		}
	}

	/**
	 * @param bool $isWatchlist Whether this is Special:Watchlist
	 * @param string $action The Flow action this line represents
	 * @return bool
	 */
	private function excludeFromChangesList( $isWatchlist, $action ) {
		// If we want to exclude things from watchlist, we can add exclude_from_watchlist
		if ( $isWatchlist ) {
			return false;
		} else {
			return (bool) $this->actions->getValue( $action, 'exclude_from_recentchanges' );
		}
	}

	/**
	 * @param null $cl No longer used
	 * @param RecentChange $rc
	 * @param bool $isWatchlist
	 * @return RecentChangesRow|bool False on failure
	 * @throws FlowException
	 */
	public function getResult( $cl, RecentChange $rc, $isWatchlist = false ) {
		$rcParams = $rc->getAttribute( 'rc_params' );
		$params = unserialize( $rcParams );
		if ( !$params ) {
			throw new FlowException( 'rc_params does not contain serialized content: ' . $rcParams );
		}
		$changeData = $params['flow-workflow-change'];

		if ( !is_array( $changeData ) ) {
			throw new FlowException( 'Flow data missing in recent changes.' );
		}

		/**
		 * Check to make sure revision_type exists, this is to make sure corrupted
		 * flow recent change data doesn't throw error on the page.
		 * See bug 59106 for more detail
		 */
		if ( !isset( $changeData['revision_type'] ) ) {
			throw new FlowException( 'Corrupted rc without changeData: ' . $rc->getAttribute( 'rc_id' ) );
		}

		if ( $this->excludeFromChangesList( $isWatchlist, $changeData['action'] ) ) {
			return false;
		}

		// Only show most recent items for watchlist
		if ( $isWatchlist && $this->isRecordHidden( $changeData ) ) {
			return false;
		}

		$alpha = UUID::create( $changeData['revision'] )->getAlphadecimal();
		if ( !isset( $this->revisionCache[$alpha] ) ) {
			LoggerFactory::getInstance( 'Flow' )->error(
				'Revision not found in revisionCache: {alpha}',
				array(
					'alpha' => $alpha,
					'rcParams' => $rcParams,
				)
			);
			return false;
		}
		$revision = $this->revisionCache[$alpha];

		$res = new RecentChangesRow;
		$this->buildResult( $revision, 'timestamp', $res );
		$res->recentChange = $rc;

		return $res;
	}

	/**
	 * Determines if a flow record should be displayed in Special:Watchlist
	 *
	 * @param array $changeData
	 * @return bool
	 */
	protected function isRecordHidden( array $changeData ) {
		if ( $this->extendWatchlist ) {
			return false;
		}
		// Check for legacy action names and convert it
		$alias = $this->actions->getValue( $changeData['action'] );
		if ( is_string( $alias ) ) {
			$action = $alias;
		} else {
			$action = $changeData['action'];
		}
		// * Display the most recent new post, edit post, edit title for a topic
		// * Display the most recent header edit
		// * Display all new topic and moderation actions
		switch ( $action ) {
			case 'create-header':
			case 'edit-header':
				if (
					isset( $this->displayStatus['header-' . $changeData['workflow']] ) &&
					$this->displayStatus['header-' . $changeData['workflow']] !== $changeData['revision']
				) {
					return true;
				}
				$this->displayStatus['header-' . $changeData['workflow']] = $changeData['revision'];
			break;

			case 'hide-post':
			case 'hide-topic':
			case 'delete-post':
			case 'delete-topic':
			case 'suppress-post':
			case 'suppress-topic':
			case 'restore-post':
			case 'restore-topic':
			case 'lock-topic':
				// moderation actions are always shown when visible to the user
				return false;

			case 'new-topic':
			case 'reply':
			case 'edit-post':
			case 'edit-title':
			case 'create-topic-summary':
			case 'edit-topic-summary':
				if (
					isset( $this->displayStatus['topic-' . $changeData['workflow']] ) &&
					$this->displayStatus['topic-' . $changeData['workflow']] !== $changeData['revision']
				) {
					return true;
				}
				$this->displayStatus['topic-' . $changeData['workflow']] = $changeData['revision'];
			break;
		}

		return false;
	}

	protected function changeSeparator() {
		return ' <span class="mw-changeslist-separator">. .</span> ';
	}
}

class RecentChangesRow extends FormatterRow {
	/**
	 * @var RecentChange
	 */
	public $recentChange;
}