Created
July 13, 2018 09:52
-
-
Save connordavison/0dff5d6439c082e3e75b49a548916898 to your computer and use it in GitHub Desktop.
CronHelper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* A helper class for cronjobs. | |
* | |
* @author C. Davison | |
*/ | |
class CronHelper | |
{ | |
/** | |
* Valid & unique date format strings for each type of cron part. | |
* @const MINUTE | |
* @const HOUR | |
* @const DAY_OF_MONTH | |
* @const MONTH | |
* @const DAY_OF_WEEK | |
* @see http://php.net/manual/en/function.date.php | |
*/ | |
const MINUTE = 'i'; | |
const HOUR = 'H'; | |
const DAY_OF_MONTH = 'd'; | |
const MONTH = 'm'; | |
const DAY_OF_WEEK = 'N'; | |
/** | |
* The default order of a cron, expressed as an array of datetime formats. | |
* @static array | |
*/ | |
static $part_order = array( | |
self::MINUTE, | |
self::HOUR, | |
self::DAY_OF_MONTH, | |
self::MONTH, | |
self::DAY_OF_WEEK | |
); | |
/** | |
* Match a cron to a datetime. | |
* | |
* @param array $cron A list of valid cron expressions in the order given | |
* by $part_order. | |
* @param \DateTime $datetime The DateTime to be matched. | |
* @param array [$part_order=false] The order of the cron parts. If false, | |
* this defaults to CronHelper::$part_order. | |
* @see CronHelper::matchPart | |
* @see CronHelper::$part_order | |
*/ | |
static function match( | |
array $cron, | |
\DateTime $datetime, | |
$part_order = false | |
) { | |
if (count($cron) !== count($part_order)) { | |
throw new \LengthException( | |
'Length of $cron does not match number of cron parts.' | |
); | |
} | |
// If no order is specified, use the default order | |
if (!$part_order) { | |
$part_order = self::$part_order; | |
} | |
// Run through the cron and attempt to match each part to its | |
// corresponding datetime part | |
for ($i = 0; $i < count($part_order); $i++) { | |
$cron_part = $cron[$i]; | |
$part_type = $part_order[$i]; | |
$datetime_part = $datetime->format($part_type); | |
// If the parts cannot be matched, the whole cron cannot be matched | |
if (!self::matchPart($cron_part, $datetime_part, $part_type)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
/** | |
* Match a cron part to a part of a timestamp. This presently allows | |
* standard cron expressions including: | |
* - '*': matches all values | |
* - ',': for listing values (e.g., 5,10,20) | |
* - '-': for ranges (e.g. 2010-2015) | |
* | |
* @param mixed $cron_part The cron part to match. | |
* @param mixed $datetime_part The datetime part to match. This should be | |
* numerical, and not a textual representation. | |
*/ | |
static function matchPart($cron_part, $datetime_part) | |
{ | |
if ($cron_part === '*') return true; | |
$subparts = explode(',', $cron_part); | |
foreach ($subparts as $subpart) { | |
if ($subpart === '*') continue; | |
// If there's a hyphen in this subpart, it represents a range of | |
// values | |
if (strpos($subpart, '-') !== false) { | |
$subpart = explode('-', $subpart); | |
$end = $subpart[1]; | |
$start = $subpart[0]; | |
if ($datetime_part > $start && $datetime_part < $end) continue; | |
else return false; | |
} | |
if ($subpart === $datetime_part) continue; | |
// If we get here, the cron part has failed to match the datetime | |
// part | |
return false; | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment