Skip to content

Commit

Permalink
Improve static analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
cerbero90 committed Sep 7, 2024
1 parent d87aa07 commit d4c730e
Show file tree
Hide file tree
Showing 19 changed files with 38 additions and 26 deletions.
4 changes: 3 additions & 1 deletion src/Concerns/ParsesPages.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ trait ParsesPages
/**
* The number of items per page.
*/
protected readonly int $itemsPerPage;
protected int $itemsPerPage;

/**
* Yield paginated items and the given key from the provided response.
Expand All @@ -35,6 +35,7 @@ protected function yieldItemsAndGetKey(ResponseInterface $response, string $key)

foreach (JsonParser::parse($response)->pointers($pointers) as $item) {
if (is_object($item)) {
/** @var object{value: mixed} $item */
$value = $item->value;
} else {
yield $item;
Expand All @@ -54,6 +55,7 @@ protected function yieldItemsAndGetKey(ResponseInterface $response, string $key)
*/
protected function yieldItemsFrom(mixed $source): Generator
{
/** @phpstan-ignore-next-line */
yield from JsonParser::parse($source)->pointer($this->config->itemsPointer);
}
}
7 changes: 5 additions & 2 deletions src/Concerns/ResolvesPages.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ protected function toPage(mixed $value, bool $onlyNumerics = true): string|int|n
is_numeric($value) => (int) $value,
!is_string($value) || $value === '' => null,
!$this->isEndpoint($value) => $onlyNumerics ? null : $value,
default => $this->pageFromParsedUri(parse_url($value), $onlyNumerics),
default => $this->pageFromParsedUri(parse_url($value), $onlyNumerics), /** @phpstan-ignore-line */
};
}

/**
* Retrieve the page from the given parsed URI.
*
* @param array{path?: string, query?: string} $parsedUri
* @return ($onlyNumerics is true ? int|null : string|int|null)
*/
protected function pageFromParsedUri(array $parsedUri, bool $onlyNumerics = true): string|int|null
Expand All @@ -55,7 +56,9 @@ protected function pageFromParsedUri(array $parsedUri, bool $onlyNumerics = true
protected function uriForPage(UriInterface $uri, string $page): UriInterface
{
if ($key = $this->config->offsetKey) {
return Uri::withQueryValue($uri, $key, strval(($page - $this->config->firstPage) * $this->itemsPerPage));
$value = (intval($page) - $this->config->firstPage) * $this->itemsPerPage;

return Uri::withQueryValue($uri, $key, strval($value));
}

if (!$pattern = $this->config->pageInPath) {
Expand Down
8 changes: 5 additions & 3 deletions src/Concerns/RetriesHttpRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Cerbero\LazyJsonPages\Concerns;

use Cerbero\LazyJsonPages\Exceptions\OutOfAttemptsException;
use Closure;
use Generator;
use GuzzleHttp\Exception\TransferException;
use Illuminate\Support\LazyCollection;
Expand All @@ -20,10 +21,11 @@ trait RetriesHttpRequests
/**
* Retry to yield HTTP responses from the given callback.
*
* @param callable $callback
* @return Generator<int, mixed>
* @template TGen of Generator
* @param Closure(): TGen $callback
* @return TGen
*/
protected function retry(callable $callback): Generator
protected function retry(Closure $callback): Generator
{
$attempt = 0;
$remainingAttempts = $this->config->attempts;
Expand Down
9 changes: 6 additions & 3 deletions src/Concerns/YieldsItemsByLength.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ trait YieldsItemsByLength
* Yield paginated items until the page resolved from the given key is reached.
*
* @param ?Closure(int): int $callback
* @return Generator<int, mixed, null, int>
* @return Generator<int, mixed>
*/
protected function yieldItemsUntilKey(string $key, ?Closure $callback = null): Generator
{
Expand All @@ -38,14 +38,17 @@ protected function yieldItemsUntilKey(string $key, ?Closure $callback = null): G
/**
* Yield paginated items until the resolved page is reached.
*
* @param Closure(ResponseInterface): Generator<int, mixed, null, int> $callback
* @param Closure(ResponseInterface): Generator<int, mixed> $callback
* @return Generator<int, mixed>
*/
protected function yieldItemsUntilPage(Closure $callback): Generator
{
yield from $generator = $callback($this->source->pullResponse());

foreach ($this->fetchPagesAsynchronously($generator->getReturn()) as $response) {
/** @var int */
$totalPages = $generator->getReturn();

foreach ($this->fetchPagesAsynchronously($totalPages) as $response) {
yield from $this->yieldItemsFrom($response);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Data/RateLimit.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function wasReached(): bool
/**
* Retrieve the timestamp when this rate limit resets.
*/
public function resetsAt(): float
public function resetsAt(): ?float
{
return $this->resetsAt;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Exceptions/OutOfAttemptsException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Cerbero\LazyJsonPages\Exceptions;

use Closure;
use GuzzleHttp\Exception\TransferException;
use Illuminate\Support\LazyCollection;

Expand All @@ -15,7 +14,7 @@ class OutOfAttemptsException extends LazyJsonPagesException
* Instantiate the class.
*
* @param array<int, int> $failedPages
* @param (Closure(): Generator<int, mixed>) $items
* @param LazyCollection<int, mixed> $items
*/
public function __construct(
TransferException $e,
Expand Down
4 changes: 2 additions & 2 deletions src/LazyJsonPages.php
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,15 @@ public function onError(Closure $callback): self
* Retrieve a lazy collection yielding the paginated items.
*
* @return LazyCollection<int, mixed>
* @throws UnsupportedPaginationException
* @throws \Cerbero\LazyJsonPages\Exceptions\UnsupportedPaginationException
*/
public function collect(string $dot = '*'): LazyCollection
{
$this->config[Config::OPTION_ITEMS_POINTER] = DotsConverter::toPointer($dot);

return new LazyCollection(function () {
$client = $this->client->make();
$config = new Config(...$this->config);
$config = new Config(...$this->config); /** @phpstan-ignore-line */
$source = (new AnySource($this->source))->setClient($client);

yield from new AnyPagination($source, $client, $config);
Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/Tap.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function __construct(private readonly TapCallbacks $callbacks) {}
/**
* Handle an HTTP request before and after it is sent.
*
* @param callable(RequestInterface, array): PromiseInterface $handler
* @param callable(RequestInterface, array<string, mixed>): PromiseInterface $handler
*/
public function __invoke(callable $handler): Closure
{
Expand Down
1 change: 1 addition & 0 deletions src/Paginations/CursorAwarePagination.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function matches(): bool
public function getIterator(): Traversable
{
yield from $this->yieldItemsByCursor(function (ResponseInterface $response) {
/** @phpstan-ignore-next-line */
yield from $generator = $this->yieldItemsAndGetKey($response, $this->config->cursorKey);

return $generator->getReturn();
Expand Down
1 change: 1 addition & 0 deletions src/Paginations/LastPageAwarePagination.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
/** @phpstan-ignore-next-line */
yield from $this->yieldItemsUntilKey($this->config->lastPageKey, function (int $page) {
return $this->config->firstPage === 0 ? $page + 1 : $page;
});
Expand Down
6 changes: 2 additions & 4 deletions src/Paginations/LinkHeaderAwarePagination.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Cerbero\LazyJsonPages\Concerns\YieldsItemsByCursor;
use Cerbero\LazyJsonPages\Concerns\YieldsItemsByLength;
use Cerbero\LazyJsonPages\Exceptions\InvalidLinkHeaderException;
use Generator;
use Psr\Http\Message\ResponseInterface;
use Traversable;
Expand Down Expand Up @@ -39,10 +38,10 @@ public function matches(): bool
* Yield the paginated items.
*
* @return Traversable<int, mixed>
* @throws InvalidLinkHeaderException
*/
public function getIterator(): Traversable
{
/** @var array{last?: int, next?: string|int} */
$links = $this->parseLinkHeader($this->source->response()->getHeaderLine('link'));

yield from match (true) {
Expand All @@ -55,11 +54,10 @@ public function getIterator(): Traversable
/**
* Retrieve the parsed Link header.
*
* @template TParsed of array{last?: int, next?: string|int}
* @template TRelation of string|null
*
* @param TRelation $relation
* @return (TRelation is null ? TParsed : string|int|null)
* @return (TRelation is null ? array<string, int|string|null> : string|int|null)
*/
protected function parseLinkHeader(string $linkHeader, ?string $relation = null): array|string|int|null
{
Expand Down
1 change: 1 addition & 0 deletions src/Paginations/TotalItemsAwarePagination.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
/** @phpstan-ignore-next-line */
yield from $this->yieldItemsUntilKey($this->config->totalItemsKey, function (int $totalItems) {
return $this->itemsPerPage > 0 ? (int) ceil($totalItems / $this->itemsPerPage) : 0;
});
Expand Down
2 changes: 1 addition & 1 deletion src/Paginations/TotalPagesAwarePagination.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public function matches(): bool
*/
public function getIterator(): Traversable
{
yield from $this->yieldItemsUntilKey($this->config->totalPagesKey);
yield from $this->yieldItemsUntilKey($this->config->totalPagesKey); /** @phpstan-ignore-line */
}
}
2 changes: 2 additions & 0 deletions src/Providers/LazyJsonPagesServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

/**
* The service provider to integrate with Laravel.
*
* @property-read array{events: \Illuminate\Contracts\Events\Dispatcher} $app
*/
final class LazyJsonPagesServiceProvider extends ServiceProvider
{
Expand Down
2 changes: 1 addition & 1 deletion src/Services/RateLimits.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function resetAt(): float

foreach ($this->rateLimits as $rateLimit) {
if ($rateLimit->wasReached()) {
$timestamp = max($rateLimit->resetsAt(), $timestamp);
$timestamp = max($rateLimit->resetsAt() ?? 0.0, $timestamp);

$rateLimit->reset();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Sources/AnySource.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class AnySource extends Source
/**
* The matching source.
*/
protected readonly Source $matchingSource;
protected Source $matchingSource;

/**
* The cached HTTP response.
Expand Down
4 changes: 2 additions & 2 deletions src/Sources/Endpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class Endpoint extends Source
*/
public function matches(): bool
{
return $this->source instanceof UriInterface
|| (is_string($this->source) && $this->isEndpoint($this->source));
return (is_string($this->source) && $this->isEndpoint($this->source))
|| $this->source instanceof UriInterface;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Sources/Source.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ abstract class Source
/**
* The HTTP client.
*/
protected readonly Client $client;
protected Client $client;

/**
* Retrieve the HTTP request.
Expand Down
2 changes: 1 addition & 1 deletion src/Sources/SymfonyRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function request(): RequestInterface
return new Psr7Request(
$this->source->getMethod(),
$this->source->getUri(),
$this->source->headers->all(),
$this->source->headers->all(), /** @phpstan-ignore-line */
$this->source->getContent() ?: null,
);
}
Expand Down

0 comments on commit d4c730e

Please sign in to comment.