Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.x] Added generics to paginators #53512

Draft
wants to merge 2 commits into
base: 11.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Illuminate/Contracts/Pagination/LengthAwarePaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

namespace Illuminate\Contracts\Pagination;

/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @extends Paginator<TKey, TValue>
*/
interface LengthAwarePaginator extends Paginator
{
/**
Expand Down
7 changes: 6 additions & 1 deletion src/Illuminate/Contracts/Pagination/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

namespace Illuminate\Contracts\Pagination;

/**
* @template TKey of array-key
*
* @template-covariant TValue
*/
interface Paginator
{
/**
Expand Down Expand Up @@ -46,7 +51,7 @@ public function previousPageUrl();
/**
* Get all of the items being paginated.
*
* @return array
* @return array<TKey, TValue>
*/
public function items();

Expand Down
16 changes: 10 additions & 6 deletions src/Illuminate/Pagination/AbstractPaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
use Traversable;

/**
* @mixin \Illuminate\Support\Collection
* @template TKey of array-key
*
* @template TValue
*
* @mixin \Illuminate\Support\Collection<TKey, TValue>
*/
abstract class AbstractPaginator implements Htmlable, Stringable
{
Expand All @@ -21,7 +25,7 @@ abstract class AbstractPaginator implements Htmlable, Stringable
/**
* All of the items being paginated.
*
* @var \Illuminate\Support\Collection
* @var \Illuminate\Support\Collection<TKey, TValue>
*/
protected $items;

Expand Down Expand Up @@ -310,7 +314,7 @@ public function loadMorphCount($relation, $relations)
/**
* Get the slice of items being paginated.
*
* @return array
* @return array<TKey, TValue>
*/
public function items()
{
Expand Down Expand Up @@ -649,7 +653,7 @@ public static function useBootstrapFive()
/**
* Get an iterator for the items.
*
* @return \ArrayIterator
* @return \ArrayIterator<TKey, TValue>
*/
public function getIterator(): Traversable
{
Expand Down Expand Up @@ -689,7 +693,7 @@ public function count(): int
/**
* Get the paginator's underlying collection.
*
* @return \Illuminate\Support\Collection
* @return \Illuminate\Support\Collection<TKey, TValue>
*/
public function getCollection()
{
Expand All @@ -699,7 +703,7 @@ public function getCollection()
/**
* Set the paginator's underlying collection.
*
* @param \Illuminate\Support\Collection $collection
* @param \Illuminate\Support\Collection<TKey, TValue> $collection
* @return $this
*/
public function setCollection(Collection $collection)
Expand Down
12 changes: 11 additions & 1 deletion src/Illuminate/Pagination/LengthAwarePaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
use IteratorAggregate;
use JsonSerializable;

/**
* @template TKey of array-key
*
* @template TValue
*
* @implements Arrayable<TKey, TValue>
* @implements ArrayAccess<TKey, TValue>
* @implements LengthAwarePaginatorContract<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
*/
class LengthAwarePaginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, LengthAwarePaginatorContract
{
/**
Expand All @@ -30,7 +40,7 @@ class LengthAwarePaginator extends AbstractPaginator implements Arrayable, Array
/**
* Create a new paginator instance.
*
* @param mixed $items
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|Collection<TKey, TValue>|null $items
* @param int $total
* @param int $perPage
* @param int|null $currentPage
Expand Down
14 changes: 12 additions & 2 deletions src/Illuminate/Pagination/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
use IteratorAggregate;
use JsonSerializable;

/**
* @template TKey of array-key
*
* @template-covariant TValue
*
* @implements Arrayable<TKey, TValue>
* @implements ArrayAccess<TKey, TValue>
* @implements IteratorAggregate<TKey, TValue>
* @implements PaginatorContract<TKey, TValue>
*/
class Paginator extends AbstractPaginator implements Arrayable, ArrayAccess, Countable, IteratorAggregate, Jsonable, JsonSerializable, PaginatorContract
{
/**
Expand All @@ -23,7 +33,7 @@ class Paginator extends AbstractPaginator implements Arrayable, ArrayAccess, Cou
/**
* Create a new paginator instance.
*
* @param mixed $items
* @param TValue[] $items
* @param int $perPage
* @param int|null $currentPage
* @param array $options (path, query, fragment, pageName)
Expand Down Expand Up @@ -60,7 +70,7 @@ protected function setCurrentPage($currentPage)
/**
* Set the items for the paginator.
*
* @param mixed $items
* @param \Illuminate\Contracts\Support\Arrayable<TKey, TValue>|iterable<TKey, TValue>|Collection<TKey, TValue>|null $items
* @return void
*/
protected function setItems($items)
Expand Down
1 change: 1 addition & 0 deletions tests/Pagination/PaginatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class PaginatorTest extends TestCase
{
public function testSimplePaginatorReturnsRelevantContextInformation()
{
/** @var Paginator<int, string> $p */
$p = new Paginator(['item3', 'item4', 'item5'], 2, 2);

$this->assertEquals(2, $p->currentPage());
Expand Down
37 changes: 37 additions & 0 deletions types/Pagination/Paginator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use function PHPStan\Testing\assertType;

$items = [new Post(), new Post(), new Post()];

/** @var Paginator<int, Post> $paginator */
$paginator = new Paginator($items, 1, 1);

assertType('Post[]', $paginator->items());

Check failure on line 12 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post[], actual: array
assertType('array<int, Post>', $paginator->toArray());

Check failure on line 13 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type array<int, Post>, actual: array
assertType('ArrayIterator<TKey, TValue>', $paginator->getIterator());

Check failure on line 14 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type ArrayIterator<TKey, TValue>, actual: ArrayIterator<(int|string), mixed>

$paginator->each(function ($post) {
assertType('Post', $post);

Check failure on line 17 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post, actual: mixed
});

foreach ($paginator as $post) {
assertType('Post', $post);

Check failure on line 21 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post, actual: mixed
}

/** @var LengthAwarePaginator<int, Post> $lengthAwarePaginator */
$lengthAwarePaginator = new LengthAwarePaginator($items, 1, 1);

assertType('Post[]', $lengthAwarePaginator->items());

Check failure on line 27 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post[], actual: array
assertType('array<int, Post>', $lengthAwarePaginator->toArray());

Check failure on line 28 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type array<int, Post>, actual: array
assertType('ArrayIterator<int, Post>', $lengthAwarePaginator->getIterator());

Check failure on line 29 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type ArrayIterator<int, Post>, actual: ArrayIterator<(int|string), mixed>

$lengthAwarePaginator->each(function ($post) {
assertType('Post', $post);

Check failure on line 32 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post, actual: mixed
});

foreach ($lengthAwarePaginator as $post) {
assertType('Post', $post);

Check failure on line 36 in types/Pagination/Paginator.php

View workflow job for this annotation

GitHub Actions / Types

Expected type Post, actual: mixed
}
Loading