<?php
/**
* Copyright 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Google\Cloud\Core\Iterator;
/**
* This trait fulfills the
* [\Iterator](http://php.net/manual/en/class.iterator.php) interface and
* returns results from a paged set one at a time.
*/
trait ItemIteratorTrait
{
/**
* @var \Iterator
*/
private $pageIterator;
/**
* @var int
*/
private $pageIndex = 0;
/**
* @var int
*/
private $position = 0;
/**
* @param \Iterator $pageIterator
*/
public function __construct(\Iterator $pageIterator)
{
$this->pageIterator = $pageIterator;
}
/**
* Fetch the token used to get the next set of results.
*
* @return string|null
*/
public function nextResultToken()
{
return method_exists($this->pageIterator, 'nextResultToken')
? $this->pageIterator->nextResultToken()
: null;
}
/**
* Iterate over the results on a per page basis.
*
* @return \Iterator
*/
public function iterateByPage()
{
return $this->pageIterator;
}
/**
* Rewind the iterator.
*
* @return null
*/
#[\ReturnTypeWillChange]
public function rewind()
{
$this->pageIndex = 0;
$this->position = 0;
$this->pageIterator->rewind();
}
/**
* Get the current item.
*
* @return mixed
*/
#[\ReturnTypeWillChange]
public function current()
{
$page = $this->pageIterator->current();
return isset($page[$this->pageIndex])
? $page[$this->pageIndex]
: null;
}
/**
* Get the key current item's key.
*
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
}
/**
* Advances to the next item.
*
* @return null
*/
#[\ReturnTypeWillChange]
public function next()
{
$this->pageIndex++;
$this->position++;
if (count($this->pageIterator->current()) <= $this->pageIndex && $this->nextResultToken()) {
$this->pageIterator->next();
$this->pageIndex = 0;
}
}
/**
* Determines if the current position is valid.
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid()
{
$page = $this->pageIterator->current();
if (isset($page[$this->pageIndex])) {
return true;
}
// If there are no results, but a token for the next page
// exists let's continue paging until there are results.
while ($this->nextResultToken()) {
$this->pageIterator->next();
$page = $this->pageIterator->current();
if (isset($page[$this->pageIndex])) {
return true;
}
}
return false;
}
}