WP Crontrol - Version 1.12.1

Version Description

Download this release

Release Info

Developer johnbillion
Plugin Icon 128x128 WP Crontrol
Version 1.12.1
Comparing to
See all releases

Code changes from version 1.12.0 to 1.12.1

bin/test.sh DELETED
@@ -1,22 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # -e Exit immediately if a pipeline returns a non-zero status
4
- # -o pipefail Produce a failure return code if any command errors
5
- set -eo pipefail
6
-
7
- # Shorthand:
8
- WP_PORT=`docker port wp-crontrol-wordpress | grep "[0-9]+$" -ohE | head -1`
9
- CHROME_PORT=`docker port wp-crontrol-chrome | grep "[0-9]+$" -ohE | head -1`
10
- WP_URL="http://host.docker.internal:${WP_PORT}"
11
- WP="docker-compose run --rm wpcli wp --url=${WP_URL}"
12
-
13
- # Reset or install the test database:
14
- $WP db reset --yes
15
-
16
- # Install WordPress:
17
- $WP core install --title="Example" --admin_user="admin" --admin_password="admin" --admin_email="admin@example.com"
18
-
19
- # Run the functional tests:
20
- TEST_SITE_WEBDRIVER_PORT=$CHROME_PORT \
21
- TEST_SITE_WP_URL=$WP_URL \
22
- ./vendor/bin/codecept run acceptance --steps "$1"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
codeception.dist.yml DELETED
@@ -1,12 +0,0 @@
1
- paths:
2
- tests: tests
3
- output: tests/_output
4
- data: tests/_data
5
- support: tests/_support
6
- envs: tests/_envs
7
- actor_suffix: Tester
8
- extensions:
9
- enabled:
10
- - Codeception\Extension\RunFailed
11
- params:
12
- - env
 
 
 
 
 
 
 
 
 
 
 
 
js/wp-crontrol.js CHANGED
@@ -1,7 +1,5 @@
1
  /**
2
  * Functionality related to Crontrol.
3
- *
4
- * @package wp-crontrol
5
  */
6
 
7
  let hashtimer = null;
1
  /**
2
  * Functionality related to Crontrol.
 
 
3
  */
4
 
5
  let hashtimer = null;
readme.md CHANGED
@@ -3,8 +3,8 @@
3
  Contributors: johnbillion, scompt
4
  Tags: cron, wp-cron, crontrol, debug
5
  Requires at least: 4.2
6
- Tested up to: 5.9
7
- Stable tag: 1.12.0
8
  Requires PHP: 5.3
9
  Donate link: https://github.com/sponsors/johnbillion
10
 
@@ -39,11 +39,11 @@ I maintain several other plugins for developers. Check them out:
39
 
40
  ### Does this plugin work with PHP 8?
41
 
42
- Yes.
43
 
44
  ### I get the error "There was a problem spawning a call to the WP-Cron system on your site". How do I fix this?
45
 
46
- [You can read all about problems spwaning WP-Cron here](https://github.com/johnbillion/wp-crontrol/wiki/Problems-with-spawning-a-call-to-the-WP-Cron-system).
47
 
48
  ### Why do some cron events miss their schedule?
49
 
@@ -157,6 +157,11 @@ The photo was taken by <a href="https://www.flickr.com/photos/michaelpardo/21453
157
 
158
  ## Changelog ##
159
 
 
 
 
 
 
160
  ### 1.12.0 ###
161
 
162
  * Fix the PHP cron event management.
@@ -281,6 +286,12 @@ The photo was taken by <a href="https://www.flickr.com/photos/michaelpardo/21453
281
  - Terminology and i18n improvements.
282
 
283
 
 
 
 
 
 
 
284
  ### 1.3 ###
285
 
286
  - Improvements to the UI.
@@ -339,16 +350,3 @@ The photo was taken by <a href="https://www.flickr.com/photos/michaelpardo/21453
339
  - Allow a user to enter a schedule event in a human manner
340
  - Looks better on WordPress 2.5
341
 
342
-
343
- ### 0.2 ###
344
-
345
- - Fully documented the code.
346
- - Fixed the bug that the activate action wouldn't be run if the plugin wasn't in a subdirectory.
347
- - Now will play nicely in case any other plugins specify additional cron schedules.
348
- - Minor cosmetic fixes.
349
-
350
-
351
- ### 0.1 ###
352
-
353
- - Super basic, look at what's in WP-Cron functionality.
354
-
3
  Contributors: johnbillion, scompt
4
  Tags: cron, wp-cron, crontrol, debug
5
  Requires at least: 4.2
6
+ Tested up to: 6.0
7
+ Stable tag: 1.12.1
8
  Requires PHP: 5.3
9
  Donate link: https://github.com/sponsors/johnbillion
10
 
39
 
40
  ### Does this plugin work with PHP 8?
41
 
42
+ Yes, it's actively tested and working up to PHP 8.1.
43
 
44
  ### I get the error "There was a problem spawning a call to the WP-Cron system on your site". How do I fix this?
45
 
46
+ [You can read all about problems spawning WP-Cron here](https://github.com/johnbillion/wp-crontrol/wiki/Problems-with-spawning-a-call-to-the-WP-Cron-system).
47
 
48
  ### Why do some cron events miss their schedule?
49
 
157
 
158
  ## Changelog ##
159
 
160
+ ### 1.12.1 ###
161
+
162
+ * Corrects an issue where an invalid hook callback isn't always identified
163
+ * Various code quality improvements
164
+
165
  ### 1.12.0 ###
166
 
167
  * Fix the PHP cron event management.
286
  - Terminology and i18n improvements.
287
 
288
 
289
+ ### 1.3.1 ###
290
+
291
+ - Display a less scary looking message when `DISABLE_WP_CRON` is defined.
292
+ - Correct the example code for cron event arguments.
293
+
294
+
295
  ### 1.3 ###
296
 
297
  - Improvements to the UI.
350
  - Allow a user to enter a schedule event in a human manner
351
  - Looks better on WordPress 2.5
352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/event-list-table.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * List table for cron events.
4
- *
5
- * @package wp-crontrol
6
  */
7
 
8
  namespace Crontrol\Event;
@@ -19,28 +17,28 @@ class Table extends \WP_List_Table {
19
  /**
20
  * Array of cron event hooks that are persistently added by WordPress core.
21
  *
22
- * @var string[] Array of hook names.
23
  */
24
  protected static $persistent_core_hooks;
25
 
26
  /**
27
- * Whether the current user has the capability to edit files.
28
  *
29
- * @var bool Whether the user can edit files.
30
  */
31
- protected static $can_edit_files;
32
 
33
  /**
34
  * Array of the count of each hook.
35
  *
36
- * @var int[] Array of count of each hooked, keyed by hook name.
37
  */
38
  protected static $count_by_hook;
39
 
40
  /**
41
  * Array of all cron events.
42
  *
43
- * @var stdClass[] Array of event objects.
44
  */
45
  protected $all_events = array();
46
 
@@ -63,7 +61,7 @@ class Table extends \WP_List_Table {
63
  */
64
  public function prepare_items() {
65
  self::$persistent_core_hooks = \Crontrol\get_persistent_core_hooks();
66
- self::$can_edit_files = current_user_can( 'edit_files' );
67
  self::$count_by_hook = count_by_hook();
68
 
69
  $events = get();
@@ -116,8 +114,8 @@ class Table extends \WP_List_Table {
116
  /**
117
  * Returns events filtered by various parameters
118
  *
119
- * @param stdClass[] $events The list of all events.
120
- * @return stdClass[][] Array of filtered events keyed by filter name.
121
  */
122
  public static function get_filtered_events( array $events ) {
123
  $all_core_hooks = \Crontrol\get_all_core_hooks();
@@ -156,7 +154,7 @@ class Table extends \WP_List_Table {
156
  /**
157
  * Returns an array of column names for the table.
158
  *
159
- * @return string[] Array of column names keyed by their ID.
160
  */
161
  public function get_columns() {
162
  return array(
@@ -345,7 +343,7 @@ class Table extends \WP_List_Table {
345
 
346
  $links = array();
347
 
348
- if ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_edit_files ) {
349
  $link = array(
350
  'page' => 'crontrol_admin_manage_page',
351
  'crontrol_action' => 'edit-cron',
@@ -370,7 +368,7 @@ class Table extends \WP_List_Table {
370
 
371
  $links[] = "<a href='" . esc_url( $link ) . "'>" . esc_html__( 'Run Now', 'wp-crontrol' ) . '</a>';
372
 
373
- if ( ! in_array( $event->hook, self::$persistent_core_hooks, true ) && ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_edit_files ) ) {
374
  $link = array(
375
  'page' => 'crontrol_admin_manage_page',
376
  'crontrol_action' => 'delete-cron',
@@ -426,7 +424,7 @@ class Table extends \WP_List_Table {
426
  <span class="screen-reader-text">%s</span>',
427
  esc_html__( 'This is a WordPress core event and cannot be deleted', 'wp-crontrol' )
428
  );
429
- } elseif ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_edit_files ) {
430
  return sprintf(
431
  '<label class="screen-reader-text" for="%1$s">%2$s</label>
432
  <input type="checkbox" name="crontrol_delete[%3$s][%4$s]" value="%5$s" id="%1$s">',
1
  <?php
2
  /**
3
  * List table for cron events.
 
 
4
  */
5
 
6
  namespace Crontrol\Event;
17
  /**
18
  * Array of cron event hooks that are persistently added by WordPress core.
19
  *
20
+ * @var array<int,string> Array of hook names.
21
  */
22
  protected static $persistent_core_hooks;
23
 
24
  /**
25
+ * Whether the current user has the capability to create or edit PHP cron events.
26
  *
27
+ * @var bool Whether the user can create or edit PHP cron events.
28
  */
29
+ protected static $can_manage_php_crons;
30
 
31
  /**
32
  * Array of the count of each hook.
33
  *
34
+ * @var array<string,int> Array of count of each hooked, keyed by hook name.
35
  */
36
  protected static $count_by_hook;
37
 
38
  /**
39
  * Array of all cron events.
40
  *
41
+ * @var array<string,stdClass> Array of event objects.
42
  */
43
  protected $all_events = array();
44
 
61
  */
62
  public function prepare_items() {
63
  self::$persistent_core_hooks = \Crontrol\get_persistent_core_hooks();
64
+ self::$can_manage_php_crons = current_user_can( 'edit_files' );
65
  self::$count_by_hook = count_by_hook();
66
 
67
  $events = get();
114
  /**
115
  * Returns events filtered by various parameters
116
  *
117
+ * @param array<string,stdClass> $events The list of all events.
118
+ * @return array<string,array<string,stdClass>> Array of filtered events keyed by filter name.
119
  */
120
  public static function get_filtered_events( array $events ) {
121
  $all_core_hooks = \Crontrol\get_all_core_hooks();
154
  /**
155
  * Returns an array of column names for the table.
156
  *
157
+ * @return array<string,string> Array of column names keyed by their ID.
158
  */
159
  public function get_columns() {
160
  return array(
343
 
344
  $links = array();
345
 
346
+ if ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_manage_php_crons ) {
347
  $link = array(
348
  'page' => 'crontrol_admin_manage_page',
349
  'crontrol_action' => 'edit-cron',
368
 
369
  $links[] = "<a href='" . esc_url( $link ) . "'>" . esc_html__( 'Run Now', 'wp-crontrol' ) . '</a>';
370
 
371
+ if ( ! in_array( $event->hook, self::$persistent_core_hooks, true ) && ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_manage_php_crons ) ) {
372
  $link = array(
373
  'page' => 'crontrol_admin_manage_page',
374
  'crontrol_action' => 'delete-cron',
424
  <span class="screen-reader-text">%s</span>',
425
  esc_html__( 'This is a WordPress core event and cannot be deleted', 'wp-crontrol' )
426
  );
427
+ } elseif ( ( 'crontrol_cron_job' !== $event->hook ) || self::$can_manage_php_crons ) {
428
  return sprintf(
429
  '<label class="screen-reader-text" for="%1$s">%2$s</label>
430
  <input type="checkbox" name="crontrol_delete[%3$s][%4$s]" value="%5$s" id="%1$s">',
src/event.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * Functions related to cron events.
4
- *
5
- * @package wp-crontrol
6
  */
7
 
8
  namespace Crontrol\Event;
@@ -100,7 +98,7 @@ function force_schedule_single_event( $hook, $args = array() ) {
100
  'schedule' => $event->schedule,
101
  'args' => $event->args,
102
  );
103
- uksort( $crons, 'strnatcasecmp' );
104
 
105
  $result = _set_cron_array( $crons );
106
 
@@ -163,8 +161,14 @@ function add( $next_run_local, $schedule, $hook, array $args ) {
163
  }
164
 
165
  if ( '_oneoff' === $schedule || '' === $schedule ) {
 
 
 
166
  $result = wp_schedule_single_event( $next_run_utc, $hook, $args, true );
167
  } else {
 
 
 
168
  $result = wp_schedule_event( $next_run_utc, $schedule, $hook, $args, true );
169
  }
170
 
@@ -209,6 +213,9 @@ function delete( $hook, $sig, $next_run_utc ) {
209
  return $event;
210
  }
211
 
 
 
 
212
  $unscheduled = wp_unschedule_event( $event->timestamp, $event->hook, $event->args, true );
213
 
214
  /**
@@ -240,7 +247,7 @@ function delete( $hook, $sig, $next_run_utc ) {
240
  /**
241
  * Returns a flattened array of cron events.
242
  *
243
- * @return stdClass[] An array of cron event objects.
244
  */
245
  function get() {
246
  $crons = get_core_cron_array();
1
  <?php
2
  /**
3
  * Functions related to cron events.
 
 
4
  */
5
 
6
  namespace Crontrol\Event;
98
  'schedule' => $event->schedule,
99
  'args' => $event->args,
100
  );
101
+ ksort( $crons );
102
 
103
  $result = _set_cron_array( $crons );
104
 
161
  }
162
 
163
  if ( '_oneoff' === $schedule || '' === $schedule ) {
164
+ /**
165
+ * @var bool|null|\WP_Error $result
166
+ */
167
  $result = wp_schedule_single_event( $next_run_utc, $hook, $args, true );
168
  } else {
169
+ /**
170
+ * @var bool|null|\WP_Error $result
171
+ */
172
  $result = wp_schedule_event( $next_run_utc, $schedule, $hook, $args, true );
173
  }
174
 
213
  return $event;
214
  }
215
 
216
+ /**
217
+ * @var bool|null|\WP_Error $unscheduled
218
+ */
219
  $unscheduled = wp_unschedule_event( $event->timestamp, $event->hook, $event->args, true );
220
 
221
  /**
247
  /**
248
  * Returns a flattened array of cron events.
249
  *
250
+ * @return array<string,stdClass> An array of cron event objects keyed by unique signature.
251
  */
252
  function get() {
253
  $crons = get_core_cron_array();
src/request.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * Request handler.
4
- *
5
- * @package wp-crontrol
6
  */
7
 
8
  namespace Crontrol;
1
  <?php
2
  /**
3
  * Request handler.
 
 
4
  */
5
 
6
  namespace Crontrol;
src/schedule-list-table.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * List table for cron schedules.
4
- *
5
- * @package wp-crontrol
6
  */
7
 
8
  namespace Crontrol;
@@ -87,7 +85,7 @@ class Schedule_List_Table extends \WP_List_Table {
87
  /**
88
  * Returns an array of CSS class names for the table.
89
  *
90
- * @return string[] Array of class names.
91
  */
92
  protected function get_table_classes() {
93
  return array( 'widefat', 'fixed', 'striped', 'table-view-list', $this->_args['plural'] );
1
  <?php
2
  /**
3
  * List table for cron schedules.
 
 
4
  */
5
 
6
  namespace Crontrol;
85
  /**
86
  * Returns an array of CSS class names for the table.
87
  *
88
+ * @return array<int,string> Array of class names.
89
  */
90
  protected function get_table_classes() {
91
  return array( 'widefat', 'fixed', 'striped', 'table-view-list', $this->_args['plural'] );
src/schedule.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  /**
3
  * Functions related to schedules.
4
- *
5
- * @package wp-crontrol
6
  */
7
 
8
  namespace Crontrol\Schedule;
@@ -67,6 +65,12 @@ function delete( $name ) {
67
  * }>
68
  */
69
  function get() {
 
 
 
 
 
 
70
  $schedules = wp_get_schedules();
71
  uasort( $schedules, function( array $a, array $b ) {
72
  return ( $a['interval'] - $b['interval'] );
@@ -77,6 +81,14 @@ function get() {
77
  $schedule['is_too_frequent'] = ( $schedule['interval'] < WP_CRON_LOCK_TIMEOUT );
78
  } );
79
 
 
 
 
 
 
 
 
 
80
  return $schedules;
81
  }
82
 
1
  <?php
2
  /**
3
  * Functions related to schedules.
 
 
4
  */
5
 
6
  namespace Crontrol\Schedule;
65
  * }>
66
  */
67
  function get() {
68
+ /**
69
+ * @phpstan-var array<string,array{
70
+ * interval: int,
71
+ * display: string,
72
+ * }> $schedules
73
+ */
74
  $schedules = wp_get_schedules();
75
  uasort( $schedules, function( array $a, array $b ) {
76
  return ( $a['interval'] - $b['interval'] );
81
  $schedule['is_too_frequent'] = ( $schedule['interval'] < WP_CRON_LOCK_TIMEOUT );
82
  } );
83
 
84
+ /**
85
+ * @phpstan-var array<string,array{
86
+ * interval: int,
87
+ * display: string,
88
+ * name: string,
89
+ * is_too_frequent: bool,
90
+ * }> $schedules
91
+ */
92
  return $schedules;
93
  }
94
 
wp-crontrol.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: WP Crontrol enables you to view and control what's happening in the WP-Cron system.
6
  * Author: John Blackbourn & crontributors
7
  * Author URI: https://github.com/johnbillion/wp-crontrol/graphs/contributors
8
- * Version: 1.12.0
9
  * Text Domain: wp-crontrol
10
  * Domain Path: /languages/
11
  * Requires PHP: 5.3.6
@@ -26,7 +26,7 @@
26
  *
27
  * @package wp-crontrol
28
  * @author John Blackbourn <john@johnblackbourn.com> & Edward Dale <scompt@scompt.com>
29
- * @copyright Copyright 2008 Edward Dale, 2012-2021 John Blackbourn
30
  * @license http://www.gnu.org/licenses/gpl.txt GPL 2.0
31
  * @link https://wordpress.org/plugins/wp-crontrol/
32
  * @since 0.2
@@ -1795,6 +1795,17 @@ function populate_callback( array $callback ) {
1795
  $callback['name'] = $callback['function'] . '()';
1796
  }
1797
 
 
 
 
 
 
 
 
 
 
 
 
1798
  return $callback;
1799
  }
1800
 
@@ -2008,6 +2019,7 @@ function get_persistent_core_hooks() {
2008
  'recovery_mode_clean_expired_keys', // 5.2.0
2009
  'wp_site_health_scheduled_check', // 5.4.0
2010
  'wp_https_detection', // 5.7.0
 
2011
  );
2012
  }
2013
 
5
  * Description: WP Crontrol enables you to view and control what's happening in the WP-Cron system.
6
  * Author: John Blackbourn & crontributors
7
  * Author URI: https://github.com/johnbillion/wp-crontrol/graphs/contributors
8
+ * Version: 1.12.1
9
  * Text Domain: wp-crontrol
10
  * Domain Path: /languages/
11
  * Requires PHP: 5.3.6
26
  *
27
  * @package wp-crontrol
28
  * @author John Blackbourn <john@johnblackbourn.com> & Edward Dale <scompt@scompt.com>
29
+ * @copyright Copyright 2008 Edward Dale, 2012-2022 John Blackbourn
30
  * @license http://www.gnu.org/licenses/gpl.txt GPL 2.0
31
  * @link https://wordpress.org/plugins/wp-crontrol/
32
  * @since 0.2
1795
  $callback['name'] = $callback['function'] . '()';
1796
  }
1797
 
1798
+ if ( ! method_exists( '\QM_Util', 'populate_callback' ) && ! is_callable( $callback['function'] ) ) {
1799
+ $callback['error'] = new WP_Error(
1800
+ 'not_callable',
1801
+ sprintf(
1802
+ /* translators: %s: Function name */
1803
+ __( 'Function %s does not exist', 'wp-crontrol' ),
1804
+ $callback['name']
1805
+ )
1806
+ );
1807
+ }
1808
+
1809
  return $callback;
1810
  }
1811
 
2019
  'recovery_mode_clean_expired_keys', // 5.2.0
2020
  'wp_site_health_scheduled_check', // 5.4.0
2021
  'wp_https_detection', // 5.7.0
2022
+ 'wp_update_user_counts', // 6.0.0
2023
  );
2024
  }
2025