12 private $_admin_modul =
'dbxAdmin';
13 private $_fd_field =
'dbxAdmin|ddedit-field';
17 $work = dbx()->get_modul_request_var(
'dbx_run2',
'');
20 case 'create_form_fd':
21 return $this->create_form_fd();
24 return $this->delete_field();
26 case 'save_field_order':
27 return $this->save_field_order();
29 case 'create_from_dd':
30 return $this->create_from_dd();
35 return $this->run_editor();
39 private function run_editor()
41 list($modul, $fd) = $this->fd_params_from_request();
44 return $this->alert(
'warning',
'Kein Modul angegeben.');
48 return $this->create_from_dd();
51 $model = $this->load_model($modul, $fd);
53 return $this->alert(
'danger',
'FD nicht gefunden oder nicht lesbar: ' . dbx()->esc($modul .
'|' . $fd));
56 $instance_id = $this->instance_id($modul .
'_' . $fd);
57 $work_target_id =
'dbx_fdedit_work_' . $instance_id;
58 $fields = array_values((array)($model[
'fields'] ?? array()));
60 ? $this->create_form_fd($modul, $fd,
'0', $model)
61 : $this->create_form_fd($modul, $fd,
'new', $model);
68 'work_target_id' => $work_target_id,
69 'create_from_dd_url' => $this->build_url(
'create_from_dd', $modul, $fd),
70 'work_content' => $work_content,
71 'fields_order_report'=> $this->create_fields_order_report($modul, $fd, $model, $work_target_id),
74 $help = dbx()->get_include_obj(
'dbxAdminHelp',
'dbxAdmin');
75 $oTPL = dbx()->get_system_obj(
'dbxTPL');
76 $reloadAction = $oTPL->get_tpl(
'dbx|button-bar-reload-ajax', array(
77 'bar_reload_href' =>
'?dbx_modul=dbxAdmin&dbx_run1=edit_fd&modul=' . rawurlencode($modul) .
'&fd=' . rawurlencode($fd),
78 'bar_reload_target' =>
'dbx_fdedit_' . $instance_id,
79 'bar_reload_replace' =>
'target',
81 $barData = $help->moduleBarTemplateData(
'edit_fd', $reloadAction);
82 $barData[
'bar_title'] =
'FD bearbeiten: ' . $modul .
'|' . $fd;
83 $barData[
'bar_class'] =
'dbx-module-bar dbx-ddedit-head';
84 $data = array_merge($data, $barData);
86 return $oTPL->get_tpl($this->_admin_modul .
'|fdedit-frame', $data);
89 private function create_form_fd($modul =
'', $fd =
'', $field_pos =
null, $model = array())
91 if (!$modul || !$fd) {
92 list($modul, $fd) = $this->fd_params_from_request();
95 if ($field_pos ===
null) {
96 $field_pos = dbx()->get_modul_request_var(
'field_pos',
'new');
100 $model = $this->load_model($modul, $fd);
104 return $this->alert(
'danger',
'FD nicht gefunden: ' . dbx()->esc($modul .
'|' . $fd));
107 $fields = array_values((array)($model[
'fields'] ?? array()));
108 $is_new = ((string)$field_pos ===
'new');
111 $data = $this->default_field_record();
113 $pos = (int)$field_pos;
115 return $this->alert(
'warning',
'Feldposition nicht gefunden: ' . dbx()->esc((
string)$field_pos));
120 $data[
'modul'] = $modul;
122 $data[
'field_pos'] = (string)$field_pos;
123 $data[
'old_name'] = (string)($data[
'name'] ??
'');
125 $oForm = dbx()->get_system_obj(
'dbxForm');
126 $oForm->init(
'fdedit_field_' . $this->safe_id($modul .
'_' . $fd .
'_' . (
string)$field_pos),
'ddedit-field-form');
127 $oForm->_fd = $this->_fd_field;
128 $oForm->_data = $data;
129 $oForm->_action = $this->build_url(
'create_form_fd', $modul, $fd, array(
'field_pos' => (
string)$field_pos));
130 $oForm->_msg_info = $is_new
131 ?
'Bearbeite neues Feld fuer FD ' . $fd .
'.'
132 :
'Bearbeite Feld ' . (string)($data[
'name'] ?? $field_pos) .
'.';
135 if ($oForm->submit()) {
136 if (!$oForm->errors()) {
137 $field = $this->merge_record($data, $oForm->_post, $this->field_keys());
141 if (!$this->validate_field_record(
$field,
$fields, $is_new ? -1 : (
int)$field_pos, $message)) {
142 $oForm->_msg_error = $message;
143 return $oForm->run();
148 $field_pos = count(
$fields) - 1;
154 $model[
'fields'] = array_values(
$fields);
155 $ok = $this->save_model($modul, $fd, $model);
160 $field[
'field_pos'] = (string)$field_pos;
164 $oForm->_action = $this->build_url(
'create_form_fd', $modul, $fd, array(
'field_pos' => (
string)$field_pos));
165 $oForm->_msg_success =
'Feld ' . (string)(
$field[
'name'] ?? $field_pos) .
' in FD ' . $fd .
' gespeichert.';
167 $oForm->_msg_error =
'Feld ' . (string)(
$field[
'name'] ?? $field_pos) .
' konnte in FD ' . $fd .
' nicht gespeichert werden.';
170 $oForm->_msg_error =
'Feld ' . (string)($data[
'name'] ?? $field_pos) .
' bitte pruefen.';
174 $delete_url = $this->build_url(
'delete_field', $modul, $fd, array(
'field_pos' => (
string)$field_pos));
177 '&dbx_run2=delete_field&modul={modul}&dd={dd}&field_pos={field_pos}',
178 dbx()->esc($delete_url),
183 private function create_fields_order_report($modul, $fd, $model, $target_id =
'')
186 foreach (array_values((array)($model[
'fields'] ?? array())) as $pos =>
$field) {
191 $row = $this->field_row_defaults();
192 foreach (
$field as $key => $value) {
193 $row[$key] = is_array($value) ? implode(
',', $value) : (string)$value;
196 $row[
'modul'] = $modul;
199 $row[
'field_pos'] = (string)$pos;
200 $row[
'sort_no'] = (string)($pos + 1);
201 $row[
'target_id'] = $target_id;
202 $row[
'form_url'] = $this->build_url(
'create_form_fd', $modul, $fd, array(
'field_pos' => (
string)$pos));
210 'count' => count($rows),
211 'target_id' => $target_id,
212 'new_field_url' => $this->build_url(
'create_form_fd', $modul, $fd, array(
'field_pos' =>
'new')),
215 $oReport = dbx()->get_system_obj(
'dbxReport');
216 $oReport->init(
'fdedit_fields_order_' . $this->safe_id($modul .
'_' . $fd),
'fdedit-fields-order-report');
217 $oReport->_mode =
'tpl';
218 $oReport->_data = $data;
219 $oReport->_replaces = $data;
220 $oReport->_rdata = $rows;
221 $oReport->_rcount = count($rows);
222 $oReport->_rrows =
'auto';
223 $oReport->_pages =
false;
225 return $oReport->run();
228 private function delete_field()
230 list($modul, $fd) = $this->fd_params_from_request();
231 $field_pos = (int)dbx()->get_modul_request_var(
'field_pos', -1);
233 $model = $this->load_model($modul, $fd);
235 return $this->alert(
'danger',
'FD nicht gefunden.');
238 $fields = array_values((array)($model[
'fields'] ?? array()));
239 if (!isset(
$fields[$field_pos])) {
240 return $this->alert(
'warning',
'Feld nicht gefunden.');
243 $name = (string)(
$fields[$field_pos][
'name'] ?? $field_pos);
245 $model[
'fields'] = array_values(
$fields);
247 if ($this->save_model($modul, $fd, $model)) {
248 return $this->alert(
'success',
'Feld geloescht: ' . dbx()->esc($name));
251 return $this->alert(
'danger',
'Feld konnte nicht geloescht werden: ' . dbx()->esc($name));
254 private function save_field_order()
256 list($modul, $fd) = $this->fd_params_from_request();
257 $order = $this->parse_order(dbx()->get_modul_request_var(
'order', array()));
259 $model = $this->load_model($modul, $fd);
261 dbx()->json_response(array(
'ok' => 0,
'msg' =>
'FD nicht gefunden.'));
264 $new = $this->reorder_records(array_values((array)($model[
'fields'] ?? array())), $order);
265 if ($new ===
false) {
266 dbx()->json_response(array(
'ok' => 0,
'msg' =>
'Ungueltige Reihenfolge.'));
269 $model[
'fields'] = $new;
270 $ok = $this->save_model($modul, $fd, $model);
272 dbx()->json_response(array(
274 'msg' => $ok ?
'FD-Feldreihenfolge gespeichert.' :
'FD-Feldreihenfolge konnte nicht gespeichert werden.',
275 'count' => count($new),
281 private function create_from_dd()
283 list($modul, $fd) = $this->fd_params_from_request();
286 $source_modul = $this->sanitize_name(dbx()->get_modul_request_var(
'source_modul', $modul ?:
'dbx'));
287 $source_dd = $this->sanitize_name(dbx()->get_modul_request_var(
'source_dd',
''));
288 $target_modul = $this->sanitize_name(dbx()->get_modul_request_var(
'target_modul', $modul ?:
'dbx'));
289 $target_fd = $this->sanitize_name(dbx()->get_modul_request_var(
'target_fd', $fd));
290 $overwrite = (string)dbx()->get_modul_request_var(
'overwrite',
'') ===
'1';
292 if (isset(
$_SERVER[
'REQUEST_METHOD']) &&
$_SERVER[
'REQUEST_METHOD'] ===
'POST') {
293 if (!$source_modul || !$source_dd || !$target_modul || !$target_fd) {
294 $message = $this->alert(
'danger',
'Bitte Quell-DD und Ziel-FD vollstaendig angeben.');
295 } elseif ($this->fd_file_exists($target_modul, $target_fd) && !$overwrite) {
296 $message = $this->alert(
'warning',
'FD existiert bereits. Zum Ueberschreiben bitte die Checkbox aktivieren.');
298 $oDD = dbx()->get_system_obj(
'dbxDD');
299 $dd_model = $oDD->get_dd_model($source_modul .
'|' . $source_dd);
300 $fields = is_array($dd_model[
'fields'] ??
null) ? array_values($dd_model[
'fields']) : array();
303 $message = $this->alert(
'danger',
'Quell-DD hat keine Felddefinitionen oder konnte nicht gelesen werden.');
305 $ok = $this->save_model($target_modul, $target_fd, array(
'fields' =>
$fields));
307 $url =
'?dbx_modul=' . $this->_admin_modul .
308 '&dbx_run1=edit_fd&modul=' . rawurlencode($target_modul) .
309 '&fd=' . rawurlencode($target_fd);
310 $message = $this->alert(
312 'FD ' . dbx()->esc($target_modul .
'|' . $target_fd) .
' wurde aus DD ' .
313 dbx()->esc($source_modul .
'|' . $source_dd) .
' erstellt. ' .
314 '<a class="btn btn-sm btn-primary ms-2" href="' . dbx()->esc($url) .
315 '">FD bearbeiten</a>'
318 $message = $this->alert(
'danger',
'FD konnte nicht geschrieben werden.');
325 'i' => $this->instance_id(
'create_fd_' . $target_modul .
'_' . $target_fd),
326 'action' =>
'?dbx_modul=' . $this->_admin_modul .
'&dbx_run1=edit_fd&dbx_run2=create_from_dd&modul=' . rawurlencode($target_modul) .
'&fd=' . rawurlencode($target_fd),
327 'message' => $message,
328 'source_modul' => $source_modul,
329 'source_dd' => $source_dd,
330 'target_modul' => $target_modul,
331 'target_fd' => $target_fd,
332 'overwrite_checked' => $overwrite ?
'checked' :
'',
335 $oTPL = dbx()->get_system_obj(
'dbxTPL');
336 return $oTPL->get_tpl($this->_admin_modul .
'|fdedit-create-from-dd', $data);
339 private function load_model($modul, $fd)
341 if (!$modul || !$fd) {
345 $file = $this->fd_file_path($modul, $fd);
346 if (!is_file($file) || !is_readable($file)) {
354 return array(
'fields' => is_array(
$fields) ? array_values(
$fields) : array());
357 private function save_model($modul, $fd, $model)
359 if (!$modul || !$fd || !is_array($model)) {
363 $fields = is_array($model[
'fields'] ??
null) ? array_values($model[
'fields']) : array();
365 if (function_exists(
'dbx_os_path_file')) {
369 if (!is_dir(
$dir) && !mkdir(
$dir, 0775,
true)) {
373 $file = $this->fd_file_path($modul, $fd);
374 $this->backup_fd_file($modul, $fd);
376 $content =
"<?php\n\n";
382 $content .=
"\$field = array();\n";
383 foreach (
$field as $key => $value) {
384 $content .=
"\$field[" . var_export((
string)$key,
true) .
"]=" . var_export($value,
true) .
";\n";
386 $content .=
"\$fields[]=\$field;\n\n";
389 return file_put_contents($file, $content) !==
false ? 1 : 0;
392 private function normalize_field_for_write(
$field)
395 $oDD = dbx()->get_system_obj(
'dbxDD');
396 if (is_object($oDD) && method_exists($oDD,
'normalize_dd_field')) {
397 return $oDD->normalize_dd_field(
$field);
401 foreach ($this->field_keys() as $key) {
402 if (array_key_exists($key,
$field)) {
403 $out[$key] =
$field[$key];
409 private function backup_fd_file($modul, $fd)
411 $file = $this->fd_file_path($modul, $fd);
412 if (!is_file($file)) {
416 $dir = dirname($file) . DIRECTORY_SEPARATOR .
'_backup';
418 mkdir(
$dir, 0775,
true);
422 copy($file,
$dir . DIRECTORY_SEPARATOR . $fd .
'.' . date(
'Ymd-His') .
'.fd.php');
426 private function fd_params_from_request()
428 $modul = $this->sanitize_name(dbx()->get_modul_request_var(
'modul',
''));
429 $fd = $this->sanitize_name(dbx()->get_modul_request_var(
'fd',
''));
432 $fd = $this->sanitize_name(dbx()->get_modul_request_var(
'dd',
''));
436 $modul = $this->sanitize_name(dbx()->get_modul_request_var(
'xmodul',
''));
440 $modul = $this->sanitize_name($this->get_system_var(
'dbx_activ_modul',
'dbx'));
443 return array($modul, $fd);
446 private function fd_file_exists($modul, $fd)
448 return is_file($this->fd_file_path($modul, $fd));
451 private function fd_file_path($modul, $fd)
453 $file =
dbx_get_base_dir() .
'dbx/modules/' . $modul .
'/fd/' . $fd .
'.fd.php';
454 return function_exists(
'dbx_os_path_file') ?
dbx_os_path_file($file) : $file;
457 private function build_url($run2, $modul, $fd, $extra = array())
459 $url =
'?dbx_modul=' . $this->_admin_modul .
460 '&dbx_run1=edit_fd' .
461 '&dbx_run2=' . rawurlencode($run2) .
462 '&modul=' . rawurlencode($modul) .
463 '&fd=' . rawurlencode($fd);
465 foreach ((array)$extra as $key => $value) {
466 $url .=
'&' . rawurlencode((
string)$key) .
'=' . rawurlencode((
string)$value);
472 private function get_system_var($name, $default =
'')
474 if (function_exists(
'dbx')) {
476 if (is_object($obj) && method_exists($obj,
'get_system_var')) {
477 $value = $obj->get_system_var($name);
478 if ($value !==
null && $value !==
'') {
486 private function merge_record($old, $post, $keys)
488 $record = is_array($old) ? $old : array();
489 foreach ((array)$keys as $key) {
490 if (array_key_exists($key, (array)$post)) {
491 $record[$key] = $this->normalize_value($post[$key]);
497 private function strip_editor_keys($record)
499 unset($record[
'modul'], $record[
'dd'], $record[
'fd'], $record[
'field_pos'], $record[
'old_name']);
503 private function normalize_value($value)
505 if (is_array($value)) {
506 return implode(
',', array_map(
'trim', $value));
508 return trim((
string)$value);
511 private function parse_order($raw)
513 if (is_array($raw)) {
514 return array_values(array_map(
'intval', $raw));
517 $raw = trim((
string)$raw);
522 if (substr($raw, 0, 1) ===
'[') {
523 $decoded = json_decode($raw,
true);
524 if (is_array($decoded)) {
525 return array_values(array_map(
'intval', $decoded));
529 $parts = preg_split(
'/[|,\s;]+/', $raw);
530 return is_array($parts) ? array_values(array_map(
'intval', $parts)) : array();
533 private function reorder_records($records, $order)
535 $records = array_values((array)$records);
540 if (count($order) !==
$count) {
546 foreach ($order as $pos) {
548 if ($pos < 0 || $pos >=
$count || isset($seen[$pos])) {
552 $new[] = $records[$pos];
557 private function validate_field_record(
$field,
$fields, $self_pos, &$message)
559 $name = trim((
string)(
$field[
'name'] ??
''));
560 if (!$this->is_identifier($name)) {
561 $message =
'Ungueltiger Feldname: ' . $name;
566 foreach (array_values((array)
$fields) as $pos => $old) {
567 if ((
int)$pos === (
int)$self_pos) {
571 $old_name = strtolower(trim((
string)($old[
'name'] ??
'')));
572 if ($old_name !==
'') {
573 $names[$old_name] = 1;
577 if (isset($names[strtolower($name)])) {
578 $message =
'Feldname doppelt: ' . $name;
585 private function is_identifier($name)
587 return (
bool)preg_match(
'/^[A-Za-z_][A-Za-z0-9_]*$/', (
string)$name);
590 private function sanitize_name($name)
592 $name = trim((
string)$name);
593 return preg_match(
'/^[A-Za-z0-9_]+$/', $name) ? $name :
'';
596 private function safe_id($value)
598 $value = preg_replace(
'/[^A-Za-z0-9_]+/',
'_', (
string)$value);
599 $value = trim($value,
'_');
600 return $value ?:
'x';
603 private function instance_id($seed)
605 return $this->safe_id($seed .
'_' . substr(md5((
string)$seed), 0, 6));
608 private function alert($type, $msg)
610 $type = preg_replace(
'/[^a-z]/',
'', (
string)$type);
614 return '<div class="alert alert-' . $type .
'">' . $msg .
'</div>';
617 private function field_keys()
619 $oDD = dbx()->get_system_obj(
'dbxDD');
620 if (is_object($oDD) && method_exists($oDD,
'dd_field_schema_keys')) {
621 return array_merge(array(
'modul',
'dd',
'fd',
'field_pos',
'old_name'), $oDD->dd_field_schema_keys());
652 private function default_field_record()
671 'tpl' =>
'text-label',
677 private function field_row_defaults()
dbx_os_path_file($path_file)
dbx_get_base_dir($cut_Data=0)