dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxSelfTestController.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxSelfTest;
3
6{
7 private const TOKEN_SCOPE = 'dbxSelfTest.actions';
8 private ?dbxSelfTestRunner $runner = null;
9
10 private function runner(): dbxSelfTestRunner
11 {
12 if (!$this->runner) {
13 $this->runner = dbx()->get_include_obj('dbxSelfTestRunner', 'dbxSelfTest');
14 }
15 return $this->runner;
16 }
17
18 private function h($value): string
19 {
20 return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
21 }
22
23 private function url(string $action, bool $tokenized = false, array $params = array()): string
24 {
25 $url = '?dbx_modul=dbxSelfTest&dbx_run1=' . rawurlencode($action);
26 foreach ($params as $key => $value) {
27 $url .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((string)$value);
28 }
29 if ($tokenized) {
30 $url .= '&dbx_token=' . rawurlencode(dbx()->action_token(self::TOKEN_SCOPE));
31 }
32 return $url;
33 }
34
35 private function payload(): array
36 {
37 $raw = file_get_contents('php://input');
38 $data = is_string($raw) && trim($raw) !== '' ? json_decode($raw, true) : array();
39 return is_array($data) ? $data : array();
40 }
41
42 private function requireToken(string $action): void
43 {
44 $token = (string)dbx()->get_modul_var('dbx_token', '', 'varchar|max=128');
45 if (dbx()->check_action_token(self::TOKEN_SCOPE, $token)) {
46 return;
47 }
48 dbx()->sys_msg('security', 'dbxSelfTest Token abgewiesen: ' . $action);
49 http_response_code(403);
50 dbx()->json_response(array('ok' => 0, 'error' => 'Sicherheitstoken ungueltig. Bitte Seite neu laden.'), true);
51 }
52
53 private function json(array $data): void
54 {
55 dbx()->json_response($data, true);
56 }
57
58 private function publicCatalog(): array
59 {
60 return array_map(static function (array $test): array {
61 unset($test['handler']);
62 return $test;
63 }, $this->runner()->catalog('full'));
64 }
65
66 private function dashboard(): string
67 {
68 $catalog = $this->runner()->catalog('full');
69 $quick = $this->runner()->catalog('quick');
70 $categories = array_unique(array_column($catalog, 'category'));
71 sort($categories);
72 dbx()->set_system_var('dbx_title', 'System-Selbsttest');
73
74 return dbx()->get_system_obj('dbxTPL')->get_tpl('dbxSelfTest|selftest-dashboard', array(
75 'test_count' => count($catalog),
76 'quick_count' => count($quick),
77 'category_count' => count($categories),
78 'catalog_url' => $this->h($this->url('api_catalog')),
79 'start_url' => $this->h($this->url('api_start', true)),
80 'execute_url' => $this->h($this->url('api_execute', true)),
81 'finish_url' => $this->h($this->url('api_finish', true)),
82 'browser_result_url' => $this->h($this->url('api_browser_result', true)),
83 'run_url' => $this->h($this->url('api_run')),
84 'download_url' => $this->h($this->url('download')),
85 'bar_title' => 'dbxSelfTest',
86 'bar_subtitle' => 'Komplett-, Schnell- und Einzeltests mit dauerhaftem Protokoll.',
87 'bar_icon' => 'bi-clipboard2-pulse',
88 'bar_actions' => '<a class="btn btn-outline-secondary btn-sm" href="' . $this->h($this->url('dashboard')) . '"><i class="bi bi-arrow-clockwise"></i> Aktualisieren</a>',
89 'bar_class' => 'dbx-module-bar',
90 'bar_title_class' => 'dbx-module-bar-titleblock',
91 'bar_title_pre' => '',
92 'bar_title_heading_attrs' => '',
93 'bar_middle' => '',
94 'bar_extra' => '',
95 'bar_actions_class' => 'dbx-module-bar-actions',
96 ));
97 }
98
99 private function apiCatalog(): void
100 {
101 $this->json(array(
102 'ok' => 1,
103 'tests' => $this->publicCatalog(),
104 'history' => $this->runner()->history(20),
105 ));
106 }
107
108 private function apiStart(): void
109 {
110 $this->requireToken('api_start');
111 $data = $this->payload();
112 $profile = ($data['profile'] ?? '') === 'quick' ? 'quick' : 'full';
113 $ids = is_array($data['test_ids'] ?? null) ? array_slice($data['test_ids'], 0, 500) : array();
114 $mode = count($ids) === 1 ? 'single' : ($ids !== array() ? 'selection' : 'complete');
115 try {
116 $run = $this->runner()->startRun($profile, $ids, $mode);
117 $this->json(array('ok' => 1, 'run' => $run));
118 } catch (\Throwable $e) {
119 http_response_code(400);
120 $this->json(array('ok' => 0, 'error' => $e->getMessage()));
121 }
122 }
123
124 private function apiExecute(): void
125 {
126 $this->requireToken('api_execute');
127 // Umfangreiche Systempruefungen (insbesondere php -l ueber das ganze
128 // Projekt) duerfen nicht am normalen Web-Request-Limit abbrechen.
129 @set_time_limit(360);
130 $data = $this->payload();
131 try {
132 $result = $this->runner()->executeRunTest(
133 (string)($data['run_id'] ?? ''),
134 (string)($data['test_id'] ?? '')
135 );
136 $run = $this->runner()->loadRun((string)($data['run_id'] ?? ''));
137 $this->json(array('ok' => 1, 'result' => $result, 'run' => $run));
138 } catch (\Throwable $e) {
139 http_response_code(400);
140 $this->json(array('ok' => 0, 'error' => $e->getMessage()));
141 }
142 }
143
144 private function apiFinish(): void
145 {
146 $this->requireToken('api_finish');
147 $data = $this->payload();
148 try {
149 $run = $this->runner()->finishRun(
150 (string)($data['run_id'] ?? ''),
151 !empty($data['aborted'])
152 );
153 $this->json(array('ok' => 1, 'run' => $run, 'history' => $this->runner()->history(20)));
154 } catch (\Throwable $e) {
155 http_response_code(400);
156 $this->json(array('ok' => 0, 'error' => $e->getMessage()));
157 }
158 }
159
160 private function apiBrowserResult(): void
161 {
162 $this->requireToken('api_browser_result');
163 $data = $this->payload();
164 try {
165 $result = $this->runner()->recordBrowserTestResult(
166 (string)($data['run_id'] ?? ''),
167 (string)($data['test_id'] ?? ''),
168 is_array($data['result'] ?? null) ? $data['result'] : array()
169 );
170 $run = $this->runner()->loadRun((string)($data['run_id'] ?? ''));
171 $this->json(array('ok' => 1, 'result' => $result, 'run' => $run));
172 } catch (\Throwable $e) {
173 http_response_code(400);
174 $this->json(array('ok' => 0, 'error' => $e->getMessage()));
175 }
176 }
177
178 private function apiRun(): void
179 {
180 $id = (string)dbx()->get_modul_var('run_id', '', 'parameter|max=40');
181 $run = $this->runner()->loadRun($id);
182 if (!$run) {
183 http_response_code(404);
184 $this->json(array('ok' => 0, 'error' => 'Testlauf nicht gefunden.'));
185 }
186 $this->json(array('ok' => 1, 'run' => $run));
187 }
188
189 private function download(): void
190 {
191 $id = (string)dbx()->get_modul_var('run_id', '', 'parameter|max=40');
192 $path = $this->runner()->runLogPath($id);
193 if ($path === null) {
194 http_response_code(404);
195 echo 'Testprotokoll nicht gefunden.';
196 exit;
197 }
198 header('Content-Type: application/json; charset=utf-8');
199 header('Content-Disposition: attachment; filename="dbx-selftest-' . $id . '.json"');
200 header('Content-Length: ' . (string)filesize($path));
201 readfile($path);
202 exit;
203 }
204
205 public function run(): string
206 {
207 $action = (string)dbx()->get_modul_var('dbx_run1', 'dashboard', 'parameter');
208 switch ($action) {
209 case 'api_catalog':
210 $this->apiCatalog();
211 break;
212 case 'api_start':
213 $this->apiStart();
214 break;
215 case 'api_execute':
216 $this->apiExecute();
217 break;
218 case 'api_finish':
219 $this->apiFinish();
220 break;
221 case 'api_browser_result':
222 $this->apiBrowserResult();
223 break;
224 case 'api_run':
225 $this->apiRun();
226 break;
227 case 'download':
228 $this->download();
229 break;
230 }
231 return $this->dashboard();
232 }
233}
Web-Controller fuer Dashboard, AJAX-Orchestrierung und Protokolldownload.
Zentraler, auch ohne Web-Kernel nutzbarer Test-Orchestrator.
action_token(string $scope='global')
Liefert ein sessiongebundenes Token fuer zustandsaendernde Link-Aktionen.
Definition dbxApi.php:1189
check_action_token(string $scope='global', string $token='')
Prueft ein sessiongebundenes Aktions-Token.
Definition dbxApi.php:1206
exit
Definition index.php:146
DBX schema administration.
foreach(array_slice($argv ?? array(), 1) as $argument) $runner
Definition run.php:15
$profile
Definition run.php:6