Skip to content

Instantly share code, notes, and snippets.

@tad3j
Created July 24, 2014 16:14
Show Gist options
  • Save tad3j/98a79898e3d1d2161527 to your computer and use it in GitHub Desktop.
Save tad3j/98a79898e3d1d2161527 to your computer and use it in GitHub Desktop.
Extending doctrine NoObjectExists and ObjectUnique to allow custom filtering by key/value pairs
<?php
namespace Application\Validator;
use DoctrineModule\Validator\NoObjectExists as NoObjectExistsValidator;
use Zend\Validator\Exception;
use Doctrine\Common\Persistence\ObjectRepository;
class CustomNoObjectExistsValidator extends NoObjectExistsValidator
{
private $keyValueFilter;
/**
* Constructor (copied from doctrine NoObjectExistsValidator)
*
* @param array $options required keys are `object_repository`, which must be an instance of
* @param array $keyValueFilter
* Doctrine\Common\Persistence\ObjectRepository, and `fields`, with either
* a string or an array of strings representing the fields to be matched by the validator.
* @throws \Zend\Validator\Exception\InvalidArgumentException
*/
public function __construct(array $options, $keyValueFilter = null)
{
//set user id before executing original doctrines code
$this->setKeyValueFilter($keyValueFilter);
//$this->setUserId($userId);
if (!isset($options['object_repository']) || !$options['object_repository'] instanceof ObjectRepository) {
if (!array_key_exists('object_repository', $options)) {
$provided = 'nothing';
} else {
if (is_object($options['object_repository'])) {
$provided = get_class($options['object_repository']);
} else {
$provided = getType($options['object_repository']);
}
}
throw new Exception\InvalidArgumentException(
sprintf(
'Option "object_repository" is required and must be an instance of'
. ' Doctrine\Common\Persistence\ObjectRepository, %s given',
$provided
)
);
}
$this->objectRepository = $options['object_repository'];
if (!isset($options['fields'])) {
throw new Exception\InvalidArgumentException(
'Key `fields` must be provided and be a field or a list of fields to be used when searching for'
. ' existing instances'
);
}
$this->fields = $options['fields'];
$this->validateFields();
parent::__construct($options);
}
/**
* {@inheritDoc}
*/
private function validateFields()
{
$fields = (array)$this->fields;
if (empty($fields)) {
throw new Exception\InvalidArgumentException('Provided fields list was empty!');
}
foreach ($fields as $key => $field) {
if (!is_string($field)) {
throw new Exception\InvalidArgumentException(
sprintf('Provided fields must be strings, %s provided for key %s', gettype($field), $key)
);
}
}
$this->fields = array_values($fields);
}
/**
* @param array $keyValueFilter
*/
public function setKeyValueFilter($keyValueFilter)
{
$this->keyValueFilter = $keyValueFilter;
}
/**
* @return array
*/
public function getKeyValueFilter()
{
return $this->keyValueFilter;
}
/**
* {@inheritDoc}
*/
public function isValid($value)
{
$value = $this->cleanSearchValue($value);
//$value['owner'] = $this->getUserId();
foreach ((array)$this->getKeyValueFilter() as $key => $tmpValue) {
$value[$key] = $tmpValue;
}
$match = $this->objectRepository->findOneBy($value);
if (is_object($match)) {
$this->error(self::ERROR_OBJECT_FOUND, $value);
return false;
}
return true;
}
}
<?php
namespace Application\Validator;
use DoctrineModule\Validator\UniqueObject as UniqueObjectValidator;
use Doctrine\Common\Persistence\ObjectManager;
use Zend\Validator\Exception;
class CustomUniqueObjectValidator extends UniqueObjectValidator
{
private $keyValueFilter;
/***
* Constructor (copied from doctrine UniqueObjectValidator)
*
* @param array $options required keys are `object_repository`, which must be an instance of
* @param array $keyValueFilter
* Doctrine\Common\Persistence\ObjectRepository, `object_manager`, which
* must be an instance of Doctrine\Common\Persistence\ObjectManager,
* and `fields`, with either a string or an array of strings representing
* the fields to be matched by the validator.
* @throws Exception\InvalidArgumentException
*/
public function __construct(array $options, $keyValueFilter = null)
{
parent::__construct($options);
//set user id before executing original doctrines code
//$this->setUserId($userId);
$this->setKeyValueFilter($keyValueFilter);
if (!isset($options['object_manager']) || !$options['object_manager'] instanceof ObjectManager) {
if (!array_key_exists('object_manager', $options)) {
$provided = 'nothing';
} else {
if (is_object($options['object_manager'])) {
$provided = get_class($options['object_manager']);
} else {
$provided = getType($options['object_manager']);
}
}
throw new Exception\InvalidArgumentException(
sprintf(
'Option "object_manager" is required and must be an instance of'
. ' Doctrine\Common\Persistence\ObjectManager, %s given',
$provided
)
);
}
$this->objectManager = $options['object_manager'];
}
/**
* @param array $keyValueFilter
*/
public function setKeyValueFilter($keyValueFilter)
{
$this->keyValueFilter = $keyValueFilter;
}
/**
* @return array
*/
public function getKeyValueFilter()
{
return $this->keyValueFilter;
}
/**
* Returns false if there is another object with the same field values but other identifiers.
*
* @param mixed $value
* @param array $context
* @return boolean
*/
public function isValid($value, $context = null)
{
$value = $this->cleanSearchValue($value);
//$value['owner'] = $this->getUserId();
foreach ((array)$this->getKeyValueFilter() as $key => $tmpValue) {
$value[$key] = $tmpValue;
}
$match = $this->objectRepository->findOneBy($value);
if (!is_object($match)) {
return true;
}
$expectedIdentifiers = $this->getExpectedIdentifiers($context);
$foundIdentifiers = $this->getFoundIdentifiers($match);
if (count(array_diff_assoc($expectedIdentifiers, $foundIdentifiers)) == 0) {
return true;
}
$this->error(self::ERROR_OBJECT_NOT_UNIQUE, $value);
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment