Fixes #4049 -- Prevent creating duplicate storage locations.
This commit is contained in:
parent
f59fd8a9ba
commit
6bdcbf2a1c
|
@ -31,7 +31,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
* @AuditLog\Auditable
|
||||
* @AppAssert\StorageLocation()
|
||||
*/
|
||||
class StorageLocation
|
||||
class StorageLocation implements \Stringable
|
||||
{
|
||||
use Traits\TruncateStrings;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue