diff --git a/src/Event.php b/src/Event.php index bba5b13..34904e3 100644 --- a/src/Event.php +++ b/src/Event.php @@ -18,6 +18,8 @@ */ class Event extends Component { + use ManagesFrequencies; + const EVENT_BEFORE_RUN = 'beforeRun'; const EVENT_AFTER_RUN = 'afterRun'; @@ -31,7 +33,7 @@ class Event extends Component * * @var string */ - protected $_expression = '* * * * * *'; + protected $_expression = '* * * * *'; /** * The timezone the date should be evaluated on. * @@ -83,7 +85,7 @@ class Event extends Component /** * The mutex implementation. * - * @var \yii\mutex\Mutex + * @var Mutex */ protected $_mutex; @@ -112,6 +114,7 @@ public function __construct(Mutex $mutex, $command, $config = []) /** * Run the given event. * @param Application $app + * @throws InvalidConfigException */ public function run(Application $app) { @@ -138,6 +141,7 @@ protected function mutexName() * Run the command in the foreground. * * @param Application $app + * @throws InvalidConfigException */ protected function runCommandInForeground(Application $app) { @@ -222,284 +226,6 @@ protected function filtersPass(Application $app) return true; } - /** - * Schedule the event to run hourly. - * - * @return $this - */ - public function hourly() - { - return $this->cron('0 * * * * *'); - } - - /** - * The Cron expression representing the event's frequency. - * - * @param string $expression - * @return $this - */ - public function cron($expression) - { - $this->_expression = $expression; - return $this; - } - - /** - * Schedule the event to run daily. - * - * @return $this - */ - public function daily() - { - return $this->cron('0 0 * * * *'); - } - - /** - * Schedule the command at a given time. - * - * @param string $time - * @return $this - */ - public function at($time) - { - return $this->dailyAt($time); - } - - /** - * Schedule the event to run daily at a given time (10:00, 19:30, etc). - * - * @param string $time - * @return $this - */ - public function dailyAt($time) - { - $segments = explode(':', $time); - return $this->spliceIntoPosition(2, (int)$segments[0]) - ->spliceIntoPosition(1, count($segments) == 2 ? (int)$segments[1] : '0'); - } - - /** - * Splice the given value into the given position of the expression. - * - * @param int $position - * @param string $value - * @return Event - */ - protected function spliceIntoPosition($position, $value) - { - $segments = explode(' ', $this->_expression); - $segments[$position - 1] = $value; - return $this->cron(implode(' ', $segments)); - } - - /** - * Schedule the event to run twice daily. - * - * @return $this - */ - public function twiceDaily() - { - return $this->cron('0 1,13 * * * *'); - } - - /** - * Schedule the event to run only on weekdays. - * - * @return $this - */ - public function weekdays() - { - return $this->spliceIntoPosition(5, '1-5'); - } - - /** - * Schedule the event to run only on Mondays. - * - * @return $this - */ - public function mondays() - { - return $this->days(1); - } - - /** - * Set the days of the week the command should run on. - * - * @param array|int $days - * @return $this - */ - public function days($days) - { - $days = is_array($days) ? $days : func_get_args(); - return $this->spliceIntoPosition(5, implode(',', $days)); - } - - /** - * Schedule the event to run only on Tuesdays. - * - * @return $this - */ - public function tuesdays() - { - return $this->days(2); - } - - /** - * Schedule the event to run only on Wednesdays. - * - * @return $this - */ - public function wednesdays() - { - return $this->days(3); - } - - /** - * Schedule the event to run only on Thursdays. - * - * @return $this - */ - public function thursdays() - { - return $this->days(4); - } - - /** - * Schedule the event to run only on Fridays. - * - * @return $this - */ - public function fridays() - { - return $this->days(5); - } - - /** - * Schedule the event to run only on Saturdays. - * - * @return $this - */ - public function saturdays() - { - return $this->days(6); - } - - /** - * Schedule the event to run only on Sundays. - * - * @return $this - */ - public function sundays() - { - return $this->days(0); - } - - /** - * Schedule the event to run weekly. - * - * @return $this - */ - public function weekly() - { - return $this->cron('0 0 * * 0 *'); - } - - /** - * Schedule the event to run weekly on a given day and time. - * - * @param int $day - * @param string $time - * @return $this - */ - public function weeklyOn($day, $time = '0:0') - { - $this->dailyAt($time); - return $this->spliceIntoPosition(5, $day); - } - - /** - * Schedule the event to run monthly. - * - * @return $this - */ - public function monthly() - { - return $this->cron('0 0 1 * * *'); - } - - /** - * Schedule the event to run yearly. - * - * @return $this - */ - public function yearly() - { - return $this->cron('0 0 1 1 * *'); - } - - /** - * Schedule the event to run every minute. - * - * @return $this - */ - public function everyMinute() - { - return $this->cron('* * * * * *'); - } - - /** - * Schedule the event to run every N minutes. - * - * @param int|string $minutes - * @return $this - */ - public function everyNMinutes($minutes) - { - return $this->cron('*/'.$minutes.' * * * * *'); - } - - /** - * Schedule the event to run every five minutes. - * - * @return $this - */ - public function everyFiveMinutes() - { - return $this->everyNMinutes(5); - } - - /** - * Schedule the event to run every ten minutes. - * - * @return $this - */ - public function everyTenMinutes() - { - return $this->everyNMinutes(10); - } - - /** - * Schedule the event to run every thirty minutes. - * - * @return $this - */ - public function everyThirtyMinutes() - { - return $this->cron('0,30 * * * * *'); - } - - /** - * Set the timezone the date should be evaluated on. - * - * @param \DateTimeZone|string $timezone - * @return $this - */ - public function timezone($timezone) - { - $this->_timezone = $timezone; - return $this; - } - /** * Set which user the command should run as. * diff --git a/src/ManagesFrequencies.php b/src/ManagesFrequencies.php new file mode 100644 index 0000000..f9922d6 --- /dev/null +++ b/src/ManagesFrequencies.php @@ -0,0 +1,384 @@ +_expression = $expression; + + return $this; + } + + /** + * Schedule the event to run every minute. + * + * @return $this + */ + public function everyMinute() + { + return $this->spliceIntoPosition(1, '*'); + } + + /** + * Schedule the event to run every N minutes. + * + * @param int $minutes + * @return $this + */ + public function everyNMinutes($minutes) + { + return $this->spliceIntoPosition(1, '*/' . $minutes); + } + + /** + * Schedule the event to run every five minutes. + * + * @return $this + */ + public function everyFiveMinutes() + { + return $this->everyNMinutes(5); + } + + /** + * Schedule the event to run every ten minutes. + * + * @return $this + */ + public function everyTenMinutes() + { + return $this->everyNMinutes(10); + } + + /** + * Schedule the event to run every fifteen minutes. + * + * @return $this + */ + public function everyFifteenMinutes() + { + return $this->everyNMinutes(15); + } + + /** + * Schedule the event to run every thirty minutes. + * + * @return $this + */ + public function everyThirtyMinutes() + { + return $this->everyNMinutes(30); + } + + /** + * Schedule the event to run hourly. + * + * @return $this + */ + public function hourly() + { + return $this->spliceIntoPosition(1, 0); + } + + /** + * Schedule the event to run hourly at a given offset in the hour. + * + * @param array|int $offset + * @return $this + */ + public function hourlyAt($offset) + { + $offset = is_array($offset) ? implode(',', $offset) : $offset; + + return $this->spliceIntoPosition(1, $offset); + } + + /** + * Schedule the event to run daily. + * + * @return $this + */ + public function daily() + { + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0); + } + + /** + * Schedule the command at a given time. + * + * @param string $time + * @return $this + */ + public function at($time) + { + return $this->dailyAt($time); + } + + /** + * Schedule the event to run daily at a given time (10:00, 19:30, etc). + * + * @param string $time + * @return $this + */ + public function dailyAt($time) + { + $segments = explode(':', $time); + + return $this->spliceIntoPosition(2, (int)$segments[0]) + ->spliceIntoPosition(1, count($segments) === 2 ? (int)$segments[1] : '0'); + } + + /** + * Schedule the event to run twice daily. + * + * @param int $first + * @param int $second + * @return $this + */ + public function twiceDaily($first = 1, $second = 13) + { + $hours = $first . ',' . $second; + + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, $hours); + } + + /** + * Schedule the event to run only on weekdays. + * + * @return $this + */ + public function weekdays() + { + return $this->spliceIntoPosition(5, '1-5'); + } + + /** + * Schedule the event to run only on weekends. + * + * @return $this + */ + public function weekends() + { + return $this->spliceIntoPosition(5, '0,6'); + } + + /** + * Schedule the event to run only on Mondays. + * + * @return $this + */ + public function mondays() + { + return $this->days(1); + } + + /** + * Schedule the event to run only on Tuesdays. + * + * @return $this + */ + public function tuesdays() + { + return $this->days(2); + } + + /** + * Schedule the event to run only on Wednesdays. + * + * @return $this + */ + public function wednesdays() + { + return $this->days(3); + } + + /** + * Schedule the event to run only on Thursdays. + * + * @return $this + */ + public function thursdays() + { + return $this->days(4); + } + + /** + * Schedule the event to run only on Fridays. + * + * @return $this + */ + public function fridays() + { + return $this->days(5); + } + + /** + * Schedule the event to run only on Saturdays. + * + * @return $this + */ + public function saturdays() + { + return $this->days(6); + } + + /** + * Schedule the event to run only on Sundays. + * + * @return $this + */ + public function sundays() + { + return $this->days(0); + } + + /** + * Schedule the event to run weekly. + * + * @return $this + */ + public function weekly() + { + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0) + ->spliceIntoPosition(5, 0); + } + + /** + * Schedule the event to run weekly on a given day and time. + * + * @param int $day + * @param string $time + * @return $this + */ + public function weeklyOn($day, $time = '0:0') + { + $this->dailyAt($time); + + return $this->spliceIntoPosition(5, $day); + } + + /** + * Schedule the event to run monthly. + * + * @return $this + */ + public function monthly() + { + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0) + ->spliceIntoPosition(3, 1); + } + + /** + * Schedule the event to run monthly on a given day and time. + * + * @param int $day + * @param string $time + * @return $this + */ + public function monthlyOn($day = 1, $time = '0:0') + { + $this->dailyAt($time); + + return $this->spliceIntoPosition(3, $day); + } + + /** + * Schedule the event to run twice monthly. + * + * @param int $first + * @param int $second + * @return $this + */ + public function twiceMonthly($first = 1, $second = 16) + { + $days = $first . ',' . $second; + + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0) + ->spliceIntoPosition(3, $days); + } + + /** + * Schedule the event to run quarterly. + * + * @return $this + */ + public function quarterly() + { + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0) + ->spliceIntoPosition(3, 1) + ->spliceIntoPosition(4, '1-12/3'); + } + + /** + * Schedule the event to run yearly. + * + * @return $this + */ + public function yearly() + { + return $this->spliceIntoPosition(1, 0) + ->spliceIntoPosition(2, 0) + ->spliceIntoPosition(3, 1) + ->spliceIntoPosition(4, 1); + } + + /** + * Set the days of the week the command should run on. + * + * @param array|mixed $days + * @return $this + */ + public function days($days) + { + $days = is_array($days) ? $days : func_get_args(); + + return $this->spliceIntoPosition(5, implode(',', $days)); + } + + /** + * Set the timezone the date should be evaluated on. + * + * @param \DateTimeZone|string $timezone + * @return $this + */ + public function timezone($timezone) + { + $this->_timezone = $timezone; + + return $this; + } + + /** + * Splice the given value into the given position of the expression. + * + * @param int $position + * @param string $value + * @return $this + */ + protected function spliceIntoPosition($position, $value) + { + $segments = explode(' ', $this->_expression); + + $segments[$position - 1] = $value; + + return $this->cron(implode(' ', $segments)); + } +} diff --git a/tests/FrequencyTest.php b/tests/FrequencyTest.php new file mode 100644 index 0000000..0b8ae3b --- /dev/null +++ b/tests/FrequencyTest.php @@ -0,0 +1,125 @@ +mutex = $this->getMock(Mutex::className()); + } + + protected function getEvent() + { + return new Event( + $this->mutex, + '' + ); + } + + public function testEveryMinute() + { + $this->assertSame('* * * * *', $this->getEvent()->getExpression()); + $this->assertSame('* * * * *', $this->getEvent()->everyMinute()->getExpression()); + } + + public function testEveryFiveMinutes() + { + $this->assertSame('*/5 * * * *', $this->getEvent()->everyFiveMinutes()->getExpression()); + } + + public function testDaily() + { + $this->assertSame('0 0 * * *', $this->getEvent()->daily()->getExpression()); + } + + public function testTwiceDaily() + { + $this->assertSame('0 3,15 * * *', $this->getEvent()->twiceDaily(3, 15)->getExpression()); + } + + public function testOverrideWithHourly() + { + $this->assertSame('0 * * * *', $this->getEvent()->everyFiveMinutes()->hourly()->getExpression()); + $this->assertSame('37 * * * *', $this->getEvent()->hourlyAt(37)->getExpression()); + $this->assertSame('15,30,45 * * * *', $this->getEvent()->hourlyAt([15, 30, 45])->getExpression()); + } + + public function testMonthlyOn() + { + $this->assertSame('0 15 4 * *', $this->getEvent()->monthlyOn(4, '15:00')->getExpression()); + } + + public function testTwiceMonthly() + { + $this->assertSame('0 0 1,16 * *', $this->getEvent()->twiceMonthly(1, 16)->getExpression()); + } + + public function testMonthlyOnWithMinutes() + { + $this->assertSame('15 15 4 * *', $this->getEvent()->monthlyOn(4, '15:15')->getExpression()); + } + + public function testWeekdaysDaily() + { + $this->assertSame('0 0 * * 1-5', $this->getEvent()->weekdays()->daily()->getExpression()); + } + + public function testWeekdaysHourly() + { + $this->assertSame('0 * * * 1-5', $this->getEvent()->weekdays()->hourly()->getExpression()); + } + + public function testWeekdays() + { + $this->assertSame('* * * * 1-5', $this->getEvent()->weekdays()->getExpression()); + } + + public function testSundays() + { + $this->assertSame('* * * * 0', $this->getEvent()->sundays()->getExpression()); + } + + public function testMondays() + { + $this->assertSame('* * * * 1', $this->getEvent()->mondays()->getExpression()); + } + + public function testTuesdays() + { + $this->assertSame('* * * * 2', $this->getEvent()->tuesdays()->getExpression()); + } + + public function testWednesdays() + { + $this->assertSame('* * * * 3', $this->getEvent()->wednesdays()->getExpression()); + } + + public function testThursdays() + { + $this->assertSame('* * * * 4', $this->getEvent()->thursdays()->getExpression()); + } + + public function testFridays() + { + $this->assertSame('* * * * 5', $this->getEvent()->fridays()->getExpression()); + } + + public function testSaturdays() + { + $this->assertSame('* * * * 6', $this->getEvent()->saturdays()->getExpression()); + } + + public function testQuarterly() + { + $this->assertSame('0 0 1 1-12/3 *', $this->getEvent()->quarterly()->getExpression()); + } +}