Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/Import/LiquidThreadsApi/Iterators.php
<?php

namespace Flow\Import\LiquidThreadsApi;

use ArrayIterator;
use Flow\Import\IImportObject;
use Iterator;

class TopicIterator implements Iterator {
	/**
	 * @var ImportSource
	 */
	protected $importSource;

	/**
	 * @var CachedThreadData Access point for api data
	 */
	protected $threadData;

	/**
	 * @var integer|false|null Lqt id of the current topic, false if no current topic, null if unknown.
	 */
	protected $current = false;

	/**
	 * @var ImportTopic The current topic.
	 */
	protected $currentTopic = null;

	/**
	 * @var string Name of the remote page the topics exist on
	 */
	protected $pageName;

	/**
	 * @var Iterator A list of topic ids.  Iterator used to simplify maintaining
	 *  an explicit position within the list.
	 */
	protected $topicIdIterator;

	/**
	 * @var integer The maximum id received by self::loadMore
	 */
	protected $maxId;

	/**
	 * @param ImportSource     $source
	 * @param CachedThreadData $threadData
	 * @param string           $pageName
	 */
	public function __construct( ImportSource $source, CachedThreadData $threadData, $pageName ) {
		$this->importSource = $source;
		$this->threadData = $threadData;
		$this->pageName = $pageName;
		$this->topicIdIterator = new ArrayIterator( $threadData->getTopics() );
		$this->rewind();
	}

	/**
	 * @return ImportTopic
	 */
	public function current() {
		if ( $this->current === false ) {
			return null;
		}
		return $this->currentTopic;
	}

	/**
	 * @return integer
	 */
	public function key() {
		return $this->current;
	}

	public function next() {
		if ( !$this->valid() ) {
			return;
		}

		$lastOffset = $this->key();
		do {
			while( $this->topicIdIterator->valid() ) {
				$topicId = $this->topicIdIterator->current();
				$this->topicIdIterator->next();

				// this topic id has been seen before.
				if ( $topicId <= $lastOffset ) {
					continue;
				}

				// hidden and deleted threads come back as null
				$topic = $this->importSource->getTopic( $topicId );
				if ( $topic === null ) {
					continue;
				}

				$this->current = $topicId;
				$this->currentTopic = $topic;
				return;
			}
		} while( $this->loadMore() );

		// nothing found, nothing more to load
		$this->current = false;
	}

	public function rewind() {
		$this->current = null;
		$this->topicIdIterator->rewind();
		$this->next();
	}

	/**
	 * @return bool
	 */
	public function valid() {
		return $this->current !== false;
	}

	/**
	 * @return bool True when more topics were loaded
	 */
	protected function loadMore() {
		try {
			// + 1 to not return the existing max topic
			$output = $this->threadData->getFromPage( $this->pageName, $this->maxId + 1 );
		} catch ( ApiNotFoundException $e ) {
			// No more results, end loop
			return false;
		}

		$this->maxId = max( array_keys( $output ) );
		$this->topicIdIterator = new ArrayIterator( $this->threadData->getTopics() );
		$this->topicIdIterator->rewind();

		// Keep looping until we get a not found error
		return true;
	}
}

class ReplyIterator implements Iterator {
	/** @var ImportPost **/
	protected $post;
	/** @var array Array of thread IDs **/
	protected $threadReplies;
	/** @var int **/
	protected $replyIndex;
	/** @var ImportPost|null */
	protected $current;

	public function __construct( ImportPost $post ) {
		$this->post = $post;
		$this->replyIndex = 0;

		$apiResponse = $post->getApiResponse();
		$this->threadReplies = array_values( $apiResponse['replies'] );
	}

	/**
	 * @return ImportPost|null
	 */
	public function current() {
		return $this->current;
	}

	/**
	 * @return integer
	 */
	public function key() {
		return $this->replyIndex;
	}

	public function next() {
		while( ++$this->replyIndex < count( $this->threadReplies ) ) {
			try {
				$replyId = $this->threadReplies[$this->replyIndex]['id'];
				$this->current = $this->post->getSource()->getPost( $replyId );
				return;
			} catch ( ApiNotFoundException $e ) {
				// while loop fall-through handles our error case
			}
		}

		// Nothing found, set current to null
		$this->current = null;
	}

	public function rewind() {
		$this->replyIndex = -1;
		$this->next();
	}

	public function valid() {
		return $this->current !== null;
	}
}

/**
 * Iterates over the revisions of a foreign page to produce
 * revisions of a Flow object.
 */
class RevisionIterator implements Iterator {
	/** @var array **/
	protected $pageData;

	/** @var int **/
	protected $pointer;

	/** @var IImportObject **/
	protected $parent;

	public function __construct( array $pageData, IImportObject $parent, $factory ) {
		$this->pageData = $pageData;
		$this->pointer = 0;
		$this->parent = $parent;
		$this->factory = $factory;
	}

	protected function getRevisionCount() {
		if ( isset( $this->pageData['revisions'] ) ) {
			return count( $this->pageData['revisions'] );
		} else {
			return 0;
		}
	}

	public function valid() {
		return $this->pointer < $this->getRevisionCount();
	}

	public function next() {
		++$this->pointer;
	}

	public function key() {
		return $this->pointer;
	}

	public function rewind() {
		$this->pointer = 0;
	}

	public function current() {
		return call_user_func(
			$this->factory,
			$this->pageData['revisions'][$this->pointer],
			$this->parent
		);
	}
}