Created
July 27, 2013 15:01
-
-
Save intellix/6095091 to your computer and use it in GitHub Desktop.
User wants to send mail to many other users in the game. This validator checks that they all exist within a Doctrine Repository.. based on ObjectExists for Doctrine ZF2 module.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Application\Validator; | |
use Zend\Validator\AbstractValidator; | |
use Zend\Validator\Exception; | |
use Doctrine\Common\Persistence\ObjectRepository; | |
use Zend\Stdlib\ArrayUtils; | |
/** | |
* Class that validates if all objects exist in a given repository with a field and separator | |
* | |
* Example: User wants to send a mail to: 'intellix, non_existant_username' | |
* Error: 'non_existant_username' does not exist! | |
* | |
* @license MIT | |
* @link http://www.konoro.org/ | |
* @author Dominic Watson <domwatson@live.co.uk> | |
*/ | |
class ManyObjectsExist extends AbstractValidator | |
{ | |
/** | |
* Error constants | |
*/ | |
const ERROR_NO_OBJECT_FOUND = 'noObjectFound'; | |
const ERROR_NOT_ALL_OBJECTS_FOUND = 'notAllObjectsFound'; | |
/** | |
* @var array Message templates | |
*/ | |
protected $messageTemplates = array( | |
self::ERROR_NO_OBJECT_FOUND => "No object matching '%value%' was found", | |
self::ERROR_NOT_ALL_OBJECTS_FOUND => "The following objects were not found: %value%" | |
); | |
/** | |
* ObjectRepository from which to search for entities | |
* | |
* @var ObjectRepository | |
*/ | |
protected $objectRepository; | |
/** | |
* Fields to be checked | |
* | |
* @var string | |
*/ | |
protected $field; | |
/** | |
* String to split provided string up into multiple object searches | |
* @var string | |
*/ | |
protected $separator; | |
/** | |
* Constructor | |
* | |
* @param array $options required keys are `object_repository`, which must be an instance of | |
* Doctrine\Common\Persistence\ObjectRepository, `field`, 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) | |
{ | |
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['field'])) { | |
throw new Exception\InvalidArgumentException( | |
'Key `field` must be provided and be a field to be used when searching for' | |
. ' existing instances' | |
); | |
} | |
$this->field = $options['field']; | |
$this->validateField(); | |
if (!isset($options['separator'])) { | |
throw new Exception\InvalidArgumentException( | |
'Key `separator` must be provided and be a string for splitting input into an array for searching for' | |
. ' existing instances' | |
); | |
} | |
$this->separator = $options['separator']; | |
parent::__construct($options); | |
} | |
/** | |
* Filters and validates the fields passed to the constructor | |
* | |
* @throws \Zend\Validator\Exception\InvalidArgumentException | |
*/ | |
private function validateField() | |
{ | |
$field = $this->field; | |
if (!is_string($field)) { | |
throw new Exception\InvalidArgumentException(sprintf( | |
'Provided field must be a string, %s provided for key %s', | |
gettype($field), | |
$key | |
)); | |
} | |
} | |
/** | |
* @param string|array $value a field value or an array of field values if more fields have been configured to be | |
* matched | |
* @return array | |
* @throws \Zend\Validator\Exception\RuntimeException | |
*/ | |
protected function cleanSearchValue($value) | |
{ | |
$matchedFieldValue = array(); | |
$field = $this->field; | |
$separator = $this->separator; | |
$value = array_filter(array_map('trim', explode($this->separator, $value))); | |
$matchedFieldValue[$field] = $value; | |
return $matchedFieldValue; | |
} | |
/** | |
* For returning an array of values provided that weren't found | |
* within the object repository | |
* @param array $values clean list of values to search repository | |
* @param array $matches array of objects returned by repository | |
* @return array array of values that weren't found in the repository | |
*/ | |
public function getValuesNotFound($values, $matches) | |
{ | |
$field = $this->field; | |
$valuesNotFound = array_flip($values[$field]); | |
foreach ($matches as $key => $match) { | |
$fn = 'get' . ucfirst($field); | |
$value = $match->{$fn}(); | |
if (in_array($value, $valuesNotFound)) { | |
unset($valuesNotFound[$value]); | |
} | |
} | |
return array_flip($valuesNotFound); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function isValid($value) | |
{ | |
$field = $this->field; | |
$values = $this->cleanSearchValue($value); | |
$matches = $this->objectRepository->findBy($values); | |
if (count($matches) == count($values[$field])) { | |
return true; | |
} | |
$valuesNotFound = $this->getValuesNotFound($values, $matches); | |
$this->error(self::ERROR_NOT_ALL_OBJECTS_FOUND, implode(', ', $valuesNotFound)); | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment