PluginProbe
WP Crontrol / 0.3
WP Crontrol v0.3
1.21.2 trunk 0.1 0.2 0.3 1.0 1.0-beta1 1.0-beta2 1.0-beta3 1.1 1.10.0 1.11.0 1.12.0 1.12.1 1.13.0 1.13.1 1.13.2 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 All 57 releases
wp-crontrol / wp-crontrol.php

wp-crontrol.php in WP Crontrol 0.3, at wp-crontrol.php

552 lines 24.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Plugin Name: WP-Crontrol
4 * Plugin URI: http://www.scompt.com/projects/wp-crontrol
5 * Description: WP-Crontrol lets you take control over what's happening in the WP-Cron system.
6 * Author: Edward Dale
7 * Version: 0.2
8 * Author URI: http://www.scompt.com
9 */
10
11 /**
12 * WP-Crontrol lets you take control over what's happening in the WP-Cron system.
13 *
14 * LICENSE
15 * This file is part of WP-Crontrol.
16 *
17 * WP-Crontrol is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 *
31 * @package WP-Crontrol
32 * @author Edward Dale <scompt@scompt.com>
33 * @copyright Copyright 2007 Edward Dale
34 * @license http://www.gnu.org/licenses/gpl.txt GPL 2.0
35 * @version $Id$
36 * @link http://www.scompt.com/projects/wp-crontrol
37 * @since 0.2
38 */
39 class Crontrol {
40
41 /**
42 * Hook onto all of the actions and filters needed by the plugin.
43 */
44 function Crontrol() {
45 if( function_exists('add_action') ) {
46 add_action('init', array(&$this, 'init'));
47 add_action('init', array(&$this, 'handle_posts'));
48 add_action('admin_menu', array(&$this, 'admin_menu'));
49
50 // Make sure the activation works from subdirectories as well as
51 // directly in the plugin directory.
52 $activate_action = str_replace(ABSPATH.PLUGINDIR.'/', 'activate_', __FILE__);
53 add_action($activate_action, array(&$this, 'activate'));
54
55 add_filter('cron_schedules', array(&$this, 'cron_schedules'));
56 add_action('wp_ajax_delete-sched', array(&$this, 'handle_ajax'));
57 add_action('wp_ajax_delete-cron', array(&$this, 'handle_ajax'));
58 }
59 }
60
61 /**
62 * Run using the 'init' action.
63 */
64 function init() {
65 load_plugin_textdomain('crontrol', str_replace(ABSPATH, '', dirname(__FILE__).'/gettext'));
66 }
67
68 /**
69 * Run using the 'admin_print_scripts' action. Added in the 'admin_menu'
70 * hook.
71 */
72 function scripts() {
73 wp_enqueue_script( 'listman');
74 }
75
76 /**
77 * Handles any ajax requests made by the plugin. Run using
78 * the 'wp_ajax_*' actions.
79 */
80 function handle_ajax() {
81 switch( $_POST['action'] ) {
82 case 'delete-sched':
83 if( !current_user_can('manage_options') ) die('-1');
84 $to_delete = $_POST['id'];
85 $this->delete_schedule($to_delete);
86 exit('1');
87 break;
88 case 'delete-cron':
89 if( !current_user_can('manage_options') ) die('-1');
90 $to_delete = $_POST['id'];
91 $this->delete_cron($to_delete);
92 exit('1');
93 break;
94 }
95 }
96
97 /**
98 * Handles any POSTs made by the plugin. Run using the 'init' action.
99 */
100 function handle_posts() {
101 if( isset($_POST['new_cron']) ) {
102 if( !current_user_can('manage_options') ) die(__('You are not allowed to add new cron events.', 'crontrol'));
103 check_admin_referer("new-cron");
104 $next_run = $_POST['nextrun'];
105 $schedule = $_POST['schedule'];
106 $hookname = $_POST['hookname'];
107 $this->add_cron($next_run, $schedule, $hookname);
108 wp_redirect("edit.php?page=crontrol_admin_manage_page&crontrol_message=5&crontrol_name=$hookname");
109
110 } else if( isset($_POST['edit_cron']) ) {
111 if( !current_user_can('manage_options') ) die(__('You are not allowed to add new cron events.', 'crontrol'));
112 $next_run = $_POST['nextrun'];
113 $schedule = $_POST['schedule'];
114 $hookname = $_POST['hookname'];
115 $original_hookname = $_POST['original_hookname'];
116 check_admin_referer("edit-cron_{$original_hookname}");
117 $this->delete_cron($original_hookname);
118 $this->add_cron($next_run, $schedule, $hookname);
119 wp_redirect("edit.php?page=crontrol_admin_manage_page&crontrol_message=4&crontrol_name=$hookname");
120
121 } else if( isset($_POST['new_schedule']) ) {
122 if( !current_user_can('manage_options') ) die(__('You are not allowed to add new cron schedules.', 'crontrol'));
123 check_admin_referer("new-sched");
124 $name = $_POST['internal_name'];
125 $interval = $_POST['interval'];
126 $display = $_POST['display_name'];
127
128 // The user entered something that wasn't a number.
129 // Try to convert it with strtotime
130 if( !is_numeric($interval) ) {
131 $now = time();
132 $future = strtotime($interval, $now);
133 if( $future===FALSE || $future == -1 || $now>$future) {
134 wp_redirect("options-general.php?page=crontrol_admin_options_page&crontrol_message=7&crontrol_name=".urlencode($interval));
135 return;
136 }
137 $interval = $future-$now;
138 } else if( $interval<=0 ) {
139 wp_redirect("options-general.php?page=crontrol_admin_options_page&crontrol_message=7&crontrol_name=".urlencode($interval));
140 return;
141 }
142
143 $this->add_schedule($name, $interval, $display);
144 wp_redirect("options-general.php?page=crontrol_admin_options_page&crontrol_message=3&crontrol_name=$name");
145
146 } else if( isset($_GET['action']) && $_GET['action']=='delete-sched') {
147 if( !current_user_can('manage_options') ) die(__('You are not allowed to delete cron schedules.', 'crontrol'));
148 $id = $_GET['id'];
149 check_admin_referer("delete-sched_$id");
150 $this->delete_schedule($id);
151 wp_redirect("options-general.php?page=crontrol_admin_options_page&crontrol_message=2&crontrol_name=$id");
152
153 } else if( isset($_GET['action']) && $_GET['action']=='delete-cron') {
154 if( !current_user_can('manage_options') ) die(__('You are not allowed to delete cron events.', 'crontrol'));
155 $id = $_GET['id'];
156 check_admin_referer("delete-cron_$id");
157 $this->delete_cron($id);
158 wp_redirect("edit.php?page=crontrol_admin_manage_page&crontrol_message=6&crontrol_name=$id");
159
160 } else if( isset($_GET['action']) && $_GET['action']=='run-cron') {
161 if( !current_user_can('manage_options') ) die(__('You are not allowed to run cron events.', 'crontrol'));
162 $id = $_GET['id'];
163 check_admin_referer("run-cron_$id");
164 $this->run_cron($id);
165 wp_redirect("edit.php?page=crontrol_admin_manage_page&crontrol_message=1&crontrol_name=$id");
166 }
167 }
168
169 /**
170 * Executes a cron entry immediately.
171 *
172 * Executes an entry by deleting it and adding it again with a
173 * run time of 'now'.
174 *
175 * @param string $hookname The hookname of the cron entry to run
176 */
177 function run_cron($hookname) {
178 $sched = wp_get_schedule($hookname);
179 wp_clear_scheduled_hook($hookname);
180 $this->add_cron('now', $sched, $hookname);
181
182 }
183
184 /**
185 * Adds a new cron entry.
186 *
187 * @param string $next_run A human-readable (strtotime) time that the entry should be run at
188 * @param string $schedule The recurrence of the cron entry
189 * @param string $hookname The name of the hook to execute
190 */
191 function add_cron($next_run, $schedule, $hookname) {
192 $next_run = strtotime($next_run);
193 if( $next_run===FALSE || $next_run==-1 ) $next_run=time();
194 if( !wp_schedule_event( $next_run, $schedule, $hookname ) ) {
195 $error=True;
196 }
197 }
198
199 /**
200 * Deletes a cron entry.
201 *
202 * @param string $name The hookname of the entry to delete.
203 */
204 function delete_cron($to_delete) {
205 wp_clear_scheduled_hook($to_delete);
206 }
207
208 /**
209 * Adds a new custom cron schedule.
210 *
211 * @param string $name The internal name of the schedule
212 * @param int $interval The interval between executions of the new schedule
213 * @param string $display The display name of the schedule
214 */
215 function add_schedule($name, $interval, $display) {
216 $old_scheds = get_option('crontrol_schedules');
217 $old_scheds[$name] = array('interval'=>$interval, 'display'=>$display);
218 update_option('crontrol_schedules', $old_scheds);
219 }
220
221 /**
222 * Deletes a custom cron schedule.
223 *
224 * @param string $name The internal_name of the schedule to delete.
225 */
226 function delete_schedule($name) {
227 $scheds = get_option('crontrol_schedules');
228 unset($scheds[$name]);
229 update_option('crontrol_schedules', $scheds);
230 }
231
232 /**
233 * Sets up the plugin environment upon first activation.
234 *
235 * Run using the 'activate_' action.
236 */
237 function activate() {
238 $extra_scheds = array('twicedaily'=>array('interval'=>43200, 'display'=>__('Twice Daily', 'crontrol')));
239 add_option('crontrol_schedules', $extra_scheds);
240
241 // if there's never been a cron entry, _get_cron_array will return FALSE
242 if( _get_cron_array() === FALSE ) {
243 _set_cron_array(array());
244 }
245 }
246
247 /**
248 * Adds options & management pages to the admin menu.
249 *
250 * Run using the 'admin_menu' action.
251 */
252 function admin_menu() {
253 $page = add_options_page('Crontrol', 'Crontrol', 'manage_options', 'crontrol_admin_options_page', array(&$this, 'admin_options_page') );
254 add_action("admin_print_scripts-$page", array(&$this, 'scripts') );
255
256 $page = add_management_page('Crontrol', "Crontrol", 'manage_options', 'crontrol_admin_manage_page', array(&$this, 'admin_manage_page') );
257 add_action("admin_print_scripts-$page", array(&$this, 'scripts') );
258 }
259
260 /**
261 * Gives WordPress the plugin's set of cron schedules.
262 *
263 * Called by the 'cron_schedules' filter.
264 *
265 * @param array $scheds The current cron schedules. Usually an empty array.
266 * @return array The existing cron schedules along with the plugin's schedules.
267 */
268 function cron_schedules($scheds) {
269 $new_scheds = get_option('crontrol_schedules');
270 return array_merge($new_scheds, $scheds);
271 }
272
273 /**
274 * Displays the options page for the plugin.
275 */
276 function admin_options_page() {
277 $schedules = wp_get_schedules();
278 $custom_schedules = get_option('crontrol_schedules');
279 $custom_keys = array_keys($custom_schedules);
280 uasort($schedules, create_function('$a,$b', 'return $a["interval"]-$b["interval"];'));
281
282 if( isset($_GET['crontrol_message']) ) {
283 $messages = array( '2' => __("Successfully deleted the cron schedule <b>%s</b>", 'crontrol'),
284 '3' => __("Successfully added the cron schedule <b>%s</b>", 'crontrol'),
285 '7' => __("Cron schedule not added because there was a problem parsing <b>%s</b>", 'crontrol'));
286 $hook = $_GET['crontrol_name'];
287 $msg = sprintf($messages[$_GET['crontrol_message']], $hook);
288
289 echo "<div id=\"message\" class=\"updated fade\"><p>$msg</p></div>";
290 }
291
292 ?>
293 <div class="wrap">
294 <h2><?php _e("Cron Schedules", "crontrol"); ?></h2>
295 <p><?php _e('Cron schedules are the time intervals that are available to WordPress and plugin developers to schedule events. You can only delete cron schedules that you have created with WP-Crontrol.', 'crontrol'); ?></p>
296 <div id="ajax-response"></div>
297 <table class="widefat" id="the-list">
298 <thead>
299 <tr>
300 <th><?php _e('Name', 'crontrol'); ?></th>
301 <th><?php _e('Interval', 'crontrol'); ?></th>
302 <th><?php _e('Display Name', 'crontrol'); ?></th>
303 <th><?php _e('Actions', 'crontrol'); ?></th>
304 </tr>
305 </thead>
306 <tbody>
307 <?php
308 if( empty($schedules) ) {
309 ?>
310 <tr colspan="4"><td><?php _e('You currently have no cron schedules. Add one below!', 'crontrol') ?></td></tr>
311 <?php
312 } else {
313 $class = "";
314 foreach( $schedules as $name=>$data ) {
315 echo "<tr id=\"sched-$name\" class=\"$class\">";
316 echo "<td>$name</td>";
317 echo "<td>{$data['interval']} (".$this->interval($data['interval']).")</td>";
318 echo "<td>{$data['display']}</td>";
319 if( in_array($name, $custom_keys) ) {
320 echo "<td><a href='" . wp_nonce_url( "options-general.php?page=crontrol_admin_options_page&amp;action=delete-sched&amp;id=$name", 'delete-sched_' . $name ) . "' onclick=\"return deleteSomething( 'sched', '$name', '" . js_escape(sprintf( __("You are about to delete the schedule '%s'.\n'OK' to delete, 'Cancel' to stop.", 'crontrol' ), $name)) . "' );\" class='delete'>".__( 'Delete' )."</a></td>";
321 } else {
322 echo "<td>&nbsp;</td>\n";
323 }
324 echo "</tr>";
325 $class = empty($class)?"alternate":"";
326 }
327 }
328 ?>
329 </tbody>
330 </table>
331 </div>
332 <div class="wrap narrow">
333 <h2><?php _e('Add new cron schedule', 'crontrol'); ?></h2>
334 <p><?php _e('Adding a new cron schedule will allow you to schedule events that re-occur at the given interval.', 'crontrol'); ?></p>
335 <form method="post" action="options-general.php?page=crontrol_admin_options_page">
336 <table width="100%" cellspacing="2" cellpadding="5" class="editform form-table">
337 <tbody>
338 <tr>
339 <th width="33%" valign="top" scope="row"><label for="internal_name"><?php _e('Internal name', 'crontrol'); ?>:</label></th>
340 <td width="67%"><input type="text" size="40" value="" id="internal_name" name="internal_name"/></td>
341 </tr>
342 <tr>
343 <th width="33%" valign="top" scope="row"><label for="interval"><?php _e('Interval', 'crontrol'); ?>:</label></th>
344 <td width="67%"><input type="text" size="40" value="" id="interval" name="interval"/></td>
345 </tr>
346 <tr>
347 <th width="33%" valign="top" scope="row"><label for="display_name"><?php _e('Display name', 'crontrol'); ?>:</label></th>
348 <td width="67%"><input type="text" size="40" value="" id="display_name" name="display_name"/></td>
349 </tr>
350 </tbody></table>
351 <p class="submit"><input id="schedadd-submit" type="submit" value="<?php _e('Add Cron Schedule &raquo;', 'crontrol'); ?>" name="new_schedule"/></p>
352 <?php wp_nonce_field('new-sched') ?>
353 </form>
354 </div>
355 <?php
356 }
357
358 /**
359 * Displays the manage page for the plugin.
360 */
361 function admin_manage_page() {
362 if( isset($_GET['crontrol_message']) ) {
363 $messages = array( '1' => __('Successfully executed the cron entry <b>%s</b>', 'crontrol'),
364 '4' => __('Successfully edited the cron entry <b>%s</b>', 'crontrol'),
365 '5' => __('Successfully created the cron entry <b>%s</b>', 'crontrol'),
366 '6' => __('Successfully deleted the cron entry <b>%s</b>', 'crontrol'));
367 $hook = $_GET['crontrol_name'];
368 $msg = sprintf($messages[$_GET['crontrol_message']], $hook);
369
370 echo "<div id=\"message\" class=\"updated fade\"><p>$msg</p></div>";
371 }
372 $crons = _get_cron_array();
373 $schedules = wp_get_schedules();
374 $doing_edit = (isset( $_GET['action']) && $_GET['action']=='edit-cron') ? $_GET['id'] : false ;
375 ?>
376 <div class="wrap">
377 <h2><?php _e('WP-Cron Entries', 'crontrol'); ?></h2>
378 <p></p>
379 <div id="ajax-response"></div>
380 <table class="widefat" id="the-list">
381 <thead>
382 <tr>
383 <th><?php _e('Hook Name', 'crontrol'); ?></th>
384 <th><?php _e('Next Run', 'crontrol'); ?></th>
385 <th><?php _e('Recurrence', 'crontrol'); ?></th>
386 <th colspan="3"><?php _e('Actions', 'crontrol'); ?></th>
387 </tr>
388 </thead>
389 <tbody>
390 <?php
391 if( empty($crons) ) {
392 ?>
393 <tr colspan="6"><td><?php _e('You currently have no cron entries. Add one below!', 'crontrol') ?></td></tr>
394 <?php
395 } else {
396 $class = "";
397 foreach( $crons as $time=>$cron ) {
398 foreach( $cron as $hook=>$data) {
399 $data = array_shift($data);
400 if( $doing_edit && $doing_edit==$hook ) {
401 $doing_edit = array('hookname'=>$hook,
402 'nextrun'=>$time,
403 'schedule'=>$data['schedule']);
404 }
405
406 echo "<tr id=\"cron-$hook\" class=\"$class\">";
407 echo "<td>$hook</td>";
408 echo "<td>".strftime("%D %T", $time)." (".$this->time_since(time(), $time).")</td>";
409 echo "<td>{$data['interval']} (".$this->interval($data['interval']).")</td>";
410 echo "<td><a class='view' href='edit.php?page=crontrol_admin_manage_page&amp;action=edit-cron&amp;id=$hook'>Edit</a></td>";
411 echo "<td><a class='view' href='".wp_nonce_url("edit.php?page=crontrol_admin_manage_page&amp;action=run-cron&amp;id=$hook", 'run-cron_' . $hook)."' onclick=\"return confirm('". js_escape(sprintf(__("You are about to execute a cron entry.\nPress 'OK' to continue or 'Cancel' to stop.", 'crontrol')))."');\">Do Now</a></td>";
412 echo "<td><a class='delete' href='".wp_nonce_url("edit.php?page=crontrol_admin_manage_page&amp;action=delete-cron&amp;id=$hook", 'delete-cron_' . $hook)."' onclick=\"return deleteSomething( 'cron', '$hook', '" . js_escape(sprintf( __("You are about to delete the cron entry '%s'.\n'OK' to delete, 'Cancel' to stop.", 'crontrol'), $hook)) . "' );\">Delete</a></td>";
413 echo "</tr>";
414 $class = empty($class)?"alternate":"";
415 }
416 }
417 }
418 ?>
419 </tbody>
420 </table>
421 </div>
422 <?php if( is_array( $doing_edit ) ): ?>
423 <div class="wrap narrow">
424 <h2><?php _e('Edit cron entry', 'crontrol'); ?> (<a href="edit.php?page=crontrol_admin_manage_page"><?php _e('Add new', 'crontrol'); ?></a>)</h2>
425 <form method="post">
426 <?php wp_nonce_field('edit-cron_'.$doing_edit['hookname']) ?>
427 <input name="original_hookname" type="hidden" value="<?php echo $doing_edit['hookname'] ?>" />
428 <table width="100%" cellspacing="2" cellpadding="5" class="editform">
429 <tbody><tr>
430 <th width="33%" valign="top" scope="row"><label for="hookname"><?php _e('Hook name', 'crontrol'); ?>:</label></th>
431 <td width="67%"><input type="text" size="40" id="hookname" name="hookname" value="<?php echo $doing_edit['hookname'] ?>"/></td>
432 </tr><tr>
433 <th width="33%" valign="top" scope="row"><label for="nextrun"><?php _e('Next run', 'crontrol'); ?>:</label></th>
434 <td width="67%"><input type="text" size="40" id="nextrun" name="nextrun" value="<?php echo strftime("%D %T", $doing_edit['nextrun']) ?>"/></td>
435 </tr><tr>
436 <th valign="top" scope="row"><label for="schedule"><?php _e('Entry schedule', 'crontrol'); ?>:</label></th>
437 <td>
438 <select class="postform" name="schedule">
439 <?php
440 foreach( $schedules as $sched_name=>$sched_data ) {
441 $selected = $doing_edit['schedule']==$sched_name ? 'selected="selected"' : '';
442 echo "<option $selected value=\"$sched_name\">{$sched_data['display']} (".$this->interval($sched_data['interval']).")</option>\n";
443 }
444 ?>
445 </select>
446 </td>
447 </tr>
448 </tbody></table>
449 <p class="submit"><input type="submit" value="<?php _e('Modify Cron Entry &raquo;', 'crontrol'); ?>" name="edit_cron"/></p>
450 </form>
451 </div>
452 <?php else: ?>
453 <div class="wrap narrow">
454 <h2><?php _e('Add new cron entry', 'crontrol'); ?></h2>
455 <p><?php _e('Cron entries trigger actions in your code. After adding a new cron entry here, you will need to add a corresponding action hook somewhere in code, perhaps the <code>functions.php</code> file in your theme.', 'crontrol'); ?></p>
456 <form method="post">
457 <?php wp_nonce_field('new-cron') ?>
458 <table width="100%" cellspacing="2" cellpadding="5" class="editform form-table">
459 <tbody><tr>
460 <th width="33%" valign="top" scope="row"><label for="hookname"><?php _e('Hook name', 'crontrol'); ?>:</label></th>
461 <td width="67%"><input type="text" size="40" value="" id="hookname" name="hookname"/></td>
462 </tr><tr>
463 <th width="33%" valign="top" scope="row"><label for="nextrun"><?php _e('Next run', 'crontrol'); ?>:</label></th>
464 <td width="67%"><input type="text" size="40" value="now" id="nextrun" name="nextrun"/></td>
465 </tr><tr>
466 <th valign="top" scope="row"><label for="schedule"><?php _e('Entry schedule', 'crontrol'); ?>:</label></th>
467 <td>
468 <select class="postform" name="schedule">
469 <?php
470 foreach( $schedules as $sched_name=>$sched_data ) {
471 echo "<option value=\"$sched_name\">{$sched_data['display']} (".$this->interval($sched_data['interval']).")</option>\n";
472 }
473 ?>
474 </select>
475 </td>
476 </tr>
477 </tbody></table>
478 <p class="submit"><input type="submit" value="<?php _e('Add Cron Entry &raquo;', 'crontrol'); ?>" name="new_cron"/></p>
479 </form>
480 </div>
481 <?php endif;
482 }
483
484 /**
485 * Pretty-prints the difference in two times.
486 *
487 * @param time $older_date
488 * @param time $newer_date
489 * @return string The pretty time_since value
490 * @link http://binarybonsai.com/code/timesince.txt
491 */
492 function time_since($older_date, $newer_date) {
493 return $this->interval( $newer_date - $older_date );
494 }
495
496 function interval( $since ) {
497 // array of time period chunks
498 $chunks = array(
499 array(60 * 60 * 24 * 365 , 'year'),
500 array(60 * 60 * 24 * 30 , 'month'),
501 array(60 * 60 * 24 * 7, 'week'),
502 array(60 * 60 * 24 , 'day'),
503 array(60 * 60 , 'hour'),
504 array(60 , 'minute'),
505 array( 1 , 'second'),
506 );
507
508 if( $since <= 0 ) {
509 return __('now', 'crontrol');
510 }
511
512 // we only want to output two chunks of time here, eg:
513 // x years, xx months
514 // x days, xx hours
515 // so there's only two bits of calculation below:
516
517 // step one: the first chunk
518 for ($i = 0, $j = count($chunks); $i < $j; $i++)
519 {
520 $seconds = $chunks[$i][0];
521 $name = $chunks[$i][1];
522
523 // finding the biggest chunk (if the chunk fits, break)
524 if (($count = floor($since / $seconds)) != 0)
525 {
526 break;
527 }
528 }
529
530 // set output var
531 $output = ($count == 1) ? '1 '.$name : "$count {$name}s";
532
533 // step two: the second chunk
534 if ($i + 1 < $j)
535 {
536 $seconds2 = $chunks[$i + 1][0];
537 $name2 = $chunks[$i + 1][1];
538
539 if (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0)
540 {
541 // add to output var
542 $output .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s";
543 }
544 }
545
546 return $output;
547 }
548 }
549
550 // Get this show on the road
551 new Crontrol();
552 ?>