RRule\RSet::iterate PHP Method

iterate() protected method

What we need to do it to build two heaps: rlist and exlist Each heap contains multiple iterators (either RRule or ArrayIterator) At each step of the loop, it calls all of the iterators to generate a new item, and stores them in the heap, that keeps them in order. This is made slightly more complicated because this method is a generator.
protected iterate ( $reset = false ) : DateTime | null
$reset (bool) Whether to restart the iteration, or keep going
return DateTime | null
    protected function iterate($reset = false)
    {
        $previous_occurrence =& $this->_previous_occurrence;
        $total =& $this->_total;
        $use_cache =& $this->_use_cache;
        if ($reset) {
            $this->_previous_occurrence = null;
            $this->_total = 0;
            $this->_use_cache = true;
            reset($this->cache);
        }
        // go through the cache first
        if ($use_cache) {
            while (($occurrence = current($this->cache)) !== false) {
                next($this->cache);
                $total += 1;
                return clone $occurrence;
            }
            reset($this->cache);
            // now set use_cache to false to skip the all thing on next iteration
            // and start filling the cache instead
            $use_cache = false;
            // if the cache as been used up completely and we now there is nothing else
            if ($total === $this->total) {
                return null;
            }
        }
        if ($this->rlist_heap === null) {
            // rrules + rdate
            $this->rlist_heap = new \SplMinHeap();
            $this->rlist_iterator = new \MultipleIterator(\MultipleIterator::MIT_NEED_ANY);
            $this->rlist_iterator->attachIterator(new \ArrayIterator($this->rdates));
            foreach ($this->rrules as $rrule) {
                $this->rlist_iterator->attachIterator($rrule);
            }
            $this->rlist_iterator->rewind();
            // exrules + exdate
            $this->exlist_heap = new \SplMinHeap();
            $this->exlist_iterator = new \MultipleIterator(\MultipleIterator::MIT_NEED_ANY);
            $this->exlist_iterator->attachIterator(new \ArrayIterator($this->exdates));
            foreach ($this->exrules as $rrule) {
                $this->exlist_iterator->attachIterator($rrule);
            }
            $this->exlist_iterator->rewind();
        }
        while (true) {
            foreach ($this->rlist_iterator->current() as $date) {
                if ($date !== null) {
                    $this->rlist_heap->insert($date);
                }
            }
            $this->rlist_iterator->next();
            // advance the iterator for the next call
            if ($this->rlist_heap->isEmpty()) {
                break;
                // exit the loop to stop the iterator
            }
            $occurrence = $this->rlist_heap->top();
            $this->rlist_heap->extract();
            // remove the occurrence from the heap
            if ($occurrence == $previous_occurrence) {
                continue;
                // skip, was already considered
            }
            // now we need to check against exlist
            // we need to iterate exlist as long as it contains dates lower than occurrence
            // (they will be discarded), and then check if the date is the same
            // as occurrence (in which case it is discarded)
            $excluded = false;
            while (true) {
                foreach ($this->exlist_iterator->current() as $date) {
                    if ($date !== null) {
                        $this->exlist_heap->insert($date);
                    }
                }
                $this->exlist_iterator->next();
                // advance the iterator for the next call
                if ($this->exlist_heap->isEmpty()) {
                    break 1;
                    // break this loop only
                }
                $exdate = $this->exlist_heap->top();
                if ($exdate < $occurrence) {
                    $this->exlist_heap->extract();
                    continue;
                } elseif ($exdate == $occurrence) {
                    $excluded = true;
                    break 1;
                } else {
                    break 1;
                    // exdate is > occurrence, so we'll keep it for later
                }
            }
            $previous_occurrence = $occurrence;
            if ($excluded) {
                continue;
            }
            $total += 1;
            $this->cache[] = $occurrence;
            return clone $occurrence;
            // = yield
        }
        $this->total = $total;
        // save total for count cache
        return null;
        // stop the iterator
    }