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

feat: API Platform support #42

Merged
merged 21 commits into from
Apr 8, 2024
Merged
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
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
Loading