Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpdeclare(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 monthif ($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 tokensif (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-8601if ('0' === $weekday) {$weekday = 7;}$weekday = (int) $this->convertLiterals((string) $weekday);// Validate the hash fieldsif ($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 proceedif ((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 valuesif (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 # valueif (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;}}