dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxContentPageCache_test.php
Go to the documentation of this file.
1<?php
2
3class dbxContentPageCacheTestApi {
4 public array $system = array();
5 public array $request = array();
6 public array $config = array(
7 'cache_content' => 1,
8 'default_design_user' => 'dbxapp',
9 );
10 public int $effectiveUser = 0;
11 private string $fileDir;
12 private string $baseDir;
13
14 public function __construct(string $fileDir) {
15 $this->fileDir = rtrim($fileDir, '/\\') . DIRECTORY_SEPARATOR;
16 $this->baseDir = $this->fileDir . 'app' . DIRECTORY_SEPARATOR;
17 $this->writeConfigFile();
18 }
19
20 public function get_file_dir(): string {
21 return $this->fileDir;
22 }
23
24 public function get_base_dir(): string {
25 return $this->baseDir;
26 }
27
28 public function get_base_url(): string {
29 return (string)($this->system['dbx_base_url'] ?? '');
30 }
31
32 public function os_path(string $path): string {
33 return str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
34 }
35
36 public function get_config(string $module, ?string $key = null) {
37 if ($module !== 'dbx') {
38 return $key === null ? array() : 'undef';
39 }
40 return $key === null ? $this->config : ($this->config[$key] ?? 'undef');
41 }
42
43 public function set_config(string $module, array $config): int {
44 if ($module !== 'dbx') {
45 return 0;
46 }
47 $this->config = $config;
48 $this->writeConfigFile();
49 return 1;
50 }
51
52 private function writeConfigFile(): void {
53 $dir = $this->baseDir . 'dbx' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR
54 . 'dbx' . DIRECTORY_SEPARATOR . 'cfg';
55 if (!is_dir($dir)) {
56 mkdir($dir, 0755, true);
57 }
58 file_put_contents(
59 $dir . DIRECTORY_SEPARATOR . 'config.php',
60 "<?php\n\$config['cache_content'] = " . (int)($this->config['cache_content'] ?? 1) . ";\n"
61 );
62 }
63
64 public function get_request_var(string $key, $default = '', string $type = '') {
65 $value = $this->request[$key] ?? $default;
66 return $type === 'int' ? (int)$value : $value;
67 }
68
69 public function get_system_var(string $key, $default = '', string $type = '') {
70 $value = $this->system[$key] ?? $default;
71 return $type === 'int' ? (int)$value : $value;
72 }
73
74 public function set_system_var(string $key, $value): void {
75 $this->system[$key] = $value;
76 }
77
78 public function normalize_skin(string $skin): string {
79 $skin = strtolower(trim($skin));
80 return preg_match('/^[a-z0-9_-]+$/', $skin) ? $skin : 'blau';
81 }
82
83 public function is_design(string $design): bool {
84 return in_array($design, array('dbxapp', 'flowers'), true);
85 }
86
87 public function user(): int {
88 return $this->effectiveUser;
89 }
90}
91
92$testRoot = rtrim(sys_get_temp_dir(), '/\\') . DIRECTORY_SEPARATOR
93 . 'dbx-page-cache-test-' . getmypid() . '-' . bin2hex(random_bytes(4));
94if (!mkdir($testRoot, 0755, true) && !is_dir($testRoot)) {
95 fwrite(STDERR, "FAIL: Testverzeichnis konnte nicht erstellt werden.\n");
96 exit(1);
97}
98
99$deleteTree = static function (string $path) use (&$deleteTree): void {
100 $resolved = realpath($path);
101 if ($resolved === false || !str_starts_with(basename($resolved), 'dbx-page-cache-test-')) {
102 return;
103 }
104 $iterator = new RecursiveIteratorIterator(
105 new RecursiveDirectoryIterator($resolved, FilesystemIterator::SKIP_DOTS),
106 RecursiveIteratorIterator::CHILD_FIRST
107 );
108 foreach ($iterator as $item) {
109 $item->isDir() ? @rmdir($item->getPathname()) : @unlink($item->getPathname());
110 }
111 @rmdir($resolved);
112};
113
114$fail = static function (string $message, int $code = 2) use ($deleteTree, $testRoot): void {
115 $deleteTree($testRoot);
116 fwrite(STDERR, "FAIL: $message\n");
117 exit($code);
118};
119
120$GLOBALS['dbxContentPageCacheTestApi'] = new dbxContentPageCacheTestApi($testRoot);
121function dbx(): dbxContentPageCacheTestApi {
122 return $GLOBALS['dbxContentPageCacheTestApi'];
123}
124
125require_once dirname(__DIR__) . '/include/dbxContentPageCache.class.php';
126
128
129$_SERVER['REQUEST_METHOD'] = 'GET';
130$_SERVER['HTTP_HOST'] = 'localhost';
131$_SERVER['SCRIPT_NAME'] = '/dbxapp/index.php';
132$_SERVER['SERVER_PORT'] = '80';
133unset($_SERVER['HTTPS'], $_SERVER['HTTP_X_FORWARDED_PROTO']);
134$_GET = array();
135$_SESSION = array('dbx' => array('current_user' => array('id' => 0)));
136
137$api = dbx();
138$api->system = array(
139 'dbx_permalink' => 'abc/def',
140 'dbx_lng' => 'de',
141 'dbx_design' => 'dbxapp',
142 'dbx_color' => 'blau',
143 'dbx_edit' => 0,
144 'dbx_ajax' => 0,
145 'dbx_window' => 0,
146 'dbx_base_url' => 'http://localhost/dbxapp/',
147);
148
149$slashPath = dbxContentPageCache::fullPagePath('abc/def', 'de', 'dbxapp', 'blau');
150$dashPath = dbxContentPageCache::fullPagePath('abc-def', 'de', 'dbxapp', 'blau');
151if ($slashPath === $dashPath) {
152 $fail('abc/def und abc-def kollidieren weiterhin im Dateinamen.');
153}
154if (!preg_match('/-[a-f0-9]{24}_de_dbxapp_blau_[a-f0-9]{16}_[a-f0-9]{24}_v3\.htm$/', basename($slashPath))) {
155 $fail('Der V3-Dateiname enthaelt nicht alle erwarteten Hash-/Variantenanteile.');
156}
157
158$_SERVER['HTTP_HOST'] = 'dbxapp.de';
159$publicHostPath = dbxContentPageCache::fullPagePath('abc/def', 'de', 'dbxapp', 'blau');
160$_SERVER['HTTP_HOST'] = 'localhost';
161if ($publicHostPath === $slashPath) {
162 $fail('Caches verschiedener Hosts verwenden denselben Dateinamen.');
163}
164
165$legacyV2 = dirname($slashPath) . DIRECTORY_SEPARATOR . 'legacy_de_dbxapp_blau_v2.htm';
166file_put_contents($legacyV2, '<!doctype html><html></html>');
167dbxContentPageCache::ensureDirs();
168if (is_file($legacyV2)) {
169 $fail('Unsichere V2-Datei wurde nicht entfernt.');
170}
171
172$staleV3 = preg_replace(
173 '/_[a-f0-9]{24}_v3\.htm$/',
174 '_000000000000000000000000_v3.htm',
175 $slashPath
176);
177if (!is_string($staleV3) || $staleV3 === $slashPath) {
178 $fail('Testdatei einer alten Cache-Generation konnte nicht abgeleitet werden.');
179}
180file_put_contents($staleV3, '<!doctype html><html></html>');
181if (dbxContentPageCache::purgeStaleFullPages() !== 1 || is_file($staleV3)) {
182 $fail('V3-Datei einer alten Cache-Generation wurde nicht bereinigt.');
183}
184
185if (!dbxContentPageCache::prepareFullPageRequest()) {
186 $fail('Gueltiger Gast-Permalink wurde nicht fuer den Cache vorbereitet.');
187}
188$api->system['dbx_content_permalink_request'] = 1;
189$api->system['dbx_content_route_cid'] = 51;
190$api->system['dbx_master_modul'] = 'dbxContent';
191if (!dbxContentPageCache::attachResolvedContentRoute()) {
192 $fail('Aufgeloeste Content-Route wurde nicht an den Cache gebunden.');
193}
194
195$html = "<!doctype html><html><head><base href=\"http://localhost/dbxapp/\"/></head><body>Unveraendert: &amp; <script>window.x = '<tag>';</script></body></html>";
196http_response_code(200);
197if (!dbxContentPageCache::writeFullPage($html)) {
198 $fail('Vollstaendige Gastseite wurde nicht atomar gespeichert.');
199}
200if (dbxContentPageCache::readFullPage() !== $html) {
201 $fail('Cache-Lesen veraendert oder escaped die gespeicherten Bytes.');
202}
203
204$baseCheckedPath = (string)$api->system['dbx_full_page_cache_path'];
205$wrongBaseHtml = str_replace(
206 'http://localhost/dbxapp/',
207 'https://dbxapp.de/',
208 $html
209);
210file_put_contents($baseCheckedPath, $wrongBaseHtml);
211if (dbxContentPageCache::readFullPage() !== null || is_file($baseCheckedPath)) {
212 $fail('Cache-Datei mit falschem base href wurde gelesen oder nicht geloescht.');
213}
214if (dbxContentPageCache::writeFullPage($wrongBaseHtml)) {
215 $fail('HTML mit falschem base href wurde erneut in den Cache geschrieben.');
216}
217if (!dbxContentPageCache::writeFullPage($html) || dbxContentPageCache::readFullPage() !== $html) {
218 $fail('Nach ungueltigem base href wurde die korrekte Seite nicht neu gecacht.');
219}
220
221$oldPath = (string)$api->system['dbx_full_page_cache_path'];
222$oldGeneration = (string)$api->system['dbx_full_page_cache_generation'];
223dbxContentPageCache::invalidateAllFullPages();
224if (dbxContentPageCache::writeFullPage($html)) {
225 $fail('Ein vor der Invalidierung gestarteter Request konnte veraltetes HTML nachschreiben.');
226}
227
228if (!dbxContentPageCache::prepareFullPageRequest()) {
229 $fail('Cache konnte nach Generationwechsel nicht neu vorbereitet werden.');
230}
231$api->system['dbx_content_permalink_request'] = 1;
232$api->system['dbx_content_route_cid'] = 51;
233$api->system['dbx_master_modul'] = 'dbxContent';
234dbxContentPageCache::attachResolvedContentRoute();
235$newPath = (string)$api->system['dbx_full_page_cache_path'];
236$newGeneration = (string)$api->system['dbx_full_page_cache_generation'];
237if ($oldPath === $newPath || $oldGeneration === $newGeneration) {
238 $fail('Invalidierung hat die Cache-Generation nicht gewechselt.');
239}
240if (!dbxContentPageCache::writeFullPage($html)) {
241 $fail('Neue Cache-Generation konnte nicht geschrieben werden.');
242}
243
244if (!dbxContentPageCache::setConfigEnabled(false)) {
245 $fail('Cache-Konfiguration konnte im Test nicht ausgeschaltet werden.');
246}
247if (!is_file($newPath) || dbxContentPageCache::readFullPage() !== $html) {
248 $fail('Ausschalten des Cache-Schreibens hat einen vorhandenen Treffer entfernt oder deaktiviert.');
249}
250if (dbxContentPageCache::isWriteEnabled()) {
251 $fail('Ausgeschaltetes Cache-Schreiben wird weiterhin als aktiv gemeldet.');
252}
253if (dbxContentPageCache::writeFullPage(str_replace('Unveraendert', 'Neu', $html))) {
254 $fail('Bei ausgeschaltetem Cache-Schreiben wurde eine Seite gespeichert.');
255}
256if ((string)file_get_contents($newPath) !== $html) {
257 $fail('Vorhandene Cache-Datei wurde bei ausgeschaltetem Schreiben veraendert.');
258}
259$afterTogglePath = dbxContentPageCache::fullPagePath('abc/def', 'de', 'dbxapp', 'blau');
260if ($afterTogglePath !== $newPath) {
261 $fail('Ausschalten des Cache-Schreibens hat die bestehende Generation gewechselt.');
262}
263
264// Fachliche Aenderungen invalidieren auch bei pausiertem Schreiben weiterhin
265// vorhandene Treffer. Danach bleibt der MISS live und wird nicht gespeichert.
266dbxContentPageCache::invalidateAllFullPages();
267if (is_file($newPath)) {
268 $fail('Inhaltsinvalidierung hat bei pausiertem Schreiben eine alte Seite behalten.');
269}
270$afterInvalidationPath = dbxContentPageCache::fullPagePath('abc/def', 'de', 'dbxapp', 'blau');
271if ($afterInvalidationPath === $newPath) {
272 $fail('Inhaltsinvalidierung hat die Generation bei pausiertem Schreiben nicht gewechselt.');
273}
274if (!dbxContentPageCache::prepareFullPageRequest()) {
275 $fail('Lesepfad konnte bei pausiertem Schreiben nicht vorbereitet werden.');
276}
277$api->system['dbx_content_permalink_request'] = 1;
278$api->system['dbx_content_route_cid'] = 51;
279$api->system['dbx_master_modul'] = 'dbxContent';
280dbxContentPageCache::attachResolvedContentRoute();
281if (dbxContentPageCache::readFullPage() !== null || dbxContentPageCache::writeFullPage($html)) {
282 $fail('Cache-MISS wurde bei pausiertem Schreiben nicht ausschliesslich live behandelt.');
283}
284
285if (!dbxContentPageCache::setConfigEnabled(true) || !dbxContentPageCache::isWriteEnabled()) {
286 $fail('Cache-Schreiben konnte nicht wieder eingeschaltet werden.');
287}
288
289$api->effectiveUser = 1;
290if (dbxContentPageCache::isEnabled()) {
291 $fail('Effektiver Admin-/Bypass-Benutzer wird als Gast behandelt.');
292}
293$api->effectiveUser = 7;
294$_SESSION['dbx']['current_user']['id'] = '7';
295if (dbxContentPageCache::isEnabled()) {
296 $fail('Numerische Benutzer-ID als String wird als Gast behandelt.');
297}
298$api->effectiveUser = 0;
299$_SESSION['dbx']['current_user']['id'] = 0;
300$_SESSION['dbxShop_cart'] = array(12 => 2);
301if (dbxContentPageCache::isEnabled()) {
302 $fail('Gast mit Warenkorb wuerde weiterhin einen gemeinsamen Cache verwenden.');
303}
304$_SESSION['dbxShop_cart'] = array();
305
306$deleteTree($testRoot);
307echo "OK dbxContent full-page cache\n";
user($key='id')
Liest einen Wert des aktuellen Benutzers.
Definition dbxApi.php:1305
os_path(string $path)
Normalisiert einen Pfad fuer das aktuelle Betriebssystem.
Definition dbxApi.php:1538
set_config(string $modul, array $config)
Speichert die Konfiguration eines Moduls.
Definition dbxApi.php:793
get_base_dir(int $cutData=0)
Liefert das Basisverzeichnis der Installation.
Definition dbxApi.php:1507
get_file_dir()
Liefert das files/-Verzeichnis der Installation.
Definition dbxApi.php:1524
is_design($design, $page='default')
Prueft, ob ein Design fuer die angegebene Seite existiert.
Definition dbxApi.php:2217
normalize_skin(string $skin='', string $design='')
Normalisiert Skin-/Farbnamen auf gueltige Skin-IDs.
Definition dbxApi.php:1813
get_base_url()
Liefert die Basis-URL des aktuellen Requests.
Definition dbxApi.php:1488
$_SERVER['REQUEST_METHOD']
if($stored !=='files/test/') $resolved
if($resolved !==$expectedBase . 'files/test/') $config
$api system['dbx_permalink']
$GLOBALS['dbxMissingResourcesTestApi']
if(trim($second) !=='second') $design
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
exit
Definition index.php:146
DBX schema administration.