Skip to content

Commit

Permalink
Merge pull request #1 from SBSEDV/message-resolver
Browse files Browse the repository at this point in the history
Message resolver
  • Loading branch information
danielburger1337 authored Jul 9, 2023
2 parents 3007b8b + e0ae3cc commit 59d04a9
Show file tree
Hide file tree
Showing 17 changed files with 128 additions and 19 deletions.
6 changes: 6 additions & 0 deletions config/definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
->booleanNode('property_path')->defaultTrue()->end()
->end()
->end()
->arrayNode('message_resolver')
->addDefaultsIfNotSet()
->children()
->booleanNode('doctrine_type')->defaultTrue()->end()
->end()
->end()
->end()
->end()
;
Expand Down
19 changes: 19 additions & 0 deletions config/services/message_resolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types=1);

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use SBSEDV\Bundle\FormBundle\MessageResolver\ChainMessageResolver;
use SBSEDV\Bundle\FormBundle\MessageResolver\DoctrineTypeMessageResolver;
use SBSEDV\Bundle\FormBundle\MessageResolver\MessageResolverInterface;

return function (ContainerConfigurator $container): void {
$container->services()
->set(ChainMessageResolver::class)
->arg('$messageResolvers', tagged_iterator('sbsedv_form.message_resolver'))

->alias(MessageResolverInterface::class, ChainMessageResolver::class)

->set(DoctrineTypeMessageResolver::class)
->tag('sbsedv_form.message_resolver', ['priority' => -100])
;
};
2 changes: 2 additions & 0 deletions config/services/normalizers.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use SBSEDV\Bundle\FormBundle\CauseResolver\CauseResolverInterface;
use SBSEDV\Bundle\FormBundle\MessageResolver\MessageResolverInterface;
use SBSEDV\Bundle\FormBundle\ParamResolver\ParamResolverInterface;
use SBSEDV\Bundle\FormBundle\Serializer\Normalizer\FormErrorNormalizer;
use SBSEDV\Bundle\FormBundle\Serializer\Normalizer\UnsubmittedFormNormalizer;
Expand All @@ -20,6 +21,7 @@
->args([
'$causeResolver' => service(CauseResolverInterface::class),
'$paramResolver' => service(ParamResolverInterface::class),
'$messageResolver' => service(MessageResolverInterface::class),
])
->tag('serializer.normalizer', ['priority' => 0])
;
Expand Down
2 changes: 1 addition & 1 deletion src/CauseResolver/ChainCauseResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ChainCauseResolver implements CauseResolverInterface
* @param iterable<CauseResolverInterface> $causeResolvers
*/
public function __construct(
private iterable $causeResolvers
private readonly iterable $causeResolvers
) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
class BooleanTypeToBooleanDataTransformer implements DataTransformerInterface
{
public function __construct(
private array $trueValues,
private array $falseValues,
private ?bool $default = null
private readonly array $trueValues,
private readonly array $falseValues,
private readonly ?bool $default = null
) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class CapitalizeStringDataTransformer implements DataTransformerInterface
{
public function __construct(
private ?string $encoding = null
private readonly ?string $encoding = null
) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class UppercaseStringDataTransformer implements DataTransformerInterface
{
public function __construct(
private ?string $encoding = null
private readonly ?string $encoding = null
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/Form/DataTransformer/UuidToStringDataTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class UuidToStringDataTransformer implements DataTransformerInterface
protected const NIL = '00000000-0000-0000-0000-000000000000';

public function __construct(
private bool $convertNilToNull = false
private readonly bool $convertNilToNull = false
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/Form/FormProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class FormProcessor implements FormProcessorInterface
{
private PropertyAccessorInterface $propertyAccessor;
private readonly PropertyAccessorInterface $propertyAccessor;

public function __construct(?PropertyAccessorInterface $propertyAccessor)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Form/Type/BooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class BooleanType extends AbstractType
{
public function __construct(
private TranslatorInterface $translator
readonly TranslatorInterface $translator
) {
}

Expand Down
29 changes: 29 additions & 0 deletions src/MessageResolver/ChainMessageResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);

namespace SBSEDV\Bundle\FormBundle\MessageResolver;

use Symfony\Component\Form\FormError;

class ChainMessageResolver implements MessageResolverInterface
{
/**
* @param iterable<MessageResolverInterface> $messageResolvers
*/
public function __construct(
private readonly iterable $messageResolvers
) {
}

public function resolveMessage(FormError $formError): ?string
{
foreach ($this->messageResolvers as $messageResolver) {
$msg = $messageResolver->resolveMessage($formError);

if (null !== $msg) {
return $msg;
}
}

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

namespace SBSEDV\Bundle\FormBundle\MessageResolver;

use Symfony\Bridge\Doctrine\Form\Type\DoctrineType;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\FormError;

class DoctrineTypeMessageResolver implements MessageResolverInterface
{
public function resolveMessage(FormError $formError): ?string
{
$type = $formError->getOrigin()?->getConfig()->getType()->getInnerType();
$cause = $formError->getCause();

// Incase the "multiple" option is used and an invalid id is supplied
if (!$type instanceof DoctrineType || !$cause instanceof TransformationFailedException || !\str_starts_with($cause->getMessage(), 'The choices "')) {
return null;
}

// Currently this will always be NULL, someday symfony will maybe add translations for that error
if (null !== $cause->getInvalidMessage()) {
return \strtr($cause->getInvalidMessage(), $cause->getInvalidMessageParameters());
}

return $cause->getMessage();
}
}
17 changes: 17 additions & 0 deletions src/MessageResolver/MessageResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);

namespace SBSEDV\Bundle\FormBundle\MessageResolver;

use Symfony\Component\Form\FormError;

interface MessageResolverInterface
{
/**
* Resolve an error message.
*
* @param FormError $formError The FormError object to resolve from.
*
* @return string|null The error message or null if not supported.
*/
public function resolveMessage(FormError $formError): ?string;
}
2 changes: 1 addition & 1 deletion src/ParamResolver/ChainParamResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ChainParamResolver implements ParamResolverInterface
* @param iterable<ParamResolverInterface> $paramResolvers
*/
public function __construct(
private iterable $paramResolvers
private readonly iterable $paramResolvers
) {
}

Expand Down
9 changes: 9 additions & 0 deletions src/SBSEDVFormBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ public function loadExtension(array $config, ContainerConfigurator $container, C
$container->import('../config/services/cause_resolver.php');
$container->import('../config/services/form_types.php');
$container->import('../config/services/form_processor.php');
$container->import('../config/services/message_resolver.php');
$container->import('../config/services/normalizers.php');
$container->import('../config/services/param_resolver.php');

$builder
->registerForAutoconfiguration(MessageResolver\MessageResolverInterface::class)
->addTag('sbsedv_form.message_resolver')
;
if (!$config['message_resolver']['doctrine_type']) {
$container->services()->remove(MessageResolver\DoctrineTypeMessageResolver::class);
}

$builder
->registerForAutoconfiguration(CauseResolver\CauseResolverInterface::class)
->addTag('sbsedv_form.cause_resolver')
Expand Down
12 changes: 6 additions & 6 deletions src/Serializer/Normalizer/FormErrorNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
namespace SBSEDV\Bundle\FormBundle\Serializer\Normalizer;

use SBSEDV\Bundle\FormBundle\CauseResolver\CauseResolverInterface;
use SBSEDV\Bundle\FormBundle\MessageResolver\MessageResolverInterface;
use SBSEDV\Bundle\FormBundle\ParamResolver\ParamResolverInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;

class FormErrorNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
class FormErrorNormalizer implements NormalizerInterface
{
/** The value will be used as the normalized "message" key (e.g. "msg"). */
public const CONTEXT_MESSAGE_KEY = 'form_error.message_key';
Expand All @@ -19,13 +19,13 @@ class FormErrorNormalizer implements NormalizerInterface, CacheableSupportsMetho
public const CONTEXT_CAUSE_KEY = 'form_error.cause_key';
/** The value will be used as the normalized "type" key */
public const CONTEXT_TYPE_KEY = 'form_error.type_key';

/** The value that will appear under the "type" key. */
public const CONTEXT_ERROR_TYPE = 'form_error.type';

public function __construct(
private CauseResolverInterface $causeResolver,
private ParamResolverInterface $paramResolver
private readonly CauseResolverInterface $causeResolver,
private readonly ParamResolverInterface $paramResolver,
private readonly MessageResolverInterface $messageResolver
) {
}

Expand Down Expand Up @@ -53,7 +53,7 @@ public function normalize(mixed $object, string $format = null, array $context =
}

$error = [
$messageKey => $formError->getMessage(),
$messageKey => $this->messageResolver->resolveMessage($formError) ?? $formError->getMessage(),
$typeKey => $errorType,
];

Expand Down
5 changes: 2 additions & 3 deletions src/Serializer/Normalizer/UnsubmittedFormNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
namespace SBSEDV\Bundle\FormBundle\Serializer\Normalizer;

use Symfony\Component\Form\FormInterface;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

class UnsubmittedFormNormalizer implements NormalizerInterface, CacheableSupportsMethodInterface
class UnsubmittedFormNormalizer implements NormalizerInterface
{
/** The value will be used as the normalized "message" key (e.g. "msg"). */
public const CONTEXT_MESSAGE_KEY = 'form_error.message_key';
Expand All @@ -16,7 +15,7 @@ class UnsubmittedFormNormalizer implements NormalizerInterface, CacheableSupport
public const CONTEXT_ERROR_TYPE = 'form_error.type';

public function __construct(
private TranslatorInterface $translator
private readonly TranslatorInterface $translator
) {
}

Expand Down

0 comments on commit 59d04a9

Please sign in to comment.