Completed
Branch feature/better-arg-display (e2dba3)
by Juliette
03:13
created

class-debug-bar-cron.php (8 issues)

Upgrade to new PHP Analysis Engine

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;
0 ignored issues
show
$_crons does not seem to conform to the naming convention (^[a-z][a-z_0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
39
40
		/**
41
		 * Holds only the cron events initiated by WP core.
42
		 *
43
		 * @var array
44
		 */
45
		private $_core_crons;
0 ignored issues
show
$_core_crons does not seem to conform to the naming convention (^[a-z][a-z_0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
46
47
		/**
48
		 * Holds the cron events created by plugins or themes.
49
		 *
50
		 * @var array
51
		 */
52
		private $_user_crons;
0 ignored issues
show
$_user_crons does not seem to conform to the naming convention (^[a-z][a-z_0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
53
54
		/**
55
		 * Total number of cron events.
56
		 *
57
		 * @var int
58
		 */
59
		private $_total_crons = 0;
0 ignored issues
show
$_total_crons does not seem to conform to the naming convention (^[a-z][a-z_0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
60
61
		/**
62
		 * Whether cron is being executed or not.
63
		 *
64
		 * @var string
65
		 */
66
		private $_doing_cron = 'No';
0 ignored issues
show
$_doing_cron does not seem to conform to the naming convention (^[a-z][a-z_0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
67
68
69
		/**
70
		 * Give the panel a title and set the enqueues.
71
		 *
72
		 * @return void
73
		 */
74
		public function init() {
75
			load_plugin_textdomain( 'zt-debug-bar-cron', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
76
			$this->title( __( 'Cron', 'zt-debug-bar-cron' ) );
77
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) );
78
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) );
79
		}
80
81
82
		/**
83
		 * Enqueue styles.
84
		 *
85
		 * @return void
86
		 */
87
		public function enqueue_scripts_styles() {
88
			$suffix = ( ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min' );
89
90
			wp_enqueue_style(
91
				self::DBCRON_NAME,
92
				plugins_url( 'css/' . self::DBCRON_NAME . $suffix . '.css', __FILE__ ),
93
				array( 'debug-bar' ),
94
				self::DBCRON_STYLES_VERSION
95
			);
96
		}
97
98
99
		/**
100
		 * Show the menu item in Debug Bar.
101
		 *
102
		 * @return void
103
		 */
104
		public function prerender() {
105
			$this->set_visible( true );
106
		}
107
108
109
		/**
110
		 * Show the contents of the page.
111
		 *
112
		 * @return void
113
		 */
114
		public function render() {
115
			$this->get_crons();
116
117
			$this->_doing_cron = get_transient( 'doing_cron' ) ? __( 'Yes', 'zt-debug-bar-cron' ) : __( 'No', 'zt-debug-bar-cron' );
118
119
			// Get the time of the next event.
120
			$cron_times          = ( is_array( $this->_crons ) ? array_keys( $this->_crons ) : array() );
121
			$unix_time_next_cron = $cron_times[0];
122
			$time_next_cron      = date( 'Y-m-d H:i:s', $unix_time_next_cron );
123
124
			$human_time_next_cron = human_time_diff( $unix_time_next_cron );
125
126
			// Add a class if past current time and doing cron is not running.
127
			$times_class = ( time() > $unix_time_next_cron && 'No' === $this->_doing_cron ) ? ' past' : '';
128
129
			if ( ! class_exists( 'Debug_Bar_Pretty_Output' ) ) {
130
				require_once plugin_dir_path( __FILE__ ) . 'inc/debug-bar-pretty-output/class-debug-bar-pretty-output.php';
131
			}
132
133
			// Limit recursion depth if possible - method available since DBPO v1.4.
134
			if ( method_exists( 'Debug_Bar_Pretty_Output', 'limit_recursion' ) ) {
135
				Debug_Bar_Pretty_Output::limit_recursion( 2 );
136
			}
137
138
			echo '
139
			<div class="debug-bar-cron">
140
				<h2><span>', esc_html__( 'Total Events', 'zt-debug-bar-cron' ), ':</span>', intval( $this->_total_crons ), '</h2>
141
				<h2><span>', esc_html__( 'Doing Cron', 'zt-debug-bar-cron' ), ':</span>', esc_html( $this->_doing_cron ), '</h2>
142
				<h2 class="times', esc_attr( $times_class ), '"><span>', esc_html__( 'Next Event', 'zt-debug-bar-cron' ), ':</span>
143
					', esc_html( $time_next_cron ), '<br />
144
					', intval( $unix_time_next_cron ), '<br />
145
					', esc_html( $this->display_past_time( $human_time_next_cron, $unix_time_next_cron ) ), '
146
				</h2>
147
				<h2><span>', esc_html__( 'Current Time', 'zt-debug-bar-cron' ), ':</span>', esc_html( date( 'H:i:s' ) ), '</h2>
148
149
				<div class="clear"></div>
150
151
				<h3>', esc_html__( 'Custom Events', 'zt-debug-bar-cron' ), '</h3>';
152
153 View Code Duplication
			if ( ! is_null( $this->_user_crons ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
				$this->display_events( $this->_user_crons );
155
			} else {
156
				echo '
157
				<p>', esc_html__( 'No Custom Events scheduled.', 'zt-debug-bar-cron' ), '</p>';
158
			}
159
160
			echo '
161
				<h3>', esc_html__( 'Schedules', 'zt-debug-bar-cron' ), '</h3>';
162
163
			$this->display_schedules();
164
165
			echo '
166
				<h3>', esc_html__( 'Core Events', 'zt-debug-bar-cron' ), '</h3>';
167
168 View Code Duplication
			if ( ! is_null( $this->_core_crons ) ) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
				$this->display_events( $this->_core_crons );
170
			} else {
171
				echo '
172
				<p>', esc_html__( 'No Core Events scheduled.', 'zt-debug-bar-cron' ), '</p>';
173
			}
174
175
			echo '
176
			</div>';
177
			
178
			// Unset recursion depth limit if possible - method available since DBPO v1.4.
179
			if ( method_exists( 'Debug_Bar_Pretty_Output', 'unset_recursion_limit' ) ) {
180
				Debug_Bar_Pretty_Output::unset_recursion_limit();
181
			}
182
		}
183
184
185
		/**
186
		 * Gets all of the cron jobs.
187
		 *
188
		 * This function sorts the cron jobs into core crons, and custom crons. It also tallies
189
		 * a total count for the crons as this number is otherwise tough to get.
190
		 *
191
		 * @return array Array of crons.
192
		 */
193
		private function get_crons() {
194
			if ( ! is_null( $this->_crons ) ) {
195
				return $this->_crons;
196
			}
197
198
			if ( ! $crons = _get_cron_array() ) {
199
				return $this->_crons;
200
			}
201
202
			$this->_crons = $crons;
203
204
			// Lists all crons that are defined in WP Core.
205
			// @internal To find all, search WP trunk for `wp_schedule_(single_)?event`.
206
			$core_cron_hooks = array(
207
				'do_pings',
208
				'importer_scheduled_cleanup',     // WP 3.1+.
209
				'publish_future_post',
210
				'update_network_counts',          // WP 3.1+.
211
				'upgrader_scheduled_cleanup',     // WP 3.3+.
212
				'wp_maybe_auto_update',           // WP 3.7+.
213
				'wp_scheduled_auto_draft_delete', // WP 3.4+.
214
				'wp_scheduled_delete',            // WP 2.9+.
215
				'wp_split_shared_term_batch',     // WP 4.3+.
216
				'wp_update_plugins',
217
				'wp_update_themes',
218
				'wp_version_check',
219
			);
220
221
			// Sort and count crons.
222
			foreach ( $this->_crons as $time => $time_cron_array ) {
223
				foreach ( $time_cron_array as $hook => $data ) {
224
					$this->_total_crons++;
225
226
					if ( in_array( $hook, $core_cron_hooks, true ) ) {
227
						$this->_core_crons[ $time ][ $hook ] = $data;
228
					} else {
229
						$this->_user_crons[ $time ][ $hook ] = $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
		 *
243
		 * @return void|string Void on failure; table display of events on success.
244
		 */
245
		private function display_events( $events ) {
246
			if ( is_null( $events ) || empty( $events ) ) {
247
				return;
248
			}
249
250
			echo '
251
				<table class="zt-debug-bar-cron-event-table">
252
					<thead><tr>
253
						<th class="col1">', esc_html__( 'Next Execution', 'zt-debug-bar-cron' ), '</th>
254
						<th class="col2">', esc_html__( 'Hook', 'zt-debug-bar-cron' ), '</th>
255
						<th class="col3">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th>
256
						<th class="col4">', esc_html__( 'Interval Value', 'zt-debug-bar-cron' ), '</th>
257
						<th class="col5">', esc_html__( 'Args', 'zt-debug-bar-cron' ), '</th>
258
					</tr></thead>
259
					<tbody>';
260
261
			foreach ( $events as $time => $time_cron_array ) {
262
				foreach ( $time_cron_array as $hook => $data ) {
263
					echo '
264
						<tr>
265
							<td';
266
267
					// Add a class if past current time.
268
					if ( time() > $time && 'No' === $this->_doing_cron ) {
269
						echo ' class="past"';
270
					}
271
272
					echo '>
273
								', esc_html( date( 'Y-m-d H:i:s', $time ) ), '<br />
274
								', intval( $time ), '<br />
275
								', esc_html( $this->display_past_time( human_time_diff( $time ), $time ) ), '
276
							</td>
277
							<td>', esc_html( $hook ), '</td>';
278
279
					foreach ( $data as $hash => $info ) {
280
						// Report the schedule.
281
						echo '
282
							<td>';
283
						if ( $info['schedule'] ) {
284
							echo esc_html( $info['schedule'] );
285
						} else {
286
							echo esc_html__( 'Single Event', 'zt-debug-bar-cron' );
287
						}
288
						echo '</td>';
289
290
						// Report the interval.
291
						echo '
292
							<td>';
293
						if ( isset( $info['interval'] ) ) {
294
							/* TRANSLATORS: %s is number of seconds. */
295
							printf( esc_html__( '%ss', 'zt-debug-bar-cron' ) . '<br />', intval( wp_strip_all_tags( $info['interval'] ) ) );
296
							/* TRANSLATORS: %s is number of minutes. */
297
							printf( esc_html__( '%sm', 'zt-debug-bar-cron' ) . '<br />', intval( wp_strip_all_tags( $info['interval'] ) / 60 ) );
298
							/* TRANSLATORS: %s is number of hours. */
299
							printf( esc_html__( '%sh', 'zt-debug-bar-cron' ), intval( wp_strip_all_tags( $info['interval'] ) / ( 60 * 60 ) ) );
300
						} else {
301
							echo esc_html__( 'Single Event', 'zt-debug-bar-cron' );
302
						}
303
						echo '</td>';
304
305
						// Report the args.
306
						echo '
307
							<td>';
308
						$this->display_cron_arguments( $info['args'] );
309
						echo '</td>';
310
					}
311
312
					echo '
313
						</tr>';
314
				}
315
			}
316
317
			echo '
318
					</tbody>
319
				</table>';
320
		}
321
322
323
		/**
324
		 * Displays the cron arguments in a readable format.
325
		 *
326
		 * @param mixed $args Cron argument(s).
327
		 *
328
		 * @return void
329
		 */
330
		function display_cron_arguments( $args ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
331
			// Arguments defaults to an empty array if no arguments are given.
332
			if ( is_array( $args ) && array() === $args ) {
333
				echo esc_html__( 'No Args', 'zt-debug-bar-cron' );
334
				return;
335
			}
336
337
			// Ok, we have an argument, let's pretty print it.
338
			if ( defined( 'Debug_Bar_Pretty_Output::VERSION' ) ) {
339
				echo Debug_Bar_Pretty_Output::get_output( $args, '', true ); // WPCS: XSS ok.
340
			}
341
			else {
342
				// An old version of the pretty output class was loaded.
343
				// Real possibility as there are several DB plugins using the pretty print class.
344
				Debug_Bar_Pretty_Output::output( $args, '', true );
345
			}
346
		}
347
348
349
		/**
350
		 * Displays all of the schedules defined.
351
		 *
352
		 * @return void
353
		 */
354
		private function display_schedules() {
355
			echo '
356
				<table class="zt-debug-bar-cron-event-table">
357
					<thead><tr>
358
						<th class="col1">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th>
359
						<th class="col2">', esc_html__( 'Interval (S)', 'zt-debug-bar-cron' ), '</th>
360
						<th class="col3">', esc_html__( 'Interval (M)', 'zt-debug-bar-cron' ), '</th>
361
						<th class="col4">', esc_html__( 'Interval (H)', 'zt-debug-bar-cron' ), '</th>
362
						<th class="col5">', esc_html__( 'Display Name', 'zt-debug-bar-cron' ), '</th>
363
					</tr></thead>
364
					<tbody>';
365
366
367
			$schedules = wp_get_schedules();
368
			foreach ( $schedules as $interval_hook => $data ) {
369
				echo '
370
						<tr>
371
							<td>', esc_html( $interval_hook ), '</td>
372
							<td>', intval( wp_strip_all_tags( $data['interval'] ) ), '</td>
373
							<td>', intval( wp_strip_all_tags( $data['interval'] ) / 60 ), '</td>
374
							<td>', intval( wp_strip_all_tags( $data['interval'] ) / ( 60 * 60 ) ), '</td>
375
							<td>', esc_html( $data['display'] ) . '</td>
376
						</tr>';
377
			}
378
379
			echo '
380
					</tbody>
381
				</table>';
382
		}
383
384
385
		/**
386
		 * Compares time with current time and adds ' ago' if current time is greater than event time.
387
		 *
388
		 * @param string $human_time Human readable time difference.
389
		 * @param int    $time       Unix time of event.
390
		 *
391
		 * @return string
392
		 */
393
		private function display_past_time( $human_time, $time ) {
394
			if ( time() > $time ) {
395
				/* TRANSLATORS: %s is a human readable time difference. */
396
				return sprintf( __( '%s ago', 'zt-debug-bar-cron' ), $human_time );
397
			} else {
398
				return $human_time;
399
			}
400
		}
401
	} // End of class ZT_Debug_Bar_Cron.
402
403
} // End of if class_exists wrapper.
404