Fixes #4049 -- Prevent creating duplicate storage locations.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-05-06 15:13:28 -05:00
parent f59fd8a9ba
commit 6bdcbf2a1c
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
2 changed files with 45 additions and 7 deletions

View File

@ -31,7 +31,7 @@ use Symfony\Component\Validator\Constraints as Assert;
* @AuditLog\Auditable
* @AppAssert\StorageLocation()
*/
class StorageLocation
class StorageLocation implements \Stringable
{
use Traits\TruncateStrings;

View File

@ -4,6 +4,7 @@ namespace App\Validator\Constraints;
use App\Entity;
use App\Radio\Configuration;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
@ -11,11 +12,10 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
class StorageLocationValidator extends ConstraintValidator
{
protected Configuration $configuration;
public function __construct(Configuration $configuration)
{
$this->configuration = $configuration;
public function __construct(
protected Configuration $configuration,
protected EntityManagerInterface $em,
) {
}
public function validate($storageLocation, Constraint $constraint): void
@ -28,14 +28,52 @@ class StorageLocationValidator extends ConstraintValidator
throw new UnexpectedTypeException($storageLocation, Entity\StorageLocation::class);
}
// Ensure this storage location validates.
try {
$storageLocation->validate();
} catch (Exception $e) {
$message = __('This storage location could not be validated: %s', '{{ error }}');
$message = __(
'Storage location %s could not be validated: %s',
'{{ storageLocation }}',
'{{ error }}'
);
$this->context->buildViolation($message)
->setParameter('{{ storageLocation }}', (string)$storageLocation)
->setParameter('{{ error }}', $e->getMessage())
->addViolation();
}
// Ensure it's not a duplicate of other storage locations.
$qb = $this->em->createQueryBuilder()
->select('sl')
->from(Entity\StorageLocation::class, 'sl')
->where('sl.type = :type')
->setParameter('type', $storageLocation->getType())
->andWhere('sl.adapter = :adapter')
->setParameter('adapter', $storageLocation->getAdapter());
if (null !== $storageLocation->getId()) {
$qb->andWhere('sl.id != :id')
->setParameter('id', $storageLocation->getId());
}
$storageLocationUri = $storageLocation->getUri();
/** @var Entity\StorageLocation $row */
foreach ($qb->getQuery()->toIterable() as $row) {
if ($row->getUri() === $storageLocationUri) {
$message = __(
'Storage location %s already exists.',
'{{ storageLocation }}',
);
$this->context->buildViolation($message)
->setParameter('{{ storageLocation }}', (string)$storageLocation)
->addViolation();
break;
}
}
}
}