These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Debug Bar Cron - Debug Bar Panel. |
||
4 | * |
||
5 | * @package WordPress\Plugins\Debug Bar Cron |
||
6 | * @author Zack Tollman, Helen Hou-Sandi, Juliette Reinders Folmer |
||
7 | * @link https://github.com/tollmanz/debug-bar-cron |
||
8 | * @version 0.1.2 |
||
9 | * @license http://creativecommons.org/licenses/GPL/2.0/ GNU General Public License, version 2 or higher |
||
10 | */ |
||
11 | |||
12 | // Avoid direct calls to this file. |
||
13 | if ( ! function_exists( 'add_action' ) ) { |
||
14 | header( 'Status: 403 Forbidden' ); |
||
15 | header( 'HTTP/1.1 403 Forbidden' ); |
||
16 | exit(); |
||
17 | } |
||
18 | |||
19 | /** |
||
20 | * The class in this file extends the functionality provided by the parent plugin "Debug Bar". |
||
21 | */ |
||
22 | if ( ! class_exists( 'ZT_Debug_Bar_Cron' ) && class_exists( 'Debug_Bar_Panel' ) ) { |
||
23 | |||
24 | /** |
||
25 | * Add a new Debug Bar Panel. |
||
26 | */ |
||
27 | class ZT_Debug_Bar_Cron extends Debug_Bar_Panel { |
||
28 | |||
29 | const DBCRON_STYLES_VERSION = '1.0'; |
||
30 | |||
31 | const DBCRON_NAME = 'debug-bar-cron'; |
||
32 | |||
33 | /** |
||
34 | * Holds all of the cron events. |
||
35 | * |
||
36 | * @var array |
||
37 | */ |
||
38 | private $_crons; |
||
39 | |||
40 | /** |
||
41 | * Holds only the cron events initiated by WP core. |
||
42 | * |
||
43 | * @var array |
||
44 | */ |
||
45 | private $_core_crons; |
||
46 | |||
47 | /** |
||
48 | * Holds the cron events created by plugins or themes. |
||
49 | * |
||
50 | * @var array |
||
51 | */ |
||
52 | private $_user_crons; |
||
53 | |||
54 | /** |
||
55 | * Total number of cron events. |
||
56 | * |
||
57 | * @var int |
||
58 | */ |
||
59 | private $_total_crons = 0; |
||
60 | |||
61 | /** |
||
62 | * Total number of cron events created by plugins and themes. |
||
63 | * |
||
64 | * @var int |
||
65 | */ |
||
66 | private $_total_user_crons = 0; |
||
67 | |||
68 | /** |
||
69 | * Total number of WP core cron events. |
||
70 | * |
||
71 | * @var int |
||
72 | */ |
||
73 | private $_total_core_crons = 0; |
||
74 | |||
75 | /** |
||
76 | * Whether cron is being executed or not. |
||
77 | * |
||
78 | * @var string |
||
79 | */ |
||
80 | private $_doing_cron = 'No'; |
||
81 | |||
82 | |||
83 | /** |
||
84 | * Give the panel a title and set the enqueues. |
||
85 | * |
||
86 | * @return void |
||
87 | */ |
||
88 | public function init() { |
||
89 | load_plugin_textdomain( 'zt-debug-bar-cron', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); |
||
90 | $this->title( __( 'Cron', 'zt-debug-bar-cron' ) ); |
||
91 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) ); |
||
92 | add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) ); |
||
93 | } |
||
94 | |||
95 | |||
96 | /** |
||
97 | * Enqueue styles. |
||
98 | * |
||
99 | * @return void |
||
100 | */ |
||
101 | public function enqueue_scripts_styles() { |
||
102 | $suffix = ( ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min' ); |
||
103 | |||
104 | wp_enqueue_style( |
||
105 | self::DBCRON_NAME, |
||
106 | plugins_url( 'css/' . self::DBCRON_NAME . $suffix . '.css', __FILE__ ), |
||
107 | array( 'debug-bar' ), |
||
108 | self::DBCRON_STYLES_VERSION |
||
109 | ); |
||
110 | } |
||
111 | |||
112 | |||
113 | /** |
||
114 | * Show the menu item in Debug Bar. |
||
115 | * |
||
116 | * @return void |
||
117 | */ |
||
118 | public function prerender() { |
||
119 | $this->set_visible( true ); |
||
120 | } |
||
121 | |||
122 | |||
123 | /** |
||
124 | * Show the contents of the page. |
||
125 | * |
||
126 | * @return void |
||
127 | */ |
||
128 | public function render() { |
||
129 | $this->get_crons(); |
||
130 | |||
131 | $this->_doing_cron = get_transient( 'doing_cron' ) ? __( 'Yes', 'zt-debug-bar-cron' ) : __( 'No', 'zt-debug-bar-cron' ); |
||
132 | |||
133 | // Get the time of the next event. |
||
134 | $cron_times = ( is_array( $this->_crons ) ? array_keys( $this->_crons ) : array() ); |
||
135 | $unix_time_next_cron = (int) $cron_times[0]; |
||
136 | $time_next_cron = date( 'Y-m-d H:i:s', $unix_time_next_cron ); |
||
137 | |||
138 | $human_time_next_cron = human_time_diff( $unix_time_next_cron ); |
||
139 | |||
140 | // Add a class if past current time and doing cron is not running. |
||
141 | $times_class = $this->is_time_in_past( $unix_time_next_cron ) ? ' past' : ''; |
||
142 | |||
143 | $this->load_debug_bar_pretty_output(); |
||
144 | |||
145 | echo // WPCS: XSS ok. |
||
146 | ' |
||
147 | <div class="debug-bar-cron"> |
||
148 | <h2><span>', esc_html__( 'Total Events', 'zt-debug-bar-cron' ), ':</span>', $this->_total_crons, '</h2> |
||
149 | <h2><span>', esc_html__( 'Core Events', 'zt-debug-bar-cron' ), ':</span>', $this->_total_core_crons, '</h2> |
||
150 | <h2><span>', esc_html__( 'Custom Events', 'zt-debug-bar-cron' ), ':</span>', $this->_total_user_crons, '</h2> |
||
151 | <h2><span>', esc_html__( 'Doing Cron', 'zt-debug-bar-cron' ), ':</span>', esc_html( $this->_doing_cron ), '</h2> |
||
152 | <h2 class="times', esc_attr( $times_class ), '"><span>', esc_html__( 'Next Event', 'zt-debug-bar-cron' ), ':</span> |
||
153 | ', esc_html( $time_next_cron ), '<br /> |
||
154 | ', $unix_time_next_cron, '<br /> |
||
155 | ', esc_html( $this->display_past_time( $human_time_next_cron, $unix_time_next_cron ) ), ' |
||
156 | </h2> |
||
157 | <h2><span>', esc_html__( 'Current Time', 'zt-debug-bar-cron' ), ':</span>', esc_html( date( 'H:i:s' ) ), '</h2> |
||
158 | |||
159 | <div class="clear"></div> |
||
160 | |||
161 | <h3>', esc_html__( 'Schedules', 'zt-debug-bar-cron' ), '</h3>'; |
||
162 | |||
163 | $this->display_schedules(); |
||
164 | |||
165 | echo ' |
||
166 | <h3>', esc_html__( 'Custom Events', 'zt-debug-bar-cron' ), '</h3>'; |
||
167 | |||
168 | $this->display_events( $this->_user_crons, __( 'No Custom Events scheduled.', 'zt-debug-bar-cron' ) ); |
||
169 | |||
170 | echo ' |
||
171 | <h3>', esc_html__( 'Core Events', 'zt-debug-bar-cron' ), '</h3>'; |
||
172 | |||
173 | $this->display_events( $this->_core_crons, __( 'No Core Events scheduled.', 'zt-debug-bar-cron' ) ); |
||
174 | |||
175 | echo ' |
||
176 | </div>'; |
||
177 | |||
178 | $this->reset_debug_bar_pretty_output(); |
||
179 | } |
||
180 | |||
181 | |||
182 | /** |
||
183 | * Gets all of the cron jobs. |
||
184 | * |
||
185 | * This function sorts the cron jobs into core crons, and custom crons. It also tallies |
||
186 | * a total count for the crons as this number is otherwise tough to get. |
||
187 | * |
||
188 | * @return array|null Array of crons. |
||
189 | */ |
||
190 | private function get_crons() { |
||
191 | if ( is_array( $this->_crons ) ) { |
||
192 | return $this->_crons; |
||
193 | } |
||
194 | |||
195 | $crons = _get_cron_array(); |
||
196 | if ( ! is_array( $crons ) || array() === $crons ) { |
||
197 | return $this->_crons; |
||
198 | } |
||
199 | |||
200 | $this->_crons = $crons; |
||
201 | |||
202 | // Lists all crons that are defined in WP Core. |
||
203 | // @internal To find all, search WP trunk for `wp_schedule_(single_)?event`. |
||
204 | $core_cron_hooks = array( |
||
205 | 'do_pings', |
||
206 | 'importer_scheduled_cleanup', // WP 3.1+. |
||
207 | 'publish_future_post', |
||
208 | 'update_network_counts', // WP 3.1+. |
||
209 | 'upgrader_scheduled_cleanup', // WP 3.3+. |
||
210 | 'wp_maybe_auto_update', // WP 3.7+. |
||
211 | 'wp_scheduled_auto_draft_delete', // WP 3.4+. |
||
212 | 'wp_scheduled_delete', // WP 2.9+. |
||
213 | 'wp_split_shared_term_batch', // WP 4.3+. |
||
214 | 'wp_update_plugins', |
||
215 | 'wp_update_themes', |
||
216 | 'wp_version_check', |
||
217 | ); |
||
218 | |||
219 | // Sort and count crons. |
||
220 | foreach ( $this->_crons as $time => $time_cron_array ) { |
||
221 | foreach ( $time_cron_array as $hook => $data ) { |
||
222 | $this->_total_crons += count( $data ); |
||
223 | |||
224 | if ( in_array( $hook, $core_cron_hooks, true ) ) { |
||
225 | $this->_core_crons[ $time ][ $hook ] = $data; |
||
226 | $this->_total_core_crons += count( $data ); |
||
227 | } else { |
||
228 | $this->_user_crons[ $time ][ $hook ] = $data; |
||
229 | $this->_total_user_crons += count( $data ); |
||
230 | } |
||
231 | } |
||
232 | } |
||
233 | |||
234 | return $this->_crons; |
||
235 | } |
||
236 | |||
237 | |||
238 | /** |
||
239 | * Displays the events in an easy to read table. |
||
240 | * |
||
241 | * @param array $events Array of events. |
||
242 | * @param string $no_events_msg Message to display if there are no events. |
||
243 | */ |
||
244 | private function display_events( $events, $no_events_msg ) { |
||
245 | // Exit early if no events found. |
||
246 | if ( ! is_array( $events ) || empty( $events ) ) { |
||
247 | echo ' |
||
248 | <p>', esc_html( $no_events_msg ), '</p>'; |
||
249 | return; |
||
250 | } |
||
251 | |||
252 | echo ' |
||
253 | <table class="zt-debug-bar-cron-table zt-debug-bar-cron-event-table"> |
||
254 | <thead><tr> |
||
255 | <th class="col1">', esc_html__( 'Next Execution', 'zt-debug-bar-cron' ), '</th> |
||
256 | <th class="col2">', esc_html__( 'Hook', 'zt-debug-bar-cron' ), '</th> |
||
257 | <th class="col3">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th> |
||
258 | <th class="col4">', esc_html__( 'Interval Value', 'zt-debug-bar-cron' ), '</th> |
||
259 | <th class="col5">', esc_html__( 'Args', 'zt-debug-bar-cron' ), '</th> |
||
260 | </tr></thead> |
||
261 | <tbody>'; |
||
262 | |||
263 | foreach ( $events as $time => $time_cron_array ) { |
||
264 | $time = (int) $time; |
||
265 | foreach ( $time_cron_array as $hook => $data ) { |
||
266 | foreach ( $data as $hash => $info ) { |
||
267 | echo ' |
||
268 | <tr> |
||
269 | <td'; |
||
270 | |||
271 | // Add a class if past current time. |
||
272 | if ( $this->is_time_in_past( $time ) ) { |
||
273 | echo ' class="past"'; |
||
274 | } |
||
275 | |||
276 | echo // WPCS: XSS ok. |
||
277 | '> |
||
278 | ', date( 'Y-m-d H:i:s', $time ), '<br /> |
||
279 | ', $time, '<br /> |
||
280 | ', esc_html( $this->display_past_time( human_time_diff( $time ), $time ) ), ' |
||
281 | </td> |
||
282 | <td>', esc_html( $hook ), '</td>'; |
||
283 | |||
284 | |||
285 | // Report the schedule. |
||
286 | echo ' |
||
287 | <td>'; |
||
288 | if ( $info['schedule'] ) { |
||
289 | echo esc_html( $info['schedule'] ); |
||
290 | } else { |
||
291 | echo esc_html__( 'Single Event', 'zt-debug-bar-cron' ); |
||
292 | } |
||
293 | echo '</td>'; |
||
294 | |||
295 | // Report the interval. |
||
296 | echo ' |
||
297 | <td>'; |
||
298 | if ( isset( $info['interval'] ) ) { |
||
299 | $interval = (int) $info['interval']; |
||
300 | /* TRANSLATORS: %s is number of seconds. */ |
||
301 | printf( esc_html__( '%ss', 'zt-debug-bar-cron' ) . '<br />', $interval ); // WPCS: XSS ok. |
||
302 | /* TRANSLATORS: %s is number of minutes. */ |
||
303 | printf( esc_html__( '%sm', 'zt-debug-bar-cron' ) . '<br />', $this->get_minutes( $interval ) ); // WPCS: XSS ok. |
||
304 | /* TRANSLATORS: %s is number of hours. */ |
||
305 | printf( esc_html__( '%sh', 'zt-debug-bar-cron' ), $this->get_hours( $interval ) ); // WPCS: XSS ok. |
||
306 | } else { |
||
307 | echo esc_html__( 'Single Event', 'zt-debug-bar-cron' ); |
||
308 | } |
||
309 | echo '</td>'; |
||
310 | |||
311 | // Report the args. |
||
312 | echo ' |
||
313 | <td>'; |
||
314 | $this->display_cron_arguments( $info['args'] ); |
||
315 | echo '</td> |
||
316 | </tr>'; |
||
317 | } |
||
318 | } |
||
319 | } |
||
320 | |||
321 | echo ' |
||
322 | </tbody> |
||
323 | </table>'; |
||
324 | } |
||
325 | |||
326 | |||
327 | /** |
||
328 | * Displays the cron arguments in a readable format. |
||
329 | * |
||
330 | * @param mixed $args Cron argument(s). |
||
331 | * |
||
332 | * @return void |
||
333 | */ |
||
334 | private function display_cron_arguments( $args ) { |
||
335 | // Arguments defaults to an empty array if no arguments are given. |
||
336 | if ( is_array( $args ) && array() === $args ) { |
||
337 | echo esc_html__( 'No Args', 'zt-debug-bar-cron' ); |
||
338 | return; |
||
339 | } |
||
340 | |||
341 | // Ok, we have an argument, let's pretty print it. |
||
342 | $this->print_pretty_output( $args ); |
||
343 | } |
||
344 | |||
345 | |||
346 | /** |
||
347 | * Displays all of the schedules defined. |
||
348 | * |
||
349 | * @return void |
||
350 | */ |
||
351 | private function display_schedules() { |
||
352 | echo ' |
||
353 | <table class="zt-debug-bar-cron-table zt-debug-bar-cron-schedule-table"> |
||
354 | <thead><tr> |
||
355 | <th class="col1">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th> |
||
356 | <th class="col2">', esc_html__( 'Interval (S)', 'zt-debug-bar-cron' ), '</th> |
||
357 | <th class="col3">', esc_html__( 'Interval (M)', 'zt-debug-bar-cron' ), '</th> |
||
358 | <th class="col4">', esc_html__( 'Interval (H)', 'zt-debug-bar-cron' ), '</th> |
||
359 | <th class="col5">', esc_html__( 'Display Name', 'zt-debug-bar-cron' ), '</th> |
||
360 | </tr></thead> |
||
361 | <tbody>'; |
||
362 | |||
363 | |||
364 | $schedules = wp_get_schedules(); |
||
365 | ksort( $schedules ); |
||
366 | uasort( $schedules, array( $this, 'schedules_sorting' ) ); |
||
367 | foreach ( $schedules as $interval_hook => $data ) { |
||
368 | $interval = (int) $data['interval']; |
||
369 | echo // WPCS: XSS ok. |
||
370 | ' |
||
371 | <tr> |
||
372 | <td>', esc_html( $interval_hook ), '</td> |
||
373 | <td>', $interval, '</td> |
||
374 | <td>', $this->get_minutes( $interval ), '</td> |
||
375 | <td>', $this->get_hours( $interval ), '</td> |
||
376 | <td>', esc_html( $data['display'] ) . '</td> |
||
377 | </tr>'; |
||
378 | } |
||
379 | |||
380 | echo ' |
||
381 | </tbody> |
||
382 | </table>'; |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Sorting method for cron scheldules. Order by schedules interval. |
||
387 | * |
||
388 | * @param array $a First element of comparison pair. |
||
389 | * @param array $b Second element of comparison pair. |
||
390 | * |
||
391 | * @return int Return 1 if $a argument 'interval' greater then $b argument 'interval', 0 if both intervals equivalent and -1 otherwise. |
||
392 | */ |
||
393 | function schedules_sorting( $a, $b ) { |
||
0 ignored issues
–
show
|
|||
394 | if ( (int) $a['interval'] === (int) $b['interval'] ) { |
||
395 | return 0; |
||
396 | } else { |
||
397 | return ( ( (int) $a['interval'] > (int) $b['interval'] ) ? 1 : -1 ); |
||
398 | } |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * Verify if a given timestamp is in the past or the future. |
||
403 | * |
||
404 | * @param int $time Unix timestamp. |
||
405 | * |
||
406 | * @return bool True if the time has passed, false otherwise. |
||
407 | */ |
||
408 | private function is_time_in_past( $time ) { |
||
409 | return ( time() > $time && 'No' === $this->_doing_cron ); |
||
410 | } |
||
411 | |||
412 | |||
413 | /** |
||
414 | * Transform a time in seconds to minutes rounded to 2 decimals. |
||
415 | * |
||
416 | * @param int $time Unix timestamp. |
||
417 | * |
||
418 | * @return int|float |
||
419 | */ |
||
420 | private function get_minutes( $time ) { |
||
421 | return round( ( (int) $time / 60 ), 2 ); |
||
422 | } |
||
423 | |||
424 | |||
425 | /** |
||
426 | * Transform a time in seconds to hours rounded to 2 decimals. |
||
427 | * |
||
428 | * @param int $time Unix timestamp. |
||
429 | * |
||
430 | * @return int|float |
||
431 | */ |
||
432 | private function get_hours( $time ) { |
||
433 | return round( ( (int) $time / 3600 ), 2 ); |
||
434 | } |
||
435 | |||
436 | |||
437 | /** |
||
438 | * Compares time with current time and adds ' ago' if current time is greater than event time. |
||
439 | * |
||
440 | * @param string $human_time Human readable time difference. |
||
441 | * @param int $time Unix time of event. |
||
442 | * |
||
443 | * @return string |
||
444 | */ |
||
445 | private function display_past_time( $human_time, $time ) { |
||
446 | if ( time() > $time ) { |
||
447 | /* TRANSLATORS: %s is a human readable time difference. */ |
||
448 | return sprintf( __( '%s ago', 'zt-debug-bar-cron' ), $human_time ); |
||
449 | } else { |
||
450 | return $human_time; |
||
451 | } |
||
452 | } |
||
453 | |||
454 | |||
455 | /** |
||
456 | * Load the pretty output class & set the recursion limit. |
||
457 | */ |
||
458 | private function load_debug_bar_pretty_output() { |
||
459 | if ( ! class_exists( 'Debug_Bar_Pretty_Output' ) ) { |
||
460 | require_once plugin_dir_path( __FILE__ ) . 'inc/debug-bar-pretty-output/class-debug-bar-pretty-output.php'; |
||
461 | } |
||
462 | |||
463 | // Limit recursion depth if possible - method available since DBPO v1.4. |
||
464 | if ( method_exists( 'Debug_Bar_Pretty_Output', 'limit_recursion' ) ) { |
||
465 | Debug_Bar_Pretty_Output::limit_recursion( 2 ); |
||
466 | } |
||
467 | } |
||
468 | |||
469 | |||
470 | /** |
||
471 | * Print any type of variable with colour coding and a variable type indication. |
||
472 | * |
||
473 | * @param mixed $variable The variable to print. |
||
474 | */ |
||
475 | private function print_pretty_output( $variable ) { |
||
476 | if ( defined( 'Debug_Bar_Pretty_Output::VERSION' ) ) { |
||
477 | echo Debug_Bar_Pretty_Output::get_output( $variable, '', true ); // WPCS: XSS ok. |
||
478 | } else { |
||
479 | // An old version of the pretty output class was loaded. |
||
480 | // Real possibility as there are several DB plugins using the pretty print class. |
||
481 | Debug_Bar_Pretty_Output::output( $variable, '', true ); |
||
482 | } |
||
483 | } |
||
484 | |||
485 | |||
486 | /** |
||
487 | * Unset recursion depth limit for the pretty output class. |
||
488 | * |
||
489 | * @internal Method available since DBPO v1.4. |
||
490 | */ |
||
491 | private function reset_debug_bar_pretty_output() { |
||
492 | if ( method_exists( 'Debug_Bar_Pretty_Output', 'unset_recursion_limit' ) ) { |
||
493 | Debug_Bar_Pretty_Output::unset_recursion_limit(); |
||
494 | } |
||
495 | } |
||
496 | } // End of class ZT_Debug_Bar_Cron. |
||
497 | |||
498 | } // End of if class_exists wrapper. |
||
499 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.