1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Backend\Core\Engine\Base; |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of Fork CMS. |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the license |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
13
|
|
|
use Backend\Core\Engine\Exception as BackendException; |
14
|
|
|
use Backend\Core\Engine\Model as BackendModel; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* This is the base-object for cronjobs. The module-specific cronjob-files can extend the functionality from this class |
18
|
|
|
*/ |
19
|
|
|
class Cronjob extends Object |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* The current id |
23
|
|
|
* |
24
|
|
|
* @var int |
25
|
|
|
*/ |
26
|
|
|
protected $id; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Clear/removed the busy file |
30
|
|
|
*/ |
31
|
|
|
protected function clearBusyFile() |
32
|
|
|
{ |
33
|
|
|
$path = $this->getCacheDirectory() . $this->getId() . '.busy'; |
34
|
|
|
|
35
|
|
|
// remove the file |
36
|
|
|
$fs = new Filesystem(); |
37
|
|
|
$fs->remove($path); |
38
|
|
|
} |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @return string |
42
|
|
|
*/ |
43
|
|
|
protected function getCacheDirectory() |
44
|
|
|
{ |
45
|
|
|
return BackendModel::getContainer()->getParameter('kernel.cache_dir') . '/cronjobs/'; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
public function execute() |
49
|
|
|
{ |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Get the id |
54
|
|
|
* |
55
|
|
|
* @return int |
56
|
|
|
*/ |
57
|
|
|
public function getId() |
58
|
|
|
{ |
59
|
|
|
return mb_strtolower($this->getModule() . '_' . $this->getAction()); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Set the action |
64
|
|
|
* |
65
|
|
|
* We can't rely on the parent setModule function, because a cronjob requires no login |
66
|
|
|
* |
67
|
|
|
* @param string $action The action to load. |
68
|
|
|
* @param string $module The module to load. |
69
|
|
|
* |
70
|
|
|
* @throws BackendException If module is not set or the action does not exist |
71
|
|
|
*/ |
72
|
|
|
public function setAction($action, $module = null) |
73
|
|
|
{ |
74
|
|
|
// set module |
75
|
|
|
if ($module !== null) { |
76
|
|
|
$this->setModule($module); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
// check if module is set |
80
|
|
|
if ($this->getModule() === null) { |
81
|
|
|
throw new BackendException('Module has not yet been set.'); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
// path to look for actions based on the module |
85
|
|
|
if ($this->getModule() == 'Core') { |
86
|
|
|
$path = BACKEND_CORE_PATH . '/Cronjobs'; |
87
|
|
|
} else { |
88
|
|
|
$path = BACKEND_MODULES_PATH . '/' . $this->getModule() . '/Cronjobs'; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// check if file exists |
92
|
|
|
if (!is_file($path . '/' . $action . '.php')) { |
93
|
|
|
header('HTTP/1.1 403 Forbidden'); |
94
|
|
|
throw new BackendException('Action not allowed.'); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
// set property |
98
|
|
|
$this->action = (string) $action; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Set the busy file |
103
|
|
|
*/ |
104
|
|
|
protected function setBusyFile() |
105
|
|
|
{ |
106
|
|
|
// do not set busy file in debug mode |
107
|
|
|
if ($this->getContainer()->getParameter('kernel.debug')) { |
108
|
|
|
return; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
// build path |
112
|
|
|
$fs = new Filesystem(); |
113
|
|
|
$path = $this->getCacheDirectory() . $this->getId() . '.busy'; |
114
|
|
|
|
115
|
|
|
// init var |
116
|
|
|
$isBusy = false; |
117
|
|
|
|
118
|
|
|
// does the busy file already exists. |
119
|
|
|
if ($fs->exists($path)) { |
120
|
|
|
$isBusy = true; |
121
|
|
|
|
122
|
|
|
// grab counter |
123
|
|
|
$counter = (int) file_get_contents($path); |
124
|
|
|
|
125
|
|
|
// check the counter |
126
|
|
|
if ($counter > 9) { |
127
|
|
|
// build class name |
128
|
|
|
$class = 'Backend\\Modules\\' . $this->getModule() . '\\Cronjobs\\' . $this->getAction(); |
129
|
|
|
if ($this->getModule() == 'Core') { |
130
|
|
|
$class = 'Backend\\Core\\Cronjobs\\' . $this->getAction(); |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
// notify user |
134
|
|
|
throw new BackendException('Cronjob (' . $class . ') is still busy after 10 runs, check it out!'); |
135
|
|
|
} |
136
|
|
|
} else { |
137
|
|
|
$counter = 0; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
// increment counter |
141
|
|
|
++$counter; |
142
|
|
|
|
143
|
|
|
// store content |
144
|
|
|
$fs->dumpFile($path, $counter); |
145
|
|
|
|
146
|
|
|
// if the cronjob is busy we should NOT proceed |
147
|
|
|
if ($isBusy) { |
148
|
|
|
exit; |
|
|
|
|
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Set the module |
154
|
|
|
* |
155
|
|
|
* We can't rely on the parent setModule function, because a cronjob requires no login |
156
|
|
|
* |
157
|
|
|
* @param string $module The module to load. |
158
|
|
|
* |
159
|
|
|
* @throws BackendException If module is not allowed |
160
|
|
|
*/ |
161
|
|
|
public function setModule($module) |
162
|
|
|
{ |
163
|
|
|
// does this module exist? |
164
|
|
|
$modules = BackendModel::getModulesOnFilesystem(); |
165
|
|
|
if (!in_array($module, $modules)) { |
166
|
|
|
// set correct headers |
167
|
|
|
header('HTTP/1.1 403 Forbidden'); |
168
|
|
|
|
169
|
|
|
// throw exception |
170
|
|
|
throw new BackendException('Module not allowed.'); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
// set property |
174
|
|
|
$this->module = $module; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.