Skip to content

Commit

Permalink
feat: API Platform support (#42)
Browse files Browse the repository at this point in the history
* feat: api platform support

* add link to api page

* feat(`OpenApi`): change all 'page' parameters to accept string

* test: provider returning PageInterface

* feat(ApiPlatform): add `PageNormalizer` & `PagerFactory`

* bump flex

* add --no-scripts to CI

* remove flex from root composer.json

* suppress toomanyarguments for pagenormalizer

* check CI on highest dep only for now

* remove apiresource from mapping path

* limit ci to symfony 7

* Doctrine ORM support

* refactor

* spinoff common bundle classes to symfony-bridge package

* obtain itemsPerPage in PagerFactory

* add api test

* fix tests

* add type detection to QueryBuilderAdapter

* disable orm support by default, add config to enable it

* release 0.8.0
  • Loading branch information
priyadi authored Apr 8, 2024
1 parent 4ab5989 commit 0f1aad4
Show file tree
Hide file tree
Showing 53 changed files with 1,702 additions and 58 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,17 @@ jobs:
uses: ramsey/composer-install@v2
with:
dependency-versions: ${{ matrix.dep }}
composer-options: --prefer-dist --no-progress
composer-options: --prefer-dist --no-progress --no-scripts
env:
SYMFONY_REQUIRE: ${{ matrix.symfony }}

- name: Run psalm
run: vendor/bin/psalm
if: matrix.dep == 'highest' && matrix.symfony == '7.*'

- name: Run phpstan
run: vendor/bin/phpstan analyse
if: matrix.dep == 'highest' && matrix.symfony == '7.*'

- name: Lint container
run: tests/bin/console lint:container
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

* build: spinoff encoder service definition
* build: twig & twigbundle is now optional
* feat: API Platform support
* feat(`OpenApi`): change all 'page' parameters to accept string
* feat(ApiPlatform): add `PageNormalizer` & `PagerFactory`
* feat(`QueryBuilderAdapter`): add type detection

# 0.7.2

Expand Down
31 changes: 20 additions & 11 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
"psr-4": {
"Rekalogika\\Contracts\\Rekapager\\": "packages/rekapager-contracts/src/",
"Rekalogika\\Rekapager\\": "packages/rekapager-core/src/",
"Rekalogika\\Rekapager\\ApiPlatform\\": "packages/rekapager-api-platform/src/",
"Rekalogika\\Rekapager\\Bundle\\": "packages/rekapager-bundle/src/",
"Rekalogika\\Rekapager\\Doctrine\\Collections\\": "packages/rekapager-doctrine-collections-adapter/src/",
"Rekalogika\\Rekapager\\Doctrine\\ORM\\": "packages/rekapager-doctrine-orm-adapter/src/",
"Rekalogika\\Rekapager\\Keyset\\": "packages/rekapager-keyset-pagination/src/",
"Rekalogika\\Rekapager\\Offset\\": "packages/rekapager-offset-pagination/src/",
"Rekalogika\\Rekapager\\Pagerfanta\\": "packages/rekapager-pagerfanta-adapter/src/",
"Rekalogika\\Rekapager\\Bundle\\": "packages/rekapager-bundle/src/"
"Rekalogika\\Rekapager\\Symfony\\": "packages/rekapager-symfony-bridge/src/"
}
},
"autoload-dev": {
Expand All @@ -29,6 +31,7 @@
},
"require": {
"php": "^8.2",
"api-platform/core": "^3.2",
"doctrine/collections": "^2.2",
"doctrine/orm": "^2.14 || ^3.0",
"pagerfanta/core": "^4.0",
Expand All @@ -41,6 +44,7 @@
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/routing": "^6.4 || ^7.0",
"symfony/serializer": "^6.4 || ^7.0",
"symfony/stimulus-bundle": "^2.16",
"twig/twig": "^3.8"
},
"require-dev": {
Expand All @@ -59,16 +63,18 @@
"psr/log": "^2.0 || ^3.0",
"ramsey/uuid": "^4.7",
"rekalogika/doctrine-collections-decorator": "^2.3",
"symfony/asset": "^6.4 || ^7.0",
"symfony/asset-mapper": "^6.4 || ^7.0",
"symfony/browser-kit": "^6.4 || ^7.0",
"symfony/debug-bundle": "^6.4 || ^7.0",
"symfony/doctrine-bridge": "^6.4 || ^7.0",
"symfony/dotenv": "^6.4 || ^7.0",
"symfony/form": "^6.4 || ^7.0",
"symfony/framework-bundle": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"symfony/maker-bundle": "^1.55",
"symfony/monolog-bundle": "^3.0",
"symfony/runtime": "^6.4 || ^7.0",
"symfony/stimulus-bundle": "^2.16",
"symfony/translation": "^6.4 || ^7.0",
"symfony/twig-bundle": "^6.4 || ^7.0",
"symfony/uid": "^6.4 || ^7.0",
Expand All @@ -82,17 +88,20 @@
"config": {
"sort-packages": true,
"allow-plugins": {
"symfony/runtime": true
"symfony/runtime": true,
"symfony/flex": false
}
},
"replace": {
"rekalogika/rekapager-bundle": "0.7.2",
"rekalogika/rekapager-contracts": "0.7.2",
"rekalogika/rekapager-core": "0.7.2",
"rekalogika/rekapager-doctrine-collections-adapter": "0.7.2",
"rekalogika/rekapager-doctrine-orm-adapter": "0.7.2",
"rekalogika/rekapager-keyset-pagination": "0.7.2",
"rekalogika/rekapager-offset-pagination": "0.7.2",
"rekalogika/rekapager-pagerfanta-adapter": "0.7.2"
"rekalogika/rekapager-api-platform": "0.8.0",
"rekalogika/rekapager-bundle": "0.8.0",
"rekalogika/rekapager-contracts": "0.8.0",
"rekalogika/rekapager-core": "0.8.0",
"rekalogika/rekapager-doctrine-collections-adapter": "0.8.0",
"rekalogika/rekapager-doctrine-orm-adapter": "0.8.0",
"rekalogika/rekapager-keyset-pagination": "0.8.0",
"rekalogika/rekapager-offset-pagination": "0.8.0",
"rekalogika/rekapager-pagerfanta-adapter": "0.8.0",
"rekalogika/rekapager-symfony-bridge": "0.8.0"
}
}
20 changes: 20 additions & 0 deletions packages/rekapager-api-platform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# rekalogika/rekapager-api-platform

Integrates Rekapager with the API Platform framework.

Rekapager is a pagination library for PHP, supporting both offset-based and
keyset-based pagination.

## Documentation

[rekalogika.dev/rekapager](https://rekalogika.dev/rekapager)

## License

MIT

## Contributing

This framework consists of multiple repositories split from a monorepo. Be
sure to submit issues and pull requests to the
[`rekalogika/rekapager`](https://github.com/rekalogika/rekapager) monorepo.
43 changes: 43 additions & 0 deletions packages/rekapager-api-platform/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "rekalogika/rekapager-api-platform",
"description": "Adds Rekapager support to API Platform",
"homepage": "https://rekalogika.dev/rekapager",
"keywords": [
"pagination",
"symfony",
"api-platform",
"api",
"bundle",
"symfony-bundle",
"rekapager",
"pager",
"keyset-pagination",
"offset-pagination"
],
"license": "MIT",
"type": "symfony-bundle",
"authors": [
{
"name": "Priyadi Iman Nurcahyo",
"email": "priyadi@rekalogika.com"
}
],
"autoload": {
"psr-4": {
"Rekalogika\\Rekapager\\ApiPlatform\\": "src/"
}
},
"require": {
"php": "^8.2",
"api-platform/core": "^3.2",
"psr/container": "^2.0",
"rekalogika/rekapager-contracts": "^0.8",
"rekalogika/rekapager-core": "^0.8",
"rekalogika/rekapager-symfony-bridge": "^0.8",
"symfony/config": "^6.4 || ^7.0",
"symfony/dependency-injection": "^6.4 || ^7.0",
"symfony/flex": "^2.4",
"symfony/http-foundation": "^6.4 || ^7.0",
"symfony/http-kernel": "^6.4 || ^7.0"
}
}
18 changes: 18 additions & 0 deletions packages/rekapager-api-platform/config/debug.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
};
67 changes: 67 additions & 0 deletions packages/rekapager-api-platform/config/services.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

use Rekalogika\Rekapager\ApiPlatform\Implementation\PageNormalizer;
use Rekalogika\Rekapager\ApiPlatform\Implementation\PagerFactory;
use Rekalogika\Rekapager\ApiPlatform\Implementation\RekapagerExtension;
use Rekalogika\Rekapager\ApiPlatform\Implementation\RekapagerOpenApiFactoryDecorator;
use Rekalogika\Rekapager\Contracts\PageIdentifierEncoderLocatorInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();

$parameters
->set(
'rekalogika.rekapager.api_platform.enable_orm_support_by_default',
false
);

$services = $containerConfigurator->services();

$services->set('rekalogika.rekapager.api_platform.open_api_factory_decorator')
->class(RekapagerOpenApiFactoryDecorator::class)
->decorate('api_platform.openapi.factory')
->args([
'$decorated' => service('.inner'),
]);

$services->set(PagerFactory::class)
->args([
'$resourceMetadataFactory' => service('api_platform.metadata.resource.metadata_collection_factory'),
'$pageIdentifierEncoderLocator' => service(PageIdentifierEncoderLocatorInterface::class),
'$pagination' => service('api_platform.pagination'),
'$pageParameterName' => '%api_platform.collection.pagination.page_parameter_name%',
'$urlGenerationStrategy' => '%api_platform.url_generation_strategy%'
]);

$services->set('rekalogika.rekapager.api_platform.page_normalizer')
->class(PageNormalizer::class)
->decorate('api_platform.hydra.normalizer.collection')
->args([
'$collectionNormalizer' => service('.inner'),
]);

$services->set('rekalogika.rekapager.api_platform.orm.extension')
->class(RekapagerExtension::class)
->args([
'$pagerFactory' => service(PagerFactory::class),
'$pagination' => service('api_platform.pagination'),
'$enabledByDefault' => '%rekalogika.rekapager.api_platform.enable_orm_support_by_default%',
])
->tag('api_platform.doctrine.orm.query_extension.collection', [
'priority' => -48,
]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Rekapager\ApiPlatform\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('rekalogika_rekapager_api_platform');

/** @var ArrayNodeDefinition $rootNode */
$rootNode = $treeBuilder->getRootNode();

$rootNode
->children()
->booleanNode('enable_orm_support_by_default')
->defaultValue(false)
->end()
->end()
;

return $treeBuilder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Rekapager\ApiPlatform\DependencyInjection;

use Rekalogika\Rekapager\Symfony\RekapagerSymfonyBridge;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;

class RekalogikaRekapagerApiPlatformExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
// load configuration

$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

// load our services

$loader = new PhpFileLoader(
$container,
new FileLocator(__DIR__ . '/../../config')
);
$loader->load('services.php');

// load debug services

$debug = (bool) $container->getParameter('kernel.debug');

if ($debug) {
$loader->load('debug.php');
}

// load services from symfony-bridge package

RekapagerSymfonyBridge::loadServices($container);

// process config
$enableOrmSupportByDefault = $config['enable_orm_support_by_default'] ?? false;
if (!\is_bool($enableOrmSupportByDefault)) {
throw new \InvalidArgumentException('The "enable_orm_support_by_default" option must be a boolean.');
}

$container->setParameter(
'rekalogika.rekapager.api_platform.enable_orm_support_by_default',
$enableOrmSupportByDefault
);
}
}
Loading

0 comments on commit 0f1aad4

Please sign in to comment.