keboola/juicer

View on GitHub
src/Pagination/Decorator/LimitStopScrollerDecorator.php

Summary

Maintainability
A
1 hr
Test Coverage
B
89%
<?php

declare(strict_types=1);

namespace Keboola\Juicer\Pagination\Decorator;

use Keboola\Juicer\Client\RestClient;
use Keboola\Juicer\Client\RestRequest;
use Keboola\Juicer\Config\JobConfig;
use Keboola\Juicer\Exception\UserException;
use Keboola\Juicer\Pagination\ScrollerInterface;
use Psr\Log\LoggerInterface;
use function Keboola\Utils\getDataFromPath;

/**
 * Class LimitStopScrollerDecorator
 * Adds 'limit' option
 */
class LimitStopScrollerDecorator extends AbstractScrollerDecorator
{
    private ?int $countLimit = null;

    private ?string $fieldName = null;

    private int $currentCount;

    public function __construct(ScrollerInterface $scroller, array $config, LoggerInterface $logger)
    {
        parent::__construct($scroller, $logger);
        if (!empty($config['limitStop'])) {
            if (empty($config['limitStop']['field']) && empty($config['limitStop']['count'])) {
                throw new UserException("One of 'limitStop.field' or 'limitStop.count' attributes is required.");
            }
            if (!empty($config['limitStop']['field']) && !empty($config['limitStop']['count'])) {
                throw new UserException("Specify only one of 'limitStop.field' or 'limitStop.count'.");
            }
            if (!empty($config['limitStop']['field'])) {
                $this->fieldName = $config['limitStop']['field'];
            }
            if (!empty($config['limitStop']['count'])) {
                $this->countLimit = intval($config['limitStop']['count']);
            }
        }
        $this->reset();
    }

    /**
     * @inheritdoc
     */
    public function getFirstRequest(RestClient $client, JobConfig $jobConfig): ?RestRequest
    {
        $this->currentCount = 0;
        return $this->scroller->getFirstRequest($client, $jobConfig);
    }

    /**
     * @inheritdoc
     */
    public function getNextRequest(RestClient $client, JobConfig $jobConfig, $response, array $data): ?RestRequest
    {
        $this->currentCount += count($data);
        if ($this->fieldName) {
            $limit = getDataFromPath($this->fieldName, $response, '.');
        } else {
            $limit = $this->countLimit;
        }
        if ($this->currentCount >= $limit) {
            $this->logger->info(sprintf(
                'Limit reached, stopping scrolling. Current count: %d, limit: %d',
                $this->currentCount,
                $limit,
            ));
            return null;
        }

        return $this->scroller->getNextRequest($client, $jobConfig, $response, $data);
    }

    /**
     * @inheritdoc
     */
    public function reset(): void
    {
        $this->currentCount = 0;
        parent::reset();
    }
}