PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / trunk
Code Profiler – WordPress Performance Profiling and Debugging Made Easy vtrunk
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
code-profiler / wp-cron.php

wp-cron.php in Code Profiler – WordPress Performance Profiling and Debugging Made Easy trunk, at wp-cron.php

189 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * A pseudo-cron daemon for scheduling WordPress tasks.
4 *
5 * WP-Cron is triggered when the site receives a visit. In the scenario
6 * where a site may not receive enough visits to execute scheduled tasks
7 * in a timely manner, this file can be called directly or via a server
8 * cron daemon for X number of times.
9 *
10 * Defining DISABLE_WP_CRON as true and calling this file directly are
11 * mutually exclusive and the latter does not rely on the former to work.
12 *
13 * The HTTP request to this file will not slow down the visitor who happens to
14 * visit when a scheduled cron event runs.
15 *
16 * @package WordPress
17 */
18
19 ignore_user_abort( true );
20
21 if ( ! headers_sent() ) {
22 header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
23 header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
24 }
25
26 $response['status'] = 'error';
27
28 if (! empty( $_POST ) || defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) ) {
29 $response['message'] = 'Error: Cannot start wp-cron.';
30 // wp_send_json is not loaded yet.
31 echo json_encode( $response );
32 exit;
33 }
34
35 /**
36 * Tell WordPress the cron task is running.
37 */
38 define( 'DOING_CRON', true );
39
40 /**
41 * Load WordPress bootstrap file and our MU plugin.
42 */
43 if (! is_file( __DIR__ .'/tmp/profiler.inc.php') ) {
44 $response['message'] = 'Error: Cannot find [/tmp/profiler.inc.php].';
45 echo json_encode( $response );
46 exit;
47 }
48 include_once __DIR__ .'/tmp/profiler.inc.php';
49 require_once ABSPATH . 'wp-load.php';
50
51 /**
52 * No one else is allowed to run this script.
53 * Full verification is done by the MU plugin.
54 */
55 if (! isset( $_REQUEST['CODE_PROFILER_ON'] ) ||
56 ! preg_match('/^\d{10}\.\d+$/', $_REQUEST['CODE_PROFILER_ON'] ) ) {
57
58 $response['message'] = 'Not allowed.';
59 wp_send_json( $response );
60 }
61
62 /**
63 * Make sure we have a valid cron task.
64 */
65 if ( empty( $_GET['wpcron'] ) ) {
66 $response['message'] = 'Error: No cron event selected.';
67 wp_send_json( $response );
68 }
69
70 /**
71 * Get the event to run.
72 */
73 $wpcron = trim( $_GET['wpcron'] );
74 $crons = [];
75 $wpcrons = _get_cron_array();
76
77 foreach ( $wpcrons as $timestamp => $cronhooks ) {
78 foreach ( $cronhooks as $hook => $keys ) {
79 if ( $hook == $wpcron ) {
80 $time = (int) microtime( true );
81 /**
82 * There could be multiple cron events scheduled at the same time.
83 */
84 $crons[ $time - 10 ][ $hook ] = $keys;
85 break 2;
86 }
87 }
88 }
89 if ( empty( $crons ) ) {
90 $response['message'] = 'Error: Cannot find the requested cron event.';
91 wp_send_json( $response );
92 }
93
94 // Attempt to raise the PHP memory limit for cron event processing.
95 wp_raise_memory_limit( 'cron' );
96
97 /**
98 * Retrieves the cron lock.
99 *
100 * Returns the uncached `doing_cron` transient.
101 *
102 * @ignore
103 * @since 3.3.0
104 *
105 * @global wpdb $wpdb WordPress database abstraction object.
106 *
107 * @return string|int|false Value of the `doing_cron` transient, 0|false otherwise.
108 */
109 function _get_cron_lock() {
110 global $wpdb;
111
112 $value = 0;
113 if ( wp_using_ext_object_cache() ) {
114 /*
115 * Skip local cache and force re-fetch of doing_cron transient
116 * in case another process updated the cache.
117 */
118 $value = wp_cache_get( 'doing_cron', 'transient', true );
119 } else {
120 $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", '_transient_doing_cron' ) );
121 if ( is_object( $row ) ) {
122 $value = $row->option_value;
123 }
124 }
125
126 return $value;
127 }
128
129 $gmt_time = microtime( true );
130 /**
131 * The cron lock: a unix timestamp from when the cron was spawned.
132 */
133 $doing_cron_transient = get_transient( 'doing_cron' );
134 /**
135 * Use global $doing_wp_cron lock, otherwise use the GET lock. If no lock, try to grab a new lock.
136 */
137 if ( empty( $doing_wp_cron ) ) {
138 if ( empty( $_GET['doing_wp_cron'] ) ) {
139 // Called from external script/job. Try setting a lock.
140 if ( $doing_cron_transient && ( $doing_cron_transient + WP_CRON_LOCK_TIMEOUT > $gmt_time ) ) {
141 $response['message'] = 'Error: WordPress cannot set a lock.';
142 wp_send_json( $response );
143 }
144 $doing_wp_cron = sprintf( '%.22F', microtime( true ) );
145 $doing_cron_transient = $doing_wp_cron;
146 set_transient( 'doing_cron', $doing_wp_cron );
147 } else {
148 $doing_wp_cron = $_GET['doing_wp_cron'];
149 }
150 }
151
152 /*
153 * The cron lock (a unix timestamp set when the cron was spawned),
154 * must match $doing_wp_cron (the "key").
155 */
156 if ( $doing_cron_transient !== $doing_wp_cron ) {
157 $response['message'] = 'Error: Transients do not match.';
158 wp_send_json( $response );
159 }
160
161 foreach ( $crons as $timestamp => $cronhooks ) {
162 foreach ( $cronhooks as $hook => $keys ) {
163 foreach ( $keys as $k => $v ) {
164 /**
165 * Fires scheduled events.
166 *
167 * @ignore
168 * @since 2.1.0
169 *
170 * @param string $hook Name of the hook that was scheduled to be fired.
171 * @param array $args The arguments to be passed to the hook.
172 */
173 do_action_ref_array( $hook, $v['args'] );
174
175 // If the hook ran too long and another cron process stole the lock, quit.
176 if ( _get_cron_lock() !== $doing_wp_cron ) {
177 $response['message'] = 'Error: The hook ran too long.';
178 wp_send_json( $response );
179 }
180 }
181 }
182 }
183
184 if ( _get_cron_lock() === $doing_wp_cron ) {
185 delete_transient( 'doing_cron' );
186 }
187
188 die();
189