PluginProbe
WPJAM Basic / trunk
WPJAM Basic vtrunk
wpjam-basic / components / wpjam-crons.php

wpjam-crons.php in WPJAM Basic trunk, at components/wpjam-crons.php

220 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Name: 定时作业
4 URI: https://mp.weixin.qq.com/s/mSqzZdslhxwkNHGRpa3WmA
5 Description: 定时作业让你可以可视化管理 WordPress 的定时作业
6 Version: 2.0
7 */
8 class WPJAM_Cron extends WPJAM_Args{
9 public function __invoke(){
10 if(wpjam_lock($this->hook.'_lock', 10, true)){
11 return;
12 }
13
14 $jobs = $this->get_jobs();
15
16 if($this->weight){
17 $queue = $jobs;
18 $i = 0;
19
20 while($queue){
21 $i++;
22
23 $queue = array_filter($queue, fn($job)=> is_array($job) && wpjam_get($job, 'weight') >= $i);
24 $jobs = array_merge($jobs, $queue);
25 }
26 }
27
28 $count = $this->get_count(true);
29 $index = $count % count($jobs);
30 $callback = $jobs[$index]['callback'];
31
32 is_callable($callback) && $callback();
33 }
34
35 public function get_jobs(){
36 return array_values(maybe_callback($this->jobs));
37 }
38
39 public function get_count($increment=false){
40 $name = $this->hook.'_counter:'.wpjam_date('Y-m-d');
41
42 return $increment ? wpjam_increment($name) : (get_transient($name) ?: 0);
43 }
44
45 public static function cleanup(){
46 $invalid = 0;
47
48 foreach(self::get_all() as $ts => $cron){
49 foreach($cron as $hook => $dings){
50 if(!has_filter($hook)){ // 系统不存在的定时作业,�
51 理掉
52 array_walk($dings, fn($data)=> wp_unschedule_event($ts, $hook, $data['args']));
53
54 $invalid++;
55 }
56 }
57 }
58
59 return $invalid;
60 }
61
62 public static function get($id){
63 $data = wpjam_get(self::get_all(), $id);
64 $args = wpjam_lines($id, '[', fn($v)=> trim($v, ']'));
65
66 return $data ? [
67 'hook' => $args[1],
68 'timestamp' => $args[0],
69 'time' => wpjam_date('Y-m-d H:i:s', $args[0]),
70 'cron_id' => $id,
71 'schedule' => $data['schedule'] ?? '',
72 'args' => $data['args'] ?? []
73 ] : [];
74 }
75
76 public static function insert($data){
77 !has_filter($data['hook']) && wp_die('无效的 Hook');
78
79 return wpjam_schedule($data['hook'], $data);
80 }
81
82 public static function do($id){
83 return ($data = self::get($id)) ? (do_action_ref_array($data['hook'], $data['args']) || true) : true;
84 }
85
86 public static function delete($id){
87 return ($data = self::get($id)) ? wp_unschedule_event($data['timestamp'], $data['hook'], $data['args']) : true;
88 }
89
90 public static function get_all(){
91 return _get_cron_array() ?: [];
92 }
93
94 public static function query_items($args){
95 if($GLOBALS['current_tab'] == 'crons'){
96 foreach(self::get_all() as $ts => $cron){
97 foreach($cron as $hook => $dings){
98 foreach($dings as $key => $data){
99 $items[] = [
100 'cron_id' => $ts.'['.$hook.']['.$key.']',
101 'time' => wpjam_date('Y-m-d H:i:s', $ts),
102 'hook' => $hook,
103 'schedule' => $data['schedule'] ?? ''
104 ];
105 }
106 }
107 }
108
109 return $items;
110 }
111
112 return wpjam_map(wpjam_get_cron('wpjam_scheduled')->get_jobs(), fn($item)=> $item+wpjam_map([
113 'job_id' => 'uniqid',
114 'function' => 'render'
115 ], fn($v)=> wpjam_callback($v, $item['callback'])));
116 }
117
118 public static function get_actions(){
119 return $GLOBALS['current_tab'] == 'crons' ? [
120 'add' => ['title'=>'新建', 'response'=>'list'],
121 'do' => ['title'=>'立即执行', 'direct'=>true, 'confirm'=>true, 'bulk'=>2],
122 'delete' => ['title'=>'删除', 'direct'=>true, 'confirm'=>true, 'bulk'=>true, 'response'=>'list']
123 ] : [];
124 }
125
126 public static function get_fields($action_key='', $id=0){
127 return $GLOBALS['current_tab'] == 'crons' ? [
128 'hook' => ['title'=>'Hook', 'type'=>'text', 'show_admin_column'=>true],
129 'time' => ['title'=>'运行时间', 'type'=>'timestamp','show_admin_column'=>true, 'value'=>time()],
130 'schedule' => ['title'=>'频率', 'type'=>'select', 'show_admin_column'=>true, 'options'=>[''=>'只执行一次']+wp_list_pluck(wp_get_schedules(), 'display')],
131 ] : [
132 'function' => ['title'=>'回调函数', 'type'=>'view', 'show_admin_column'=>true],
133 'weight' => ['title'=>'作业权重', 'type'=>'view', 'show_admin_column'=>true],
134 ];
135 }
136
137 public static function get_tabs(){
138 return ['crons' => [
139 'title' => '定时作业',
140 'order' => 20,
141 'function' => 'list',
142 'list_table' => [
143 'plural' => 'crons',
144 'singular' => 'cron',
145 'model' => self::class,
146 'primary_key' => 'cron_id',
147 ]
148 ]]+(wpjam_get_cron('wpjam_scheduled') ? ['jobs' => [
149 'title' => '作业列表',
150 'function' => 'list',
151 'list_table' => [
152 'model' => self::class,
153 'plural' => 'jobs',
154 'singular' => 'job',
155 'primary_key' => 'job_id',
156 'per_page' => 1000,
157 'summary' => fn()=> '今天已经运行 <strong>'.wpjam_get_cron('wpjam_scheduled')->get_count().'</strong> 次',
158 ]
159 ]] : []);
160 }
161
162 public static function add_hooks(){
163 wpjam_hook('cron_schedules', '+', [
164 'five_minutes' => ['interval'=>300, 'display'=>'每5分钟一次'],
165 'fifteen_minutes' => ['interval'=>900, 'display'=>'每15分钟一次']
166 ]);
167 }
168 }
169
170 function wpjam_register_cron($hook, $args=[]){
171 if(is_callable($hook)){
172 return wpjam_register_job($hook, $args);
173 }
174
175 $cb = ($args['callback'] ?? '') ?: wpjam_register('WPJAM_Cron', $hook, $args+['hook'=>$hook]);
176
177 add_action($hook, $cb);
178
179 wpjam_is_scheduled_event($hook) || wpjam_schedule_event($hook, $args);
180
181 return $cb;
182 }
183
184 function wpjam_register_job($job, $args=[]){
185 $args = is_array($args) ? $args : (is_numeric($args) ? ['weight'=>$args] : []);
186 $args = array_merge($args, is_callable($job) ? ['callback'=>$job] : []);
187
188 if(!empty($args['callback']) && is_callable($args['callback'])){
189 $cron = 'wpjam_scheduled';
190 $cron = wpjam_get_cron($cron) ?: wpjam_register_cron($cron, ['recurrence'=>'five_minutes', 'weight'=>true]);
191
192 return $cron->update_arg('jobs[]', wp_parse_args($args, ['weight'=>1, 'day'=>-1]));
193 }
194 }
195
196 function wpjam_get_cron($hook){
197 return wpjam_get_registered('WPJAM_Cron', $hook);
198 }
199
200 function wpjam_schedule_event($hook, $data){
201 $args = array_filter([$data['recurrence'] ?? '']);
202 $cb = 'wp_schedule_'.($args ? '' : 'single_').'event';
203
204 return $cb($data['timestamp'] ?? time(), ...[...$args, $hook, $data['args'] ?? []]);
205 }
206
207 function wpjam_is_scheduled_event($hook){ // 不用判断参数
208 return array_any(WPJAM_Cron::get_all(), fn($cron)=> isset($cron[$hook]));
209 }
210
211 wpjam_add_menu_page('wpjam-crons', [
212 'parent' => 'wpjam-basic',
213 'menu_title' => '定时作业',
214 'order' => 9,
215 'summary' => __FILE__,
216 'network' => false,
217 'function' => 'tab',
218 'model' => 'WPJAM_Cron'
219 ]);
220