HEX
Server: nginx/1.18.0
System: Linux iZj6c1ieg2jrpk1z5tzi19Z 6.3.9-1.el7.elrepo.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 21 22:18:40 EDT 2023 x86_64
User: www (1001)
PHP: 8.2.4
Disabled: passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv
Upload Files
File: /www/wwwroot/www.cytocare.cn/wp-content/plugins/wpjam-basic/components/wpjam-crons.php
<?php
/*
Name: 定时作业
URI: https://mp.weixin.qq.com/s/mSqzZdslhxwkNHGRpa3WmA
Description: 定时作业让你可以可视化管理 WordPress 的定时作业
Version: 2.0
*/
class WPJAM_Cron extends WPJAM_Args{
	public function callback(){
		if(wpjam_lock($this->hook.'_lock', 5, true)){
			return;
		}

		$queue = $this->queue();

		if($queue){
			$count		= wpjam_increment($this->get_count('name'));
			$index		= wpjam_increment($this->hook.'_index', count($queue));
			$callback	= array_column($queue, 'callback')[$index];

			if(is_callable($callback)){
				$callback();
			}else{
				trigger_error('invalid_job_callback'.var_export($callback, true));
			}
		}
	}

	public function queue($jobs=null){
		$jobs	??= $this->jobs;
		$jobs	= is_callable($jobs) ? $jobs() : $jobs;
		$jobs	= array_values($jobs);
		$queue	= [];

		if($this->weight){
			foreach($jobs as $job){
				if(is_array($job) && wpjam_get($job, 'weight') > 1){
					$job['weight'] --;

					$queue[]	= $job;	
				}
			}
		}

		return array_merge($jobs, ($queue ? $this->queue($queue) : []));
	}

	public function get_count($output=''){
		$name	= $this->hook.'_counter:'.wpjam_date('Y-m-d');

		return $output == 'name' ? $name : (get_transient($name) ?: 0);
	}

	public static function is_scheduled($hook) {	// 不用判断参数
		return array_any(self::get_all(), fn($cron)=> isset($cron[$hook]));
	}

	public static function schedule($data){
		$args	= [$data['time'], $data['hook'], $data['args'] ?? []];

		if($data['recurrence']){
			wp_schedule_event(...wpjam_add_at($args, 1, $data['recurrence']));
		}else{
			wp_schedule_single_event(...$args);
		}

		return true;
	}

	public static function cleanup(){
		$invalid	= 0;

		foreach(self::get_all() as $ts => $cron){
			foreach($cron as $hook => $dings){
				if(!has_filter($hook)){	// 系统不存在的定时作业,清理掉
					array_walk($dings, fn($data)=> wp_unschedule_event($ts, $hook, $data['args']));

					$invalid++;
				}
			}
		}

		return $invalid;
	}

	public static function get($id){
		[$ts, $hook, $key]	= explode('--', $id);

		$data	= self::get_all()[$ts][$hook][$key] ?? [];

		return $data ? [
			'hook'		=> $hook,
			'timestamp'	=> $ts,
			'time'		=> wpjam_date('Y-m-d H:i:s', $ts),
			'cron_id'	=> $id,
			'schedule'	=> $data['schedule'] ?? '',
			'args'		=> $data['args'] ?? []
		] : [];
	}

	public static function insert($data){
		if(!has_filter($data['hook'])){
			wp_die('无效的 Hook');
		}

		return self::schedule($data);
	}

	public static function do($id){
		$data	= self::get($id);

		return $data ? (wpjam_throw_if_error(do_action_ref_array($data['hook'], $data['args'])) || true) : true;
	}

	public static function delete($id){
		$data = self::get($id);

		return $data ? wp_unschedule_event($data['timestamp'], $data['hook'], $data['args']) : true;
	}

	public static function get_all(){
		return _get_cron_array() ?: [];
	}

	public static function get_jobs(){
		$day	= (wpjam_date('H') > 2 && wpjam_date('H') < 6) ? 0 : 1;

		return array_filter(wpjam_get_items('cron_job'), fn($job)=> $job['day'] == -1 || $job['day'] == $day);
	}

	public static function add_job($name, $args=[]){
		$args	= is_array($args) ? $args : (is_numeric($args) ? ['weight'=>$args] : []);

		if(is_callable($name)){
			$args['callback']	= $name;

			if(is_object($name)){
				$name	= get_class($name);
			}elseif(is_array($name)){
				$name[0]= is_object($name[0]) ? get_class($name[0]) : $name[0];
				$name	= implode(':', $name);
			}
		}else{
			if(empty($args['callback']) || !is_callable($args['callback'])){
				return null;
			}
		}

		if(!wpjam_get_items('cron_job')){
			self::add('wpjam_scheduled', [
				'recurrence'	=> 'five_minutes',
				'jobs'			=> [self::class, 'get_jobs'],
				'weight'		=> true
			]);
		}

		return wpjam_add_item('cron_job', $name, wp_parse_args($args, ['weight'=>1, 'day'=>-1]));
	}

	public static function query_items($args){
		if($GLOBALS['current_tab'] == 'crons'){
			foreach(self::get_all() as $ts => $cron){
				foreach($cron as $hook => $dings){
					foreach($dings as $key => $data){
						$items[] = [
							'cron_id'	=> $ts.'--'.$hook.'--'.$key,
							'time'		=> wpjam_date('Y-m-d H:i:s', $ts),
							'hook'		=> $hook,
							'schedule'	=> $data['schedule'] ?? ''
						];
					}
				}
			}

			return $items ?? [];
		}else{
			return array_values(wpjam_map(wpjam_get_items('cron_job'), fn($item, $name)=> $item+[
				'job_id'	=> $name,
				'function'	=> wpjam_render_callback($item['callback'])
			]));
		}
	}

	public static function get_actions(){
		return $GLOBALS['current_tab'] == 'crons' ? [
			'add'		=> ['title'=>'新建',		'response'=>'list'],
			'do'		=> ['title'=>'立即执行',	'direct'=>true,	'confirm'=>true,	'bulk'=>2],
			'delete'	=> ['title'=>'删除',		'direct'=>true,	'confirm'=>true,	'bulk'=>true,	'response'=>'list']
		] : [];
	}

	public static function get_fields($action_key='', $id=0){
		return $GLOBALS['current_tab'] == 'crons' ? [
			'hook'		=> ['title'=>'Hook',	'type'=>'text',		'show_admin_column'=>true],
			'time'		=> ['title'=>'运行时间',	'type'=>'timestamp','show_admin_column'=>true,	'value'=>time()],
			'schedule'	=> ['title'=>'频率',		'type'=>'select',	'show_admin_column'=>true,	'options'=>[''=>'只执行一次']+wp_list_pluck(wp_get_schedules(), 'display')],
		] : [
			'function'	=> ['title'=>'回调函数',	'type'=>'view',	'show_admin_column'=>true],
			'weight'	=> ['title'=>'作业权重',	'type'=>'view',	'show_admin_column'=>true],
			'day'		=> ['title'=>'运行时间',	'type'=>'view',	'show_admin_column'=>true,	'options'=>['-1'=>'全天','1'=>'白天','0'=>'晚上']],
		];
	}

	public static function get_tabs(){
		$tabs['crons']	= [
			'title'			=> '定时作业',
			'order'			=> 20,
			'function'		=> 'list',
			'list_table'	=> [
				'plural'		=> 'crons',
				'singular'		=> 'cron',
				'model'			=> self::class,
				'primary_key'	=> 'cron_id',
			]
		];

		$cron	= wpjam_get_cron('wpjam_scheduled');

		if($cron){
			$tabs['jobs']	= [
				'title'			=> '作业列表',
				'summary'		=> '今天已经运行 <strong>'.$cron->get_count().'</strong> 次',
				'function'		=> 'list',
				'list_table'	=> [
					'plural'		=> 'jobs',
					'singular'		=> 'job',
					'primary_key'	=> 'job_id',
					'model'			=> 'WPJAM_Cron',
				],
			];
		}

		return $tabs;
	}

	public static function add($hook, $args){
		$args	+= ['hook'=>$hook, 'time'=>time(), 'recurrence'=>false, 'callback'=>''];
		$object	= $args['callback'] ? null : wpjam_add_instance('cron', $hook, new self($args));

		add_action($hook, $args['callback'] ?: [$object, 'callback']);

		if(!self::is_scheduled($hook)){
			self::schedule($args);
		}

		return $object;
	}

	public static function add_hooks(){
		add_filter('cron_schedules', fn($schedules)=> array_merge($schedules, [
			'five_minutes'		=> ['interval'=>300,	'display'=>'每5分钟一次'],
			'fifteen_minutes'	=> ['interval'=>900,	'display'=>'每15分钟一次'],
		]));

		if(is_admin()){
			add_action('wpjam_admin_init', fn()=> wpjam_add_menu_page('wpjam-crons',	[
				'parent'		=> 'wpjam-basic',
				'menu_title'	=> '定时作业',
				'order'			=> 9,
				'summary'		=> __FILE__,
				'function'		=> 'tab',
				'network'		=> false,
				'tabs'			=> [self::class, 'get_tabs']
			]));
		}
	}
}

function wpjam_register_cron($name, $args=[]){
	if(is_callable($name)){
		return wpjam_register_job($name, $args);
	}

	return WPJAM_Cron::add($name, $args);
}

function wpjam_get_cron($name){
	return wpjam_get_instance('cron', $name);
}

function wpjam_register_job($name, $args=[]){
	return WPJAM_Cron::add_job($name, $args);
}

function wpjam_is_scheduled_event($hook){
	return WPJAM_Cron::is_scheduled($hook);
}

WPJAM_Cron::add_hooks();