Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?phpnamespace Aws;use GuzzleHttp\Promise;/*** Iterator that yields each page of results of a pageable operation.*/class ResultPaginator implements \Iterator{/** @var AwsClientInterface Client performing operations. */private $client;/** @var string Name of the operation being paginated. */private $operation;/** @var array Args for the operation. */private $args;/** @var array Configuration for the paginator. */private $config;/** @var Result Most recent result from the client. */private $result;/** @var string|array Next token to use for pagination. */private $nextToken;/** @var int Number of operations/requests performed. */private $requestCount = 0;/*** @param AwsClientInterface $client* @param string $operation* @param array $args* @param array $config*/public function __construct(AwsClientInterface $client,$operation,array $args,array $config) {$this->client = $client;$this->operation = $operation;$this->args = $args;$this->config = $config;}/*** Runs a paginator asynchronously and uses a callback to handle results.** The callback should have the signature: function (Aws\Result $result).* A non-null return value from the callback will be yielded by the* promise. This means that you can return promises from the callback that* will need to be resolved before continuing iteration over the remaining* items, essentially merging in other promises to the iteration. The last* non-null value returned by the callback will be the result that fulfills* the promise to any downstream promises.** @param callable $handleResult Callback for handling each page of results.* The callback accepts the result that was* yielded as a single argument. If the* callback returns a promise, the promise* will be merged into the coroutine.** @return Promise\Promise*/public function each(callable $handleResult){return Promise\Coroutine::of(function () use ($handleResult) {$nextToken = null;do {$command = $this->createNextCommand($this->args, $nextToken);$result = (yield $this->client->executeAsync($command));$nextToken = $this->determineNextToken($result);$retVal = $handleResult($result);if ($retVal !== null) {yield Promise\Create::promiseFor($retVal);}} while ($nextToken);});}/*** Returns an iterator that iterates over the values of applying a JMESPath* search to each result yielded by the iterator as a flat sequence.** @param string $expression JMESPath expression to apply to each result.** @return \Iterator*/public function search($expression){// Apply JMESPath expression on each result, but as a flat sequence.return flatmap($this, function (Result $result) use ($expression) {return (array) $result->search($expression);});}/*** @return Result*/#[\ReturnTypeWillChange]public function current(){return $this->valid() ? $this->result : false;}#[\ReturnTypeWillChange]public function key(){return $this->valid() ? $this->requestCount - 1 : null;}#[\ReturnTypeWillChange]public function next(){$this->result = null;}#[\ReturnTypeWillChange]public function valid(){if ($this->result) {return true;}if ($this->nextToken || !$this->requestCount) {//Forward/backward paging can result in a case where the last page's nextforwardtoken//is the same as the one that came before it. This can cause an infinite loop.$hasBidirectionalPaging = $this->config['output_token'] === 'nextForwardToken';if ($hasBidirectionalPaging && $this->nextToken) {$tokenKey = $this->config['input_token'];$previousToken = $this->nextToken[$tokenKey];}$this->result = $this->client->execute($this->createNextCommand($this->args, $this->nextToken));$this->nextToken = $this->determineNextToken($this->result);if (isset($previousToken)&& $previousToken === $this->nextToken[$tokenKey]) {return false;}$this->requestCount++;return true;}return false;}#[\ReturnTypeWillChange]public function rewind(){$this->requestCount = 0;$this->nextToken = null;$this->result = null;}private function createNextCommand(array $args, array $nextToken = null){return $this->client->getCommand($this->operation, array_merge($args, ($nextToken ?: [])));}private function determineNextToken(Result $result){if (!$this->config['output_token']) {return null;}if ($this->config['more_results']&& !$result->search($this->config['more_results'])) {return null;}$nextToken = is_scalar($this->config['output_token'])? [$this->config['input_token'] => $this->config['output_token']]: array_combine($this->config['input_token'], $this->config['output_token']);return array_filter(array_map(function ($outputToken) use ($result) {return $result->search($outputToken);}, $nextToken));}}