Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
TopicIterator
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 7
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 current
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 key
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 next
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
 rewind
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 valid
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 loadMore
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Flow\Import\LiquidThreadsApi;
4
5use ArrayIterator;
6use Iterator;
7
8class TopicIterator implements Iterator {
9    /**
10     * @var ImportSource
11     */
12    protected $importSource;
13
14    /**
15     * @var CachedThreadData Access point for api data
16     */
17    protected $threadData;
18
19    /**
20     * @var int|false|null Lqt id of the current topic, false if no current topic, null if unknown.
21     */
22    protected $current = false;
23
24    /**
25     * @var ImportTopic The current topic.
26     */
27    protected $currentTopic = null;
28
29    /**
30     * @var string Name of the remote page the topics exist on
31     */
32    protected $pageName;
33
34    /**
35     * @var Iterator A list of topic ids.  Iterator used to simplify maintaining
36     *  an explicit position within the list.
37     */
38    protected $topicIdIterator;
39
40    /**
41     * @var int The maximum id received by self::loadMore
42     */
43    protected $maxId;
44
45    /**
46     * @param ImportSource $source
47     * @param CachedThreadData $threadData
48     * @param string $pageName
49     */
50    public function __construct( ImportSource $source, CachedThreadData $threadData, $pageName ) {
51        $this->importSource = $source;
52        $this->threadData = $threadData;
53        $this->pageName = $pageName;
54        $this->topicIdIterator = new ArrayIterator( $threadData->getTopics() );
55        $this->rewind();
56    }
57
58    public function current(): ?ImportTopic {
59        if ( $this->current === false ) {
60            return null;
61        }
62        return $this->currentTopic;
63    }
64
65    public function key(): mixed {
66        return $this->current;
67    }
68
69    public function next(): void {
70        if ( !$this->valid() ) {
71            return;
72        }
73
74        $lastOffset = $this->key();
75        do {
76            while ( $this->topicIdIterator->valid() ) {
77                $topicId = $this->topicIdIterator->current();
78                $this->topicIdIterator->next();
79
80                // this topic id has been seen before.
81                if ( $topicId <= $lastOffset ) {
82                    continue;
83                }
84                $lastOffset = $topicId;
85
86                // hidden and deleted threads come back as null
87                $topic = $this->importSource->getTopic( $topicId );
88                if ( $topic === null ) {
89                    continue;
90                }
91
92                $this->current = $topicId;
93                $this->currentTopic = $topic;
94                return;
95            }
96        } while ( $this->loadMore() );
97
98        // nothing found, nothing more to load
99        $this->current = false;
100    }
101
102    public function rewind(): void {
103        $this->current = null;
104        $this->topicIdIterator->rewind();
105        $this->next();
106    }
107
108    public function valid(): bool {
109        return $this->current !== false;
110    }
111
112    /**
113     * @return bool True when more topics were loaded
114     */
115    protected function loadMore() {
116        try {
117            // + 1 to not return the existing max topic
118            $output = $this->threadData->getFromPage( $this->pageName, $this->maxId + 1 );
119        } catch ( ApiNotFoundException ) {
120            // No more results, end loop
121            return false;
122        }
123
124        $this->maxId = max( array_keys( $output ) );
125        $this->topicIdIterator = new ArrayIterator( $this->threadData->getTopics() );
126        $this->topicIdIterator->rewind();
127
128        // Keep looping until we get a not found error
129        return true;
130    }
131}