Skip to content

Commit

Permalink
Merge pull request #148 from acelaya-forks/feature/phpstan-generics
Browse files Browse the repository at this point in the history
Enable missing generics checks with phpstan
  • Loading branch information
acelaya authored Jul 29, 2024
2 parents e89f465 + acf6034 commit 144e5c1
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 31 deletions.
1 change: 0 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ includes:
parameters:
ignoreErrors:
- identifier: missingType.iterableValue
- identifier: missingType.generics
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<exclude>
<file>./src/Entity/AbstractEntity.php</file>
<file>./src/Cache/ShlinkPredisClient.php</file>
<file>./src/Paginator/Util/PagerfantaUtilsTrait.php</file>
</exclude>
</source>
</phpunit>
4 changes: 4 additions & 0 deletions src/Paginator/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

use function max;

/**
* @template T
* @extends Pagerfanta<T>
*/
class Paginator extends Pagerfanta
{
public const ALL_ITEMS = -1;
Expand Down
58 changes: 58 additions & 0 deletions src/Paginator/Util/PagerfantaUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Shlinkio\Shlink\Common\Paginator\Util;

use Laminas\Stdlib\ArrayUtils;
use Pagerfanta\Pagerfanta;

use function array_map;
use function count;
use function sprintf;

/**
* @template T
*/
final class PagerfantaUtils
{
/**
* @param Pagerfanta<T> $paginator
* @param null|callable(T): mixed $serializer
*/
public static function serializePaginator(
Pagerfanta $paginator,
?callable $serializer = null,
string $dataProp = 'data',
): array {
$currentPageItems = ArrayUtils::iteratorToArray($paginator->getCurrentPageResults());

return [
$dataProp => self::serializeItems($currentPageItems, $serializer),
'pagination' => [
'currentPage' => $paginator->getCurrentPage(),
'pagesCount' => $paginator->getNbPages(),
'itemsPerPage' => $paginator->getMaxPerPage(),
'itemsInCurrentPage' => count($currentPageItems),
'totalItems' => $paginator->getNbResults(),
],
];
}

/**
* @param T[] $items
* @param null|callable(T): array $serializer
*/
private static function serializeItems(array $items, ?callable $serializer = null): array
{
return $serializer === null ? $items : array_map($serializer, $items);
}

/**
* @param Pagerfanta<T> $paginator
*/
public static function formatCurrentPageMessage(Pagerfanta $paginator, string $pattern): string
{
return sprintf($pattern, $paginator->getCurrentPage(), $paginator->getNbPages());
}
}
37 changes: 14 additions & 23 deletions src/Paginator/Util/PagerfantaUtilsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,33 @@

namespace Shlinkio\Shlink\Common\Paginator\Util;

use Laminas\Stdlib\ArrayUtils;
use Pagerfanta\Pagerfanta;
use Shlinkio\Shlink\Common\Rest\DataTransformerInterface;

use function array_map;
use function count;
use function sprintf;

/**
* @deprecated Use PagerfantaUtils instead
*/
trait PagerfantaUtilsTrait
{
/**
* @template T
* @param Pagerfanta<T> $paginator
*/
private function serializePaginator(
Pagerfanta $paginator,
?DataTransformerInterface $transformer = null,
string $dataProp = 'data',
): array {
$currentPageItems = ArrayUtils::iteratorToArray($paginator->getCurrentPageResults());

return [
$dataProp => $this->serializeItems($currentPageItems, $transformer),
'pagination' => [
'currentPage' => $paginator->getCurrentPage(),
'pagesCount' => $paginator->getNbPages(),
'itemsPerPage' => $paginator->getMaxPerPage(),
'itemsInCurrentPage' => count($currentPageItems),
'totalItems' => $paginator->getNbResults(),
],
];
}

private function serializeItems(array $items, ?DataTransformerInterface $transformer = null): array
{
return $transformer === null ? $items : array_map([$transformer, 'transform'], $items);
$serializer = $transformer !== null ? fn ($value) => $transformer->transform($value) : null;
return PagerfantaUtils::serializePaginator($paginator, $serializer, $dataProp);
}

/**
* @template T
* @param Pagerfanta<T> $paginator
*/
private function formatCurrentPageMessage(Pagerfanta $paginator, string $pattern): string
{
return sprintf($pattern, $paginator->getCurrentPage(), $paginator->getNbPages());
return PagerfantaUtils::formatCurrentPageMessage($paginator, $pattern);
}
}
1 change: 1 addition & 0 deletions src/Rest/DataTransformerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Shlinkio\Shlink\Common\Rest;

/** @deprecated */
interface DataTransformerInterface
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/Validation/OrderByFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use function is_string;
use function Shlinkio\Shlink\Common\parseOrderBy;

/**
* @extends AbstractFilter<array{}>
*/
class OrderByFilter extends AbstractFilter
{
/**
Expand Down
1 change: 1 addition & 0 deletions test/Doctrine/Mapping/EnhancedPHPDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
class EnhancedPHPDriverTest extends TestCase
{
private MockObject & FileLocator $loader;
/** @var MockObject & ClassMetadata<stdClass> */
private MockObject & ClassMetadata $meta;

public function setUp(): void
Expand Down
3 changes: 3 additions & 0 deletions test/Mock/MockRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Doctrine\ORM\EntityRepository;

/**
* @extends EntityRepository<object>
*/
class MockRepository extends EntityRepository
{
}
5 changes: 5 additions & 0 deletions test/Paginator/PaginatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Common\Paginator\Paginator;

/**
* @template T
*/
class PaginatorTest extends TestCase
{
/** @var Paginator<T> */
private Paginator $paginator;
/** @var MockObject & AdapterInterface<T> */
private MockObject & AdapterInterface $adapter;

protected function setUp(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtilsTrait;
use Shlinkio\Shlink\Common\Paginator\Util\PagerfantaUtils;

use function range;

class PagerfantaUtilsTraitTest extends TestCase
/**
* @template T
*/
class PagerfantaUtilsTest extends TestCase
{
use PagerfantaUtilsTrait;

/**
* @param Pagerfanta<T> $paginator
*/
#[Test, DataProvider('providePaginatorAdapters')]
public function paginatorIsSerializedAsExpected(array $expectedSerialization, Pagerfanta $paginator): void
{
$result = $this->serializePaginator($paginator);
$result = PagerfantaUtils::serializePaginator($paginator);
self::assertEquals($expectedSerialization, $result);
}

Expand Down Expand Up @@ -86,7 +90,7 @@ public static function providePaginatorAdapters(): iterable
#[Test, DataProvider('provideDataProps')]
public function paginatorIsSerializedWithExpectedDataProp(string $prop): void
{
$result = $this->serializePaginator(new Pagerfanta(new ArrayAdapter([])), null, $prop);
$result = PagerfantaUtils::serializePaginator(new Pagerfanta(new ArrayAdapter([])), dataProp: $prop);

self::assertArrayNotHasKey('data', $result);
self::assertArrayHasKey($prop, $result);
Expand All @@ -99,13 +103,27 @@ public static function provideDataProps(): iterable
yield 'something' => ['something'];
}

#[Test]
public function paginatorIsSerializedWithProvidedCallback(): void
{
['data' => $data] = PagerfantaUtils::serializePaginator(
new Pagerfanta(new ArrayAdapter(range(1, 10))),
static fn (int $value) => $value * 2,
);

self::assertEquals([2, 4, 6, 8, 10, 12, 14, 16, 18, 20], $data);
}

/**
* @param Pagerfanta<T> $paginator
*/
#[Test, DataProvider('providePaginatorsToFormat')]
public function pageMessageIsProperlyFormatted(
string $expectedMessage,
string $pattern,
Pagerfanta $paginator,
): void {
self::assertEquals($expectedMessage, $this->formatCurrentPageMessage($paginator, $pattern));
self::assertEquals($expectedMessage, PagerfantaUtils::formatCurrentPageMessage($paginator, $pattern));
}

public static function providePaginatorsToFormat(): iterable
Expand Down
3 changes: 3 additions & 0 deletions test/Repository/CustomRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Doctrine\ORM\EntityRepository;

/**
* @extends EntityRepository<object>
*/
class CustomRepository extends EntityRepository
{
}

0 comments on commit 144e5c1

Please sign in to comment.