1 | <?php |
||||||
2 | |||||||
3 | namespace WP_Queue; |
||||||
4 | |||||||
5 | class Cron { |
||||||
6 | |||||||
7 | /** |
||||||
8 | * @var string |
||||||
9 | */ |
||||||
10 | protected $id; |
||||||
11 | |||||||
12 | /** |
||||||
13 | * @var Worker |
||||||
14 | */ |
||||||
15 | protected $worker; |
||||||
16 | |||||||
17 | /** |
||||||
18 | * @var int |
||||||
19 | */ |
||||||
20 | protected $interval; |
||||||
21 | |||||||
22 | /** |
||||||
23 | * Timestamp of when processing the queue started. |
||||||
24 | * |
||||||
25 | * @var int |
||||||
26 | */ |
||||||
27 | protected $start_time; |
||||||
28 | |||||||
29 | /** |
||||||
30 | * Cron constructor. |
||||||
31 | * |
||||||
32 | * @param string $id |
||||||
33 | * @param Worker $worker |
||||||
34 | * @param int $interval |
||||||
35 | */ |
||||||
36 | 1 | public function __construct( $id, $worker, $interval ) { |
|||||
37 | 1 | $this->id = strtolower( str_replace( '\\', '_', $id ) ); |
|||||
38 | 1 | $this->worker = $worker; |
|||||
39 | 1 | $this->interval = $interval; |
|||||
40 | 1 | } |
|||||
41 | |||||||
42 | /** |
||||||
43 | * Is the cron queue worker enabled? |
||||||
44 | * |
||||||
45 | * @return bool |
||||||
46 | */ |
||||||
47 | 1 | protected function is_enabled() { |
|||||
48 | 1 | if ( defined( 'DISABLE_WP_QUEUE_CRON' ) && DISABLE_WP_QUEUE_CRON ) { |
|||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
49 | return false; |
||||||
50 | } |
||||||
51 | |||||||
52 | 1 | return true; |
|||||
53 | } |
||||||
54 | |||||||
55 | /** |
||||||
56 | * Init cron class. |
||||||
57 | * |
||||||
58 | * @return bool |
||||||
59 | */ |
||||||
60 | 1 | public function init() { |
|||||
61 | 1 | if ( ! $this->is_enabled() ) { |
|||||
62 | return false; |
||||||
63 | } |
||||||
64 | |||||||
65 | 1 | add_filter( 'cron_schedules', array( $this, 'schedule_cron' ) ); |
|||||
66 | 1 | add_action( $this->id, array( $this, 'cron_worker' ) ); |
|||||
67 | |||||||
68 | 1 | if ( ! wp_next_scheduled( $this->id ) ) { |
|||||
69 | // Schedule health check |
||||||
70 | wp_schedule_event( time(), $this->id, $this->id ); |
||||||
0 ignored issues
–
show
The function
wp_schedule_event was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
71 | } |
||||||
72 | |||||||
73 | 1 | return true; |
|||||
74 | } |
||||||
75 | |||||||
76 | /** |
||||||
77 | * Add interval to cron schedules. |
||||||
78 | * |
||||||
79 | * @param array $schedules |
||||||
80 | * |
||||||
81 | * @return array |
||||||
82 | */ |
||||||
83 | public function schedule_cron( $schedules ) { |
||||||
84 | $schedules[ $this->id ] = array( |
||||||
85 | 'interval' => MINUTE_IN_SECONDS * $this->interval, |
||||||
0 ignored issues
–
show
|
|||||||
86 | 'display' => sprintf( __( 'Every %d Minutes' ), $this->interval ), |
||||||
87 | ); |
||||||
88 | |||||||
89 | return $schedules; |
||||||
90 | } |
||||||
91 | |||||||
92 | /** |
||||||
93 | * Process any jobs in the queue. |
||||||
94 | */ |
||||||
95 | public function cron_worker() { |
||||||
96 | if ( $this->is_worker_locked() ) { |
||||||
97 | return; |
||||||
98 | } |
||||||
99 | |||||||
100 | $this->start_time = time(); |
||||||
101 | |||||||
102 | $this->lock_worker(); |
||||||
103 | |||||||
104 | while ( ! $this->time_exceeded() && ! $this->memory_exceeded() ) { |
||||||
105 | if ( ! $this->worker->process() ) { |
||||||
106 | break; |
||||||
107 | } |
||||||
108 | } |
||||||
109 | |||||||
110 | $this->unlock_worker(); |
||||||
111 | } |
||||||
112 | |||||||
113 | /** |
||||||
114 | * Is the cron worker locked? |
||||||
115 | * |
||||||
116 | * @return bool |
||||||
117 | */ |
||||||
118 | protected function is_worker_locked() { |
||||||
119 | return (bool) get_site_transient( $this->id ); |
||||||
0 ignored issues
–
show
The function
get_site_transient was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
120 | } |
||||||
121 | |||||||
122 | /** |
||||||
123 | * Lock the cron worker. |
||||||
124 | */ |
||||||
125 | protected function lock_worker() { |
||||||
126 | set_site_transient( $this->id, time(), 300 ); |
||||||
0 ignored issues
–
show
The function
set_site_transient was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
127 | } |
||||||
128 | |||||||
129 | /** |
||||||
130 | * Unlock the cron worker. |
||||||
131 | */ |
||||||
132 | protected function unlock_worker() { |
||||||
133 | delete_site_transient( $this->id ); |
||||||
0 ignored issues
–
show
The function
delete_site_transient was not found. Maybe you did not declare it correctly or list all dependencies?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
134 | } |
||||||
135 | |||||||
136 | /** |
||||||
137 | * Memory exceeded |
||||||
138 | * |
||||||
139 | * Ensures the worker process never exceeds 80% |
||||||
140 | * of the maximum allowed PHP memory. |
||||||
141 | * |
||||||
142 | * @return bool |
||||||
143 | */ |
||||||
144 | protected function memory_exceeded() { |
||||||
145 | $memory_limit = $this->get_memory_limit() * 0.8; // 80% of max memory |
||||||
146 | $current_memory = memory_get_usage( true ); |
||||||
147 | $return = false; |
||||||
148 | |||||||
149 | if ( $current_memory >= $memory_limit ) { |
||||||
150 | $return = true; |
||||||
151 | } |
||||||
152 | |||||||
153 | return apply_filters( 'wp_queue_cron_memory_exceeded', $return ); |
||||||
154 | } |
||||||
155 | |||||||
156 | /** |
||||||
157 | * Get memory limit. |
||||||
158 | * |
||||||
159 | * @return int |
||||||
160 | */ |
||||||
161 | protected function get_memory_limit() { |
||||||
162 | if ( function_exists( 'ini_get' ) ) { |
||||||
163 | $memory_limit = ini_get( 'memory_limit' ); |
||||||
164 | } else { |
||||||
165 | $memory_limit = '256M'; |
||||||
166 | } |
||||||
167 | |||||||
168 | if ( ! $memory_limit || - 1 == $memory_limit ) { |
||||||
169 | // Unlimited, set to 1GB |
||||||
170 | $memory_limit = '1000M'; |
||||||
171 | } |
||||||
172 | |||||||
173 | return intval( $memory_limit ) * 1024 * 1024; |
||||||
174 | } |
||||||
175 | |||||||
176 | /** |
||||||
177 | * Time exceeded |
||||||
178 | * |
||||||
179 | * Ensures the worker never exceeds a sensible time limit (20s by default). |
||||||
180 | * A timeout limit of 30s is common on shared hosting. |
||||||
181 | * |
||||||
182 | * @return bool |
||||||
183 | */ |
||||||
184 | protected function time_exceeded() { |
||||||
185 | $finish = $this->start_time + apply_filters( 'wp_queue_cron_time_limit', 20 ); // 20 seconds |
||||||
186 | $return = false; |
||||||
187 | |||||||
188 | if ( time() >= $finish ) { |
||||||
189 | $return = true; |
||||||
190 | } |
||||||
191 | |||||||
192 | return apply_filters( 'wp_queue_cron_time_exceeded', $return ); |
||||||
193 | } |
||||||
194 | } |