Skip to content

Commit fa430c6

Browse files
committed
fix(laravel): defaults and pagination fixes
1 parent e9818e1 commit fa430c6

File tree

6 files changed

+106
-48
lines changed

6 files changed

+106
-48
lines changed

src/Laravel/ApiPlatformProvider.php

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,11 @@ public function register(): void
349349
new ConcernsResourceMetadataCollectionFactory(
350350
null,
351351
$app->make(LoggerInterface::class),
352-
[
353-
'routePrefix' => $config->get('api-platform.routes.prefix') ?? '/',
354-
],
352+
$config->get('api-platform.defaults', []),
355353
$config->get('api-platform.graphql.enabled'),
356354
),
357355
$app->make(LoggerInterface::class),
358-
[
359-
'routePrefix' => $config->get('api-platform.routes.prefix') ?? '/',
360-
],
356+
$config->get('api-platform.defaults', []),
361357
$config->get('api-platform.graphql.enabled'),
362358
),
363359
)
@@ -439,7 +435,8 @@ public function register(): void
439435
/** @var ConfigRepository */
440436
$config = $app['config'];
441437

442-
return new JsonApiProvider($app->make(ValidateProvider::class), $config->get('api-platform.collection.order.parameter_name'));
438+
// TODO: improve the JsonApiProvider and check the operation parameters for an OrderFilter
439+
return new JsonApiProvider($app->make(ValidateProvider::class), 'sort');
443440
});
444441

445442
$this->app->singleton(DeserializeProvider::class, function (Application $app) {
@@ -679,25 +676,26 @@ public function register(): void
679676
/** @var ConfigRepository */
680677
$config = $app['config'];
681678

682-
return new Pagination($config->get('api-platform.collection.pagination'), []);
679+
return new Pagination($config->get('api-platform.pagination'), []);
683680
});
684681

685682
$this->app->singleton(PaginationOptions::class, function (Application $app) {
686683
/** @var ConfigRepository */
687684
$config = $app['config'];
688-
$pagination = $config->get('api-platform.collection.pagination');
685+
$defaults = $config->get('api-platform.defaults');
686+
$pagination = $config->get('api-platform.pagination');
689687

690688
return new PaginationOptions(
691-
$pagination['enabled'],
689+
$defaults['pagination_enabled'],
692690
$pagination['page_parameter_name'],
693-
$pagination['client_items_per_page'],
691+
$defaults['pagination_client_items_per_page'],
694692
$pagination['items_per_page_parameter_name'],
695-
$pagination['client_enabled'],
693+
$defaults['pagination_client_enabled'],
696694
$pagination['enabled_parameter_name'],
697-
$pagination['items_per_page'],
698-
$pagination['maximum_items_per_page'],
699-
$pagination['partial'],
700-
$pagination['client_partial'],
695+
$defaults['pagination_items_per_page'],
696+
$defaults['pagination_maximum_items_per_page'],
697+
$defaults['pagination_partial'],
698+
$defaults['pagination_client_partial'],
701699
$pagination['partial_parameter_name'],
702700
);
703701
});
@@ -828,7 +826,7 @@ public function register(): void
828826

829827
return new JsonApiCollectionNormalizer(
830828
$app->make(ResourceClassResolverInterface::class),
831-
$config->get('api-platform.collection.pagination.page_parameter_name'),
829+
$config->get('api-platform.pagination.page_parameter_name'),
832830
$app->make(ResourceMetadataCollectionFactoryInterface::class),
833831
);
834832
});
@@ -1124,7 +1122,7 @@ private function registerGraphQl(Application $app): void
11241122
$app->singleton(GraphiQlController::class, function (Application $app) {
11251123
/** @var ConfigRepository */
11261124
$config = $app['config'];
1127-
$prefix = $config->get('api-platform.routes.prefix') ?? '';
1125+
$prefix = $config->get('api-platform.defaults.route_prefix') ?? '';
11281126

11291127
return new GraphiQlController($prefix);
11301128
});
@@ -1194,7 +1192,7 @@ public function boot(ResourceNameCollectionFactoryInterface $resourceNameCollect
11941192
}
11951193
}
11961194

1197-
$prefix = $config->get('api-platform.routes.prefix') ?? '';
1195+
$prefix = $config->get('api-platform.defaults.route_prefix') ?? '';
11981196
$route = new Route(['GET'], $prefix.'/contexts/{shortName?}{_format?}', [ContextAction::class, '__invoke']);
11991197
$route->name('api_jsonld_context')->middleware(ApiPlatformMiddleware::class);
12001198
$routeCollection->add($route);

src/Laravel/Eloquent/Paginator.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
*/
2424
final class Paginator implements PaginatorInterface, \IteratorAggregate
2525
{
26-
public function __construct(// @phpstan-ignore-line
26+
/**
27+
* @param LengthAwarePaginator<object> $paginator
28+
*/
29+
public function __construct(
2730
private readonly LengthAwarePaginator $paginator,
2831
) {
2932
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Laravel\Eloquent;
15+
16+
use ApiPlatform\State\Pagination\PartialPaginatorInterface;
17+
use Illuminate\Pagination\AbstractPaginator;
18+
use IteratorAggregate;
19+
20+
/**
21+
* @implements IteratorAggregate<mixed,object>
22+
* @implements PartialPaginatorInterface<object>
23+
*/
24+
final class PartialPaginator implements PartialPaginatorInterface, \IteratorAggregate
25+
{
26+
/**
27+
* @param AbstractPaginator<object> $paginator
28+
*/
29+
public function __construct(
30+
private readonly AbstractPaginator $paginator,
31+
) {
32+
}
33+
34+
public function count(): int
35+
{
36+
return $this->paginator->count();
37+
}
38+
39+
public function getCurrentPage(): float
40+
{
41+
return $this->paginator->currentPage();
42+
}
43+
44+
public function getItemsPerPage(): float
45+
{
46+
return $this->paginator->perPage();
47+
}
48+
49+
public function getIterator(): \Traversable
50+
{
51+
return $this->paginator->getIterator();
52+
}
53+
}

src/Laravel/Eloquent/State/CollectionProvider.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use ApiPlatform\Laravel\Eloquent\Extension\QueryExtensionInterface;
1717
use ApiPlatform\Laravel\Eloquent\Paginator;
18+
use ApiPlatform\Laravel\Eloquent\PartialPaginator;
1819
use ApiPlatform\Metadata\Operation;
1920
use ApiPlatform\State\Pagination\Pagination;
2021
use ApiPlatform\State\ProviderInterface;
@@ -23,7 +24,7 @@
2324
use Psr\Container\ContainerInterface;
2425

2526
/**
26-
* @implements ProviderInterface<Paginator|Collection<int, Model>>
27+
* @implements ProviderInterface<Paginator|Collection<int, Model>|PartialPaginator>
2728
*/
2829
final class CollectionProvider implements ProviderInterface
2930
{
@@ -61,12 +62,17 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
6162
return $query->get();
6263
}
6364

64-
return new Paginator(
65-
$query
66-
->paginate(
67-
perPage: $this->pagination->getLimit($operation, $context),
68-
page: $this->pagination->getPage($context),
69-
)
70-
);
65+
$isPartial = $operation->getPaginationPartial();
66+
$collection = $query
67+
->{$isPartial ? 'simplePaginate' : 'paginate'}(
68+
perPage: $this->pagination->getLimit($operation, $context),
69+
page: $this->pagination->getPage($context),
70+
);
71+
72+
if ($isPartial) {
73+
return new PartialPaginator($collection);
74+
}
75+
76+
return new Paginator($collection);
7177
}
7278
}

src/Laravel/config/api-platform.php

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
'version' => '1.0.0',
1111

1212
'routes' => [
13-
'prefix' => '/api',
14-
'middleware' => [],
1513
],
1614

1715
/*
@@ -42,25 +40,25 @@
4240
'jsonproblem' => ['application/problem+json'],
4341
],
4442

45-
'collection' => [
46-
'pagination' => [
47-
'enabled' => true,
48-
'partial' => false,
49-
'client_enabled' => false,
50-
'client_items_per_page' => false,
51-
'client_partial' => false,
52-
'items_per_page' => 30,
53-
'maximum_items_per_page' => null,
54-
'page_parameter_name' => 'page',
55-
'enabled_parameter_name' => 'pagination',
56-
'items_per_page_parameter_name' => 'itemsPerPage',
57-
'partial_parameter_name' => 'partial',
58-
],
59-
'order' => [
60-
'parameter_name' => 'order',
61-
],
43+
'defaults' => [
44+
'pagination_enabled' => true,
45+
'pagination_partial' => false,
46+
'pagination_client_enabled' => false,
47+
'pagination_client_items_per_page' => false,
48+
'pagination_client_partial' => false,
49+
'pagination_items_per_page' => 30,
50+
'pagination_maximum_items_per_page' => 30,
51+
'route_prefix' => '/api',
52+
'middleware' => [],
6253
],
6354

55+
'pagination' => [
56+
'page_parameter_name' => 'page',
57+
'enabled_parameter_name' => 'pagination',
58+
'items_per_page_parameter_name' => 'itemsPerPage',
59+
'partial_parameter_name' => 'partial',
60+
],
61+
6462
'graphql' => [
6563
'enabled' => false,
6664
'nesting_separator' => '__',

src/Metadata/Resource/Factory/OperationDefaultsTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private function addGlobalDefaults(ApiResource|Operation $operation): ApiResourc
6666
$operation = $operation->{'with'.$upperKey}(array_merge($value, $currentValue));
6767
}
6868

69-
if (null !== $currentValue) {
69+
if (null !== $currentValue || null === $value) {
7070
continue;
7171
}
7272

0 commit comments

Comments
 (0)