source: branches/1.2/content/plugins/cron/cron.php @ 1315

Revision 1315, 13.3 KB checked in by shibuya246, 3 years ago (diff)

[branch] first version of auto cron job for hotaru (ported from wp)

Line 
1<?php
2/**
3 * name: Cron
4 * description: Enables setting of cron jobs
5 * version: 0.1
6 * folder: cron
7 * class: Cron
8 * type: cron
9 * hooks: install_plugin, admin_header_include, admin_plugin_settings, admin_sidebar_plugin_settings, admin_plugin_dropdown_menu, theme_index_top, admin_theme_index_top, cron_schedule_event, cron_update_job
10 *
11 * PHP version 5
12 *
13 * cron view functions modelled on plugin: Cron GUI developed for wordpress by Simon Wheatley http://simonwheatley.co.uk/wordpress/cron-gui
14 * main cron functions ported from wordpress http://wordpress.org
15 *
16 * LICENSE: Hotaru CMS is free software: you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation, either version 3 of
19 * the License, or (at your option) any later version.
20 *
21 * Hotaru CMS is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 * FITNESS FOR A PARTICULAR PURPOSE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with Hotaru CMS. If not, see http://www.gnu.org/licenses/.
27 *
28 * @category  Content Management System
29 * @package   HotaruCMS
30 * @author    shibuya246 <blog@shibuya246.com>
31 * @copyright Copyright (c) 2010
32 * @license   http://www.gnu.org/copyleft/gpl.html GNU General Public License
33 * @link      http://shibuya246.com
34 */
35class Cron
36{
37        /*
38         * Setup the default settings
39         * */
40    public function install_plugin($h)
41    {
42                //$cron_settings['cron_location'] = BASEURL;
43                //$h->updateSetting('cron_settings', serialize($cron_settings));
44    } 
45
46   public function theme_index_top($h) {
47        $this->admin_theme_index_top($h);
48   }
49
50    public function admin_theme_index_top($h) {       
51        $h->vars['cron_settings'] = $h->getSerializedSettings();
52        $this->checkrunCron($h);
53        //$this->run_cron($h);
54    }
55
56
57/**
58 * @param int $timestamp Timestamp for when to run the event.
59 * @param string $hook Action hook to execute when cron is run.
60 * @param array $args Optional. Arguments to pass to the hook's callback function.
61 */
62public function cron_schedule_single_event( $timestamp, $hook, $args = array()) {
63        // don't schedule a duplicate if there's already an identical event due in the next 10 minutes
64        $next = cron_next_scheduled($hook, $args);
65        if ( $next && $next <= $timestamp + 600 )
66                return;
67
68        $crons = _get_cron_array();
69        $key = md5(serialize($args));
70        $crons[$timestamp][$hook][$key] = array( 'schedule' => false, 'args' => $args );
71        uksort( $crons, "strnatcasecmp" );
72        _set_cron_array( $crons );
73}
74
75
76public function cron_schedule_event($h, $timestamp, $recurrence, $hook, $args = array()) {   
77        $crons = $this->_get_cron_array($h);
78        $schedules = $this->cron_get_schedules($h);
79        $key = md5(serialize($args));       
80        if ( !isset( $schedules[$recurrence] ) )
81                return false;
82        $crons[$timestamp][$hook][$key] = array( 'schedule' => $recurrence, 'args' => $args, 'interval' => $schedules[$recurrence]['interval'] );
83        uksort( $crons, "strnatcasecmp" );
84       
85        //echo "--> <pre>";
86        //print_r ($crons);
87        //echo "</pre>";
88        $this->_set_cron_array($h, $crons );
89}
90
91/**
92 * Reschedule a recurring event.
93 *
94 * @since 2.1.0
95 *
96 * @param int $timestamp Timestamp for when to run the event.
97 * @param string $recurrence How often the event should recur.
98 * @param string $hook Action hook to execute when cron is run.
99 * @param array $args Optional. Arguments to pass to the hook's callback function.
100 * @return bool|null False on failure. Null when event is rescheduled.
101 */
102public function cron_reschedule_event($h, $timestamp, $recurrence, $hook, $args = array()) {
103        $crons = $this->_get_cron_array($h);
104        $schedules =  $this->cron_get_schedules($h);
105        $key = md5(serialize($args));
106        $interval = 0;
107
108        // First we try to get it from the schedule
109        if ( 0 == $interval )
110                $interval = $schedules[$recurrence]['interval'];
111        // Now we try to get it from the saved interval in case the schedule disappears
112        if ( 0 == $interval )
113                $interval = $crons[$timestamp][$hook][$key]['interval'];
114        // Now we assume something is wrong and fail to schedule
115        if ( 0 == $interval )
116                return false;
117
118        $now = time();
119
120    if ( $timestamp >= $now )
121        $timestamp = $now + $interval;
122    else
123        $timestamp = $now + ($interval - (($now - $timestamp) % $interval));   
124        $this->cron_schedule_event($h, $timestamp, $recurrence, $hook, $args );
125}
126
127/**
128 * Unschedule a previously scheduled cron job.
129 *
130 * The $timestamp and $hook parameters are required, so that the event can be
131 * identified.
132 *
133 * @since 2.1.0
134 *
135 * @param int $timestamp Timestamp for when to run the event.
136 * @param string $hook Action hook, the execution of which will be unscheduled.
137 * @param array $args Arguments to pass to the hook's callback function.
138 * Although not passed to a callback function, these arguments are used
139 * to uniquely identify the scheduled event, so they should be the same
140 * as those used when originally scheduling the event.
141 */
142public function cron_unschedule_event($h, $timestamp, $hook, $args = array() ) {
143        $crons = $this->_get_cron_array($h);
144        $key = md5(serialize($args));       
145        unset( $crons[$timestamp][$hook][$key] );
146        if ( empty($crons[$timestamp][$hook]) )
147                unset( $crons[$timestamp][$hook] );
148        if ( empty($crons[$timestamp]) )             
149                unset( $crons[$timestamp] );     
150        $this->_set_cron_array($h, $crons );
151}
152
153/**
154 * Unschedule all cron jobs attached to a specific hook.
155 *
156 * @since 2.1.0
157 *
158 * @param string $hook Action hook, the execution of which will be unscheduled.
159 * @param mixed $args,... Optional. Event arguments.
160 */
161function cron_clear_scheduled_hook($h, $hook ) {
162        $args = array_slice( func_get_args(), 1 );
163
164        while ( $timestamp = wp_next_scheduled( $hook, $args ) )
165                $this->cron_unschedule_event($h, $timestamp, $hook, $args );
166}
167
168/**
169 * Retrieve the next timestamp for a cron event.
170 *
171 * @since 2.1.0
172 *
173 * @param string $hook Action hook to execute when cron is run.
174 * @param array $args Optional. Arguments to pass to the hook's callback function.
175 * @return bool|int The UNIX timestamp of the next time the scheduled event will occur.
176 */
177public function cron_next_scheduled( $hook, $args = array() ) {
178        $crons = _get_cron_array();
179        $key = md5(serialize($args));
180        if ( empty($crons) )
181                return false;
182        foreach ( $crons as $timestamp => $cron ) {
183                if ( isset( $cron[$hook][$key] ) )
184                        return $timestamp;
185        }
186        return false;
187}
188
189/**
190 * Send request to run cron through HTTP request that doesn't halt page loading.
191 *
192 * @since 2.1.0
193 *
194 * @return null Cron could not be spawned, because it is not needed to run.
195 */
196public function spawn_cron($h, $local_time = 0 ) {
197
198        if ( !$local_time )
199                $local_time = time();
200
201        if ( defined('DOING_CRON') || isset($_GET['doing_cron']) )
202                return;
203
204        /*
205         * do not even start the cron if local server timer has drifted
206         * such as due to power failure, or misconfiguration
207         */
208        $timer_accurate = $this->check_server_timer( $local_time );
209        if ( !$timer_accurate )
210                return;
211
212        /*
213        * multiple processes on multiple web servers can run this code concurrently
214        * try to make this as atomic as possible by setting doing_cron switch
215        */
216        $flag = $h->getSetting('doing_cron');
217
218        if ( $flag > $local_time + 10*60 )
219                $flag = 0;
220
221        // don't run if another process is currently running it or more than once every 60 sec.
222        if ( $flag + 60 > $local_time )
223                return;
224
225        //sanity check
226        $crons = $this->_get_cron_array($h);
227        if ( !is_array($crons) )
228                return;
229
230        $keys = array_keys( $crons );
231        if ( isset($keys[0]) && $keys[0] > $local_time )
232                return;
233
234         $h->updateSetting('doing_cron',  $local_time);
235
236        //$cron_url = get_option( 'siteurl' ) . '/wp-cron.php?doing_wp_cron';
237        //wp_remote_post( $cron_url, array('timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters('https_local_ssl_verify', true)) );
238
239        $this->checkrunCron($h);
240}
241
242/**
243 * Run scheduled callbacks or spawn cron for all scheduled events.
244 *
245 * @since 2.1.0
246 *
247 * @return null When doesn't need to run Cron.
248 */
249public function run_cron($h) {
250
251        if ( false === $crons = $this->_get_cron_array($h) )
252                return;
253
254        $local_time = time();
255        $keys = array_keys( $crons );
256        if ( isset($keys[0]) && $keys[0] > $local_time )
257                return;
258       
259        $schedules = $this->cron_get_schedules($h);
260        foreach ( $crons as $timestamp => $cronhooks ) {
261                if ( $timestamp > $local_time ) break;
262                foreach ( (array) $cronhooks as $hook => $args ) {
263                        if ( isset($schedules[$hook]['callback']) && !call_user_func( $schedules[$hook]['callback'] ) )
264                                continue;
265                        $this->spawn_cron($h, $local_time );
266                        break 2;
267                }
268        }
269}
270
271/**
272 * Retrieve supported and filtered Cron recurrences.
273 *
274 * The supported recurrences are 'hourly' and 'daily'. A plugin may add more by
275 * hooking into the 'cron_schedules' filter. The filter accepts an array of
276 * arrays. The outer array has a key that is the name of the schedule or for
277 * example 'weekly'. The value is an array with two keys, one is 'interval' and
278 * the other is 'display'.
279 *
280 * The 'interval' is a number in seconds of when the cron job should run. So for
281 * 'hourly', the time is 3600 or 60*60. For weekly, the value would be
282 * 60*60*24*7 or 604800. The value of 'interval' would then be 604800.
283 *
284 * The 'display' is the description. For the 'weekly' key, the 'display' would
285 * be <code>__('Once Weekly')</code>.
286 *
287 * For your plugin, you will be passed an array. you can easily add your
288 * schedule by doing the following.
289 * <code>
290 * // filter parameter variable name is 'array'
291 *      $array['weekly'] = array(
292 *              'interval' => 604800,
293 *              'display' => __('Once Weekly')
294 *      );
295 * </code>
296 *
297 * @since 2.1.0
298 *
299 * @return array
300 */
301public function cron_get_schedules($h) {
302        $schedules = array(
303                'hourly' => array( 'interval' => 3600, 'display' => 'Once Hourly' ),
304                'twicedaily' => array( 'interval' => 43200, 'display' => 'Twice Daily' ),
305                'daily' => array( 'interval' => 86400, 'display' => 'Once Daily' ),
306        );
307        //return array_merge( apply_filters( 'cron_schedules', array() ), $schedules );
308        return $schedules;
309}
310
311/**
312 * Retrieve Cron schedule for hook with arguments.
313 *
314 * @since 2.1.0
315 *
316 * @param string $hook Action hook to execute when cron is run.
317 * @param array $args Optional. Arguments to pass to the hook's callback function.
318 * @return string|bool False, if no schedule. Schedule on success.
319 */
320public function cron_get_schedule($hook, $args = array()) {
321        $crons = _get_cron_array();
322        $key = md5(serialize($args));
323        if ( empty($crons) )
324                return false;
325        foreach ( $crons as $timestamp => $cron ) {
326                if ( isset( $cron[$hook][$key] ) )
327                        return $cron[$hook][$key]['schedule'];
328        }
329        return false;
330}
331
332//
333// Private functions
334//
335
336/**
337 * Retrieve cron info array option.
338 *
339 */
340public function _get_cron_array($h)  {
341        //$cron = get_option('cron');
342        $cron = $h->vars['cron_settings'];
343        if ( ! is_array($cron) )
344                return false;
345
346        return $cron;
347}
348
349/**
350 * Updates the CRON settings.
351 *
352 */
353public function _set_cron_array($h,$cron) {     
354        $h->updateSetting('cron_settings', serialize($cron));
355        $h->vars['cron_settings'] = $cron;
356}
357
358// stub for checking server timer accuracy, using outside standard time sources
359public function check_server_timer( $local_time ) {
360        return true;
361}
362
363public function checkrunCron($h) {
364    if ( !empty($_POST) || defined('DOING_AJAX') || defined('DOING_CRON') )
365        return;
366
367   define('DOING_CRON', true);   
368
369   if ( false === $crons = $this->_get_cron_array($h) )
370        return;
371
372   $keys = array_keys( $crons );
373   $local_time = time();
374
375   if ( isset($keys[0]) && $keys[0] > $local_time )     
376       return;
377
378   foreach ($crons as $timestamp => $cronhooks) {
379        if ( $timestamp > $local_time )
380            return;
381
382        foreach ($cronhooks as $hook => $keys) {
383            foreach ($keys as $k => $v) {
384                $schedule = $v['schedule'];
385                if ($schedule != false) {
386                        $new_args = array($timestamp, $schedule, $hook, $v['args']);                   
387                        $this->cron_reschedule_event($h,$timestamp, $schedule, $hook, $v['args']);
388                }
389                $this->cron_unschedule_event($h, $timestamp, $hook, $v['args']);
390
391                //print "** run cron " . $hook . " ***********  ";
392                //call function to do task required for cron
393                 $h->pluginHook($hook, '', $v['args']);
394               
395                //print "supposed to run ... " . $hook . " with these args -> ";
396                //print_r ($v['args']);
397            }
398        }
399   }   
400
401}
402
403public function cron_update_job($h, $cron_data)
404{
405    $h->vars['cron_settings'] = $h->getSerializedSettings();
406   
407    //print "hi";
408    //print_r ($cron_data);
409    $timestamp = $cron_data['timestamp'];
410    $recurrence = $cron_data['recurrence'];
411    $hook = $cron_data['hook'];
412    $args = $cron_data['args'];
413    $id = $cron_data['args']['id'];
414
415    //print "id= " . $id;
416    // check whether already have existing event for this autoreader job
417    $crons = $this->_get_cron_array($h);
418    foreach ($crons as $timestamp => $cronhooks) {
419   //   foreach ($cronhooks as $hook => $keys) {
420   //     foreach ($keys as $k => $v) {
421   //         if ($k == 'id' && $v =$id) {
422   //           $cron_id = $timestamp => $id;
423   //         }
424   //     }
425   //   }
426    }
427
428    // $this->cron_reschedule_event($h,$timestamp, $schedule, $hook, $v['args']);
429    // $this->cron_unschedule_event($h, $timestamp, $hook, $v['args']);
430
431    $this->cron_schedule_event($h, $timestamp, $recurrence, $hook, $args);
432}
433
434}
Note: See TracBrowser for help on using the repository browser.