Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add callable support to Validator::requirePresence().
While `Validator::add()`, `Validator::allowEmpty()` and
`Validator::notEmpty()` do accept callables,
`Validator::requirePresence()` does not, making it unnecessarily
"complicated" to handle data, where, depending on conditions, some
fields may be absent.
  • Loading branch information
ndm2 committed Sep 25, 2015
1 parent 9c3f728 commit 3c9abb5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
30 changes: 21 additions & 9 deletions src/Validation/Validator.php
Expand Up @@ -106,7 +106,10 @@ public function errors(array $data, $newRecord = true)
foreach ($this->_fields as $name => $field) {
$keyPresent = array_key_exists($name, $data);

if (!$keyPresent && !$this->_checkPresence($field, $newRecord)) {
$providers = $this->_providers;
$context = compact('data', 'newRecord', 'field', 'providers');

if (!$keyPresent && !$this->_checkPresence($field, $context)) {
$errors[$name]['_required'] = isset($this->_presenceMessages[$name])
? $this->_presenceMessages[$name]
: $requiredMessage;
Expand All @@ -116,8 +119,6 @@ public function errors(array $data, $newRecord = true)
continue;
}

$providers = $this->_providers;
$context = compact('data', 'newRecord', 'field', 'providers');
$canBeEmpty = $this->_canBeEmpty($field, $context);
$isEmpty = $this->_fieldIsEmpty($data[$name]);

Expand Down Expand Up @@ -423,7 +424,9 @@ public function remove($field, $rule = null)
* Sets whether a field is required to be present in data array.
*
* @param string $field the name of the field
* @param bool|string $mode Valid values are true, false, 'create', 'update'
* @param bool|string|callable $mode Valid values are true, false, 'create', 'update'.
* If a callable is passed then the field will be required only when the callback
* returns true.
* @param string|null $message The message to show if the field presence validation fails.
* @return $this
*/
Expand Down Expand Up @@ -553,25 +556,34 @@ public function isEmptyAllowed($field, $newRecord)
* record.
*
* @param string $field Field name.
* @param bool $newRecord whether the data to be validated is new or to be updated.
* @param bool $newRecord Whether the data to be validated is new or to be updated.
* @return bool
*/
public function isPresenceRequired($field, $newRecord)
{
return !$this->_checkPresence($this->field($field), $newRecord);
$providers = $this->_providers;
$data = [];
$context = compact('data', 'newRecord', 'field', 'providers');
return !$this->_checkPresence($this->field($field), $context);
}

/**
* Returns false if any validation for the passed rule set should be stopped
* due to the field missing in the data array
*
* @param ValidationSet $field the set of rules for a field
* @param bool $newRecord whether the data to be validated is new or to be updated.
* @param ValidationSet $field The set of rules for a field.
* @param array $context A key value list of data containing the validation context.
* @return bool
*/
protected function _checkPresence($field, $newRecord)
protected function _checkPresence($field, $context)
{
$required = $field->isPresenceRequired();

if (!is_string($required) && is_callable($required)) {
return !$required($context);
}

$newRecord = $context['newRecord'];
if (in_array($required, ['create', 'update'], true)) {
return (
($required === 'create' && !$newRecord) ||
Expand Down
22 changes: 22 additions & 0 deletions tests/TestCase/Validation/ValidatorTest.php
Expand Up @@ -191,6 +191,28 @@ public function testRequirePresence()
$this->assertEquals('update', $validator->field('title')->isPresenceRequired());
}

/**
* Tests the requirePresence method when passing a callback
*
* @return void
*/
public function testRequirePresenceCallback()
{
$validator = new Validator;
$require = true;
$validator->requirePresence('title', function ($context) use (&$require) {
$this->assertEquals([], $context['data']);
$this->assertEquals([], $context['providers']);
$this->assertEquals('title', $context['field']);
$this->assertTrue($context['newRecord']);
return $require;
});
$this->assertTrue($validator->isPresenceRequired('title', true));

$require = false;
$this->assertFalse($validator->isPresenceRequired('title', true));
}

/**
* Tests the isPresenceRequired method
*
Expand Down

0 comments on commit 3c9abb5

Please sign in to comment.