Completed
Push — feature/code-quality ( 3bbe70...458ff8 )
by Juliette
03:01
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
			echo '
130
			<div class="debug-bar-cron">
131
				<h2><span>', esc_html__( 'Total Events', 'zt-debug-bar-cron' ), ':</span>', intval( $this->_total_crons ), '</h2>
132
				<h2><span>', esc_html__( 'Doing Cron', 'zt-debug-bar-cron' ), ':</span>', esc_html( $this->_doing_cron ), '</h2>
133
				<h2 class="times', esc_attr( $times_class ), '"><span>', esc_html__( 'Next Event', 'zt-debug-bar-cron' ), ':</span>
134
					', esc_html( $time_next_cron ), '<br />
135
					', intval( $unix_time_next_cron ), '<br />
136
					', esc_html( $this->display_past_time( $human_time_next_cron, $unix_time_next_cron ) ), '
137
				</h2>
138
				<h2><span>', esc_html__( 'Current Time', 'zt-debug-bar-cron' ), ':</span>', esc_html( date( 'H:i:s' ) ), '</h2>
139
140
				<div class="clear"></div>
141
142
				<h3>', esc_html__( 'Custom Events', 'zt-debug-bar-cron' ), '</h3>';
143
144 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...
145
				$this->display_events( $this->_user_crons );
146
			} else {
147
				echo '
148
				<p>', esc_html__( 'No Custom Events scheduled.', 'zt-debug-bar-cron' ), '</p>';
149
			}
150
151
			echo '
152
				<h3>', esc_html__( 'Schedules', 'zt-debug-bar-cron' ), '</h3>';
153
154
			$this->display_schedules();
155
156
			echo '
157
				<h3>', esc_html__( 'Core Events', 'zt-debug-bar-cron' ), '</h3>';
158
159 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...
160
				$this->display_events( $this->_core_crons );
161
			} else {
162
				echo '
163
				<p>', esc_html__( 'No Core Events scheduled.', 'zt-debug-bar-cron' ), '</p>';
164
			}
165
166
			echo '
167
			</div>';
168
		}
169
170
171
		/**
172
		 * Gets all of the cron jobs.
173
		 *
174
		 * This function sorts the cron jobs into core crons, and custom crons. It also tallies
175
		 * a total count for the crons as this number is otherwise tough to get.
176
		 *
177
		 * @return array Array of crons.
178
		 */
179
		private function get_crons() {
180
			if ( ! is_null( $this->_crons ) ) {
181
				return $this->_crons;
182
			}
183
184
			if ( ! $crons = _get_cron_array() ) {
185
				return $this->_crons;
186
			}
187
188
			$this->_crons = $crons;
189
190
			// Lists all crons that are defined in WP Core.
191
			// @internal To find all, search WP trunk for `wp_schedule_(single_)?event`.
192
			$core_cron_hooks = array(
193
				'do_pings',
194
				'importer_scheduled_cleanup',     // WP 3.1+.
195
				'publish_future_post',
196
				'update_network_counts',          // WP 3.1+.
197
				'upgrader_scheduled_cleanup',     // WP 3.3+.
198
				'wp_maybe_auto_update',           // WP 3.7+.
199
				'wp_scheduled_auto_draft_delete', // WP 3.4+.
200
				'wp_scheduled_delete',            // WP 2.9+.
201
				'wp_split_shared_term_batch',     // WP 4.3+.
202
				'wp_update_plugins',
203
				'wp_update_themes',
204
				'wp_version_check',
205
			);
206
207
			// Sort and count crons.
208
			foreach ( $this->_crons as $time => $time_cron_array ) {
209
				foreach ( $time_cron_array as $hook => $data ) {
210
					$this->_total_crons++;
211
212
					if ( in_array( $hook, $core_cron_hooks, true ) ) {
213
						$this->_core_crons[ $time ][ $hook ] = $data;
214
					} else {
215
						$this->_user_crons[ $time ][ $hook ] = $data;
216
					}
217
				}
218
			}
219
220
			return $this->_crons;
221
		}
222
223
224
		/**
225
		 * Displays the events in an easy to read table.
226
		 *
227
		 * @param array $events Array of events.
228
		 *
229
		 * @return void|string Void on failure; table display of events on success.
230
		 */
231
		private function display_events( $events ) {
232
			if ( is_null( $events ) || empty( $events ) ) {
233
				return;
234
			}
235
236
			echo '
237
				<table class="zt-debug-bar-cron-event-table">
238
					<thead><tr>
239
						<th class="col1">', esc_html__( 'Next Execution', 'zt-debug-bar-cron' ), '</th>
240
						<th class="col2">', esc_html__( 'Hook', 'zt-debug-bar-cron' ), '</th>
241
						<th class="col3">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th>
242
						<th class="col4">', esc_html__( 'Interval Value', 'zt-debug-bar-cron' ), '</th>
243
						<th class="col5">', esc_html__( 'Args', 'zt-debug-bar-cron' ), '</th>
244
					</tr></thead>
245
					<tbody>';
246
247
			foreach ( $events as $time => $time_cron_array ) {
248
				foreach ( $time_cron_array as $hook => $data ) {
249
					echo '
250
						<tr>
251
							<td';
252
253
					// Add a class if past current time.
254
					if ( time() > $time && 'No' === $this->_doing_cron ) {
255
						echo ' class="past"';
256
					}
257
258
					echo '>
259
								', esc_html( date( 'Y-m-d H:i:s', $time ) ), '<br />
260
								', intval( $time ), '<br />
261
								', esc_html( $this->display_past_time( human_time_diff( $time ), $time ) ), '
262
							</td>
263
							<td>', esc_html( wp_strip_all_tags( $hook ) ), '</td>';
264
265
					foreach ( $data as $hash => $info ) {
266
						// Report the schedule.
267
						echo '
268
							<td>';
269
						if ( $info['schedule'] ) {
270
							echo esc_html( wp_strip_all_tags( $info['schedule'] ) );
271
						} else {
272
							echo esc_html__( 'Single Event', 'zt-debug-bar-cron' );
273
						}
274
						echo '</td>';
275
276
						// Report the interval.
277
						echo '
278
							<td>';
279
						if ( isset( $info['interval'] ) ) {
280
							/* TRANSLATORS: %s is number of seconds. */
281
							printf( esc_html__( '%ss', 'zt-debug-bar-cron' ) . '<br />', intval( wp_strip_all_tags( $info['interval'] ) ) );
282
							/* TRANSLATORS: %s is number of minutes. */
283
							printf( esc_html__( '%sm', 'zt-debug-bar-cron' ) . '<br />', intval( wp_strip_all_tags( $info['interval'] ) / 60 ) );
284
							/* TRANSLATORS: %s is number of hours. */
285
							printf( esc_html__( '%sh', 'zt-debug-bar-cron' ), intval( wp_strip_all_tags( $info['interval'] ) / ( 60 * 60 ) ) );
286
						} else {
287
							echo esc_html__( 'Single Event', 'zt-debug-bar-cron' );
288
						}
289
						echo '</td>';
290
291
						// Report the args.
292
						echo '
293
							<td>';
294
						if ( is_array( $info['args'] ) && ! empty( $info['args'] ) ) {
295
							foreach ( $info['args'] as $key => $value ) {
296
								$this->display_cron_arguments( $key, $value );
297
							}
298
						} else if ( is_string( $info['args'] ) && '' !== $info['args'] ) {
299
							echo esc_html( $info['args'] );
300
						} else {
301
							echo esc_html__( 'No Args', 'zt-debug-bar-cron' );
302
						}
303
						echo '</td>';
304
					}
305
306
					echo '
307
						</tr>';
308
				}
309
			}
310
311
			echo '
312
					</tbody>
313
				</table>';
314
		}
315
316
317
		/**
318
		 * Displays the cron arguments in a readable format.
319
		 *
320
		 * @param int|string $key   Key of the array element.
321
		 * @param mixed      $value Cron argument(s).
322
		 * @param int        $depth Current recursion depth.
323
		 *
324
		 * @return void
325
		 */
326
		function display_cron_arguments( $key, $value, $depth = 0 ) {
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...
327
			if ( is_string( $value ) || is_int( $value ) ) {
328
				echo str_repeat( '&nbsp;', ( $depth * 2 ) ) . wp_strip_all_tags( $key ) . ' => ' . esc_html( $value ) . '<br />';
329
			} else if ( is_array( $value ) ) {
330
				if ( count( $value ) > 0 ) {
331
					echo str_repeat( '&nbsp;', ( $depth * 2 ) ) . wp_strip_all_tags( $key ) . ' => array(<br />';
332
					$depth++;
333
					foreach ( $value as $k => $v ) {
334
						$this->display_cron_arguments( $k, $v, $depth );
335
					}
336
					echo str_repeat( '&nbsp;', ( ( $depth - 1 ) * 2 ) ) . ')';
337
				} else {
338
					echo esc_html( 'Empty Array', 'zt-debug-bar-cron' );
339
				}
340
			}
341
		}
342
343
344
		/**
345
		 * Displays all of the schedules defined.
346
		 *
347
		 * @return void
348
		 */
349
		private function display_schedules() {
350
			echo '
351
				<table class="zt-debug-bar-cron-event-table">
352
					<thead><tr>
353
						<th class="col1">', esc_html__( 'Interval Hook', 'zt-debug-bar-cron' ), '</th>
354
						<th class="col2">', esc_html__( 'Interval (S)', 'zt-debug-bar-cron' ), '</th>
355
						<th class="col3">', esc_html__( 'Interval (M)', 'zt-debug-bar-cron' ), '</th>
356
						<th class="col4">', esc_html__( 'Interval (H)', 'zt-debug-bar-cron' ), '</th>
357
						<th class="col5">', esc_html__( 'Display Name', 'zt-debug-bar-cron' ), '</th>
358
					</tr></thead>
359
					<tbody>';
360
361
			foreach ( wp_get_schedules() as $interval_hook => $data ) {
362
				echo '
363
						<tr>
364
							<td>', esc_html( $interval_hook ), '</td>
365
							<td>', intval( wp_strip_all_tags( $data['interval'] ) ), '</td>
366
							<td>', intval( wp_strip_all_tags( $data['interval'] ) / 60 ), '</td>
367
							<td>', intval( wp_strip_all_tags( $data['interval'] ) / ( 60 * 60 ) ), '</td>
368
							<td>', esc_html( $data['display'] ) . '</td>
369
						</tr>';
370
			}
371
372
			echo '
373
					</tbody>
374
				</table>';
375
		}
376
377
378
		/**
379
		 * Compares time with current time and adds ' ago' if current time is greater than event time.
380
		 *
381
		 * @param string $human_time Human readable time difference.
382
		 * @param int    $time       Unix time of event.
383
		 *
384
		 * @return string
385
		 */
386
		private function display_past_time( $human_time, $time ) {
387
			if ( time() > $time ) {
388
				/* TRANSLATORS: %s is a human readable time difference. */
389
				return sprintf( __( '%s ago', 'zt-debug-bar-cron' ), $human_time );
390
			} else {
391
				return $human_time;
392
			}
393
		}
394
	} // End of class ZT_Debug_Bar_Cron.
395
396
} // End of if class_exists wrapper.
397