10 private const PROVISION_VERSION = 7;
11 private const CONFIG_KEY =
'context_help_provision_version';
13 public static function run(): void {
14 $version = (int)
dbx()->get_config(
'dbxContent', self::CONFIG_KEY);
15 if (
$version >= self::PROVISION_VERSION) {
19 $db =
dbx()->get_system_obj(
'dbxDB');
20 if (!is_object(
$db)) {
31 self::markProvisioned();
36 $result = array(
'folders' => 0,
'created' => 0,
'updated' => 0,
'skipped' => 0,
'errors' => array());
37 if (!is_object(
$db)) {
38 $result[
'errors'][] =
'Keine DB-Verbindung.';
42 $helpFolderId = self::ensureHelpFolder(
$db,
$result);
43 if ($helpFolderId <= 0) {
47 $help = new \dbx\dbxAdmin\dbxAdminHelp();
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.';
55 $tplDir = dirname(__DIR__, 2) .
'/dbxAdmin/tpl/htm/';
57 $sorter = self::nextContentSorter(
$db, $helpFolderId);
59 foreach (
$help->topics() as $topic => $meta) {
60 if (!is_array($meta)) {
64 $permalink = $contextHelp->permalinkForTopic((
string) $topic);
65 if ($permalink ===
'') {
66 $result[
'errors'][] =
'Permalink fuer Topic ' . $topic .
' leer.';
70 $tplName = trim((
string) ($meta[
'tpl'] ??
''));
71 $title = trim((
string) ($meta[
'title'] ?? $topic));
72 $content = self::loadTemplateHtml($tplDir, $tplName);
74 $result[
'errors'][] =
'Template fehlt: ' . $tplName;
78 $marker =
'dbx-help-' . $contextHelp->topicSlug((
string)$topic);
79 $existing = self::findExistingPage(
83 $contextHelp->legacyPermalinksForTopic((
string)$topic),
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);
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) {
102 if (is_array($existing) && (
int) ($existing[
'id'] ?? 0) > 0) {
103 $id = (int) $existing[
'id'];
107 unset($pageData[
'sorter'], $pageData[
'folder']);
111 'patch' => $pageData,
113 $plan =
$cms->bundleBuildPlan(
'page.update', $params);
114 $cms->bundleExecutePlan(
'page.update', $params,
$plan);
119 $params = array_merge($pageData, array(
121 'folder_id' => $helpFolderId,
123 $plan =
$cms->bundleBuildPlan(
'page.create', $params);
127 throw new \RuntimeException(
'Keine ID nach page.create.');
130 $sorter = self::nextSorterAfter($sorter);
131 }
catch (\Throwable $e) {
132 $result[
'errors'][] =
'dbxKi ' . $permalink .
': ' . $e->getMessage();
141 private static function markProvisioned(): void {
146 $config[self::CONFIG_KEY] = self::PROVISION_VERSION;
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);
155 if ($outsideId <= 0) {
156 $result[
'errors'][] =
'Ordner outside konnte nicht angelegt werden.';
160 $helpId = self::findFolderByName(
$db,
'help', $outsideId);
162 $helpId = self::insertFolder(
$db,
'help', $outsideId,
'parent',
$result);
165 $result[
'errors'][] =
'Ordner help konnte nicht angelegt werden.';
172 private static function findFolderByName(
$db,
string $name,
int $parentId): int {
173 $dd = dbxContentLng::ddFolder();
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'])) {
181 return (
int)
$rows[0][
'id'];
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')) {
191 'lng' => dbxContentLng::current(),
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',
206 $plan =
$cms->bundleBuildPlan(
'folder.create', $params);
209 }
catch (\Throwable $e) {
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)));
223 $candidate = trim((
string)$candidate);
224 if ($candidate ===
'') {
227 $row =
$db->select1(
$dd, array(
'permalink' => $candidate),
$fields, 0);
228 if (is_array($row) && (
int)($row[
'id'] ?? 0) > 0) {
233 $escapedMarker = str_replace(
"'",
"''", $marker);
234 $rows =
$db->select(
$dd,
"keywords = '" . $escapedMarker .
"'",
$fields,
'id',
'ASC',
'', 2, 0, 0);
240 $escapedTitle = str_replace(
"'",
"''", $title);
241 $rows =
$db->select(
$dd,
"title = '" . $escapedTitle .
"'",
$fields,
'id',
'ASC',
'', 2, 0, 0);
245 private static function pageData(
int $folderId,
string $title,
string $permalink,
string $content,
string $sorter,
string $groupRead =
'admin',
string $marker =
''): array {
248 'folder' => $folderId,
249 'title' => substr($title, 0, 254),
250 'permalink' => substr($permalink, 0, 254),
252 'keywords' => $marker,
253 'group_read' => $groupRead,
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',
273 private static function loadTemplateHtml(
string $tplDir,
string $tplName): string {
274 $tplName = trim($tplName);
275 if ($tplName ===
'') {
278 $path = rtrim($tplDir,
'/\\') . DIRECTORY_SEPARATOR . $tplName .
'.htm';
279 if (!is_file($path) || !is_readable($path)) {
282 $html = file_get_contents($path);
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);
291 $max = (int) (
$rows[0][
'sorter'] ?? 0);
293 return sprintf(
'%04d', $max + 10);
296 private static function nextSorterAfter(
string $sorter): string {
297 $num = (int) $sorter;
298 return sprintf(
'%04d', $num + 10);
static ddContent(string $lng='')