Skip to content

Commit

Permalink
Add before_or_equal and after_or_equal rules
Browse files Browse the repository at this point in the history
  • Loading branch information
themsaid committed Nov 21, 2016
1 parent c658c75 commit 609d4f4
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 42 deletions.
117 changes: 75 additions & 42 deletions src/Illuminate/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class Validator implements ValidatorContract
protected $dependentRules = [
'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll',
'RequiredIf', 'RequiredUnless', 'Confirmed', 'Same', 'Different', 'Unique',
'Before', 'After',
'Before', 'After', 'BeforeOrEqual', 'AfterOrEqual'
];

/**
Expand Down Expand Up @@ -1853,34 +1853,22 @@ protected function validateBefore($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'before');

if (! is_string($value) && ! is_numeric($value) && ! $value instanceof DateTimeInterface) {
return false;
}

if ($format = $this->getDateFormat($attribute)) {
return $this->validateBeforeWithFormat($format, $value, $parameters);
}

if (! $date = $this->getDateTimestamp($parameters[0])) {
$date = $this->getDateTimestamp($this->getValue($parameters[0]));
}

return $this->getDateTimestamp($value) < $date;
return $this->compareDates($attribute, $value, $parameters, '<');
}

/**
* Validate the date is before a given date with a given format.
* Validate the date is before or equal a given date.
*
* @param string $format
* @param string $attribute
* @param mixed $value
* @param array $parameters
* @return bool
*/
protected function validateBeforeWithFormat($format, $value, $parameters)
protected function validateBeforeOrEqual($attribute, $value, $parameters)
{
$param = $this->getValue($parameters[0]) ?: $parameters[0];
$this->requireParameterCount(1, $parameters, 'before_or_equal');

return $this->checkDateTimeOrder($format, $value, $param);
return $this->compareDates($attribute, $value, $parameters, '<=');
}

/**
Expand All @@ -1895,51 +1883,68 @@ protected function validateAfter($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'after');

return $this->compareDates($attribute, $value, $parameters, '>');
}

/**
* Validate the date is equal or after a given date.
*
* @param string $attribute
* @param mixed $value
* @param array $parameters
* @return bool
*/
protected function validateAfterOrEqual($attribute, $value, $parameters)
{
$this->requireParameterCount(1, $parameters, 'after_or_equal');

return $this->compareDates($attribute, $value, $parameters, '>=');
}

/**
* Compare a given date against another using an operator.
*
* @param string $attribute
* @param mixed $value
* @param array $parameters
* @param string $operator
* @return bool
*/
protected function compareDates($attribute, $value, $parameters, $operator)
{
if (! is_string($value) && ! is_numeric($value) && ! $value instanceof DateTimeInterface) {
return false;
}

if ($format = $this->getDateFormat($attribute)) {
return $this->validateAfterWithFormat($format, $value, $parameters);
$param = $this->getValue($parameters[0]) ?: $parameters[0];

return $this->checkDateTimeOrder($format, $value, $param, $operator);
}

if (! $date = $this->getDateTimestamp($parameters[0])) {
$date = $this->getDateTimestamp($this->getValue($parameters[0]));
}

return $this->getDateTimestamp($value) > $date;
}

/**
* Validate the date is after a given date with a given format.
*
* @param string $format
* @param mixed $value
* @param array $parameters
* @return bool
*/
protected function validateAfterWithFormat($format, $value, $parameters)
{
$param = $this->getValue($parameters[0]) ?: $parameters[0];

return $this->checkDateTimeOrder($format, $param, $value);
return $this->compare($this->getDateTimestamp($value), $date, $operator);
}

/**
* Given two date/time strings, check that one is after the other.
*
* @param string $format
* @param string $before
* @param string $after
* @param string $first
* @param string $second
* @param string $operator
* @return bool
*/
protected function checkDateTimeOrder($format, $before, $after)
protected function checkDateTimeOrder($format, $first, $second, $operator)
{
$before = $this->getDateTimeWithOptionalFormat($format, $before);
$first = $this->getDateTimeWithOptionalFormat($format, $first);

$after = $this->getDateTimeWithOptionalFormat($format, $after);
$second = $this->getDateTimeWithOptionalFormat($format, $second);

return ($before && $after) && ($after > $before);
return ($first && $second) && ($this->compare($first, $second, $operator));
}

/**
Expand Down Expand Up @@ -3340,6 +3345,34 @@ protected function requireParameterCount($count, $parameters, $rule)
}
}

/**
* Determine if a comparison passes between the given values.
*
* @param mixed $first
* @param mixed $second
* @param string $operator
* @return bool
*/
protected function compare($first, $second, $operator)
{
switch ($operator) {
case '<':
return $first < $second;
break;
case '>':
return $first > $second;
break;
case '<=':
return $first <= $second;
break;
case '>=':
return $first >= $second;
break;
default:
throw new \InvalidArgumentException();
}
}

/**
* Handle dynamic calls to class methods.
*
Expand Down
35 changes: 35 additions & 0 deletions tests/Validation/ValidationValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,41 @@ public function testBeforeAndAfterWithFormat()
$this->assertTrue($v->fails());
}

public function testWeakBeforeAndAfter()
{
date_default_timezone_set('UTC');
$trans = $this->getIlluminateArrayTranslator();
$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'before_or_equal:2012-01-15']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'before_or_equal:2012-01-16']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'before_or_equal:2012-01-14']);
$this->assertTrue($v->fails());

$v = new Validator($trans, ['x' => '31/12/2012'], ['x' => 'date_format:d/m/Y|before_or_equal:31/12/2012']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '31/12/2012'], ['x' => 'date_format:d/m/Y|before_or_equal:29/12/2012']);
$this->assertTrue($v->fails());

$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'after_or_equal:2012-01-15']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'after_or_equal:2012-01-14']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '2012-01-15'], ['x' => 'after_or_equal:2012-01-16']);
$this->assertTrue($v->fails());

$v = new Validator($trans, ['x' => '31/12/2012'], ['x' => 'date_format:d/m/Y|after_or_equal:31/12/2012']);
$this->assertTrue($v->passes());

$v = new Validator($trans, ['x' => '31/12/2012'], ['x' => 'date_format:d/m/Y|after_or_equal:02/01/2013']);
$this->assertTrue($v->fails());
}

public function testSometimesAddingRules()
{
$trans = $this->getIlluminateArrayTranslator();
Expand Down

1 comment on commit 609d4f4

@gerardnll
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@themsaid What about the replacement methods for after_or_equal and before_or_equal? When printing validation messages, this method method_exists($this, $replacer = "replace{$rule}") will return false and there will be ':date' on the messages, am I right? Because it does not work for me.

Please sign in to comment.