Skip to content

Commit

Permalink
Allow specifying how a label should be supplied and read back on input (
Browse files Browse the repository at this point in the history
#8)

* Allow specifying how a label should be supplied and read back on input when using #[FromKey]

* Fix nelmio incompatibility

* Update method visibility

* Update tests
  • Loading branch information
pkly authored Feb 1, 2023
1 parent 342e0f1 commit d7b6a25
Show file tree
Hide file tree
Showing 36 changed files with 493 additions and 230 deletions.
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@
"symfony/stopwatch": "^5.4|^6.2",
"symfony/web-profiler-bundle": "^5.4|^6.2",
"doctrine/doctrine-bundle": "^2",
"doctrine/orm": "^2"
"doctrine/orm": "^2|^3"
},
"conflict": {
"nelmio/api-doc-bundle": "<4"
"nelmio/api-doc-bundle": "<4",
"doctrine/doctrine-bundle": "<2.4"
},
"autoload": {
"psr-4": {
Expand All @@ -56,9 +57,8 @@
"test": "phpunit"
},
"suggest": {
"nelmio/api-doc-bundle": "^4",
"doctrine/doctrine-bundle": "^2",
"doctrine/orm": "^2"
"nelmio/api-doc-bundle": "Adds api docs for endpoints for your DTOs",
"doctrine/doctrine-bundle": "Symfony's ORM of choice"
},
"extra": {
"symfony": {
Expand Down
16 changes: 16 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use DualMedia\DtoRequestBundle\EventSubscriber\HttpDtoActionSubscriber;
use DualMedia\DtoRequestBundle\Interfaces\Dynamic\ResolverServiceInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\ComplexLoaderServiceInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\LabelProcessorServiceInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\ProviderServiceInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\TargetProviderInterface;
use DualMedia\DtoRequestBundle\Interfaces\Resolver\DtoResolverInterface;
Expand All @@ -15,6 +16,9 @@
use DualMedia\DtoRequestBundle\Interfaces\Validation\TypeValidationInterface;
use DualMedia\DtoRequestBundle\Service\Entity\ComplexLoaderService;
use DualMedia\DtoRequestBundle\Service\Entity\EntityProviderService;
use DualMedia\DtoRequestBundle\Service\Entity\LabelProcessor\DefaultProcessor;
use DualMedia\DtoRequestBundle\Service\Entity\LabelProcessor\PascalCaseProcessor;
use DualMedia\DtoRequestBundle\Service\Entity\LabelProcessorService;
use DualMedia\DtoRequestBundle\Service\Entity\TargetProviderService;
use DualMedia\DtoRequestBundle\Service\Http\ActionValidatorService;
use DualMedia\DtoRequestBundle\Service\Http\OnNullActionValidator;
Expand Down Expand Up @@ -77,6 +81,7 @@

$services->set(EnumCoercer::class)
->arg(0, new Reference('validator'))
->arg(1, new Reference(LabelProcessorServiceInterface::class))
->tag(Bundle::COERCER_TAG);

$services->set(DateTimeImmutableCoercer::class)
Expand All @@ -96,6 +101,16 @@
$services->set(DynamicResolverService::class)
->arg(0, new TaggedIteratorArgument(Bundle::DYNAMIC_RESOLVER_TAG));

$services->alias(LabelProcessorServiceInterface::class, LabelProcessorService::class);
$services->set(LabelProcessorService::class)
->arg(0, []);

$services->set(DefaultProcessor::class)
->tag(Bundle::LABEL_PROCESSOR_TAB);

$services->set(PascalCaseProcessor::class)
->tag(Bundle::LABEL_PROCESSOR_TAB);

$services->alias(ComplexLoaderServiceInterface::class, ComplexLoaderService::class);
$services->set(ComplexLoaderService::class)
->arg(0, [])
Expand Down Expand Up @@ -129,6 +144,7 @@

$services->set(DtoOADescriber::class)
->arg(0, new Reference(DtoTypeExtractorInterface::class))
->arg(1, new Reference(LabelProcessorServiceInterface::class))
->tag('nelmio_api_doc.route_describer');

// Subscribers
Expand Down
9 changes: 9 additions & 0 deletions src/Attributes/Dto/FromKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@
namespace DualMedia\DtoRequestBundle\Attributes\Dto;

use DualMedia\DtoRequestBundle\Interfaces\Attribute\DtoAttributeInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\LabelProcessorInterface;
use DualMedia\DtoRequestBundle\Service\Entity\LabelProcessor\DefaultProcessor;

/**
* This class should be put on enums when you want the enum to be created by looking at the const (key) name, not the value
*/
#[\Attribute(\Attribute::TARGET_PROPERTY)]
class FromKey implements DtoAttributeInterface
{
/**
* @param class-string<LabelProcessorInterface>|string $normalizer service id for normalizer
*/
public function __construct(
public readonly string $normalizer = DefaultProcessor::class
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace DualMedia\DtoRequestBundle\DependencyInjection\Entity\CompilerPass;

use DualMedia\DtoRequestBundle\DtoBundle;
use DualMedia\DtoRequestBundle\Service\Entity\LabelProcessorService;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class LabelProcessorCompilerPass implements CompilerPassInterface
{
public function process(
ContainerBuilder $container
): void {
// @codeCoverageIgnoreStart
if (!$container->hasDefinition(LabelProcessorService::class)) {
return;
}
// @codeCoverageIgnoreEnd

$args = [];

foreach ($container->findTaggedServiceIds(DtoBundle::LABEL_PROCESSOR_TAB) as $id => $tags) {
$args[$id] = new Reference($id);
}

$container->getDefinition(LabelProcessorService::class)->setArgument(0, $args);
}
}
8 changes: 8 additions & 0 deletions src/DtoBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

use DualMedia\DtoRequestBundle\DependencyInjection\Entity\CompilerPass\ComplexLoaderCompilerPass;
use DualMedia\DtoRequestBundle\DependencyInjection\Entity\CompilerPass\DoctrineRepositoryCompilerPass;
use DualMedia\DtoRequestBundle\DependencyInjection\Entity\CompilerPass\LabelProcessorCompilerPass;
use DualMedia\DtoRequestBundle\DependencyInjection\Entity\CompilerPass\ProviderServiceCompilerPass;
use DualMedia\DtoRequestBundle\DependencyInjection\Shared\CompilerPass\RemoveSpecificTagCompilerPass;
use DualMedia\DtoRequestBundle\DependencyInjection\Shared\TaggingExtension;
use DualMedia\DtoRequestBundle\DependencyInjection\Validation\CompilerPass\ValidationGroupAddingCompilerPass;
use DualMedia\DtoRequestBundle\Interfaces\Dynamic\ResolverInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\ComplexLoaderInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\LabelProcessorInterface;
use DualMedia\DtoRequestBundle\Interfaces\Entity\ProviderInterface;
use DualMedia\DtoRequestBundle\Interfaces\Http\ActionValidatorInterface;
use DualMedia\DtoRequestBundle\Interfaces\Type\CoercerInterface;
Expand All @@ -33,6 +35,8 @@ class DtoBundle extends Bundle
public const COMPLEX_LOADER_TAG = 'dto_bundle.complex_loader';
public const GROUP_PROVIDER_TAG = 'dto_bundle.validation_group_provider';

public const LABEL_PROCESSOR_TAB = 'dto_bundle.label_processor';

public function build(
ContainerBuilder $container
): void {
Expand All @@ -43,6 +47,7 @@ public function build(
ResolverInterface::class => self::DYNAMIC_RESOLVER_TAG,
ComplexLoaderInterface::class => self::COMPLEX_LOADER_TAG,
ActionValidatorInterface::class => self::HTTP_ACTION_VALIDATOR_TAG,
LabelProcessorInterface::class => self::LABEL_PROCESSOR_TAB,
]));

// Doctrine autoconfigure
Expand Down Expand Up @@ -74,5 +79,8 @@ public function build(

// complex loaders
$container->addCompilerPass(new ComplexLoaderCompilerPass());

// label processors
$container->addCompilerPass(new LabelProcessorCompilerPass());
}
}
10 changes: 10 additions & 0 deletions src/Exception/Entity/LabelProcessorNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace DualMedia\DtoRequestBundle\Exception\Entity;

/**
* Thrown when a label processor cannot be found for the specified service id
*/
class LabelProcessorNotFoundException extends \RuntimeException
{
}
28 changes: 28 additions & 0 deletions src/Interfaces/Entity/LabelProcessorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace DualMedia\DtoRequestBundle\Interfaces\Entity;

interface LabelProcessorInterface
{
/**
* Turns the label into a possible result key
*
* @param string $value
*
* @return string
*/
public function normalize(
string $value
): string;

/**
* Turns the possible result key into a label
*
* @param string $value
*
* @return string
*/
public function denormalize(
string $value
): string;
}
14 changes: 14 additions & 0 deletions src/Interfaces/Entity/LabelProcessorServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace DualMedia\DtoRequestBundle\Interfaces\Entity;

interface LabelProcessorServiceInterface
{
/**
* @param string $service
* @return LabelProcessorInterface
*/
public function getProcessor(
string $service
): LabelProcessorInterface;
}
Loading

0 comments on commit d7b6a25

Please sign in to comment.