CrontabRepository.php
5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<?php
namespace common\components\crontabs;
use Exception;
use InvalidArgumentException;
use LogicException;
use function set_error_handler;
use function preg_match;
use function restore_error_handler;
use function array_push;
use function array_search;
use function strtoupper;
use function substr;
use function explode;
use function in_array;
/**
* Class CrontabRepository
* 任务仓库
* Access and manage CrontabJob Objects (add, modify, delete).
* 访问和管理CrontabJob对象(添加,修改,删除)
* @package common\components\crontabs
*/
class CrontabRepository
{
private $crontabAdapter;
private $crontabJobs = [];
/**
* 任务文件顶部的注释
* @var string
*/
public $headerComments;
/**
* 解析定时任务的时候,排除不是任务命令
* @var array
*/
public $crontabLinesToBypass = [
//用来代表解析默认的Ubuntu任务头部例子
'# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/'
];
/**
* 实例化一个CrontabRepository仓库实例
* CrontabAdapter用来提供系统的"crontab"命令行
* @param CrontabAdapter $crontabAdapter
*/
public function __construct(CrontabAdapter $crontabAdapter)
{
$this->crontabAdapter = $crontabAdapter;
$this->readCrontab();
}
/**
* 返回所有定时任务实例
* @return array CrontabJobs数组
*/
public function getJobs()
{
return $this->crontabJobs;
}
/**
* 通过命令行特征来查找任务实例
*
* @param String $regex
* @throws InvalidArgumentException
* @return array CrontabJobs数组
*/
public function findJobByRegex($regex)
{
/* Test if regex is valid */
set_error_handler(function ($severity, $message, $file, $line) {
throw new Exception($message);
});
try {
preg_match($regex, 'test');
restore_error_handler();
} catch (Exception $e) {
restore_error_handler();
throw new InvalidArgumentException('Not a valid Regex : ' . $e->getMessage());
}
$crontabJobs = [];
if (!empty($this->crontabJobs)) {
foreach ($this->crontabJobs as $crontabJob) {
if (preg_match($regex, $crontabJob->formatCrontabLine())) {
array_push($crontabJobs, $crontabJob);
}
}
}
return $crontabJobs;
}
/**
* 新增一个定时任务
* @param CrontabJob $crontabJob
*/
public function addJob(CrontabJob $crontabJob)
{
if (array_search($crontabJob, $this->crontabJobs) !== false) {
$exceptionMessage = 'This job is already in the crontab. Please consider cloning the'
. 'CrontabJob object if you want it to be registered twice.'
;
throw new LogicException($exceptionMessage);
}
array_push($this->crontabJobs, $crontabJob);
}
/**
* 移除一个CrontabJob定时任务
* @param CrontabJob $crontabJob
*/
public function removeJob(CrontabJob $crontabJob)
{
$jobKey = array_search($crontabJob, $this->crontabJobs, true);
if ($jobKey === false) {
throw new LogicException('This job is not part of this crontab');
}
unset($this->crontabJobs[$jobKey]);
}
/**
* 清空定时任务
*/
public function clearJob()
{
$this->crontabJobs = [];
}
/**
* 保存所有活动任务的选项,并启动
*/
public function persist()
{
$crontabRawData = '';
if (!empty($this->headerComments)) {
$crontabRawData .= $this->headerComments;
}
if (!empty($this->crontabJobs)) {
foreach ($this->crontabJobs as $crontabJob) {
try {
$crontabLine = $crontabJob->formatCrontabLine();
$crontabRawData .= ($crontabLine . "\n");
} catch (Exception $e) {
;
}
}
}
$this->crontabAdapter->writeCrontab($crontabRawData);
}
/**
* 读取系统的原命令行并解析它,
* 解析好的命令会自动放入 $this->crontabJobs数组中
*/
private function readCrontab()
{
// windows系统直接返回
if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'){
return;
}
$crontabRawData = $this->crontabAdapter->readCrontab();
if (empty($crontabRawData)) {
return;
}
$crontabRawLines = explode("\n", $crontabRawData);
foreach ($crontabRawLines as $crontabRawLine) {
try {
//使用任务工厂方法来测试当前命令行是否是定时任务命令
$crontabJob = CrontabJob::createFromCrontabLine($crontabRawLine);
$isCrontabJob = true;
} catch (Exception $e) {
$isCrontabJob = false;
}
if ($isCrontabJob && !in_array($crontabRawLine, $this->crontabLinesToBypass)) {
array_push($this->crontabJobs, $crontabJob);
} else {
//如果没有任何的crontabjobs,那么该行就是头部注释
if (empty($this->crontabJobs)) {
if (empty($this->headerComments)) {
$this->headerComments = $crontabRawLine . "\n";
} else {
$this->headerComments .= ($crontabRawLine . "\n");
}
}
}
}
}
}