Skip to content

Instantly share code, notes, and snippets.

@RafaelKa
Last active December 11, 2015 13:58
Show Gist options
  • Save RafaelKa/4610495 to your computer and use it in GitHub Desktop.
Save RafaelKa/4610495 to your computer and use it in GitHub Desktop.
<?php
namespace TYPO3\Flow\Validation\Validator;
/* *
* This script belongs to the TYPO3 Flow framework. *
* *
* It is free software; you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License, either version 3 *
* of the License, or (at your option) any later version. *
* *
* The TYPO3 project - inspiring people to share! *
* */
use TYPO3\Flow\Annotations as Flow,
TYPO3\Flow\Reflection\ObjectAccess,
TYPO3\Flow\Validation\Exception\InvalidValidationOptionsException;
/**
* Validator for uniqueness of entities.
*
* @api
*/
class UniqueEntityValidator extends AbstractValidator {
/**
* @Flow\Inject
* @var \TYPO3\Flow\Reflection\ReflectionService
*/
protected $reflectionService;
/**
* @Flow\Inject
* @var \TYPO3\Flow\Persistence\PersistenceManagerInterface
*/
protected $persistenceManager;
/**
* @var array
*/
protected $supportedOptions = array(
'properties' => array(NULL, 'name of the unique property or comma separated list for all names of compound properties', 'string')
);
/**
* Checks if the given property ($object) is a unique entity depending on it's identity properties.
*
* @param object $object The object that should be validated
* @return void
* @throws \TYPO3\Flow\Validation\Exception\InvalidValidationOptionsException
* @api
*/
protected function isValid($object) {
$classSchema = $this->reflectionService->getClassSchema($object);
if ($classSchema->getModelType() !== \TYPO3\Flow\Reflection\ClassSchema::MODELTYPE_ENTITY) {
throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must be an entity.', 1358454270);
}
if (!empty($this->options['properties'])) {
$customIdentityProperties = split(',', $this->options['properties']);
foreach ($customIdentityProperties as $key => $customIdentityProperty) {
$customIdentityProperties[$key] = trim($customIdentityProperty);
if (!$classSchema->hasProperty(trim($customIdentityProperty))) {
throw new \TYPO3\Flow\Validation\Exception\InvalidValidationOptionsException('Given for UniqueEntity validator property "' . $customIdentityProperty . '" does not exists in "' . $classSchema->getClassName() . '".', 1358960500);
}
}
$identityProperties = $customIdentityProperties;
} else {
$identityProperties = $classSchema->getIdentityProperties();
}
if (count($identityProperties) === 0) {
throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must have at least one identity property.', 1358459831);
}
$identifierProperties = $this->reflectionService->getPropertyNamesByAnnotation($classSchema->getClassName(), 'Doctrine\ORM\Mapping\Id');
if (count($identifierProperties) > 1) {
throw new InvalidValidationOptionsException('The object supplied for the UniqueEntityValidator must only have one identifier property @ORM\Id.', 1358501745);
}
$identifierPropertyName = count($identifierProperties) > 0 ? array_shift($identifierProperties) : 'Persistence_Object_Identifier';
$query = $this->persistenceManager->createQueryForType($classSchema->getClassName());
$constraints = array($query->logicalNot($query->equals($identifierPropertyName, $this->persistenceManager->getIdentifierByObject($object))));
foreach ($identityProperties as $propertyName => $propertyType) {
$constraints[] = $query->equals($propertyName, ObjectAccess::getProperty($object, $propertyName));
}
if ($query->matching($query->logicalAnd($constraints))->count() > 0) {
$this->addError('Another entity with the same unique identifiers already exists', 1355785874);
}
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment