Blame | Last modification | View Log | Download
<?php namespace ProcessWire;/*** ProcessWire LazyCron Module* ===========================** Provides hooks that are automatically executed at various intervals.* It is called 'lazy' because it's triggered by a pageview, so it's accuracy* executing at specific times will depend upon how may pageviews your site gets.* So when a specified time is triggered, it's guaranteed to have been that length* of time OR longer. This is fine for most cases.* But here's how you make it NOT lazy:** Setup a real CRON job to pull a page from your site once per minute.* Here is an example of a command that you could schedule to execute once per* minute:** wget --quiet --no-cache -O - http://www.your-site.com > /dev/null** This module is compatible with ProcessWire 2.1 only.*** USAGE IN YOUR MODULES:* ----------------------** // In your own module or template, add the function you want executed:* public function myFunc(HookEvent $e) { echo "30 Minutes have passed!"; }** // Then add the hook to it in your module's init() function:* $this->addHook('LazyCron::every30Minutes', $this, 'myFunc');*** PROCEDURAL USAGE (i.e. in templates):* -------------------------------------** // create your hook function* function myHook(HookEvent $e) { echo "30 Minutes have passed!"; }** // add a hook to it:* $wire->addHook('LazyCron::every30Minutes', null, 'myFunc');*** FUNCTIONS YOU CAN HOOK:* -----------------------** every30Seconds* everyMinute* every2Minutes* every3Minutes* every4Minutes* every5Minutes* every10Minutes* every15Minutes* every30Minutes* every45Minutes* everyHour* every2Hours* every4Hours* every6Hours* every12Hours* everyDay* every2Days* every4Days* everyWeek* every2Weeks* every4Weeks*** ProcessWire 3.x, Copyright 2016 by Ryan Cramer* https://processwire.com****/class LazyCron extends WireData implements Module {public static function getModuleInfo() {return array('title' => 'Lazy Cron','version' => 102,'summary' =>"Provides hooks that are automatically executed at various intervals. " ."It is called 'lazy' because it's triggered by a pageview, so the interval " ."is guaranteed to be at least the time requested, rather than exactly the " ."time requested. This is fine for most cases, but you can make it not lazy " ."by connecting this to a real CRON job. See the module file for details. ",'href' => 'https://processwire.com/api/modules/lazy-cron/','permanent' => false,'singular' => true,'autoload' => true,);}/*** Hookable time functions that we are allowing indexed by number of seconds.**/protected $timeFuncs = array(30 => 'every30Seconds',60 => 'everyMinute',120 => 'every2Minutes',180 => 'every3Minutes',240 => 'every4Minutes',300 => 'every5Minutes',600 => 'every10Minutes',900 => 'every15Minutes',1800 => 'every30Minutes',2700 => 'every45Minutes',3600 => 'everyHour',7200 => 'every2Hours',14400 => 'every4Hours',21600 => 'every6Hours',43200 => 'every12Hours',86400 => 'everyDay',172800 => 'every2Days',345600 => 'every4Days',604800 => 'everyWeek',1209600 => 'every2Weeks',2419200 => 'every4Weeks',);/*** Initialize the hooks**/public function init() {$this->addHookAfter('ProcessPageView::finished', $this, 'afterPageView');}/*** Function triggered after every page view.** This is intentionally scheduled after the page has been delivered so* that the cron jobs don't slow down the pageview.**/public function afterPageView(HookEvent $e) {// don't execute cron now if this is anything other than a normal response$responseType = $e->object->getResponseType();if($responseType != ProcessPageView::responseTypeNormal) return;$time = time();$filename = $this->config->paths->cache . "LazyCron.cache";$lockfile = $this->config->paths->cache . "LazyCronLock.cache";$times = array();$writeFile = false;if(is_file($lockfile)) {// other LazyCron process potentially runningif(filemtime($lockfile) < (time() - 3600)) {// expired lock file, some fatal error must have occurred during last LazyCron run$this->wire('files')->unlink($lockfile);} else {// skip running this time as an active lock file existsreturn;}}if(!file_put_contents($lockfile, time(), LOCK_EX)) {$this->error("Unable to write lock file: $lockfile", Notice::logOnly);return;}if(is_file($filename)) {$filedata = file($filename, FILE_IGNORE_NEW_LINES);// file is probably locked, so skip it this timeif($filedata === false) {$this->wire('files')->unlink($lockfile);return;}} else {// file does not exist$filedata = false;}if($filedata) {$n = 0;foreach($this->timeFuncs as $seconds => $func) {$lasttime = (int) (isset($filedata[$n]) ? $filedata[$n] : $time);$elapsedTime = $time - $lasttime;if(empty($filedata[$n]) || $elapsedTime >= $seconds) {try {$this->$func($elapsedTime);} catch(\Exception $e) {$this->error($e->getMessage(), Notice::logOnly);}$lasttime = $time;$writeFile = true;}$times[$seconds] = $lasttime;$n++;}} else {// file does not exist$writeFile = true;foreach($this->timeFuncs as $seconds => $func) {try {$this->$func(0);} catch(\Exception $e) {$this->error($e->getMessage(), Notice::logOnly);}$times[$seconds] = $time;}}if($writeFile && file_put_contents($filename, implode("\n", $times), LOCK_EX)) {if($this->config->chmodFile) @chmod($filename, octdec($this->config->chmodFile));}$this->wire('files')->unlink($lockfile);}/*** One or more of the following functions is called if the given interval has passed.** You can hook into any of these functions and your hook will be called at the given interval.** @param int $seconds The number of seconds that have actually elapsed. Most likely not useful, but provided just in case.**/public function ___every30Seconds($seconds) { }public function ___everyMinute($seconds) { }public function ___every2Minutes($seconds) { }public function ___every3Minutes($seconds) { }public function ___every4Minutes($seconds) { }public function ___every5Minutes($seconds) { }public function ___every10Minutes($seconds) { }public function ___every15Minutes($seconds) { }public function ___every30Minutes($seconds) { }public function ___every45Minutes($seconds) { }public function ___everyHour($seconds) { }public function ___every2Hours($seconds) { }public function ___every4Hours($seconds) { }public function ___every6Hours($seconds) { }public function ___every12Hours($seconds) { }public function ___everyDay($seconds) { }public function ___every2Days($seconds) { }public function ___every4Days($seconds) { }public function ___everyWeek($seconds) { }public function ___every2Weeks($seconds) { }public function ___every4Weeks($seconds) { }}