Skip to content
Permalink
Browse files

Merge pull request #82 from tarlepp/feat/entity-reference-exists

feat/entity-reference-exists
  • Loading branch information...
tarlepp committed Jul 1, 2019
2 parents 28e3da1 + 086a0fd commit 9add2c983805a3e16e88b07e6136cd1056d10651
@@ -14,6 +14,7 @@
use App\Entity\EntityInterface;
use App\Entity\UserGroup as UserGroupEntity;
use App\Entity\UserGroupAwareInterface;
use App\Validator\Constraints as AppAssert;
use Symfony\Component\Validator\Constraints as Assert;
use function array_map;
@@ -51,6 +52,8 @@ class ApiKey extends RestDto
/**
* @var UserGroupEntity[]
*
* @AppAssert\EntityReferenceExists()
*/
protected $userGroups = [];
@@ -19,7 +19,6 @@
*/
trait PatchUserGroups
{
/** @noinspection PhpMissingParentCallCommonInspection */
/**
* Method to patch entity user groups.
*
@@ -79,6 +79,8 @@ class User extends RestDto
/**
* @var UserGroupEntity[]
*
* @AppAssert\EntityReferenceExists()
*/
protected $userGroups = [];
@@ -13,6 +13,7 @@
use App\Entity\EntityInterface;
use App\Entity\Role as RoleEntity;
use App\Entity\UserGroup as Entity;
use App\Validator\Constraints as AppAssert;
use Symfony\Component\Validator\Constraints as Assert;
/**
@@ -38,6 +39,8 @@ class UserGroup extends RestDto
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
/**
* @var \App\Entity\Role
*
* @AppAssert\EntityReferenceExists()
*/
protected $role;
@@ -86,7 +86,7 @@ public function getId(): string
*/
public function getTimestamp(): DateTime
{
return $this->timestamp;
return $this->getCreatedAt();
}
/**
@@ -104,9 +104,9 @@ public function setTimestamp(DateTime $timestamp): self
/**
* Returns createdAt.
*
* @return DateTime|null
* @return DateTime
*/
public function getCreatedAt(): ?DateTime
public function getCreatedAt(): DateTime
{
return $this->timestamp;
}
@@ -123,16 +123,16 @@ public function getUser(): User
*/
public function getTimestamp(): DateTime
{
return $this->timestamp;
return $this->getCreatedAt();
}
/**
* Returns createdAt.
*
* @return DateTime|null
* @return DateTime
*/
public function getCreatedAt(): ?DateTime
public function getCreatedAt(): DateTime
{
return $this->getTimestamp();
return $this->timestamp;
}
}
@@ -0,0 +1,61 @@
<?php
declare(strict_types = 1);
/**
* /src/Validator/Constraints/EntityReferenceExists.php
*
* @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
*/
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Class EntityReferenceExists
*
* @Annotation
* @Target({"PROPERTY"})
*
* @package App\Validator\Constraints
* @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
*/
class EntityReferenceExists extends Constraint
{
/**
* Unique constant for validator constrain
*/
public const ENTITY_REFERENCE_EXISTS_ERROR = '64888b5e-bded-449b-82ed-0cc1f73df14d';
/**
* Message for validation error
*/
public const MESSAGE_SINGLE = 'Invalid id value "{{ id }}" given for entity "{{ entity }}".';
/**
* Message for validation error
*/
public const MESSAGE_MULTIPLE = 'Invalid id values "{{ id }}" given for entity "{{ entity }}".';
/**
* Error names configuration
*
* @var mixed[]
*/
protected static $errorNames = [
self::ENTITY_REFERENCE_EXISTS_ERROR => 'ENTITY_REFERENCE_EXISTS_ERROR',
];
/** @noinspection PhpMissingParentCallCommonInspection */
/**
* Returns whether the constraint can be put onto classes, properties or both.
*
* This method should return one or more of the constants
* Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
*
* @return string One or more constant values
*/
public function getTargets(): string
{
return self::PROPERTY_CONSTRAINT;
}
}
@@ -0,0 +1,131 @@
<?php
declare(strict_types = 1);
/**
* /src/App/Validator/Constraints/EntityReferenceExistsValidator.php
*
* @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
*/
namespace App\Validator\Constraints;
use App\Entity\EntityInterface;
use App\Helpers\LoggerAwareTrait;
use Closure;
use Doctrine\ORM\EntityNotFoundException;
use Doctrine\ORM\Proxy\Proxy;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use function array_filter;
use function array_map;
use function count;
use function get_class;
use function implode;
use function is_array;
use function str_replace;
/**
* Class EntityReferenceExistsValidator
*
* @package App\Validator\Constraints
* @author TLe, Tarmo Leppänen <tarmo.leppanen@protacon.com>
*/
class EntityReferenceExistsValidator extends ConstraintValidator
{
// Traits
use LoggerAwareTrait;
/**
* Checks if the passed value is valid.
*
* @param EntityInterface|mixed $value The value that should be validated
* @param Constraint|UniqueEmail $constraint The constraint for the validation
*/
public function validate($value, Constraint $constraint): void
{
if (!$constraint instanceof EntityReferenceExists) {
throw new UnexpectedTypeException($constraint, __NAMESPACE__ . '\EntityReferenceExists');
}
$this->check($this->normalize($value));
}
/**
* @param EntityInterface|mixed $input
*
* @return array
*/
private function normalize($input): array
{
$values = is_array($input) ? $input : [$input];
foreach ($values as $value) {
if (!$value instanceof Proxy) {
throw new UnexpectedValueException($value, Proxy::class);
}
if (!$value instanceof EntityInterface) {
throw new UnexpectedValueException($value, EntityInterface::class);
}
}
return $values;
}
/**
* @param array $entities
*/
private function check(array $entities): void
{
$invalidIds = $this->getInvalidValues($entities);
if (count($invalidIds) > 0) {
$message = count($invalidIds) === 1
? EntityReferenceExists::MESSAGE_SINGLE
: EntityReferenceExists::MESSAGE_MULTIPLE;
$entity = get_class($entities[0]);
$this->context
->buildViolation($message)
->setParameter('{{ entity }}', str_replace('Proxies\\__CG__\\', '', $entity))
->setParameter('{{ id }}', count($invalidIds) > 1 ? implode('", "', $invalidIds) : $invalidIds[0])
->setCode(EntityReferenceExists::ENTITY_REFERENCE_EXISTS_ERROR)
->addViolation();
}
}
/**
* @param array $entities
*
* @return array
*/
private function getInvalidValues(array $entities): array
{
$iterator = static function (EntityInterface $entity): string {
return $entity->getId();
};
return array_map($iterator, array_filter($entities, $this->getFilterClosure()));
}
/**
* @return Closure
*/
private function getFilterClosure(): Closure
{
return function (EntityInterface $entity): bool {
$output = false;
try {
$entity->getCreatedAt();
} catch (EntityNotFoundException $exception) {
$this->logger->error($exception->getMessage());
$output = true;
}
return $output;
};
}
}

0 comments on commit 9add2c9

Please sign in to comment.
You can’t perform that action at this time.