dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxContentContextHelpProvision.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxContent;
3
4require_once __DIR__ . '/dbxContent_bootstrap_sync.php';
5require_once __DIR__ . '/dbxContentContextHelp.class.php';
6require_once dirname(__DIR__, 2) . '/dbxAdmin/include/dbxAdminHelp.class.php';
7
9
10 private const PROVISION_VERSION = 7;
11 private const CONFIG_KEY = 'context_help_provision_version';
12
13 public static function run(): void {
14 $version = (int) dbx()->get_config('dbxContent', self::CONFIG_KEY);
15 if ($version >= self::PROVISION_VERSION) {
16 return;
17 }
18
19 $db = dbx()->get_system_obj('dbxDB');
20 if (!is_object($db)) {
21 return;
22 }
23
24 $server = 'dbx|dbxContent.db3';
25 if (!$db->connect_db_server($server)) {
26 return;
27 }
28
30 if (empty($result['errors'])) {
31 self::markProvisioned();
32 }
33 }
34
35 public static function provisionAll($db): array {
36 $result = array('folders' => 0, 'created' => 0, 'updated' => 0, 'skipped' => 0, 'errors' => array());
37 if (!is_object($db)) {
38 $result['errors'][] = 'Keine DB-Verbindung.';
39 return $result;
40 }
41
42 $helpFolderId = self::ensureHelpFolder($db, $result);
43 if ($helpFolderId <= 0) {
44 return $result;
45 }
46
47 $help = new \dbx\dbxAdmin\dbxAdminHelp();
48
49 $contextHelp = new dbxContentContextHelp();
50 $cms = dbx()->get_include_obj('dbxKiCmsService', 'dbxKi');
51 if (!is_object($cms) || !method_exists($cms, 'bundleBuildPlan') || !method_exists($cms, 'bundleExecutePlan')) {
52 $result['errors'][] = 'dbxKi CMS-Service ist nicht verfuegbar.';
53 return $result;
54 }
55 $tplDir = dirname(__DIR__, 2) . '/dbxAdmin/tpl/htm/';
57 $sorter = self::nextContentSorter($db, $helpFolderId);
58
59 foreach ($help->topics() as $topic => $meta) {
60 if (!is_array($meta)) {
61 continue;
62 }
63
64 $permalink = $contextHelp->permalinkForTopic((string) $topic);
65 if ($permalink === '') {
66 $result['errors'][] = 'Permalink fuer Topic ' . $topic . ' leer.';
67 continue;
68 }
69
70 $tplName = trim((string) ($meta['tpl'] ?? ''));
71 $title = trim((string) ($meta['title'] ?? $topic));
72 $content = self::loadTemplateHtml($tplDir, $tplName);
73 if ($content === '') {
74 $result['errors'][] = 'Template fehlt: ' . $tplName;
75 continue;
76 }
77
78 $marker = 'dbx-help-' . $contextHelp->topicSlug((string)$topic);
79 $existing = self::findExistingPage(
80 $db,
81 $dd,
82 $permalink,
83 $contextHelp->legacyPermalinksForTopic((string)$topic),
84 $marker,
85 $title
86 );
87 $groupRead = in_array($topic, array('consent_privacy', 'impressum', 'workflow_use', 'workflow_run'), true) ? '*' : 'admin';
88 $pageData = self::pageData($helpFolderId, $title, $permalink, $content, $sorter, $groupRead, $marker);
89
90 if (is_array($existing)
91 && (int) ($existing['id'] ?? 0) > 0
92 && trim((string) ($existing['title'] ?? '')) === $title
93 && trim((string) ($existing['permalink'] ?? '')) === $permalink
94 && trim((string) ($existing['content'] ?? '')) === trim($content)
95 && trim((string) ($existing['group_read'] ?? '')) === $groupRead
96 && trim((string) ($existing['keywords'] ?? '')) === $marker) {
97 $result['skipped']++;
98 continue;
99 }
100
101 try {
102 if (is_array($existing) && (int) ($existing['id'] ?? 0) > 0) {
103 $id = (int) $existing['id'];
104 // Ein vom Benutzer verschobenes Hilfedokument bleibt in seinem
105 // neuen Ordner. Nur seine stabile Identitaet und sein Inhalt
106 // werden aktualisiert.
107 unset($pageData['sorter'], $pageData['folder']);
108 $params = array(
109 'lng' => dbxContentLng::current(),
110 'id' => $id,
111 'patch' => $pageData,
112 );
113 $plan = $cms->bundleBuildPlan('page.update', $params);
114 $cms->bundleExecutePlan('page.update', $params, $plan);
115 $result['updated']++;
116 continue;
117 }
118
119 $params = array_merge($pageData, array(
120 'lng' => dbxContentLng::current(),
121 'folder_id' => $helpFolderId,
122 ));
123 $plan = $cms->bundleBuildPlan('page.create', $params);
124 $created = $cms->bundleExecutePlan('page.create', $params, $plan);
125 $id = (int) ($created['id'] ?? 0);
126 if ($id <= 0) {
127 throw new \RuntimeException('Keine ID nach page.create.');
128 }
129 $result['created']++;
130 $sorter = self::nextSorterAfter($sorter);
131 } catch (\Throwable $e) {
132 $result['errors'][] = 'dbxKi ' . $permalink . ': ' . $e->getMessage();
133 }
134 }
135
137
138 return $result;
139 }
140
141 private static function markProvisioned(): void {
142 $config = dbx()->get_config('dbxContent');
143 if (!is_array($config)) {
144 $config = array();
145 }
146 $config[self::CONFIG_KEY] = self::PROVISION_VERSION;
147 dbx()->set_config('dbxContent', $config);
148 }
149
150 private static function ensureHelpFolder($db, array &$result): int {
151 $outsideId = self::findFolderByName($db, 'outside', 0);
152 if ($outsideId <= 0) {
153 $outsideId = self::insertFolder($db, 'outside', 0, 'admin', $result);
154 }
155 if ($outsideId <= 0) {
156 $result['errors'][] = 'Ordner outside konnte nicht angelegt werden.';
157 return 0;
158 }
159
160 $helpId = self::findFolderByName($db, 'help', $outsideId);
161 if ($helpId <= 0) {
162 $helpId = self::insertFolder($db, 'help', $outsideId, 'parent', $result);
163 }
164 if ($helpId <= 0) {
165 $result['errors'][] = 'Ordner help konnte nicht angelegt werden.';
166 return 0;
167 }
168
169 return $helpId;
170 }
171
172 private static function findFolderByName($db, string $name, int $parentId): int {
173 $dd = dbxContentLng::ddFolder();
174 $name = trim($name);
175 $parentId = (int) $parentId;
176 $where = "name = '" . str_replace("'", "''", $name) . "' AND parent_id = " . $parentId;
177 $rows = $db->select($dd, $where, 'id', 'id', 'ASC', '', 1, 0, 0);
178 if (!is_array($rows) || !isset($rows[0]['id'])) {
179 return 0;
180 }
181 return (int) $rows[0]['id'];
182 }
183
184 private static function insertFolder($db, string $name, int $parentId, string $groupRead, array &$result): int {
185 $cms = dbx()->get_include_obj('dbxKiCmsService', 'dbxKi');
186 if (!is_object($cms) || !method_exists($cms, 'bundleBuildPlan') || !method_exists($cms, 'bundleExecutePlan')) {
187 return 0;
188 }
189
190 $params = array(
191 'lng' => dbxContentLng::current(),
192 'name' => $name,
193 'parent_id' => (int) $parentId,
194 'group_read' => $groupRead,
195 'template' => $parentId > 0 ? 'parent' : 'c-content',
196 'hero_template' => $parentId > 0 ? 'parent' : 'image-hero',
197 'hero_image_id' => 'parent',
198 'hero_margin_top' => 'parent',
199 'hero_height' => 'parent',
200 'hero_variant' => 'parent',
201 'hero_sticky' => 'parent',
202 'hero_scroll_layer' => 'parent',
203 );
204
205 try {
206 $plan = $cms->bundleBuildPlan('folder.create', $params);
207 $created = $cms->bundleExecutePlan('folder.create', $params, $plan);
208 $id = (int) ($created['id'] ?? 0);
209 } catch (\Throwable $e) {
210 return 0;
211 }
212
213 if ($id > 0) {
214 $result['folders']++;
215 }
216 return $id;
217 }
218
219 private static function findExistingPage($db, string $dd, string $permalink, array $legacyPermalinks, string $marker, string $title): ?array {
220 $fields = 'id,title,content,group_read,keywords,permalink,folder';
221 $candidates = array_values(array_unique(array_merge(array($permalink), $legacyPermalinks)));
222 foreach ($candidates as $candidate) {
223 $candidate = trim((string)$candidate);
224 if ($candidate === '') {
225 continue;
226 }
227 $row = $db->select1($dd, array('permalink' => $candidate), $fields, 0);
228 if (is_array($row) && (int)($row['id'] ?? 0) > 0) {
229 return $row;
230 }
231 }
232
233 $escapedMarker = str_replace("'", "''", $marker);
234 $rows = $db->select($dd, "keywords = '" . $escapedMarker . "'", $fields, 'id', 'ASC', '', 2, 0, 0);
235 if (is_array($rows) && count($rows) === 1) {
236 return $rows[0];
237 }
238
239 // Einmalige Uebernahme bereits verschobener Altseiten ohne Marker.
240 $escapedTitle = str_replace("'", "''", $title);
241 $rows = $db->select($dd, "title = '" . $escapedTitle . "'", $fields, 'id', 'ASC', '', 2, 0, 0);
242 return is_array($rows) && count($rows) === 1 ? $rows[0] : null;
243 }
244
245 private static function pageData(int $folderId, string $title, string $permalink, string $content, string $sorter, string $groupRead = 'admin', string $marker = ''): array {
246 return array(
247 'activ' => 1,
248 'folder' => $folderId,
249 'title' => substr($title, 0, 254),
250 'permalink' => substr($permalink, 0, 254),
251 'description' => '',
252 'keywords' => $marker,
253 'group_read' => $groupRead,
254 'sorter' => $sorter,
255 'template' => 'parent',
256 'hero_template' => 'parent',
257 'hero_image_id' => 'parent',
258 'hero_margin_top' => 'parent',
259 'hero_height' => 'parent',
260 'hero_variant' => 'parent',
261 'hero_sticky' => 'parent',
262 'hero_scroll_layer' => 'parent',
263 'gallery_template' => 'image-gallery',
264 'gallery_visible_count' => '3',
265 'gallery_image_size' => 'original',
266 'gallery_lightbox_width' => '100vw',
267 'gallery_overflow' => 'grid',
268 'gallery_click_behavior' => 'lightbox',
269 'content' => $content,
270 );
271 }
272
273 private static function loadTemplateHtml(string $tplDir, string $tplName): string {
274 $tplName = trim($tplName);
275 if ($tplName === '') {
276 return '';
277 }
278 $path = rtrim($tplDir, '/\\') . DIRECTORY_SEPARATOR . $tplName . '.htm';
279 if (!is_file($path) || !is_readable($path)) {
280 return '';
281 }
282 $html = file_get_contents($path);
283 return is_string($html) ? trim($html) : '';
284 }
285
286 private static function nextContentSorter($db, int $folderId): string {
287 $folderId = (int) $folderId;
288 $rows = $db->select(dbxContentLng::ddContent(), 'folder = ' . $folderId, 'sorter', 'sorter,id', 'DESC', '', 1, 0, 0);
289 $max = 0;
290 if (is_array($rows) && isset($rows[0]) && is_array($rows[0])) {
291 $max = (int) ($rows[0]['sorter'] ?? 0);
292 }
293 return sprintf('%04d', $max + 10);
294 }
295
296 private static function nextSorterAfter(string $sorter): string {
297 $num = (int) $sorter;
298 return sprintf('%04d', $num + 10);
299 }
300}
static ddContent(string $lng='')
if($resolved !==$expectedBase . 'files/test/') $config
if(!is_object( $db)) if($db->connect_db_server($server) !==1) $created
DBX schema administration.