Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
### Unreleased

### v0.1.4 (2018-04-30)

* Add StrictDate::on_or_after for validating date >= date ignoring any time component

### v0.1.3 (2018-02-22)

* Extract the basic ValidNumber class for validating minimum
Expand Down
51 changes: 46 additions & 5 deletions src/Validation/StrictDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,65 @@ class StrictDate
* Validate that value of one field is a date after the value of another
*
* @param \ArrayAccess $validation
* @param string $from_field
* @param string $to_field
* @param string $from_field
* @param string $to_field
*
* @return bool
*/
public static function date_after(\ArrayAccess $validation, $from_field, $to_field)
{
if ( ! $dates = static::get_valid_date_pair($validation, $from_field, $to_field)) {
// Return true if either value is empty or invalid, this will be picked up by other rules
return TRUE;
}

list($from, $to) = $dates;

return ($to > $from);
}

/**
* Validate that value of one field is a date on or after value of another (>= ignoring time)
*
* @param \ArrayAccess $validation
* @param string $from_field
* @param string $to_field
*
* @return bool
*/
public static function date_on_or_after(\ArrayAccess $validation, $from_field, $to_field)
{
if ( ! $dates = static::get_valid_date_pair($validation, $from_field, $to_field)) {
// Return true if either value is empty or invalid, this will be picked up by other rules
return TRUE;
}

list($from, $to) = $dates;

return ($to->format('Y-m-d') >= $from->format('Y-m-d'));
}

/**
* @param \ArrayAccess $validation
* @param string $from_field
* @param string $to_field
*
* @return \DateTimeImmutable[]
*/
protected static function get_valid_date_pair(\ArrayAccess $validation, $from_field, $to_field)
{
$from = $validation[$from_field];
$to = $validation[$to_field];

// Return true if either value is empty or invalid, this will be picked up by other rules
if ($from instanceof InvalidUserDateTime OR ! $from instanceof \DateTimeImmutable) {
return TRUE;
return NULL;
}
if ($to instanceof InvalidUserDateTime OR ! $to instanceof \DateTimeImmutable) {
return TRUE;
return NULL;
}

return ($to > $from);
return [$from, $to];
}

/**
Expand Down Expand Up @@ -107,6 +147,7 @@ public static function rule($rulename)
{
switch ($rulename) {
case 'date_after':
case 'date_on_or_after':
case 'date_immutable':
case 'datetime_immutable':
case 'iso_date':
Expand Down
65 changes: 59 additions & 6 deletions test/unit/Validation/StrictDateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function test_it_validates_date_immutable_instance($value, $expect)
$this->assertSame($expect, StrictDate::date_immutable($value));
}

public function provider_date_after_date()
public function provider_date_before_after_invalid_inputs()
{
return [
[['from' => NULL, 'to' => NULL], 'from', 'to', TRUE],
Expand All @@ -89,6 +89,28 @@ public function provider_date_after_date()
'to',
TRUE
],
];
}

/**
* @dataProvider provider_date_before_after_invalid_inputs
*/
public function test_date_compare_funcs_validate_invalid_input($data, $from_field, $to_field)
{
// This is so that an invalid date just says "invalid date" rather than also "must be after"
$data = new \ArrayObject($data);
$this->assertTrue(StrictDate::date_after($data, $from_field, $to_field), 'date_after');
$this->assertTrue(
StrictDate::date_on_or_after($data, $from_field, $to_field),
'date_on_or_after'
);
}

public function provider_date_after_date()
{
return [
// Invalid inputs all true as they should be caught by other rules
// Simple > the first one
[
['a' => new \DateTimeImmutable, 'b' => new \DateTimeImmutable('-5 mins')],
'a',
Expand All @@ -105,16 +127,47 @@ public function provider_date_after_date()
}

/**
* @dataProvider provider_date_after_date
* @testWith ["", "-5 mins", false]
* ["-5 mins", "", true]
*/
public function test_it_validates_date_after_date($data, $from_field, $to_field, $expect)
public function test_it_validates_date_after_date($from, $to, $expect)
{
$this->assertSame(
$expect,
StrictDate::date_after(
new \ArrayObject($data),
$from_field,
$to_field
new \ArrayObject(
[
'from' => new \DateTimeImmutable($from),
'to' => new \DateTimeImmutable($to)
]
),
'from',
'to'
)
);
}

/**
* @testWith ["2017-01-05 00:00:00", "2017-01-04 23:59:59", false]
* ["2017-01-04 10:00:00", "2017-01-04 23:59:59", true]
* ["2017-01-04 00:00:00", "2017-01-04 00:00:00", true]
* ["2017-01-04 10:00:00", "2017-01-04 08:00:00", true]
* ["2017-05-06 10:00:00", "2018-12-30 00:00:00", true]
*
*/
public function test_it_validates_date_on_or_after_date($from, $to, $expect)
{
$this->assertSame(
$expect,
StrictDate::date_on_or_after(
new \ArrayObject(
[
'from' => new \DateTimeImmutable($from),
'to' => new \DateTimeImmutable($to)
]
),
'from',
'to'
)
);
}
Expand Down