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

Commit

Permalink
Merge pull request #15 from NicolasGuilloux/fix-param-converter-errors
Browse files Browse the repository at this point in the history
Handles the exception made by the manager
  • Loading branch information
NicolasGuilloux committed Nov 13, 2019
2 parents ee718c7 + 9370c13 commit 195a3f9
Show file tree
Hide file tree
Showing 17 changed files with 681 additions and 399 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -19,3 +19,4 @@
# PHPUnit
/phpunit-filter.php
/coverage
/.phpunit.result.cache
7 changes: 4 additions & 3 deletions .travis.yml
@@ -1,5 +1,4 @@
language: php
sudo: required
services:
- docker

Expand All @@ -10,11 +9,13 @@ branches:
- master

before_script:
- docker-compose up --build -d
- chmod 777 -R ./
- docker-compose up -d
- docker-compose exec application composer install --prefer-dist --no-interaction

script:
- docker-compose exec application phpdbg -qrr ./phpunit --configuration phpunit.xml.dist --colors=never --coverage-clover build/logs/clover.xml
- docker-compose exec application php -d zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so ./phpunit --configuration phpunit.xml.dist --dump-xdebug-filter phpunit-filter.php
- docker-compose exec application php -d zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so ./phpunit --prepend phpunit-filter.php --configuration phpunit.xml.dist --colors=never --coverage-clover build/logs/clover.xml

after_success:
- travis_retry docker-compose run --rm -e TRAVIS="TRAVIS" -e TRAVIS_JOB_ID="$TRAVIS_JOB_ID" -e TRAVIS_BRANCH="$TRAVIS_BRANCH" application php vendor/bin/php-coveralls -v
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog

## 2.2.2

Bug fix:
* Handles the exception returned by the manager during the conversion, and transforms it into violations.

## 2.2.1

Bug fix:
Expand Down
8 changes: 0 additions & 8 deletions Dockerfile

This file was deleted.

73 changes: 71 additions & 2 deletions ParamConverter/DataTransferObjectParamConverter.php
Expand Up @@ -20,10 +20,14 @@
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validator\ValidatorInterface;

Expand Down Expand Up @@ -61,6 +65,11 @@ class DataTransferObjectParamConverter implements ParamConverterInterface
*/
protected $taggedDtoClasses;

/**
* @var TranslatorInterface
*/
protected $translator;

/**
* @var ValidatorInterface
*/
Expand All @@ -72,18 +81,21 @@ class DataTransferObjectParamConverter implements ParamConverterInterface
* @param array $bypassParamConverterExceptionClasses
* @param array $httpValidationGroups
* @param ParamConverterManager $paramConverterManager
* @param TranslatorInterface $translator
* @param ValidatorInterface|null $validator
*/
public function __construct(
array $bypassParamConverterExceptionClasses,
array $httpValidationGroups,
ParamConverterManager $paramConverterManager,
TranslatorInterface $translator,
ValidatorInterface $validator = null
) {
$this->bypassParamConverterExceptionClasses = $bypassParamConverterExceptionClasses;
$this->manager = $paramConverterManager;
$this->validator = $validator;
$this->taggedDtoClasses = [];
$this->translator = $translator;
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();

usort(
Expand Down Expand Up @@ -121,8 +133,8 @@ public function apply(Request $request, ParamConverter $configuration): bool
{
$options = (array) $configuration->getOptions();
$reflectionClass = new \ReflectionClass($configuration->getClass());

$uuid = \uniqid('', false);

// Null when the processed DTO is at the top level in case of nested DTO
$actualDtoName = $request->attributes->get($configuration->getName())
? $configuration->getName()
Expand All @@ -141,7 +153,7 @@ public function apply(Request $request, ParamConverter $configuration): bool
$this->validate($object, $request, $preValidationOptions);
}

$this->manager->apply($request, $config);
$this->applyParamConverters($request, $config);

$object = $this->buildObject($request, $configuration, $uuid);
$request->attributes->set($configuration->getName(), $object);
Expand Down Expand Up @@ -308,6 +320,63 @@ protected function autoConfigureOne(
return $paramConfiguration;
}

/**
* @param Request $request
* @param array $configurations
*
* @return void
*/
protected function applyParamConverters(Request $request, array $configurations): void
{
$errors = new ConstraintViolationList();

/** @var ParamConverter $paramConverterConfiguration */
foreach ($configurations as $paramConverterConfiguration) {
try {
$this->manager->apply($request, $paramConverterConfiguration);
} catch (DataTransferObjectValidationException $e) {
$errors->addAll($e->getViolations());
} catch (\Exception $e) {
$errors->add($this->getViolationFromException($request, $e, $paramConverterConfiguration));
}
}

if ($errors->count() !== 0) {
throw new DataTransferObjectValidationException($errors, Response::HTTP_BAD_REQUEST);
}
}

/**
* @param Request $request
* @param \Exception $exception
* @param ParamConverter $paramConverter
*
* @return ConstraintViolation
*/
protected function getViolationFromException(Request $request, \Exception $exception, ParamConverter $paramConverter): ConstraintViolation
{
$name = $paramConverter->getName();
$message = $exception->getMessage();
$value = $request->attributes->get($name);
$keyParts = \explode('_', $name);
$propertyName = \implode('_', \array_slice($keyParts, 2));

if ($exception instanceof NotFoundHttpException) {
$message = $this->translator->trans('dto_handler.entity_not_found', ['%value%' => $value]);
}

return new ConstraintViolation(
$message,
null,
[],
null,
$propertyName,
$value,
null,
$exception->getCode()
);
}

/**
* @param Request $request
* @param ParamConverter $configuration
Expand Down
1 change: 1 addition & 0 deletions Resources/config/services.xml
Expand Up @@ -15,6 +15,7 @@
<argument key="$bypassParamConverterExceptionClasses">%chaplean_dto_handler.bypass_param_converter_exception%</argument>
<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="$validator" type="service" id="validator" />
<tag name="request.param_converter" converter="data_transfer_object_converter" />
</service>
Expand Down
2 changes: 2 additions & 0 deletions Resources/translations/messages.en.yml
@@ -0,0 +1,2 @@
dto_handler:
entity_not_found: 'No entity can be found with the value "%value%".'
2 changes: 2 additions & 0 deletions Resources/translations/messages.fr.yml
@@ -0,0 +1,2 @@
dto_handler:
entity_not_found: 'Aucune entité ne peut être trouvée avec la valeur "%value%".'
Expand Up @@ -30,7 +30,7 @@ class DataTransferObjectValidationExceptionSubscriberTest extends MockeryTestCas
/**
* @return void
*/
public function setUp()
public function setUp(): void
{
$this->dataTransferObjectValidationExceptionSubscriber = new DataTransferObjectValidationExceptionSubscriber();

Expand Down

0 comments on commit 195a3f9

Please sign in to comment.