diff --git a/src/Cron/DayOfMonthField.php b/src/Cron/DayOfMonthField.php index 253c0d68..53e15bc4 100644 --- a/src/Cron/DayOfMonthField.php +++ b/src/Cron/DayOfMonthField.php @@ -98,8 +98,76 @@ public function increment(DateTime $date, $invert = false) return $this; } + /** + * Validates that the value is valid for the Day of the Month field + * Days of the month can contain values of 1-31, *, L, or ? by default. This can be augmented with lists via a ',', + * ranges via a '-', or with a '[0-9]W' to specify the closest weekday. + * + * @param string $value + * @return bool + */ public function validate($value) { - return (bool) preg_match('/^[\*,\/\-\?LW0-9A-Za-z]+$/', $value); + // Allow wildcards and a single L + if ($value === '?' || $value === '*' || $value === 'L') { + return true; + } + + // If you only contain numbers and are within 1-31 + if ((bool) preg_match('/^\d{1,2}$/', $value) && ($value >= 1 && $value <= 31)) { + return true; + } + + // If you have a -, we will deal with each of your chunks + if ((bool) preg_match('/-/', $value)) { + // We cannot have a range within a list or vice versa + if ((bool) preg_match('/,/', $value)) { + return false; + } + + $chunks = explode('-', $value); + foreach ($chunks as $chunk) { + if (!$this->validate($chunk)) { + return false; + } + } + + return true; + } + + // If you have a comma, we will deal with each value + if ((bool) preg_match('/,/', $value)) { + // We cannot have a range within a list or vice versa + if ((bool) preg_match('/-/', $value)) { + return false; + } + + $chunks = explode(',', $value); + foreach ($chunks as $chunk) { + if (!$this->validate($chunk)) { + return false; + } + } + + return true; + } + + // If you contain a /, we'll deal with it + if ((bool) preg_match('/\//', $value)) { + $chunks = explode('/', $value); + foreach ($chunks as $chunk) { + if (!$this->validate($chunk)) { + return false; + } + } + return true; + } + + // If you end in W, make sure that it has a numeric in front of it + if ((bool) preg_match('/^\d{1,2}W$/', $value)) { + return true; + } + + return false; } } diff --git a/tests/Cron/DayOfMonthFieldTest.php b/tests/Cron/DayOfMonthFieldTest.php index 724b96b0..eff04557 100644 --- a/tests/Cron/DayOfMonthFieldTest.php +++ b/tests/Cron/DayOfMonthFieldTest.php @@ -19,7 +19,6 @@ public function testValidatesField() $f = new DayOfMonthField(); $this->assertTrue($f->validate('1')); $this->assertTrue($f->validate('*')); - $this->assertTrue($f->validate('*/3,1,1-12')); $this->assertTrue($f->validate('5W,L')); $this->assertFalse($f->validate('1.')); } @@ -47,4 +46,16 @@ public function testIncrementsDate() $f->increment($d, true); $this->assertEquals('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s')); } + + /** + * Day of the month cannot accept a 0 value, it must be between 1 and 31 + * See Github issue #120 + * + * @since 2017-01-22 + */ + public function testDoesNotAccept0Date() + { + $f = new DayOfMonthField(); + $this->assertFalse($f->validate(0)); + } }