Merge branch '5.5'
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / acp / action / WorkerProxyAction.class.php
1 <?php
2
3 namespace wcf\acp\action;
4
5 use wcf\action\AbstractSecureAction;
6 use wcf\action\AJAXInvokeAction;
7 use wcf\system\exception\ImplementationException;
8 use wcf\system\exception\SystemException;
9 use wcf\system\WCF;
10 use wcf\system\worker\IWorker;
11 use wcf\util\JSON;
12
13 /**
14 * Handles worker actions.
15 *
16 * @author Alexander Ebert
17 * @copyright 2001-2019 WoltLab GmbH
18 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
19 */
20 final class WorkerProxyAction extends AJAXInvokeAction
21 {
22 /**
23 * @inheritDoc
24 */
25 const DO_NOT_LOG = true;
26
27 /**
28 * loop counter
29 * @var int
30 */
31 protected $loopCount = -1;
32
33 /**
34 * parameters for worker action
35 * @var array
36 */
37 protected $parameters = [];
38
39 /**
40 * worker object
41 * @var IWorker
42 */
43 protected $worker;
44
45 public static $allowInvoke = [];
46
47 /**
48 * @inheritDoc
49 */
50 public function readParameters()
51 {
52 AbstractSecureAction::readParameters();
53
54 if (isset($_POST['className'])) {
55 $this->className = $_POST['className'];
56 }
57 if (isset($_POST['loopCount'])) {
58 $this->loopCount = \intval($_POST['loopCount']);
59 }
60 if (isset($_POST['parameters']) && \is_array($_POST['parameters'])) {
61 $this->parameters = $_POST['parameters'];
62 }
63
64 $this->validate();
65 }
66
67 /**
68 * Validates class name.
69 */
70 protected function validate()
71 {
72 if (empty($this->className)) {
73 throw new SystemException("class name cannot be empty.");
74 }
75
76 if (!\is_subclass_of($this->className, IWorker::class)) {
77 throw new ImplementationException($this->className, IWorker::class);
78 }
79 }
80
81 /**
82 * @inheritDoc
83 */
84 public function execute()
85 {
86 AbstractSecureAction::execute();
87
88 if ($this->loopCount == -1) {
89 $this->sendResponse();
90 }
91
92 // init worker
93 $this->worker = new $this->className($this->parameters);
94 $this->worker->setLoopCount($this->loopCount);
95
96 // validate worker parameters
97 $this->worker->validate();
98
99 // calculate progress, triggers countObjects()
100 $progress = $this->worker->getProgress();
101
102 // execute worker
103 $this->worker->execute();
104
105 $this->worker->finalize();
106
107 // send current state
108 $this->sendResponse($progress, $this->worker->getParameters(), $this->worker->getProceedURL());
109 }
110
111 /**
112 * Sends a JSON-encoded response.
113 *
114 * @param int $progress
115 * @param array $parameters
116 * @param string $proceedURL
117 */
118 protected function sendResponse($progress = 0, ?array $parameters = null, $proceedURL = '')
119 {
120 if ($parameters === null) {
121 $parameters = $this->parameters;
122 }
123
124 // build return values
125 $returnValues = [
126 'className' => $this->className,
127 'loopCount' => $this->loopCount + 1,
128 'parameters' => $parameters,
129 'proceedURL' => $proceedURL,
130 'progress' => $progress,
131 ];
132
133 // include template on startup
134 if ($this->loopCount == -1) {
135 $returnValues['template'] = WCF::getTPL()->fetch('worker');
136 }
137
138 // send JSON-encoded response
139 \header('Content-type: application/json; charset=UTF-8');
140 echo JSON::encode($returnValues);
141
142 exit;
143 }
144 }