11 parent::__construct();
16 $tpl =
dbx()->get_system_obj(
'dbxTPL');
17 $record[
'graphic_html'] = $this->renderModuleImages($record);
18 $record[
'groups_html'] = $this->renderGroups($record);
19 $record[
'dd_html'] = $this->renderDdList($record);
20 $record[
'card_state_class'] = ((string)($record[
'active'] ??
'1') ===
'0') ?
' dbx-module-row-inactive' :
'';
21 $record[
'install_button_html'] = $this->renderInstallButton($record);
22 $record[
'active_toggle_button_html'] = $this->renderActiveToggleButton($record);
23 $record[
'delete_button_html'] = $this->renderDeleteButton($record);
24 $record[
'actions_html'] = $tpl->get_tpl(
'dbxAdmin|module-card-actions', $record);
25 $record[
'access_inline_html'] = $this->renderAccessInline($record);
26 $record[
'select_html'] = $this->_create_row_select
29 return $tpl->get_tpl(
'dbxAdmin|module-card', $record);
33 return $this->renderDdList($record);
37 $record = is_array($this->_record) ? $this->_record : array();
39 $content = (string)$content;
41 if (strpos($content,
'[rpt:row]') !==
false) {
42 $content = str_replace(
'[rpt:row]', $card, $content);
51 return $this->buildModuleImagesTargetHtml($record);
55 return $this->buildModuleImagesGalleryHtml($record);
58 private function renderModuleImages(array $record): string {
59 $tpl =
dbx()->get_system_obj(
'dbxTPL');
60 $defaultRun1 = trim((
string)($record[
'default_run1'] ??
'run'));
61 if ($defaultRun1 ===
'') {
64 $defaultRun2 = trim((
string)($record[
'default_run2'] ??
''));
65 $record[
'symbol_preview_html'] = $this->buildModuleSymbolPreviewHtml($record);
66 $record[
'images_gallery_html'] = $this->buildModuleImagesGalleryHtml($record);
67 $record[
'default_run1'] =
dbx()->esc($defaultRun1);
68 $record[
'default_run2'] =
dbx()->esc($defaultRun2);
69 $record[
'image_count'] = (string)count($record[
'image_items'] ?? array());
70 $record[
'images_add_url'] =
dbx()->esc((
string)($record[
'images_add_url'] ??
''));
71 $record[
'images_upload_url'] =
dbx()->esc((
string)($record[
'images_upload_url'] ??
''));
72 $record[
'images_remove_url'] =
dbx()->esc((
string)($record[
'images_remove_url'] ??
''));
73 $record[
'symbol_add_url'] =
dbx()->esc((
string)($record[
'symbol_add_url'] ??
'?dbx_modul=dbxAdmin&dbx_run1=modules&dbx_run2=modul_symbol_add'));
74 $record[
'symbol_media_url'] =
dbx()->esc((
string)($record[
'symbol_media_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_media&images=1&media_type=image'));
75 $record[
'symbol_upload_url'] =
dbx()->esc((
string)($record[
'symbol_upload_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_upload'));
76 $record[
'symbol_mediafolders_url'] =
dbx()->esc((
string)($record[
'symbol_mediafolders_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_media_folders'));
77 $record[
'symbol_mediafoldercreate_url'] =
dbx()->esc((
string)($record[
'symbol_mediafoldercreate_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_media_folder_create'));
78 $record[
'symbol_mediafolderdelete_url'] =
dbx()->esc((
string)($record[
'symbol_mediafolderdelete_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_media_folder_delete'));
79 $record[
'symbol_deletemedia_url'] =
dbx()->esc((
string)($record[
'symbol_deletemedia_url'] ??
'?dbx_modul=dbxContent_admin&dbx_run1=cms_delete_media'));
80 $record[
'placeholder_url'] =
dbx()->esc((
string)($record[
'placeholder_url'] ??
''));
81 $record[
'placeholder_alt'] =
dbx()->esc((
string)($record[
'placeholder_alt'] ?? $this->moduleImagesPlaceholderAlt()));
82 $run1List = $this->buildModuleImagesRun1Datalist($record, $defaultRun1);
83 $record[
'run1_list_id'] =
dbx()->esc((
string)($run1List[
'id'] ??
''));
84 $record[
'run1_options_html'] = (string)($run1List[
'options_html'] ??
'');
85 return $tpl->get_tpl(
'dbxAdmin|module-card-images', $record);
88 private function buildModuleImagesRun1Datalist(array $record,
string $defaultRun1): array {
89 $modul = (string)($record[
'xmodul'] ??
'mod');
90 $listId =
'dbx_modimg_run1_' . preg_replace(
'/[^a-zA-Z0-9_]/',
'_', $modul);
91 $cases = $record[
'run_cases'] ?? array();
92 if (!is_array($cases)) {
95 if (!$cases && $defaultRun1 !==
'') {
96 $cases = array($defaultRun1);
101 foreach ($cases as $run1) {
102 $run1 = trim((
string)$run1);
103 if ($run1 ===
'' || isset($seen[$run1])) {
107 $options .=
'<option value="' .
dbx()->esc($run1) .
'"></option>';
112 'options_html' => $options,
116 private function buildModuleSymbolPreviewHtml(array $record): string {
117 $modul =
dbx()->esc((string)($record[
'xmodul'] ??
''));
118 $url =
dbx()->esc((
string)($record[
'graphic_url'] ??
''));
119 $alt =
dbx()->esc((
string)($record[
'graphic_alt'] ?? $modul));
122 return '<img src="' . $url .
'" alt="' . $alt .
'" class="dbx-module-symbol-img" loading="lazy">';
125 $placeholder =
dbx()->esc($this->moduleImagesPlaceholderUrl($record));
126 if ($placeholder !==
'') {
127 return '<img src="' . $placeholder .
'" alt="' .
dbx()->esc($this->moduleImagesPlaceholderAlt()) .
'" class="dbx-module-symbol-img is-placeholder" loading="lazy">';
130 return '<span class="dbx-module-images-placeholder-icon" aria-hidden="true"><i class="bi bi-box-seam"></i></span>';
133 private function moduleImagesPlaceholderUrl(array $record): string {
134 return $this->registry->moduleImageEmptyPlaceholderUrl();
137 private function moduleImagesPlaceholderAlt(): string {
138 return $this->registry->moduleImageEmptyPlaceholderAlt();
141 private function buildModuleImagesPreviewHtml(array $record): string {
142 $modul =
dbx()->esc((string)($record[
'xmodul'] ??
''));
143 $items = $record[
'image_items'] ?? array();
144 if (is_array($items) && isset($items[0]) && is_array($items[0])) {
146 $url =
dbx()->esc((
string)($first[
'url'] ??
''));
147 $label =
dbx()->esc((
string)($first[
'label'] ?? ($first[
'file'] ?? $modul)));
149 return '<img src="' . $url .
'" alt="' . $label .
'" class="dbx-module-images-preview-img" loading="lazy">';
153 $placeholder =
dbx()->esc($this->moduleImagesPlaceholderUrl($record));
154 if ($placeholder !==
'') {
155 $alt =
dbx()->esc($this->moduleImagesPlaceholderAlt());
156 return '<img src="' . $placeholder .
'" alt="' . $alt .
'" class="dbx-module-images-preview-img is-placeholder" loading="lazy">';
159 return '<span class="dbx-module-images-placeholder-icon" aria-hidden="true"><i class="bi bi-box-seam"></i></span>';
162 private function buildModuleImagesTargetHtml(array $record): string {
163 $modul =
dbx()->esc((string)($record[
'xmodul'] ??
''));
164 $defaultRun1 = trim((
string)($record[
'default_run1'] ??
'run'));
165 if ($defaultRun1 ===
'') {
166 $defaultRun1 =
'run';
168 $defaultRun2 = trim((
string)($record[
'default_run2'] ??
''));
169 $usesRun2 = (string)($record[
'uses_run2'] ??
'0') ===
'1';
170 $cases = $record[
'run_cases'] ?? array();
171 if (!is_array($cases)) {
175 $cases = array($defaultRun1);
178 $listId =
'dbx_modimg_run1_' . preg_replace(
'/[^a-zA-Z0-9_]/',
'_', (
string)($record[
'xmodul'] ??
'mod'));
181 foreach ($cases as $run1) {
182 $run1 = trim((
string)$run1);
183 if ($run1 ===
'' || isset($seen[$run1])) {
187 $selected = ($run1 === $defaultRun1) ?
' selected' :
'';
188 $options .=
'<option value="' .
dbx()->esc($run1) .
'"' . $selected .
'>' .
dbx()->esc($run1) .
'</option>';
191 $run2Class =
'dbx-module-images-run2-wrap';
194 $images =
new dbxModuleImages();
195 $previewName =
dbx()->esc($images->stemForRuns((
string)($record[
'xmodul'] ??
''), $defaultRun1, $defaultRun2) .
'.*');
197 return '<div class="dbx-module-images-target">'
198 .
'<label class="dbx-module-images-target-field">'
199 .
'<span>dbx_run1</span>'
200 .
'<input type="text" class="form-control form-control-sm dbx-module-images-run1" list="' . $listId .
'" value="' .
dbx()->esc($defaultRun1) .
'" placeholder="z.B. form" required>'
201 .
'<datalist id="' . $listId .
'">' . $options .
'</datalist>'
203 .
'<label class="' . $run2Class .
' dbx-module-images-target-field">'
204 .
'<span>dbx_run2</span>'
205 .
'<input type="text" class="form-control form-control-sm dbx-module-images-run2" value="' .
dbx()->esc($defaultRun2) .
'" placeholder="optional"' . $run2Disabled .
'>'
207 .
'<div class="dbx-module-images-filename">'
208 .
'<span>Dateiname</span>'
209 .
'<code class="dbx-module-images-filename-preview" data-modul="' . $modul .
'">' . $previewName .
'</code>'
214 private function resolveImagePreviewRuns(array $item, array $record): array {
215 $run1 = trim((string)($item[
'run1'] ??
''));
216 $run2 = trim((
string)($item[
'run2'] ??
''));
218 if ($run1 ===
'' || $run2 ===
'') {
219 $params = trim((
string)($item[
'default_params'] ??
''));
220 if ($params !==
'') {
221 if ($run1 ===
'' && preg_match(
'/(?:^|&)dbx_run1=([^&]+)/', $params, $m)) {
222 $run1 = rawurldecode($m[1]);
224 if ($run2 ===
'' && preg_match(
'/(?:^|&)dbx_run2=([^&]+)/', $params, $m)) {
225 $run2 = rawurldecode($m[1]);
231 $run1 = trim((
string)($record[
'default_run1'] ??
''));
234 $run2 = trim((
string)($record[
'default_run2'] ??
''));
237 return array($run1, $run2);
240 private function buildModuleImagesGalleryHtml(array $record): string {
241 $items = $record[
'image_items'] ?? array();
242 $xmodul = (string)($record[
'xmodul'] ??
'');
243 if (!is_array($items) || !$items) {
244 return '<div class="dbx-module-images-empty-list text-muted small">Keine Modulbilder</div>';
248 foreach ($items as $i => $item) {
249 if (!is_array($item)) {
252 $file =
dbx()->esc((
string)($item[
'file'] ??
''));
253 $url =
dbx()->esc((
string)($item[
'url'] ??
''));
254 $label =
dbx()->esc((
string)($item[
'label'] ?? $file));
255 $params = trim((
string)($item[
'default_params'] ??
''));
256 $call =
'dbx_modul=' . rawurlencode($xmodul);
257 if ($params !==
'') {
258 $call .=
'&' . $params;
260 $call =
dbx()->esc($call);
261 list($run1, $run2) = $this->resolveImagePreviewRuns($item, $record);
262 $run1Esc =
dbx()->esc($run1);
263 $run2Esc =
dbx()->esc($run2);
264 $previewUrl =
dbx()->esc($this->registry->modulUrl($xmodul, $run1, $run2));
265 $previewTitle =
dbx()->esc(
'Vorschau: ' . $xmodul);
266 $active = ($i === 0) ?
' is-active' :
'';
268 if ($run1 !==
'' || $params !==
'') {
269 $previewBtn =
'<a class="btn btn-outline-secondary btn-sm dbx-win dbx-module-images-preview" href="' . $previewUrl .
'" data-url="' . $previewUrl .
'" data-title="' . $previewTitle .
'" data-width="88%" data-height="88%" title="Modul aufrufen"><i class="bi bi-box-arrow-up-right"></i></a>';
271 $html .=
'<div class="dbx-module-images-item' . $active .
'" data-file="' . $file .
'" data-params="' .
dbx()->esc($params) .
'" data-url="' . $url .
'" data-run1="' . $run1Esc .
'" data-run2="' . $run2Esc .
'">'
272 .
'<span class="dbx-module-images-thumb">'
273 .
'<img src="' . $url .
'" alt="' . $label .
'" loading="lazy">'
275 .
'<span class="dbx-module-images-meta">'
276 .
'<code class="dbx-module-images-call">' . $call .
'</code>'
277 .
'<span class="dbx-module-images-file">' . $file .
'</span>'
279 .
'<span class="dbx-module-images-actions">'
281 .
'<button type="button" class="btn btn-outline-danger btn-sm dbx-module-images-remove" title="Bild entfernen"><i class="bi bi-trash"></i></button>'
286 return $html !==
'' ? $html :
'<div class="dbx-module-images-empty-list text-muted small">Keine Modulbilder</div>';
290 return $this->buildModuleImagesPreviewHtml($record);
293 private function renderGraphic(array $record): string {
294 $previewUrl =
dbx()->esc((string)($record[
'preview_url'] ??
''));
295 $title =
dbx()->esc((
string)($record[
'title'] ??
''));
296 $winAttrs =
' class="dbx-module-graphic dbx-win" href="' . $previewUrl .
'" data-url="' . $previewUrl
297 .
'" data-title="Vorschau: ' . $title .
'" data-width="88%" data-height="88%" title="Modul-Vorschau oeffnen"';
299 $items = $record[
'image_items'] ?? array();
300 if (!is_array($items)) {
306 foreach ($items as $i => $item) {
307 if (!is_array($item)) {
310 $url =
dbx()->esc((
string)($item[
'url'] ??
''));
311 $label =
dbx()->esc((
string)($item[
'label'] ??
''));
312 $active = ($i === 0) ?
' is-active' :
'';
313 $slides .=
'<img src="' . $url .
'" alt="' . $label .
'" class="dbx-module-graphic-img' . $active .
'" loading="lazy">';
315 if ($slides !==
'') {
316 return '<a' . $winAttrs .
'><div class="dbx-module-graphic-stack">' . $slides .
'</div></a>';
320 $graphicUrl = trim((
string)($record[
'graphic_url'] ??
''));
321 $alt =
dbx()->esc((
string)($record[
'graphic_alt'] ?? $record[
'title'] ??
''));
323 if ($graphicUrl !==
'') {
324 $badge = trim((
string)($record[
'graphic_badge'] ??
''));
327 $badgeHtml =
'<span class="dbx-module-graphic-badge">' .
dbx()->esc($badge) .
'</span>';
330 return '<a' . $winAttrs .
'>'
331 .
'<img src="' .
dbx()->esc($graphicUrl) .
'" alt="' . $alt .
'" class="dbx-module-graphic-img is-active" loading="lazy">'
336 return '<a' . $winAttrs .
'>'
337 .
'<span class="dbx-module-graphic-placeholder" aria-hidden="true">'
338 .
'<i class="bi bi-box-seam dbx-module-graphic-fallback-icon"></i>'
339 .
'<span class="dbx-module-graphic-placeholder-label">Vorschau</span>'
344 private function renderInstallButton(array $record): string {
345 if (empty($record[
'install_url'])) {
349 $url =
dbx()->esc((
string)$record[
'install_url']);
350 $title =
dbx()->esc((
string)($record[
'title'] ??
''));
352 return '<a class="btn btn-outline-secondary dbx-win" href="' . $url .
'" data-url="' . $url .
'" data-title="Installation: ' . $title .
'" data-width="82%" data-height="82%" title="Modul installieren">'
353 .
'<i class="bi bi-database-gear"></i> Install</a>';
356 private function renderActiveToggleButton(array $record): string {
357 $modul =
dbx()->esc((string)($record[
'xmodul'] ??
''));
358 $url =
dbx()->esc((
string)($record[
'active_toggle_url'] ??
''));
359 if ($modul ===
'' || $url ===
'') {
362 $active = (string)($record[
'active'] ??
'1') ===
'1';
363 $btnClass = $active ?
'btn-success' :
'btn-outline-secondary';
364 $icon = $active ?
'bi-toggle-on' :
'bi-toggle-off';
365 $label = $active ?
'Aktiv' :
'Inaktiv';
366 $state = $active ?
'1' :
'0';
368 return '<button type="button" class="btn ' . $btnClass .
' dbx-module-active-toggle" data-modul="' . $modul
369 .
'" data-active="' . $state .
'" data-toggle-url="' . $url .
'" title="Modul aktivieren/deaktivieren">'
370 .
'<i class="bi ' . $icon .
'"></i> ' . $label .
'</button>';
373 private function renderDeleteButton(array $record): string {
374 if ((string)($record[
'can_delete'] ??
'0') !==
'1') {
377 $modul =
dbx()->esc((
string)($record[
'xmodul'] ??
''));
378 $title =
dbx()->esc((
string)($record[
'title'] ??
''));
379 $url =
dbx()->esc((
string)($record[
'delete_url'] ??
''));
380 if ($modul ===
'' || $url ===
'') {
384 return '<button type="button" class="btn btn-outline-danger dbx-module-delete-btn" data-modul="' . $modul
385 .
'" data-delete-url="' . $url .
'" data-title="' . $title .
'" title="Modul komplett loeschen">'
386 .
'<i class="bi bi-trash"></i> Loeschen</button>';
389 private function renderAccessInline(array $record): string {
390 $tpl =
dbx()->get_system_obj(
'dbxTPL');
391 $groups = $record[
'groups'] ?? array();
392 if (!is_array($groups)) {
395 $selected = array_flip($groups);
397 foreach ($this->registry->groupOptions() as $value => $label) {
398 $sel = isset($selected[$value]) ?
' selected' :
'';
399 $options .=
'<option value="' .
dbx()->esc($value) .
'"' . $sel .
'>' .
dbx()->esc($label) .
'</option>';
403 'xmodul' =>
dbx()->esc((
string)($record[
'xmodul'] ??
'')),
404 'access_save_url' =>
dbx()->esc((
string)($record[
'access_save_url'] ??
'')),
405 'groups_options_html' => $options,
408 return $tpl->get_tpl(
'dbxAdmin|module-card-access-inline', $data);
411 private function renderGroups(array $record): string {
412 $groups = $record[
'groups'] ?? array();
413 if (!is_array($groups)) {
417 $labels = $this->registry->groupOptions();
419 foreach ($groups as $group) {
420 $group = trim((
string)$group);
424 $label = $labels[$group] ?? $group;
425 $html .=
'<span class="badge rounded-pill text-bg-light border">' .
dbx()->esc($label) .
'</span>';
429 $html =
'<span class="text-muted small">Keine Gruppe gesetzt</span>';
435 private function renderDdList(array $record): string {
436 $tpl =
dbx()->get_system_obj(
'dbxTPL');
437 $items = $record[
'dd_items'] ?? array();
438 if (!is_array($items) || !$items) {
439 return $tpl->get_tpl(
'dbxAdmin|module-card-dd-empty', $record);
443 $selectId = (string)($record[
'dd_select_id'] ??
'');
444 foreach ($items as $i => $item) {
445 if (!is_array($item)) {
448 $url =
dbx()->esc((
string)($item[
'edit_url'] ??
''));
449 $title =
dbx()->esc((
string)($item[
'edit_title'] ??
''));
450 $label =
dbx()->esc((
string)($item[
'label'] ??
''));
451 $active = ($i === 0) ?
' is-active' :
'';
452 $stripe = ($i % 2 === 0) ?
' odd' :
' even';
453 $gallery .=
'<button type="button" class="dbx-module-dd-item' . $active . $stripe .
'" role="option"'
454 .
' data-edit-url="' . $url .
'" data-edit-title="' . $title .
'"'
455 .
' aria-selected="' . ($i === 0 ?
'true' :
'false') .
'" title="' . $title .
'">'
456 .
'<span class="dbx-module-dd-item-name">' . $label .
'</span>'
460 $record[
'dd_gallery_html'] = $gallery;
461 return $tpl->get_tpl(
'dbxAdmin|module-card-dd', $record);