Skip to content
This repository has been archived by the owner on May 4, 2022. It is now read-only.

v3.0.0 #25

Draft
wants to merge 27 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
44b43eb
[WIP] Begin v3.0.0
NicolasGuilloux May 20, 2020
d708f90
Fix circular services injection
NicolasGuilloux May 22, 2020
3475897
Improve normalizer
NicolasGuilloux May 29, 2020
1f3e37d
Merge branch 'master' into v3.0.0
Jun 17, 2020
10af235
Try to be minimalistic in updateCollection, add an optional argument …
Jun 29, 2020
7d59a1c
Fix bad EntityIdNormalizer context tag in dto normalizer
NicolasGuilloux Aug 27, 2020
e8d04be
Fix systematic entity id normalization on dto
NicolasGuilloux Aug 27, 2020
4fe13a3
Allow merging from new list to entity list in updateCollection
mdevlamynck Sep 7, 2020
02079db
Fix a small issue in the normalizer
NicolasGuilloux Nov 23, 2020
31746c7
Merge branch 'v3.0.0' of github.com:NicolasGuilloux/chaplean-dto-hand…
NicolasGuilloux Nov 23, 2020
4a04a7a
Merge branch 'master' into v3.0.0
mdevlamynck Jan 5, 2021
28cf00f
Fix a instanciation bug when no value is given
NicolasGuilloux Jan 27, 2021
529fe08
Merge branch 'v3.0.0' of github.com:NicolasGuilloux/chaplean-dto-hand…
NicolasGuilloux Jan 27, 2021
257fb0f
Fix array convertion
Apr 16, 2021
714a10c
Enlarge compatibility to Symfony 5, fix tests
NicolasGuilloux Jul 8, 2021
77c8889
Merge branch 'v3.0.0' of github.com:NicolasGuilloux/chaplean-dto-hand…
NicolasGuilloux Jul 8, 2021
cb6f0f8
Extends compatibility to Symfony 5 fuly with attributes
NicolasGuilloux Jul 8, 2021
ca486fb
Fix PHPUnit in CI
NicolasGuilloux Jul 8, 2021
3be8499
Fix translator interface class
NicolasGuilloux Jul 8, 2021
28a8f8f
Fix composer PHP dependency
NicolasGuilloux Jul 20, 2021
db30764
Add SubKey Annotation
Jan 31, 2022
3a6546c
Add SubKey Annotation
Jan 31, 2022
cb0b9b1
Add new validation groups key in context
Feb 4, 2022
594b473
Edit SubKey condition
Feb 7, 2022
f967f8f
Add AbstractClassResolverInterface
Apr 26, 2022
42b6cf2
Add OBJECT_TO_POPULATE option
Apr 29, 2022
ed73b47
Fix compiler pass
May 3, 2022
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
Prev Previous commit
Next Next commit
Add AbstractClassResolverInterface
Dumazeau committed Apr 26, 2022
commit f967f8f1a3dd60b47ceedb5f790799ff1bba7da7
6 changes: 6 additions & 0 deletions ChapleanDtoHandlerBundle.php
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@

namespace Chaplean\Bundle\DtoHandlerBundle;

use Chaplean\Bundle\DtoHandlerBundle\DependencyInjection\CompilerPass\AbstractClassCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

/**
@@ -23,4 +25,8 @@
*/
class ChapleanDtoHandlerBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new AbstractClassCompilerPass());
}
}
4 changes: 4 additions & 0 deletions DependencyInjection/ChapleanDtoHandlerExtension.php
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@

namespace Chaplean\Bundle\DtoHandlerBundle\DependencyInjection;

use Chaplean\Bundle\DtoHandlerBundle\DependencyInjection\CompilerPass\AbstractClassCompilerPass;
use Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolverInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@@ -42,6 +44,8 @@ public function load(array $configs, ContainerBuilder $container): void

$container->setParameter(Configuration::CONFIG_NODE, $config);
$this->setParameters($container, Configuration::CONFIG_NODE, $config);

$container->registerForAutoconfiguration(AbstractClassResolverInterface::class)->addTag(AbstractClassCompilerPass::TAG);
}

/**
52 changes: 52 additions & 0 deletions DependencyInjection/CompilerPass/AbstractClassCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Chaplean\Bundle\DtoHandlerBundle\DependencyInjection\CompilerPass;

use Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolver;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

final class AbstractClassCompilerPass implements CompilerPassInterface
{
public const TAG = 'chaplean_dto_handler.abstract_class_resolver';

public function process(ContainerBuilder $container)
{
$references = $this->getReferences($container);
$definition = $container->getDefinition(AbstractClassResolver::class);
$definition->setProperty('resolvers', $references);
}

/** @return Reference[] */
private function getReferences(ContainerBuilder $container): array
{
$serviceConfigs = $container->findTaggedServiceIds(self::TAG);
$serviceIds = array_keys($serviceConfigs);

$references = array_map(
static function (string $serviceId): Reference {
return new Reference($serviceId);
},
$serviceIds
);

usort(
$references,
static function (Reference $left, Reference $right): int {
$leftPriority = $left::getPriority();
$rightPriority = $right::getPriority();

if ($leftPriority === $rightPriority) {
return 0;
}

return $leftPriority > $rightPriority ? -1 : 1;
}
);

return $references;
}
}
29 changes: 26 additions & 3 deletions ParamConverter/DataTransferObjectParamConverter.php
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
use Chaplean\Bundle\DtoHandlerBundle\ConfigurationExtractor\PropertyConfigurationExtractor;
use Chaplean\Bundle\DtoHandlerBundle\DataTransferObject\DataTransferObjectInterface;
use Chaplean\Bundle\DtoHandlerBundle\Exception\DataTransferObjectValidationException;
use Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolver;
use Doctrine\Common\Annotations\AnnotationException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
@@ -74,6 +75,11 @@ class DataTransferObjectParamConverter implements ParamConverterInterface
*/
protected $translator;

/**
* @var AbstractClassResolver
*/
protected $abstractClassResolver;

/**
* @var ValidatorInterface
*/
@@ -86,20 +92,23 @@ class DataTransferObjectParamConverter implements ParamConverterInterface
* @param array $httpValidationGroups
* @param ParamConverterManager $paramConverterManager
* @param TranslatorInterface $translator
* @param AbstractClassResolver $abstractClassResolver
* @param ValidatorInterface|null $validator
*/
public function __construct(
array $bypassParamConverterExceptionClasses,
array $httpValidationGroups,
ParamConverterManager $paramConverterManager,
TranslatorInterface $translator,
AbstractClassResolver $abstractClassResolver,
ValidatorInterface $validator = null
) {
$this->bypassParamConverterExceptionClasses = $bypassParamConverterExceptionClasses;
$this->manager = $paramConverterManager;
$this->validator = $validator;
$this->taggedDtoClasses = [];
$this->translator = $translator;
$this->abstractClassResolver = $abstractClassResolver;
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();

usort(
@@ -286,16 +295,30 @@ protected function autoConfigureOne(
$name = $prefix . '_' . $propertyConfigurationModel->getName();
$request->attributes->set($name, $value);

if ($propertyConfigurationModel->getType() === null) {
$type_ = $propertyConfigurationModel->getType();

if ($type_ === null) {
return $paramConfiguration;
}

if (\class_exists($type_)) {
$reflectionClass = new \ReflectionClass($type_);

if ($reflectionClass->isAbstract()) {
$resolvedClass = $this->abstractClassResolver->getClassFor($type_, $request, $value);

if ($resolvedClass !== null) {
$type_ = $resolvedClass;
}
}
}

$config = new ParamConverter([]);
$config->setName($name);
$config->setClass($propertyConfigurationModel->getType());
$config->setClass($type_);
$config->setIsOptional(true);

if (!\in_array($propertyConfigurationModel->getType(), $this->bypassParamConverterExceptionClasses, true)) {
if (!\in_array($type_, $this->bypassParamConverterExceptionClasses, true)) {
$config->setIsOptional($propertyConfigurationModel->isOptional());
}

22 changes: 22 additions & 0 deletions Resolver/AbstractClassResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php declare(strict_types=1);

namespace Chaplean\Bundle\DtoHandlerBundle\Resolver;

use Symfony\Component\HttpFoundation\Request;

class AbstractClassResolver
{
/** @var AbstractClassResolverInterface[] */
public $resolvers = [];

public function getClassFor(string $abstractClass, Request $request, $value): ?string
{
foreach ($this->resolvers as $resolver) {
if ($resolver->supports($abstractClass)) {
return $resolver->getClass($request, $value);
}
}

return null;
}
}
14 changes: 14 additions & 0 deletions Resolver/AbstractClassResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types=1);

namespace Chaplean\Bundle\DtoHandlerBundle\Resolver;

use Symfony\Component\HttpFoundation\Request;

interface AbstractClassResolverInterface
{
public function getClass(Request $request, $value): string;

public function supports(string $abstractClass): bool;

public static function getPriority(): int;
}
3 changes: 3 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
@@ -16,12 +16,15 @@
<argument key="$httpValidationGroups">%chaplean_dto_handler.http_code_validation_groups%</argument>
<argument key="$paramConverterManager" type="service" id="sensio_framework_extra.converter.manager" />
<argument key="$translator" type="service" id="translator" />
<argument key="$abstractClassResolver" type="service" id="Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolver" />
<argument key="$validator" type="service" id="validator" />
<tag name="request.param_converter" converter="data_transfer_object_converter" />
</service>

<service id="Chaplean\Bundle\DtoHandlerBundle\Validator\Constraints\UniqueEntityDataValidator" />

<service id="Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolver" />

<!-- Serializer -->
<service id="Chaplean\Bundle\DtoHandlerBundle\Serializer\DataTransferObjectDenormalizer">
<argument key="$paramConverterManager" type="service" id="sensio_framework_extra.converter.manager" />
8 changes: 8 additions & 0 deletions Tests/ParamConverter/DataTransferObjectParamConverterTest.php
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

use Chaplean\Bundle\DtoHandlerBundle\Exception\DataTransferObjectValidationException;
use Chaplean\Bundle\DtoHandlerBundle\ParamConverter\DataTransferObjectParamConverter;
use Chaplean\Bundle\DtoHandlerBundle\Resolver\AbstractClassResolver;
use Doctrine\Common\Annotations\AnnotationException;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use Mockery\MockInterface;
@@ -59,6 +60,11 @@ class DataTransferObjectParamConverterTest extends MockeryTestCase
*/
private $validator;

/**
* @var AbstractClassResolver|MockInterface
*/
private $abstractClassResolver;

/**
* @return void
*/
@@ -69,6 +75,7 @@ public function setUp(): void
$this->manager = \Mockery::mock(ParamConverterManager::class);
$this->translator = \Mockery::mock(TranslatorInterface::class);
$this->validator = \Mockery::mock(ValidatorInterface::class);
$this->abstractClassResolver = \Mockery::mock(AbstractClassResolver::class);

PHPMockery::mock('Chaplean\Bundle\DtoHandlerBundle\ParamConverter', 'uniqid')->andReturn('hash');

@@ -80,6 +87,7 @@ public function setUp(): void
],
$this->manager,
$this->translator,
$this->abstractClassResolver,
$this->validator
);
}