Viewing file: DayOfWeekField.php (5.62 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
declare(strict_types=1);
namespace Cron;
use DateTimeInterface; use InvalidArgumentException;
/** * Day of week field. Allows: * / , - ? L #. * * Days of the week can be represented as a number 0-7 (0|7 = Sunday) * or as a three letter string: SUN, MON, TUE, WED, THU, FRI, SAT. * * 'L' stands for "last". It allows you to specify constructs such as * "the last Friday" of a given month. * * '#' is allowed for the day-of-week field, and must be followed by a * number between one and five. It allows you to specify constructs such as * "the second Friday" of a given month. */ class DayOfWeekField extends AbstractField { /** * {@inheritdoc} */ protected $rangeStart = 0;
/** * {@inheritdoc} */ protected $rangeEnd = 7;
/** * @var array Weekday range */ protected $nthRange;
/** * {@inheritdoc} */ protected $literals = [1 => 'MON', 2 => 'TUE', 3 => 'WED', 4 => 'THU', 5 => 'FRI', 6 => 'SAT', 7 => 'SUN'];
/** * Constructor */ public function __construct() { $this->nthRange = range(1, 5); parent::__construct(); }
/** * @inheritDoc */ public function isSatisfiedBy(DateTimeInterface $date, $value, bool $invert): bool { if ('?' === $value) { return true; }
// Convert text day of the week values to integers $value = $this->convertLiterals($value);
$currentYear = (int) $date->format('Y'); $currentMonth = (int) $date->format('m'); $lastDayOfMonth = (int) $date->format('t');
// Find out if this is the last specific weekday of the month if ($lPosition = strpos($value, 'L')) { $weekday = $this->convertLiterals(substr($value, 0, $lPosition)); $weekday %= 7;
$daysInMonth = (int) $date->format('t'); $remainingDaysInMonth = $daysInMonth - (int) $date->format('d'); return (($weekday === (int) $date->format('w')) && ($remainingDaysInMonth < 7)); }
// Handle # hash tokens if (strpos($value, '#')) { [$weekday, $nth] = explode('#', $value);
if (!is_numeric($nth)) { throw new InvalidArgumentException("Hashed weekdays must be numeric, {$nth} given"); } else { $nth = (int) $nth; }
// 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601 if ('0' === $weekday) { $weekday = 7; }
$weekday = (int) $this->convertLiterals((string) $weekday);
// Validate the hash fields if ($weekday < 0 || $weekday > 7) { throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given"); }
if (!\in_array($nth, $this->nthRange, true)) { throw new InvalidArgumentException("There are never more than 5 or less than 1 of a given weekday in a month, {$nth} given"); }
// The current weekday must match the targeted weekday to proceed if ((int) $date->format('N') !== $weekday) { return false; }
$tdate = clone $date; $tdate = $tdate->setDate($currentYear, $currentMonth, 1); $dayCount = 0; $currentDay = 1; while ($currentDay < $lastDayOfMonth + 1) { if ((int) $tdate->format('N') === $weekday) { if (++$dayCount >= $nth) { break; } } $tdate = $tdate->setDate($currentYear, $currentMonth, ++$currentDay); }
return (int) $date->format('j') === $currentDay; }
// Handle day of the week values if (false !== strpos($value, '-')) { $parts = explode('-', $value); if ('7' === $parts[0]) { $parts[0] = 0; } elseif ('0' === $parts[1]) { $parts[1] = 7; } $value = implode('-', $parts); }
// Test to see which Sunday to use -- 0 == 7 == Sunday $format = \in_array(7, array_map(function ($value) { return (int) $value; }, str_split($value)), true) ? 'N' : 'w'; $fieldValue = (int) $date->format($format);
return $this->isSatisfied($fieldValue, $value); }
/** * @inheritDoc */ public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface { if (! $invert) { $date = $date->add(new \DateInterval('P1D')); $date = $date->setTime(0, 0); } else { $date = $date->sub(new \DateInterval('P1D')); $date = $date->setTime(23, 59); }
return $this; }
/** * {@inheritdoc} */ public function validate(string $value): bool { $basicChecks = parent::validate($value);
if (!$basicChecks) { if ('?' === $value) { return true; }
// Handle the # value if (false !== strpos($value, '#')) { $chunks = explode('#', $value); $chunks[0] = $this->convertLiterals($chunks[0]);
if (parent::validate($chunks[0]) && is_numeric($chunks[1]) && \in_array((int) $chunks[1], $this->nthRange, true)) { return true; } }
if (preg_match('/^(.*)L$/', $value, $matches)) { return $this->validate($matches[1]); }
return false; }
return $basicChecks; } }
|