dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxContent_sections.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxContent_admin;
3
4dbx()->use_system_class('dbxReport');
5require_once dirname(__DIR__, 2) . '/dbxContent/include/dbxContent_bootstrap_sync.php';
6
7use dbx\dbxContent\dbxContentLng;
8use dbx\dbxContent\dbxContentLngSync;
9use dbx\dbxContent\dbxContentPageCache;
10use dbx\dbxContent\dbxContent_permalink;
11
13
14 public function run_body($content) {
15 $record = $this->_record;
16 $path = trim((string)($record['path'] ?? ''));
17
18 if ($path !== '') {
19 $url = '?dbx_modul=dbxEditor&dbx_run1=edit&file=' . rawurlencode($path);
20 $record['edit'] =
21 '<a class="btn btn-outline-primary btn-sm dbx-win" href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
22 'data-url="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" data-title="' .
23 htmlspecialchars($this->get_fd_message('edit_template'), ENT_QUOTES, 'UTF-8') . '" ' .
24 'title="' . htmlspecialchars($this->get_fd_message('edit_template'), ENT_QUOTES, 'UTF-8') .
25 '"><i class="bi bi-pencil"></i></a>';
26 }
27
28 $editUrl = trim((string)($record['edit_url'] ?? ''));
29 if ($editUrl !== '') {
30 $record['edit'] =
31 '<a class="btn btn-outline-primary btn-sm" href="' . htmlspecialchars($editUrl, ENT_QUOTES, 'UTF-8') . '" ' .
32 'title="' . htmlspecialchars($this->get_fd_message('edit_in_cms'), ENT_QUOTES, 'UTF-8') .
33 '"><i class="bi bi-pencil"></i></a>';
34 }
35
36 $this->_record = $record;
37 return $this->forward_run_body($content);
38 }
39}
40
42
43 private $content_folders = array();
44 private $media_usages = array();
45 private $sectionTexts = null;
46
47 private function section_texts() {
48 if ($this->sectionTexts) return $this->sectionTexts;
49 dbx()->get_system_obj('dbxForm', 'use');
50 $texts = new \dbxForm();
51 $texts->init('content-section-texts');
52 $texts->_fd = 'dbxContent_admin|rpt-content-list-selection';
53 $texts->load_fd_messages();
54 $texts->set_form_help_enabled(false);
55 $this->sectionTexts = $texts;
56 return $this->sectionTexts;
57 }
58
59 private function render_section($title, $subtitle, $content, $barActions = '') {
60 return dbx()->get_system_obj('dbxTPL')->get_tpl('dbxContent_admin|content-admin-section', array(
61 'title' => $title,
62 'subtitle' => $subtitle,
63 'content' => $content,
64 'bar_actions' => $barActions,
65 ));
66 }
67
68 private function is_ajax_request() {
69 return (int)dbx()->get_system_var('dbx_ajax', 0, 'int') === 1;
70 }
71
72 private function render_section_or_ajax($title, $subtitle, $content, $barActions = '') {
73 if ($this->is_ajax_request()) {
74 return $content;
75 }
76
77 return $this->render_section($title, $subtitle, $content, $barActions);
78 }
79
80 private function base_url($action, $params = array()) {
81 $url = '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=' . rawurlencode((string)$action);
82 foreach ($params as $key => $value) {
83 $url .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((string)$value);
84 }
85 return $url;
86 }
87
88 private function request_json() {
89 $raw = file_get_contents('php://input');
90 $data = $raw ? json_decode($raw, true) : array();
91 return is_array($data) ? $data : array();
92 }
93
94 private function content_grid_folder_editor_values() {
95 if (!$this->content_folders) {
96 $db = dbx()->get_system_obj('dbxDB');
97 $this->load_content_folders_map($db);
98 }
99
100 $pairs = array('0=/');
101 $folderIds = array_keys($this->content_folders);
102 usort($folderIds, function ($a, $b) {
103 return strcmp($this->content_folder_path($a), $this->content_folder_path($b));
104 });
105
106 foreach ($folderIds as $folderId) {
107 $path = $this->content_folder_path($folderId);
108 $label = str_replace(array('~', '=', ';'), array(' ', ' ', ' '), $path);
109 $pairs[] = (int)$folderId . '=' . $label;
110 }
111
112 return implode('~', $pairs);
113 }
114
115 private function content_grid_cols($texts) {
116 $folderValues = $this->content_grid_folder_editor_values();
117
118 return implode(',', array(
119 'id[ID]:number:p:width=72;hozAlign=center;headerHozAlign=center',
120 'title[' . $texts->get_fd_message('column_title') . ']:text::width=240',
121 'permalink[' . $texts->get_fd_message('column_permalink') . ']:text::width=200',
122 'folder[' . $texts->get_fd_message('column_folder') . ']:text::editor=list;values=' . $folderValues . ';width=220',
123 'activ[' . $texts->get_fd_message('column_active') . ']:text::editor=list;values=0='
124 . $texts->get_fd_message('status_inactive') . '~1=' . $texts->get_fd_message('status_active') . ';width=110',
125 'update_date[' . $texts->get_fd_message('column_updated') . ']:text:p:width=170',
126 ));
127 }
128
129 private function load_content_folders_map($db) {
130 $folderRows = $db->select(
131 dbxContentLng::ddFolder(),
132 '',
133 'id,name,parent_id',
134 'id',
135 'ASC',
136 '',
137 0,
138 0,
139 0
140 );
141 $this->content_folders = array();
142 if (is_array($folderRows)) {
143 foreach ($folderRows as $folderRow) {
144 $folderId = (int)($folderRow['id'] ?? 0);
145 if ($folderId > 0) {
146 $this->content_folders[$folderId] = $folderRow;
147 }
148 }
149 }
150 }
151
152 private function enrich_content_row(array $row) {
153 $row['folder_path'] = $this->content_folder_path($row['folder'] ?? 0);
154 if (isset($row['update_date'])) {
155 $row['update_date'] = preg_replace('/\.\d+$/', '', trim((string)$row['update_date']));
156 }
157 $id = (int)($row['id'] ?? 0);
158 if ($id > 0) {
159 $row['profile_link'] = $this->base_url('edit', array('cid' => $id)) . '&dbx_window=1';
160 $row['show_link'] = '?dbx_modul=dbxContent&dbx_run1=show&dbx_cid=' . $id . '&dbx_window=1';
161 }
162 return $row;
163 }
164
165 private function grid_sort_from_request() {
166 $rsort = 'id';
167 $rdesc = 'DESC';
168 $allowed = array('id', 'title', 'permalink', 'activ', 'update_date', 'folder');
169 $sort = dbx()->get_request_var('dbx_sorters', '', '*');
170 if ($sort) {
171 $sorters = json_decode($sort, true);
172 if (is_array($sorters) && isset($sorters[0]['field'])) {
173 $field = (string)$sorters[0]['field'];
174 if (in_array($field, $allowed, true)) {
175 $rsort = $field;
176 $rdesc = strtolower((string)($sorters[0]['dir'] ?? 'asc')) === 'desc' ? 'DESC' : 'ASC';
177 }
178 }
179 }
180 return array($rsort, $rdesc);
181 }
182
183 private function content_grid_read() {
184 $db = dbx()->get_system_obj('dbxDB');
185 $dd = dbxContentLng::ddContent();
186 $this->load_content_folders_map($db);
187
188 $page = (int)dbx()->get_request_var('page', 0, 'int');
189 $size = (int)dbx()->get_request_var('size', 0, 'int');
190
191 $search = dbx()->get_request_var('dbx_search', '', 'sqlsearch|max=128');
192 $where = $db->build_search_where($dd, $search, array('title', 'permalink'), array('id'), 'contains');
193 list($rsort, $rdesc) = $this->grid_sort_from_request();
194
195 $flds = array('id', 'title', 'permalink', 'folder', 'activ', 'update_date');
196
197 if ($page > 0 && $size > 0) {
198 $size = max(1, min(200, $size));
199 $rpos = ($page - 1) * $size;
200 $count = (int)$db->count($dd, $where);
201 $rows = $db->select($dd, $where, $flds, $rsort, $rdesc, '', $size, $rpos);
202 } else {
203 $rows = $db->select($dd, $where, $flds, $rsort, $rdesc, '', 0, 0);
204 $count = is_array($rows) ? count($rows) : 0;
205 }
206 if (!is_array($rows)) {
207 $rows = array();
208 }
209
210 $out = array();
211 foreach ($rows as $row) {
212 if (!is_array($row)) {
213 continue;
214 }
215 $out[] = $this->enrich_content_row($row);
216 }
217
218 $count = (int)$count;
219 $last_page = ($page > 0 && $size > 0) ? max(1, (int)ceil($count / $size)) : 1;
220
221 dbx()->json_response(array(
222 'ok' => 1,
223 'count' => $count,
224 'last_page' => $last_page,
225 'last_row' => $count,
226 'rows' => $out,
227 'server_time' => (new \DateTime())->format('Y-m-d H:i:s.v'),
228 ), true);
229 }
230
231 private function content_grid_sync() {
232 $db = dbx()->get_system_obj('dbxDB');
233 $dd = dbxContentLng::ddContent();
234 $this->load_content_folders_map($db);
235
236 $last_update = trim((string)dbx()->get_request_var('last_update', ''));
237 if ($last_update === '') {
238 $last_update = trim((string)dbx()->get_modul_var('last_update', ''));
239 }
240 if ($last_update === '') {
241 $last_update = '1970-01-01 00:00:00';
242 }
243
244 $where = "update_date > '" . str_replace("'", "''", $last_update) . "'";
245 $flds = array('id', 'title', 'permalink', 'folder', 'activ', 'update_date');
246 $rows = $db->select($dd, $where, $flds, 'update_date', 'ASC', '', 0, 0);
247 if (!is_array($rows)) {
248 $rows = array();
249 }
250
251 $out = array();
252 foreach ($rows as $row) {
253 if (!is_array($row)) {
254 continue;
255 }
256 $out[] = $this->enrich_content_row($row);
257 }
258
259 dbx()->json_response(array(
260 'ok' => 1,
261 'count' => count($out),
262 'rows' => $out,
263 'server_time' => (new \DateTime())->format('Y-m-d H:i:s.v'),
264 ), true);
265 }
266
267 private function content_grid_save() {
268 $db = dbx()->get_system_obj('dbxDB');
269 $cms = dbx()->get_include_obj('dbxContent_cms');
270 if (is_object($cms) && method_exists($cms, 'ensure_schema')) {
271 $cms->ensure_schema($db);
272 }
273
274 $payload = $this->request_json();
275 $rows = is_array($payload['rows'] ?? null) ? $payload['rows'] : array();
276 $dd = dbxContentLng::ddContent();
277 $allowed = array_flip(array('title', 'permalink', 'activ', 'folder'));
278 $saved = array();
279
280 $this->load_content_folders_map($db);
281
282 foreach ($rows as $row) {
283 if (!is_array($row)) {
284 continue;
285 }
286 $id = (int)($row['id'] ?? 0);
287 if ($id <= 0) {
288 continue;
289 }
290
291 $data = array();
292 foreach ($allowed as $field => $_) {
293 if (!array_key_exists($field, $row)) {
294 continue;
295 }
296 if ($field === 'activ' || $field === 'folder') {
297 $data[$field] = (int)$row[$field];
298 } else {
299 $data[$field] = trim((string)$row[$field]);
300 }
301 }
302 if (!$data) {
303 continue;
304 }
305
306 if (array_key_exists('folder', $data)) {
307 $folderId = (int)$data['folder'];
308 if ($folderId < 0 || ($folderId > 0 && !isset($this->content_folders[$folderId]))) {
309 continue;
310 }
311 }
312
313 if (array_key_exists('permalink', $data)) {
314 if ($data['permalink'] === '') {
315 $current = $db->select1($dd, $id, 'title,folder', 0);
316 $pageTitle = (string)($data['title'] ?? ($current['title'] ?? 'Seite'));
317 $pageFolder = (int)($data['folder'] ?? ($current['folder'] ?? 0));
318 $data['permalink'] = dbxContent_permalink::build(
319 $db,
320 dbxContentLng::ddFolder(),
321 $pageFolder,
322 $pageTitle,
323 $id
324 );
325 } elseif (!dbxContent_permalink::isValid($data['permalink'])) {
326 dbx()->json_response(array(
327 'ok' => 0,
328 'success' => false,
329 'field' => 'permalink',
330 'id' => $id,
331 'msg' => 'Permalink: nur Kleinbuchstaben, Zahlen und einzelne Bindestriche sind erlaubt.',
332 ), true);
333 } elseif (dbxContent_permalink::exists($db, $dd, $data['permalink'], $id)) {
334 dbx()->json_response(array(
335 'ok' => 0,
336 'success' => false,
337 'field' => 'permalink',
338 'id' => $id,
339 'msg' => 'Dieser Permalink wird bereits von einer anderen Seite verwendet.',
340 ), true);
341 }
342 }
343
344 if ($db->update($dd, $data, $id) >= 0) {
345 dbxContentLngSync::afterPageSave($db, $id, false);
346 dbxContentPageCache::invalidateContent($id);
347 dbxContentPageCache::invalidateAllMenus();
348 $fresh = $db->select1($dd, $id, 'id,title,permalink,folder,activ,update_date', 0);
349 if (is_array($fresh)) {
350 $saved[] = $this->enrich_content_row($fresh);
351 }
352 }
353 }
354
355 $this->load_content_folders_map($db);
356
357 dbx()->json_response(array(
358 'ok' => 1,
359 'success' => true,
360 'rows' => $saved,
361 ), true);
362 }
363
364 private function content_grid_delete() {
365 $payload = $this->request_json();
366 $id = (int)($payload['id'] ?? 0);
367 if ($id <= 0) {
368 dbx()->json_response(array('ok' => 0, 'success' => false, 'msg' => 'Keine Seiten-ID.'), true);
369 }
370
371 $cms = dbx()->get_include_obj('dbxContent_cms');
372 $result = is_object($cms) ? $cms->delete_page_record($id) : array('ok' => 0, 'errors' => array('CMS nicht verfuegbar.'));
373 $errors = is_array($result['errors'] ?? null) ? $result['errors'] : array();
374
375 dbx()->json_response(array(
376 'ok' => (int)($result['ok'] ?? 0),
377 'success' => (int)($result['ok'] ?? 0) === 1,
378 'msg' => implode(' ', $errors),
379 ), true);
380 }
381
382 private function report_content_grid() {
383 $oReport = dbx()->get_system_obj('dbxReport');
384 $db = dbx()->get_system_obj('dbxDB');
385 $dd = dbxContentLng::ddContent();
386 $all = (int)$db->count($dd);
387 $active = (int)$db->count($dd, 'activ = 1');
388
389 $oReport->init('content-admin-content-grid', 'content-admin-content-grid');
390 $oReport->_fd = 'dbxContent_admin|rpt-content-list-selection';
391 $oReport->load_fd_messages();
392 $oReport->add_rep('shell_panel_class', 'dbx-grid dbx-content-list-grid');
393 $oReport->add_rep('frame_use_form', '0');
394 $oReport->add_rep('bar_title', $oReport->get_fd_message('bar_title'));
395 $oReport->add_rep('bar_subtitle', $oReport->get_fd_message('bar_subtitle'));
396 $oReport->_mode = 'tabulurator';
397 $oReport->_rrows = 600;
398 $oReport->_grid_id = 'dbx_content_list_grid';
399 $oReport->_grid_cols = $this->content_grid_cols($oReport);
400 $oReport->_grid_layout = 'fitDataStretch';
401 $oReport->_grid_read_url = $this->base_url('content_grid_read');
402 $oReport->_grid_save_url = $this->base_url('content_grid_save');
403 $oReport->_grid_delete_url = $this->base_url('content_grid_delete');
404 $oReport->_grid_sync_url = $this->base_url('content_grid_sync');
405 $oReport->_grid_synctime = '1.5';
406 $oReport->add_grid_stats(array(
407 array('label' => $oReport->get_fd_message('stats_pages'), 'value' => (string)$all),
408 array('label' => $oReport->get_fd_message('stats_active'), 'value' => (string)$active, 'tone' => 'ok'),
409 array('label' => $oReport->get_fd_message('stats_inactive'), 'value' => (string)max(0, $all - $active)),
410 ), $oReport->get_fd_message('stats_title'));
411 $oReport->add_obj('bar_actions', 'obj-value',
412 '<a class="btn btn-outline-primary btn-sm" href="' . dbx()->esc($this->base_url('edit')) . '">' .
413 '<i class="bi bi-pencil-square"></i><span>' . dbx()->esc($oReport->get_fd_message('cms_label')) . '</span></a>'
414 );
415
416 return $oReport->run();
417 }
418
419 private function report_rows($action, array $fields, array $rows, $msgSuccess = '', $msgError = '') {
421 $report->init('content-admin-report');
422 $report->_fd = 'dbxContent_admin|rpt-content-list-selection';
423 $report->load_fd_messages();
424 $report->set_form_help_enabled(false);
425 $report->_action = '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=' . rawurlencode($action);
426 $report->_create_sel_flds = 0;
427 $report->_rflds = $fields;
428 $report->_mode = 'table';
429 $report->_rdata = $rows;
430 $report->_rcount = count($rows);
431 $report->_rrows = count($rows) > 0 ? count($rows) : 1;
432 $report->_rpos = 0;
433
434 if ($msgSuccess !== '') {
435 $report->_msg_success = $msgSuccess;
436 }
437 if ($msgError !== '') {
438 $report->_msg_error = $msgError;
439 }
440
441 if ($action === 'list_folder') {
442 $report->set_callback_owner($this);
443 $report->set_callback('next_record', 'folder_next_record');
444 $report->set_callback('row_action_data', 'folder_row_action_data');
445 $report->_create_row_edit = 1;
446 $report->_create_row_delete = 1;
447 $report->_msg_confirm_delete = $report->get_fd_message('confirm_folder_delete');
448 $report->set_tabel_tpl('tpl_row_edit', 'modul|content-admin-row-edit');
449 } elseif ($action === 'list_media') {
450 $report->set_callback_owner($this);
451 $report->set_callback('next_record', 'media_next_record');
452 $report->set_callback('row_action_data', 'media_row_action_data');
453 $report->_create_row_delete = 1;
454 $report->_msg_confirm_delete = $report->get_fd_message('confirm_media_delete');
455 $report->set_tabel_tpl('tpl_row_delete', 'modul|content-admin-row-delete-media');
456 } elseif ($action === 'templates') {
457 $report->set_callback_owner($this);
458 $report->set_callback('row_action_data', 'template_row_action_data');
459 $report->_create_row_edit = 1;
460 $report->_create_row_delete = 1;
461 $report->_fld_id = 'name';
462 $report->_msg_confirm_delete = $report->get_fd_message('confirm_template_delete');
463 $report->_rpt_format['modified'] = 'php-datetime-usr';
464 $report->_table_buttons = 'left';
465 $report->set_tabel_tpl('tpl_row_edit', 'modul|content-admin-row-edit');
466 $report->set_tabel_tpl('tpl_row_delete', 'modul|content-admin-row-delete-template');
467 }
468
469 return $report->run();
470 }
471
472 private function content_folder_path($folderId) {
473 $folderId = (int)$folderId;
474 if ($folderId <= 0) {
475 return '/';
476 }
477
478 $parts = array();
479 $seen = array();
480
481 while ($folderId > 0 && isset($this->content_folders[$folderId]) && !isset($seen[$folderId])) {
482 $seen[$folderId] = true;
483 $folder = $this->content_folders[$folderId];
484 $name = trim((string)($folder['name'] ?? ''), " \t\n\r\0\x0B/");
485
486 if ($name !== '') {
487 array_unshift($parts, $name);
488 }
489
490 $parentId = (int)($folder['parent_id'] ?? 0);
491 if ($parentId === $folderId) {
492 break;
493 }
494 $folderId = $parentId;
495 }
496
497 return '/' . implode('/', $parts);
498 }
499
500 public function content_next_record($report, $record) {
501 if (!is_array($record)) {
502 return $record;
503 }
504
505 $record['folder_path'] = $this->content_folder_path($record['folder'] ?? 0);
506 if (isset($record['update_date'])) {
507 $record['update_date'] = preg_replace('/\.\d+$/', '', trim((string)$record['update_date']));
508 }
509 return $record;
510 }
511
512 public function content_row_action_data($report, $data) {
513 if (!is_array($data) || !isset($data['data']) || !is_array($data['data'])) {
514 return $data;
515 }
516
517 $type = (string)($data['type'] ?? '');
518 $rid = (int)($data['data']['rid'] ?? 0);
519
520 if ($type === 'edit') {
521 $url = '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=edit&cid=' . $rid . '&dbx_window=1';
522 $data['data']['action'] = $url;
523 $data['data']['edit_url'] = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
524 $data['data']['edit_title'] = htmlspecialchars('Content im CMS bearbeiten', ENT_QUOTES, 'UTF-8');
525 $data['data']['class'] = 'openWin';
526 } elseif ($type === 'delete') {
527 $data['data']['action'] =
528 '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=list_content';
529 }
530
531 return $data;
532 }
533
534 public function media_next_record($report, $record) {
535 if (!is_array($record)) {
536 return $record;
537 }
538
539 $id = (int)($record['id'] ?? 0);
540 $type = strtolower(trim((string)($record['media_type'] ?? '')));
541 $provider = strtolower(trim((string)($record['provider'] ?? '')));
542 $providerId = trim((string)($record['provider_id'] ?? ''));
543 $title = trim((string)($record['title'] ?? $record['file_name'] ?? 'Medium'));
544 $preview = '<span class="text-muted"><i class="bi bi-file-earmark"></i></span>';
545
546 if ($id > 0 && in_array($type, array('image', 'video', 'external_video'), true)) {
547 $mediaUrl = 'index.php?dbx_modul=dbxContent&dbx_run1=media&dbx_mid=' . $id;
548 $url = '?dbx_modul=dbxContent_admin&dbx_run1=media_view&rid=' . $id . '&dbx_window=1';
549 $thumbUrl = $mediaUrl . '&dbx_thumb=1';
550 if ($type === 'external_video' && $provider === 'youtube' && preg_match('/^[A-Za-z0-9_-]{11}$/', $providerId)) {
551 $thumbUrl = 'https://img.youtube.com/vi/' . rawurlencode($providerId) . '/hqdefault.jpg';
552 }
553 $preview =
554 '<a class="openWin dbx-win" href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
555 'data-url="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
556 'data-title="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" ' .
557 'title="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '">' .
558 '<img src="' . htmlspecialchars($thumbUrl, ENT_QUOTES, 'UTF-8') . '" ' .
559 'alt="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" loading="lazy" ' .
560 'class="rounded border bg-light" style="width:96px;height:64px;object-fit:cover">' .
561 '</a>';
562 }
563
564 $record['thumbnail'] = $preview;
565 $usages = $this->media_usages[$id] ?? array();
566 $usageHtml = array();
567 foreach ($usages as $usage) {
568 $lng = strtolower(trim((string)($usage['lng'] ?? '')));
569 $usageId = (int)($usage['id'] ?? 0);
570 $type = (string)($usage['type'] ?? 'page');
571 $label = trim((string)($usage['title'] ?? ''));
572 $url = '?dbx_modul=dbxContent_admin&dbx_run1=cms&dbx_lng=' . rawurlencode($lng) .
573 ($type === 'folder' ? '&fid=' : '&cid=') . $usageId . '&dbx_window=1';
574 $usageHtml[] =
575 '<a class="openWin dbx-win d-block text-decoration-none mb-1" ' .
576 'href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
577 'data-url="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
578 'data-title="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '" ' .
579 'title="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '">' .
580 '<span class="badge text-bg-secondary me-1">' . htmlspecialchars(strtoupper($lng), ENT_QUOTES, 'UTF-8') . '</span>' .
581 htmlspecialchars($label, ENT_QUOTES, 'UTF-8') .
582 '</a>';
583 }
584 $record['usage'] = count($usageHtml)
585 ? implode('', $usageHtml)
586 : '<span class="text-muted">Nicht verwendet</span>';
587 $record['_usage_count'] = count($usages);
588 return $record;
589 }
590
591 public function media_row_action_data($report, $data) {
592 if (!is_array($data) || !isset($data['data']) || !is_array($data['data'])) {
593 return $data;
594 }
595
596 if ((string)($data['type'] ?? '') !== 'delete') {
597 return $data;
598 }
599
600 $rid = (int)($data['data']['rid'] ?? 0);
601 $used = count($this->media_usages[$rid] ?? array()) > 0;
602 $data['data']['delete_url'] =
603 '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=list_media&dbx_do=row_delete&rid=' . $rid;
604 $data['data']['delete_class'] = $used ? 'disabled text-muted' : 'dbxAjax dbxConfirm text-danger';
605 $data['data']['delete_title'] = $used
606 ? 'Medium wird verwendet und kann nicht geloescht werden'
607 : 'Medium loeschen';
608 $data['data']['delete_disabled'] = $used ? 'aria-disabled="true" tabindex="-1"' : '';
609 $data['data']['confirm'] = $report->_msg_confirm_delete;
610
611 return $data;
612 }
613
614 private function add_media_usage(array &$map, int $mediaId, string $lng, int $id, string $title, string $type = 'page'): void {
615 if ($mediaId <= 0 || $id <= 0 || $lng === '') {
616 return;
617 }
618
619 $key = $type . '|' . $lng . '|' . $id;
620 $map[$mediaId][$key] = array(
621 'lng' => $lng,
622 'id' => $id,
623 'title' => ($type === 'folder' ? 'Ordner: ' : '') . ($title !== '' ? $title : ('#' . $id)),
624 'type' => $type,
625 );
626 }
627
628 private function load_media_usages($db): array {
629 $map = array();
630 $usageRows = $db->select('dbxMediaUsage', 'active = 1', 'media_id,content_id,folder_id,content_lng', 'media_id,id', 'ASC', '', 0, 0, 0);
631 $usageRows = is_array($usageRows) ? $usageRows : array();
632
633 foreach (dbxContentLngSync::accessibleLngs() as $lng) {
634 $lng = strtolower(trim((string)$lng));
635 if ($lng === '') {
636 continue;
637 }
638
639 $pages = $db->select(
640 dbxContentLng::ddContent($lng),
641 '',
642 'id,title,hero_image_id,seo_image_id,content',
643 'id',
644 'ASC',
645 '',
646 0,
647 0,
648 0
649 );
650 $folders = $db->select(
651 dbxContentLng::ddFolder($lng),
652 '',
653 'id,name,hero_image_id',
654 'id',
655 'ASC',
656 '',
657 0,
658 0,
659 0
660 );
661
662 $pagesById = array();
663 foreach (is_array($pages) ? $pages : array() as $page) {
664 $pageId = (int)($page['id'] ?? 0);
665 if ($pageId <= 0) {
666 continue;
667 }
668 $pagesById[$pageId] = $page;
669
670 $heroId = (int)($page['hero_image_id'] ?? 0);
671 if ($heroId > 0) {
672 $this->add_media_usage($map, $heroId, $lng, $pageId, (string)($page['title'] ?? ''), 'page');
673 }
674 $seoId = (int)($page['seo_image_id'] ?? 0);
675 if ($seoId > 0) {
676 $this->add_media_usage($map, $seoId, $lng, $pageId, (string)($page['title'] ?? ''), 'page');
677 }
678 $inlineIds = array();
679 $content = (string)($page['content'] ?? '');
680 if (preg_match_all('/data-cms-media-id=["\']?(\d+)/i', $content, $matches)) {
681 foreach ($matches[1] as $mediaId) $inlineIds[(int)$mediaId] = (int)$mediaId;
682 }
683 if (preg_match_all('/(?:dbx_mid|media_id)=(\d+)(?:[^0-9]|$)/i', $content, $matches)) {
684 foreach ($matches[1] as $mediaId) $inlineIds[(int)$mediaId] = (int)$mediaId;
685 }
686 foreach ($inlineIds as $mediaId) {
687 if ($mediaId > 0) {
688 $this->add_media_usage($map, (int)$mediaId, $lng, $pageId, (string)($page['title'] ?? ''), 'page');
689 }
690 }
691 }
692
693 $foldersById = array();
694 foreach (is_array($folders) ? $folders : array() as $folder) {
695 $folderId = (int)($folder['id'] ?? 0);
696 if ($folderId <= 0) {
697 continue;
698 }
699 $foldersById[$folderId] = $folder;
700 $heroId = (int)($folder['hero_image_id'] ?? 0);
701 if ($heroId > 0) {
702 $this->add_media_usage($map, $heroId, $lng, $folderId, (string)($folder['name'] ?? ''), 'folder');
703 }
704 }
705
706 foreach ($usageRows as $usage) {
707 if (strtolower(trim((string)($usage['content_lng'] ?? 'de'))) !== $lng) continue;
708 $mediaId = (int)($usage['media_id'] ?? 0);
709 $contentId = (int)($usage['content_id'] ?? 0);
710 $folderId = (int)($usage['folder_id'] ?? 0);
711 if ($contentId > 0 && isset($pagesById[$contentId])) {
712 $this->add_media_usage(
713 $map,
714 $mediaId,
715 $lng,
716 $contentId,
717 (string)($pagesById[$contentId]['title'] ?? ''),
718 'page'
719 );
720 } elseif ($folderId > 0 && isset($foldersById[$folderId])) {
721 $this->add_media_usage(
722 $map,
723 $mediaId,
724 $lng,
725 $folderId,
726 (string)($foldersById[$folderId]['name'] ?? ''),
727 'folder'
728 );
729 }
730 }
731 }
732
733 foreach ($map as $mediaId => $items) {
734 $map[$mediaId] = array_values($items);
735 }
736 return $map;
737 }
738
739 public function folder_next_record($report, $record) {
740 if (!is_array($record)) {
741 return $record;
742 }
743
744 $record['folder_path'] = $this->content_folder_path($record['id'] ?? 0);
745 return $record;
746 }
747
748 public function folder_row_action_data($report, $data) {
749 if (!is_array($data) || !isset($data['data']) || !is_array($data['data'])) {
750 return $data;
751 }
752
753 $type = (string)($data['type'] ?? '');
754 $rid = (int)($data['data']['rid'] ?? 0);
755
756 if ($type === 'edit') {
757 $url = '?dbx_modul=dbxContent_admin&dbx_run1=cms&fid=' . $rid . '&dbx_window=1';
758 $data['data']['action'] = $url;
759 $data['data']['edit_url'] = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
760 $data['data']['edit_title'] = htmlspecialchars(
761 $this->section_texts()->get_fd_message('edit_folder_in_cms'),
762 ENT_QUOTES,
763 'UTF-8'
764 );
765 $data['data']['class'] = 'openWin';
766 } elseif ($type === 'delete') {
767 $data['data']['action'] =
768 '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=list_folder';
769 }
770
771 return $data;
772 }
773
774 private function report_content() {
775 return $this->report_content_grid();
776 }
777
778 private function report_folders() {
779 $db = dbx()->get_system_obj('dbxDB');
780 $texts = $this->section_texts();
781
782 $deleteId = (int)dbx()->get_modul_var('rid', 0, 'int');
783 if (dbx()->get_modul_var('dbx_do', '', 'parameter') === 'row_delete' && $deleteId > 0) {
784 $cms = dbx()->get_include_obj('dbxContent_cms');
785 $cms->delete_folder_record($deleteId);
786 }
787
788 $fields = array(
789 'id' => 'ID',
790 'folder_path' => $texts->get_fd_message('column_folder'),
791 'template' => $texts->get_fd_message('column_template'),
792 'group_read' => $texts->get_fd_message('column_read_rights'),
793 );
794
795 $rows = $db->select(
796 dbxContentLng::ddFolder(),
797 '',
798 'id,name,parent_id,template,group_read',
799 'name',
800 'ASC',
801 '',
802 0,
803 0,
804 0
805 );
806 if (!is_array($rows)) {
807 $rows = array();
808 }
809
810 $this->content_folders = array();
811 foreach ($rows as $index => $row) {
812 $folderId = (int)($row['id'] ?? 0);
813 if ($folderId > 0) {
814 $this->content_folders[$folderId] = $row;
815 }
816 $rows[$index]['folder_path'] = '';
817 }
818
819 return $this->report_rows('list_folder', $fields, $rows);
820 }
821
822 private function report_media() {
823 $db = dbx()->get_system_obj('dbxDB');
824 $texts = $this->section_texts();
825
826 $this->media_usages = $this->load_media_usages($db);
827 $deleteId = (int)dbx()->get_modul_var('rid', 0, 'int');
828 if (dbx()->get_modul_var('dbx_do', '', 'parameter') === 'row_delete' && $deleteId > 0) {
829 $cms = dbx()->get_include_obj('dbxContent_cms');
830 $cms->delete_media_record($deleteId);
831 $this->media_usages = $this->load_media_usages($db);
832 }
833
834 $fields = array(
835 'thumbnail' => $texts->get_fd_message('column_preview'),
836 'id' => 'ID',
837 'title' => $texts->get_fd_message('column_title'),
838 'media_type' => $texts->get_fd_message('column_type'),
839 'media_folder' => $texts->get_fd_message('column_folder'),
840 'provider' => $texts->get_fd_message('column_provider'),
841 'usage' => $texts->get_fd_message('column_usage'),
842 'active' => $texts->get_fd_message('column_active'),
843 );
844
845 $rows = $db->select(
846 'dbxMedia',
847 '',
848 'id,title,media_type,file_name,media_folder,provider,provider_id,active',
849 'id',
850 'DESC',
851 '',
852 0,
853 0,
854 0
855 );
856 if (!is_array($rows)) {
857 $rows = array();
858 }
859
860 foreach ($rows as $index => $row) {
861 $rows[$index]['thumbnail'] = '';
862 $rows[$index]['usage'] = '';
863 }
864
865 return $this->report_rows('list_media', $fields, $rows);
866 }
867
868 private function media_view() {
869 $id = (int)dbx()->get_modul_var('rid', 0, 'int');
870 $db = dbx()->get_system_obj('dbxDB');
871 $row = $id > 0 ? $db->select1('dbxMedia', $id) : array();
872
873 if (!is_array($row) || !count($row)) {
874 return dbx()->get_system_obj('dbxTPL')->get_tpl('dbx|alert-warning', array(
875 'msg' => $this->section_texts()->get_fd_message('media_not_found'),
876 ));
877 }
878
879 $type = strtolower(trim((string)($row['media_type'] ?? 'file')));
880 $provider = strtolower(trim((string)($row['provider'] ?? '')));
881 $providerId = trim((string)($row['provider_id'] ?? ''));
882 $title = trim((string)($row['title'] ?? $row['file_name'] ?? ('Medium #' . $id)));
883 $mime = trim((string)($row['mime'] ?? ''));
884 $mediaUrl = 'index.php?dbx_modul=dbxContent&dbx_run1=media&dbx_mid=' . $id;
885 $mediaHtml = '';
886
887 if ($type === 'image') {
888 $mediaHtml =
889 '<img src="' . htmlspecialchars($mediaUrl, ENT_QUOTES, 'UTF-8') . '" ' .
890 'alt="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" ' .
891 'class="img-fluid rounded border bg-light" style="max-height:72vh;object-fit:contain">';
892 } elseif ($type === 'video') {
893 $poster = !empty($row['thumb_file_path'])
894 ? ' poster="' . htmlspecialchars($mediaUrl . '&dbx_thumb=1', ENT_QUOTES, 'UTF-8') . '"'
895 : '';
896 $mediaHtml =
897 '<video class="w-100 rounded border bg-dark" style="max-height:72vh" controls preload="metadata" playsinline' . $poster . '>' .
898 '<source src="' . htmlspecialchars($mediaUrl, ENT_QUOTES, 'UTF-8') . '"' .
899 ($mime !== '' ? ' type="' . htmlspecialchars($mime, ENT_QUOTES, 'UTF-8') . '"' : '') . '>' .
900 'Ihr Browser kann dieses Video nicht wiedergeben.</video>';
901 } elseif ($type === 'external_video' && $provider === 'youtube' && preg_match('/^[A-Za-z0-9_-]{11}$/', $providerId)) {
902 $embedUrl = 'https://www.youtube.com/embed/' . rawurlencode($providerId);
903 $mediaHtml =
904 '<div class="ratio ratio-16x9"><iframe src="' . htmlspecialchars($embedUrl, ENT_QUOTES, 'UTF-8') . '" ' .
905 'title="' . htmlspecialchars($title, ENT_QUOTES, 'UTF-8') . '" ' .
906 'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" ' .
907 'allowfullscreen></iframe></div>';
908 } else {
909 $mediaHtml =
910 '<div class="text-center py-5"><i class="bi bi-file-earmark fs-1 d-block mb-3"></i>' .
911 '<a class="btn btn-primary" href="' . htmlspecialchars($mediaUrl, ENT_QUOTES, 'UTF-8') . '">' .
912 '<i class="bi bi-box-arrow-up-right"></i> Datei anzeigen</a></div>';
913 }
914
915 return dbx()->get_system_obj('dbxTPL')->get_tpl('dbxContent_admin|content-admin-media-view', array(
916 'title' => htmlspecialchars($title, ENT_QUOTES, 'UTF-8'),
917 'media' => $mediaHtml,
918 'type' => htmlspecialchars($type, ENT_QUOTES, 'UTF-8'),
919 'folder' => htmlspecialchars((string)($row['media_folder'] ?? ''), ENT_QUOTES, 'UTF-8'),
920 'mime' => htmlspecialchars($mime, ENT_QUOTES, 'UTF-8'),
921 'id' => (string)$id,
922 ));
923 }
924
925 public function template_row_action_data($report, $data) {
926 if (!is_array($data) || !isset($data['data']) || !is_array($data['data'])) {
927 return $data;
928 }
929
930 $record = is_array($data['record'] ?? null) ? $data['record'] : array();
931 $type = (string)($data['type'] ?? '');
932 $tpl = trim((string)($record['name'] ?? ''));
933
934 if ($type === 'edit') {
935 $modul = trim((string)($record['modul'] ?? 'dbxContent'));
936 $fileType = trim((string)($record['type'] ?? 'htm'));
937
938 $relPath = 'dbx/modules/' . $modul . '/tpl/' . $fileType . '/' . $tpl . '.' . $fileType;
939 $url = '?dbx_modul=dbxEditor&dbx_run1=edit&file=' . rawurlencode($relPath) . '&dbx_window=1';
940
941 $data['data']['action'] = $url;
942 $data['data']['edit_url'] = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
943 $data['data']['edit_title'] = htmlspecialchars($modul . '|' . $tpl, ENT_QUOTES, 'UTF-8');
944 $data['data']['class'] = 'openWin';
945 } elseif ($type === 'delete' && $tpl !== '') {
946 $data['data']['delete_url'] =
947 '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=templates&dbx_do=row_delete&rid=' .
948 rawurlencode($tpl);
949 $data['data']['delete_class'] = 'dbxAjax dbxConfirm text-danger';
950 $data['data']['delete_title'] = 'Template loeschen';
951 $data['data']['delete_disabled'] = '';
952 $data['data']['confirm'] = $report->_msg_confirm_delete;
953 }
954
955 return $data;
956 }
957
958 private function template_dir() {
959 return dbx()->os_path(dbx()->get_base_dir() . 'dbx/modules/dbxContent/tpl/htm/');
960 }
961
962 private function normalize_template_name($name) {
963 $name = trim((string)$name);
964 $name = preg_replace('/\.htm$/i', '', $name);
965
966 if ($name !== '' && stripos($name, 'c-') !== 0) {
967 $name = 'c-' . $name;
968 }
969
970 if ($name === '' || !preg_match('/^c-[a-zA-Z0-9][a-zA-Z0-9_-]*$/', $name)) {
971 return '';
972 }
973
974 return $name;
975 }
976
977 private function template_file_path($name) {
978 $name = $this->normalize_template_name($name);
979 if ($name === '') {
980 return '';
981 }
982
983 $dir = rtrim($this->template_dir(), '/\\') . DIRECTORY_SEPARATOR;
984 if (!is_dir($dir)) {
985 return '';
986 }
987
988 return $dir . $name . '.htm';
989 }
990
991 private function default_template_markup() {
992 return <<<'HTML'
993<article id="dbx_target_{i}" class="c-cms default">
994
995 <div class="title">
996 <h1>{cms:title}</h1>
997 </div>
998
999 <section class="cms-hero {cms:hero_class}" style="{hero:style}">
1000 <div class="hero">{cms:hero}</div>
1001 </section>
1002
1003 <section class="cms-header header">{cms:header}</section>
1004
1005 <section class="gallery {cms:gallery_class}">
1006 <div class="gallery-list"
1007 style="{gallery:style}"{gallery:data_dbx}>{cms:gallery}</div>
1008 </section>
1009
1010 <section class="cols cols-{cms:cols}">
1011 <div class="col col-1">{cms:col1}</div>
1012 <div class="col col-2">{cms:col2}</div>
1013 <div class="col col-3">{cms:col3}</div>
1014 </section>
1015
1016 <footer class="footer">{cms:footer}</footer>
1017
1018</article>
1019
1020HTML;
1021 }
1022
1023 private function delete_template_file($name) {
1024 $path = $this->template_file_path($name);
1025 if ($path === '' || !is_file($path)) {
1026 return false;
1027 }
1028
1029 return @unlink($path);
1030 }
1031
1032 private function create_template_file($name) {
1033 $texts = $this->section_texts();
1034 $name = $this->normalize_template_name($name);
1035 if ($name === '') {
1036 return array('ok' => false, 'msg' => $texts->get_fd_message('template_invalid_name'));
1037 }
1038
1039 $path = $this->template_file_path($name);
1040 if ($path === '') {
1041 return array('ok' => false, 'msg' => $texts->get_fd_message('template_path_error'));
1042 }
1043
1044 if (is_file($path)) {
1045 return array('ok' => false, 'msg' => $texts->format_fd_message('template_exists', array('name' => $name)));
1046 }
1047
1048 $bytes = @file_put_contents($path, $this->default_template_markup());
1049 if ($bytes === false) {
1050 return array('ok' => false, 'msg' => $texts->get_fd_message('template_create_error'));
1051 }
1052
1053 return array(
1054 'ok' => true,
1055 'msg' => $texts->format_fd_message('template_created', array('name' => $name)),
1056 'name' => $name
1057 );
1058 }
1059
1060 private function templates_bar_actions() {
1061 $texts = $this->section_texts();
1062 $url = '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=template_new&dbx_window=1';
1063
1064 return '<a class="btn btn-primary btn-sm openWin dbx-win" href="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
1065 'data-url="' . htmlspecialchars($url, ENT_QUOTES, 'UTF-8') . '" ' .
1066 'data-title="' . htmlspecialchars($texts->get_fd_message('template_new_title'), ENT_QUOTES, 'UTF-8') .
1067 '" title="' . htmlspecialchars($texts->get_fd_message('template_new_action_title'), ENT_QUOTES, 'UTF-8') . '">' .
1068 '<i class="bi bi-plus-lg"></i> ' .
1069 htmlspecialchars($texts->get_fd_message('template_new_button'), ENT_QUOTES, 'UTF-8') . '</a>';
1070 }
1071
1078 private function template_new() {
1079 $action = '?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=template_new';
1080 $form = dbx()->get_system_obj('dbxForm');
1081 $form->init('content-template-new', 'content-admin-template-new');
1082 $form->_fd = 'dbxContent_admin|rpt-content-list-selection';
1083 $form->load_fd_messages();
1084 $form->_action = $action;
1085 // Den von init() erzeugten Security-Wert erhalten.
1086 $form->_data = array_merge($form->_data, array('template_name' => ''));
1087 $form->_msg_info = $form->get_fd_message('template_new_info');
1088 $form->add_fld(
1089 'template_name',
1090 'text-label',
1091 label: $form->get_fd_message('template_name_label'),
1092 rules: 'parameter|min=3|max=120',
1093 placeholder: 'c-mein-layout',
1094 errormsg: $form->get_fd_message('template_name_error')
1095 );
1096
1097 $help = dbx()->get_include_obj('dbxAdminHelp', 'dbxAdmin');
1098 $helpButton = is_object($help) && method_exists($help, 'formButton')
1099 ? $help->formButton('dbxContent_admin', 'content-template-new', $form->get_fd_message('template_new_title'))
1100 : '';
1101 $form->add_rep('help_button', $helpButton);
1102
1103 if ($form->submit()) {
1104 if (!$form->errors()) {
1105 $templateName = trim((string)$form->get_post('template_name', '', 'parameter|min=3|max=120'));
1106 $result = $this->create_template_file($templateName);
1107 if (!empty($result['ok'])) {
1108 return dbx()->redirect('?dbx_modul=dbxContent_admin&dbx_run1=content&dbx_run2=templates');
1109 }
1110 $form->add_fld_error('template_name', (string)($result['msg'] ?? $form->get_fd_message('template_create_error')));
1111 $form->_msg_error = (string)($result['msg'] ?? $form->get_fd_message('template_create_error'));
1112 } else {
1113 $form->_msg_error = $form->get_fd_message('template_name_validation');
1114 }
1115 }
1116
1117 return $form->run();
1118 }
1119
1120 private function report_templates() {
1121 $texts = $this->section_texts();
1122 $msgSuccess = '';
1123 $msgError = '';
1124 $dbxDo = (string)dbx()->get_request_var('dbx_do', '', 'alphanum');
1125 $deleteName = trim((string)dbx()->get_request_var('rid', '', 'alphanum'));
1126 if ($dbxDo === 'row_delete' && $deleteName !== '') {
1127 if ($this->delete_template_file($deleteName)) {
1128 $msgSuccess = $texts->format_fd_message('template_deleted', array('name' => $deleteName));
1129 } else {
1130 $msgError = $texts->get_fd_message('template_delete_error');
1131 }
1132 }
1133
1134 $dir = $this->template_dir();
1135 $files = is_dir($dir) ? glob($dir . '*.htm') : array();
1136 $rows = array();
1137
1138 if (is_array($files)) {
1139 sort($files, SORT_NATURAL | SORT_FLAG_CASE);
1140 foreach ($files as $file) {
1141 if (!is_file($file)) {
1142 continue;
1143 }
1144
1145 $name = pathinfo($file, PATHINFO_FILENAME);
1146 if (stripos($name, 'c-') !== 0) {
1147 continue;
1148 }
1149
1150 $rows[] = array(
1151 'modul' => 'dbxContent',
1152 'name' => $name,
1153 'type' => pathinfo($file, PATHINFO_EXTENSION),
1154 'size' => (string)filesize($file),
1155 'modified' => date('Y-m-d H:i:s', filemtime($file)),
1156 );
1157 }
1158 }
1159
1160 $fields = array(
1161 'modul' => $texts->get_fd_message('column_module'),
1162 'name' => $texts->get_fd_message('column_template'),
1163 'type' => $texts->get_fd_message('column_type'),
1164 'size' => $texts->get_fd_message('column_bytes'),
1165 'modified' => $texts->get_fd_message('column_updated'),
1166 );
1167
1168 return $this->report_rows('templates', $fields, $rows, $msgSuccess, $msgError);
1169 }
1170
1171 public function run($work = '') {
1172 switch ($work) {
1173 case 'content_grid_read':
1174 $this->content_grid_read();
1175 break;
1176
1177 case 'content_grid_save':
1178 $this->content_grid_save();
1179 break;
1180
1181 case 'content_grid_delete':
1182 $this->content_grid_delete();
1183 break;
1184
1185 case 'content_grid_sync':
1186 $this->content_grid_sync();
1187 break;
1188
1189 case 'list_content':
1190 return $this->report_content();
1191
1192 case 'list_folder':
1193 $texts = $this->section_texts();
1194 return $this->render_section(
1195 $texts->get_fd_message('section_folders_title'),
1196 $texts->get_fd_message('section_folders_subtitle'),
1197 $this->report_folders()
1198 );
1199
1200 case 'list_media':
1201 $texts = $this->section_texts();
1202 return $this->render_section(
1203 $texts->get_fd_message('section_media_title'),
1204 $texts->get_fd_message('section_media_subtitle'),
1205 $this->report_media()
1206 );
1207
1208 case 'media_view':
1209 return $this->media_view();
1210
1211 case 'templates':
1212 $texts = $this->section_texts();
1213 return $this->render_section_or_ajax(
1214 $texts->get_fd_message('section_templates_title'),
1215 $texts->get_fd_message('section_templates_subtitle'),
1216 $this->report_templates(),
1217 $this->templates_bar_actions()
1218 );
1219
1220 case 'template_new':
1221 return $this->template_new();
1222 }
1223
1224 return dbx()->get_system_obj('dbxTPL')->get_tpl('dbx|alert-warning', array(
1225 'msg' => $this->section_texts()->format_fd_message(
1226 'section_undefined',
1227 array('section' => $work)
1228 ),
1229 ));
1230 }
1231}
1232
1233?>
get_fd_message(string $key, string $default='')
Liefert eine Meldung aus der aktuell geladenen FD.
$_record
Aktueller Datensatz im Body-Lauf.
forward_run_body($content)
if((string)($formActionPolicy['action'] ?? '') !=='dbxAction.save'||!dbx() ->check_action_token((string)($formActionPolicy['scope'] ?? ''),(string)($formActionRoute['params']['dbx_token'] ?? ''))) $report
dbx()
Liefert die zentrale dbXapp-API als Singleton.
Definition dbxApi.php:2805
get_base_dir(int $cutData=0)
Liefert das Basisverzeichnis der Installation.
Definition dbxApi.php:1507
esc($value)
Escaped einen Wert fuer HTML-Text und HTML-Attribute.
Definition dbxApi.php:2310
if($web->content_permalink_redirect_target() !=='') $tpl
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
if( $demoId<=0) foreach(array('create_date', 'create_uid', 'update_date', 'update_uid', 'owner',) as $systemField) $items
DBX schema administration.
if($cinematic===''||!str_contains($cinematic, 'data-dbx-cinema')) $page