338 public $_try_msg =
'Max {try_count} try. Suspend for {sec} seconds';
413 $this->oValidator =
dbx()->get_system_obj(
'dbxValidator');
414 $this->oTPL =
dbx()->get_system_obj(
'dbxTPL');
415 $this->oDB =
dbx()->get_system_obj(
'dbxDB');
422 $this->
init($id, $tpl);
458 $this->_sys = array();
520 $this->_reload_record = 0;
521 $this->_reload_run = 0;
523 $this->_obj = array();
524 $this->_js = array();
525 $this->_css = array();
526 $this->_flds = array();
527 $this->_infos = array();
528 $this->_errors = array();
529 $this->_warnings = array();
530 $this->_post = array();
531 $this->_sys = array();
532 $this->_data = array();
533 $this->_replaces = array();
534 $this->_module_bar_form_actions = array();
536 $this->_fld_changes = -1;
537 $this->_form_submit = -1;
538 $this->_form_validate = -1;
539 $this->_general_error =
'';
544 $this->_fld_id =
'id';
545 $this->_callback_owner =
null;
546 $this->_callback_id =
'';
547 $this->_callbacks = array();
551 $this->_editor_files = array();
561 $this->_editor_class_file = $file;
574 $kind = strtolower(trim($kind));
576 if ($file ===
'' || $kind ===
'') {
580 $path =
dbx()->editor_file_path($file);
581 $key = $kind .
'|' . $path;
582 $this->_editor_files[$key] = array(
'kind' => $kind,
'file' => $path);
583 dbx()->register_editor_file($kind, $path);
593 $edit = (int)
dbx()->get_system_var(
'dbx_edit', 0,
'int');
595 if (($edit >= 4 && $edit <= 8) || $edit === 9) {
599 if ($this->_editor_class_file !==
'') {
603 foreach (dbx()->get_editor_files() as $file) {
604 if (isset($file[
'kind'], $file[
'file'])) {
609 if ($content ===
'' || !$this->_editor_files) {
615 foreach ($this->_editor_files as $file) {
616 $kind = strtolower((
string) ($file[
'kind'] ??
''));
619 if ($kind ===
'fd' || $kind ===
'dd') {
623 $marker = dbx()->editor_marker($file[
'kind'], $file[
'file']);
624 $needle = trim($marker);
626 if ($marker !==
'' && strpos($content, $needle) ===
false && strpos($markers, $needle) ===
false) {
631 if ($markers ===
'') {
635 return $markers . $content .
"\n<!-- DBX-EDITOR-END -->\n";
695 $this->_dbx_modul =
dbx()->get_system_var(
'dbx_activ_modul',
'modul');
696 $this->_dbx_action =
dbx()->get_system_var(
'dbx_activ_action',
'run');
697 $this->_dbx_page =
dbx()->get_system_var(
'dbx_page',
'default');
698 $this->_dbx_design =
dbx()->get_system_var(
'dbx_design',
'default');
699 $this->_dbx_lng =
dbx()->get_system_var(
'dbx_lng',
'de');
700 $this->_dbx_modul_id =
dbx()->get_system_var(
'dbx_activ_modul_id', 1);
702 $this->_data = array();
704 $this->_form_validate = -1;
705 $this->_form_submit = -1;
709 'fid' => $this->_fid,
710 'tpl' => $this->_tpl,
711 'i' => $this->_next_i,
714 $init = $this->
callback(
'init', $init);
716 if (is_array($init)) {
717 if (isset($init[
'fid'])) $this->_fid = $init[
'fid'];
718 if (isset($init[
'tpl'])) $this->_tpl = $init[
'tpl'];
719 if (isset($init[
'i'])) $this->_next_i = $init[
'i'];
726 $secure_fld = $this->secure_fld_name();
727 $this->
add_fld($secure_fld,
'dbx|hidden', $secure_fld, rules:
'parameter', dd:
'');
728 $this->sync_secure_field($secure_fld, $this->secure_token($secure_fld));
734 if (!isset($this->_replaces[
'bar_title']) || (
string)$this->_replaces[
'bar_title'] ===
'') {
735 $this->
add_rep(
'bar_title', (
string)$title);
737 if (!isset($this->_replaces[
'bar_icon']) || (
string)$this->_replaces[
'bar_icon'] ===
'') {
738 $this->
add_rep(
'bar_icon', (
string)$icon);
740 if (!isset($this->_replaces[
'bar_subtitle']) || (
string)$this->_replaces[
'bar_subtitle'] ===
'') {
741 $this->
add_rep(
'bar_subtitle', (
string)$subtitle);
752 'delete_title' =>
'Datensatz loeschen',
753 'delete_hint' =>
'Dieser Vorgang kann nicht rueckgaengig gemacht werden.',
755 $this->_module_bar_form_actions = array_merge($defaults, $options);
759 if (!isset($this->_replaces[
'form_shell_class'])) {
760 $this->
add_rep(
'form_shell_class', (
string)($options[
'class'] ??
''));
762 if (!isset($this->_replaces[
'form_class'])) {
763 $this->
add_rep(
'form_class', (
string)($options[
'form_class'] ??
''));
765 if (!isset($this->_replaces[
'form_attrs'])) {
766 $this->
add_rep(
'form_attrs', (
string)($options[
'form_attrs'] ??
''));
772 'bar_class' =>
'dbx-module-bar',
773 'bar_title_class' =>
'dbx-module-bar-titleblock',
774 'bar_actions_class' =>
'dbx-module-bar-actions',
776 'bar_icon' =>
'bi-grid',
777 'bar_subtitle' =>
'',
778 'bar_title_pre' =>
'',
779 'bar_title_heading_attrs' =>
'',
787 $formClass = trim((string)($this->_replaces[
'form_class'] ??
''));
788 $formAttrs = trim((
string)($this->_replaces[
'form_attrs'] ??
''));
789 $shellClass = trim((
string)($this->_replaces[
'form_shell_class'] ??
''));
790 $panelClass = trim(
'dbxForm_wrapper ' . $shellClass);
791 $frameId = trim((
string)($this->_replaces[
'frame_id'] ??
''));
792 if ($frameId ===
'') {
793 $frameId =
'dbx_target_' . $i;
796 $this->add_rep(
'frame_id', $frameId);
797 if (trim((
string)($this->_replaces[
'frame_panel_class'] ??
'')) ===
'') {
798 $this->add_rep(
'frame_panel_class', $panelClass);
800 $this->add_rep(
'frame_panel_attrs', (
string)($this->_replaces[
'frame_panel_attrs'] ??
''));
801 $this->add_rep(
'frame_subbar',
'');
802 $this->add_rep(
'frame_body_class',
'');
803 if ((
string)($this->_replaces[
'frame_skip_form_wrap'] ??
'') !==
'1') {
804 $this->add_rep(
'frame_form_open',
'<form action="' . htmlspecialchars((
string)$this->_action, ENT_QUOTES) .
'" method="post" id="dbx_form_' . $i .
'" class="dbxAjax' . ($formClass !==
'' ?
' ' . $formClass :
'') .
'"' . ($formAttrs !==
'' ?
' ' . $formAttrs :
'') .
'>');
805 $this->add_rep(
'frame_body_head',
'<div class="row"><div class="col">{obj:form_msg}</div></div>');
806 $this->add_rep(
'frame_form_close',
'</form>');
808 if (!isset($this->_replaces[
'frame_form_open'])) {
809 $this->add_rep(
'frame_form_open',
'');
811 if (!isset($this->_replaces[
'frame_body_head'])) {
812 $this->add_rep(
'frame_body_head',
'');
814 if (!isset($this->_replaces[
'frame_form_close'])) {
815 $this->add_rep(
'frame_form_close',
'');
818 $this->add_rep(
'frame_body_tail',
'');
824 foreach ($defaults as $key => $value) {
825 $this->
add_rep($key, (
string) $value);
830 if (!$this->_module_bar_form_actions) {
834 $opts = $this->_module_bar_form_actions;
835 $i = (int)$this->_next_i;
837 $i = (int)$this->
next_i();
840 $formId =
'dbx_form_' . $i;
843 if (!empty($opts[
'save'])) {
844 $html .= $this->
get_tpl(
'dbx|button-bar-save', array(
845 'bar_form_id' => $formId,
849 if (!empty($opts[
'delete']) && trim((
string)($opts[
'delete_url'] ??
'')) !==
'') {
850 $html .= $this->
get_tpl(
'dbx|button-bar-delete', array(
851 'bar_delete_url' => htmlspecialchars((
string)($opts[
'delete_url'] ??
''), ENT_QUOTES),
852 'bar_delete_title' => htmlspecialchars((
string)($opts[
'delete_title'] ??
'Datensatz loeschen'), ENT_QUOTES),
853 'bar_delete_hint' => htmlspecialchars((
string)($opts[
'delete_hint'] ??
''), ENT_QUOTES),
857 if (!empty($opts[
'reload'])) {
858 $reloadUrl = trim((
string)($opts[
'reload_url'] ??
''));
859 if ($reloadUrl ===
'') {
860 $reloadUrl = (string)$this->_action;
863 $html .= $this->
get_tpl(
'dbx|button-bar-reload', array(
864 'bar_reload_url' => htmlspecialchars($reloadUrl, ENT_QUOTES),
872 $modul = (string)
dbx()->get_system_var(
'dbx_modul',
'');
873 $isAdmin = ($modul ===
'dbxAdmin' || str_ends_with($modul,
'_admin'));
874 $barTitle = trim((
string)($this->_replaces[
'bar_title'] ??
''));
876 if (!$isAdmin && $barTitle ===
'') {
881 $help =
dbx()->get_include_obj(
'dbxAdminHelp',
'dbxAdmin');
882 $topic = $help->resolveTopic($modul);
884 if ($isAdmin && $topic ===
'') {
888 $actions = trim((
string)($this->_replaces[
'bar_actions'] ??
''));
889 if ($actions ===
'' && isset($this->_obj[
'bar_actions'])) {
890 $actions = (string)$this->_obj[
'bar_actions'];
894 if ($formActions !==
'') {
895 $actions = ($actions !==
'') ? ($actions .
' ' . $formActions) : $formActions;
898 $title = (string)($this->_replaces[
'bar_title'] ??
'');
899 $icon = (string)($this->_replaces[
'bar_icon'] ??
'bi-grid');
900 $subtitle = (string)($this->_replaces[
'bar_subtitle'] ??
'');
903 $meta = $help->barMeta($topic);
904 if (is_array($meta) && $meta) {
906 $title = (string)($meta[
'title'] ?? $topic);
908 if ($icon ===
'' || $icon ===
'bi-grid') {
909 $icon = (string)($meta[
'icon'] ??
'bi-grid');
911 if ($subtitle ===
'') {
912 $subtitle = (string)($meta[
'subtitle'] ??
'');
919 $helpButton = $help->button($topic);
920 } elseif (isset($this->_obj[
'help_button'])) {
921 $helpButton = (string)$this->_obj[
'help_button'];
924 $barClass = trim((
string)($this->_replaces[
'bar_class'] ??
''));
925 if ($barClass ===
'') {
926 $barClass =
'dbx-module-bar';
930 'bar_class' => $barClass,
931 'bar_title' => $title,
932 'bar_icon' => $icon !==
'' ? $icon :
'bi-grid',
933 'bar_subtitle' => $subtitle,
934 'bar_actions' => $actions,
935 'bar_extra' => $helpButton,
937 }
catch (\Throwable $e) {
942 $modul = (string)
dbx()->get_system_var(
'dbx_modul',
'');
943 if ($modul !==
'dbxAdmin' && !str_ends_with($modul,
'_admin')) {
948 $help =
dbx()->get_include_obj(
'dbxAdminHelp',
'dbxAdmin');
950 $topic = $help->resolveTopic($modul);
955 $this->
add_obj(
'help_button', $help->button($topic));
957 $barMeta = $help->barMeta($topic);
958 if (is_array($barMeta) && $barMeta) {
960 (
string)($barMeta[
'title'] ??
''),
961 (
string)($barMeta[
'icon'] ??
'bi-grid'),
962 (
string)($barMeta[
'subtitle'] ??
'')
965 }
catch (\Throwable $e) {
969 private function get_token(): string {
971 return bin2hex(random_bytes(32));
972 }
catch (\Throwable $e) {
973 return hash(
'sha256', uniqid(
'',
true) .
'|' . mt_rand());
977 private function secure_fld_name(): string {
978 return
'_' . (string)$this->_fid;
981 private function secure_token(
string $fld): string {
982 if (!isset($this->_sys[
'_csrf']) || !is_array($this->_sys[
'_csrf'])) {
983 $this->_sys[
'_csrf'] = array();
986 $token = (string)($this->_sys[
'_csrf'][$fld] ?? $this->_sys[$fld] ??
'');
987 if (!preg_match(
'/^[a-f0-9]{64}$/', $token)) {
988 $token = $this->get_token();
991 $this->_sys[
'_csrf'][$fld] = $token;
992 $this->_sys[$fld] = $token;
993 $this->_data[$fld] = $token;
998 private function sync_secure_field(
string $fld,
string $token): void {
999 $this->_sys[
'_csrf'][$fld] = $token;
1000 $this->_sys[$fld] = $token;
1001 $this->_data[$fld] = $token;
1003 if (isset($this->_flds[$fld])) {
1004 $this->_flds[$fld][
'value'] = $token;
1005 $this->_flds[$fld][
'origin'] =
'csrf';
1006 $this->_flds[$fld][
'verify'] = 1;
1007 $this->_flds[$fld][
'error'] = 0;
1011 private function rotate_secure_token(
string $fld): void {
1012 $this->sync_secure_field($fld, $this->get_token());
1032 if (!is_array($data)) {
1033 $first = substr((
string) $data, 0, 1);
1035 if ($data && $first !=
'=') {
1036 if (strpos((
string) $data,
'=') !==
false) {
1037 parse_str($data, $xdata);
1054 $this->_msg_info = $msg;
1065 $this->_msg_success = $msg;
1076 $this->_msg_error = $msg;
1087 $this->_msg_warning = $msg;
1103 return dbx()->part_select(
' name="',
'"', $fld);
1124 $oTPL =
dbx()->get_system_obj(
'dbxTPL');
1125 if (is_object(
$oTPL) && method_exists(
$oTPL,
'cleanup_optional_placeholders')) {
1126 $content =
$oTPL->cleanup_optional_placeholders((
string)$content);
1129 if (isset($_SESSION[
'dbx'][
'norep']) && is_array($_SESSION[
'dbx'][
'norep'])) {
1130 $xnorep = $_SESSION[
'dbx'][
'norep'];
1132 for ($i = 0; $i < 2; $i++) {
1133 foreach ($xnorep as $id => $norep) {
1134 $xid =
'[' . $id .
']';
1135 $content = str_replace($xid, $norep, $content);
1163 $oInterpreter =
dbx()->get_system_obj(
'dbxInterpreter');
1187 public function get_tpl($tpl, $data =
'', $type =
'htm', $i = 0) {
1188 return $this->oTPL->get_tpl($tpl, $data, $type, $i);
1207 $rep =
'{obv:' . $id .
'}';
1210 if (is_string($value)) {
1211 $val = htmlspecialchars($value, ENT_QUOTES);
1212 $content = str_replace($rep, $val, $content);
1237 $editor =
dbx()->get_system_var(
'dbx_editor', 0,
'int');
1239 if (!$i && !$editor) {
1240 $i = $this->_next_i;
1243 $replaces = array();
1244 $replaces[
'dbx_modul'] = $this->_dbx_modul;
1245 $replaces[
'dbx_run1'] = $this->_dbx_action;
1246 $replaces[
'dbx_page'] = $this->_dbx_page;
1247 $replaces[
'dbx_design'] = $this->_dbx_design;
1248 $replaces[
'dbx_lng'] = $this->_dbx_lng;
1249 $replaces[
'action'] = $this->_action;
1250 $replaces[
'fid'] = $this->_fid;
1251 $replaces[
'rid'] = $this->_rid;
1252 $replaces[
'self'] =
dbx()->get_self_url();
1255 $replaces[
'i'] = $i;
1258 return $this->oTPL->replaces($tpl, $replaces);
1279 if (is_array($this->_obj)) {
1280 foreach ($this->_obj as $id => $obj) {
1281 $fid =
'{obj:' . $id .
'}';
1282 $obj = $this->oTPL->replaces($obj, $this->_replaces);
1283 $content = str_replace($fid, $obj, $content);
1306 $section = $this->_fid;
1307 $modul = $this->_dbx_modul;
1308 $mode = $this->_store_mode;
1309 $value = $this->_sys;
1312 if ($section && $mode ==
'session') {
1313 dbx()->set_session_var($key, $value, $section, $modul);
1334 $section = $this->_fid;
1335 $modul = $this->_dbx_modul;
1340 $sysdata =
dbx()->get_session_var($key, $empty, $section, $modul);
1343 return is_array($sysdata) ? $sysdata : array();
1367 $xkey =
'_activ-row_id_' . $key;
1368 return dbx()->get_remember_var($xkey, 0,
'dbx');
1384 $xkey =
'_activ-row_id_' . $key;
1385 dbx()->set_remember_var($xkey, $value,
'dbx');
1401 $this->_replaces[$key] = $val;
1421 if ($javascript !==
'') {
1422 $this->_js[] = $javascript;
1447 $js = $function .
"('" . addslashes((
string) $target) .
"'";
1477 foreach ($this->_flds as $no => $fld) {
1478 if (($fld[
'name'] ??
'') == $name) {
1481 $fld[
'data'][
'class'] = trim(($fld[
'data'][
'class'] ??
'') .
' fld-error');
1482 $fld[
'data'][
'errormsg'] = $msg;
1483 $this->_flds[$no] = $fld;
1503 dbx()->debug(
"add fld-error fld=($name) Msg=($msg)");
1504 $this->_errors[$name] = $msg;
1517 $this->_warnings[$name] = $msg;
1537 private function resolve_fld_val($name, $default =
'', $rules =
'', $useRequest =
true, $fallbackToState =
true) {
1538 $stateValue = $default;
1539 $origin =
'default';
1541 if (isset($this->_data[$name])) {
1542 $stateValue = $this->_data[$name];
1546 if (isset($this->_sys[$name])) {
1547 $stateValue = $this->_sys[$name];
1551 $value = $fallbackToState ? $stateValue : $default;
1553 if (!$fallbackToState) {
1554 $origin =
'default';
1558 if (isset($_POST[$name])) {
1559 $value = $_POST[$name];
1561 } elseif (isset($_GET[$name])) {
1562 $value = $_GET[$name];
1567 if ($value ===
null) {
1574 $ok = $this->oValidator->validate($value, $rules, $name);
1579 'origin' => $origin,
1580 'ok' => $ok ? 1 : 0,
1584 public function get_fld_val($name, $default =
'', $rules =
'', $submit = -1) {
1585 $resolved = $this->resolve_fld_val($name, $default, $rules,
true,
true);
1586 $value = $resolved[
'value'];
1588 if (!$resolved[
'ok']) {
1593 $this->_data[$name] = $value;
1594 $this->_sys[$name] = $value;
1596 if (isset($this->_flds[$name])) {
1597 $this->_flds[$name][
'value'] = $value;
1598 $this->_flds[$name][
'origin'] = $resolved[
'origin'];
1603 public function get_fld_value($name, $default =
'', $rules =
'', $submit = -1) {
1604 return $this->
get_fld_val($name, $default, $rules, $submit);
1617 $danger_value = $this->_get_post_data($name, $default);
1620 $ok = $this->oValidator->validate($danger_value, $rules, $name);
1624 $danger_value = $default;
1628 return $danger_value;
1640 public function get_post($name, $default =
'', $rules =
'alphanum') {
1641 $danger_value = $this->_get_post($name, $default);
1644 $ok = $this->oValidator->validate($danger_value, $rules, $name);
1648 $danger_value = $default;
1652 return $danger_value;
1668 private function _get_post_data($name, $default =
'') {
1672 if (isset($_POST[$name])) {
1673 $value = $_POST[$name];
1675 } elseif (isset($_GET[$name])) {
1676 $value = $_GET[$name];
1680 if (!$set && isset($this->_data[$name])) {
1681 $value = $this->_data[$name];
1699 private function _get_post($name, $default =
'') {
1702 if (isset($_POST[$name])) {
1703 $value = $_POST[$name];
1704 } elseif (isset($_GET[$name])) {
1705 $value = $_GET[$name];
1730 public function add_obj($obj, $tpl, $data =
'', $data2 =
'') {
1731 if ($tpl !=
'obj-value' && $tpl !=
'obv-value') {
1732 $tpl = $this->
get_tpl($tpl, $data);
1734 if ($tpl ==
'obv-value') {
1735 $tpl = htmlspecialchars((
string) $data, ENT_QUOTES);
1738 if ($tpl ==
'obj-value') {
1742 $tpl = $this->oTPL->replaces((
string) $tpl, $data2);
1745 $tpl = str_replace(
'{class}',
'', $tpl);
1746 $tpl = str_replace(
'{tooltip}',
'', $tpl);
1748 $this->_obj[$obj] = $tpl;
1766 public function add_action($obj, $tpl, $action =
'', $data =
'') {
1767 $xaction = $this->_action;
1769 if ($action !==
'' && $action[0] ==
'&') {
1770 $x_action = $xaction . $action;
1772 $x_action = $action;
1776 $xdata[
'action'] = $x_action;
1778 if (is_array($data)) {
1779 $xdata = array_merge($xdata, $data);
1782 $tpl = $this->
get_tpl($tpl, $xdata);
1783 $tpl = str_replace(
'{class}',
'', $tpl);
1784 $tpl = str_replace(
'{tooltip}',
'', $tpl);
1786 $this->_obj[$obj] = $tpl;
1813 private function get_active_field_source($source =
'fd::'): string {
1814 if ($source ===
'fd::') {
1816 return (
string) $this->_fd;
1819 return (
string) $this->_dd;
1822 if ($source ===
'dd::') {
1823 return (
string) $this->_dd;
1826 return (
string) $source;
1860 private function get_fld_marker_value_from_records($value,
string $var, $field_record = array(), $dd_record = array()) {
1861 if (!is_array($field_record)) {
1862 $field_record = array();
1865 if (!is_array($dd_record)) {
1866 $dd_record = array();
1869 if ($value ===
'fd::') {
1870 return $field_record[$var] ??
'';
1873 if ($value ===
'dd::') {
1874 return $dd_record[$var] ??
'';
1911 private function get_dd_fields_source(
string $dd): array {
1914 if ($dd ===
'' || $dd ===
'dd') {
1921 foreach (array(
'cfg:',
'def:',
'mod:',
'fd:',
'dd:') as $prefix) {
1922 if (strpos($dd, $prefix) === 0) {
1923 $mod = substr($prefix, 0, -1);
1924 $name = substr($dd, strlen($prefix));
1929 if ($mod ===
'dd' && strpos($dd,
'|') !==
false) {
1934 if ($mod ===
'dd') {
1935 $fields = $this->oDB->get_dd_fields($name);
1936 if (method_exists($this->oDB,
'get_dd_file')) {
1937 $this->add_editor_file(
'dd', $this->oDB->get_dd_file($name));
1954 $modul =
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
1959 $fd_modul = $this->_dbx_modul ? $this->_dbx_modul :
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
1962 if (strpos($name,
'|') !==
false) {
1963 $parts = explode(
'|', $name, 2);
1964 $fd_modul = trim($parts[0]);
1965 $fd_name = trim($parts[1]);
1968 if ($fd_modul ===
'') {
1969 $fd_modul =
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
1972 $dd_file = function_exists(
'dbx_lng_resolve_file')
1973 ? dbx_lng_resolve_file(
1981 if ($dd_file ===
'' || !is_file($dd_file)) {
1982 $dd_file =
dbx_get_base_dir() .
"dbx/modules/$fd_modul/fd/$fd_name.fd.php";
1987 return $this->read_dd_fields_direct($dd_file);
2019 private function read_dd_fields_direct(
string $dd_file): array {
2026 if (!file_exists($dd_file)) {
2030 $real_file = realpath($dd_file);
2032 $real_file = $dd_file;
2035 $normalized = str_replace(
'\\',
'/', $real_file);
2036 $kind = (substr($normalized, -7) ===
'.fd.php') ?
'fd' :
'dd';
2037 $mtime = @filemtime($real_file);
2038 $size = @filesize($real_file);
2039 $cache_key = md5($normalized);
2041 $this->add_editor_file($kind, $real_file);
2042 $runtime_cache =& $this->session_cache_section(
'form',
'field_source_runtime');
2043 $field_source_cache =& $this->session_cache_section(
'form',
'field_source');
2045 if (isset($runtime_cache[$cache_key])) {
2046 $entry = $runtime_cache[$cache_key];
2050 ($entry[
'mtime'] ?? 0) === $mtime &&
2051 ($entry[
'size'] ?? 0) === $size &&
2052 isset($entry[
'fields']) &&
2053 is_array($entry[
'fields'])
2055 return $entry[
'fields'];
2060 !isset($field_source_cache[$cache_key]) &&
2061 isset($_SESSION[
'dbx'][
'cache'][
'field_source'][$cache_key]) &&
2062 is_array($_SESSION[
'dbx'][
'cache'][
'field_source'][$cache_key])
2064 $field_source_cache[$cache_key] = $_SESSION[
'dbx'][
'cache'][
'field_source'][$cache_key];
2065 unset($_SESSION[
'dbx'][
'cache'][
'field_source'][$cache_key]);
2068 if (isset($field_source_cache[$cache_key])) {
2069 $entry = $field_source_cache[$cache_key];
2073 ($entry[
'mtime'] ?? 0) === $mtime &&
2074 ($entry[
'size'] ?? 0) === $size &&
2075 isset($entry[
'fields']) &&
2076 is_array($entry[
'fields'])
2078 $runtime_cache[$cache_key] = $entry;
2079 return $entry[
'fields'];
2090 'path' => $normalized,
2097 $runtime_cache[$cache_key] = $entry;
2098 $field_source_cache[$cache_key] = $entry;
2116 private function get_dd_fld(array
$fields,
string $fld): array {
2118 if (isset($record[
'name']) && $record[
'name'] === $fld) {
2126 private function &session_cache_section(
string $bereich,
string $section) {
2127 if (!isset($_SESSION[
'dbx']) || !is_array($_SESSION[
'dbx'])) {
2128 $_SESSION[
'dbx'] = array();
2131 if (!isset($_SESSION[
'dbx'][
'cache']) || !is_array($_SESSION[
'dbx'][
'cache'])) {
2132 $_SESSION[
'dbx'][
'cache'] = array();
2135 if (!isset($_SESSION[
'dbx'][
'cache'][$bereich]) || !is_array($_SESSION[
'dbx'][
'cache'][$bereich])) {
2136 $_SESSION[
'dbx'][
'cache'][$bereich] = array();
2139 if (!isset($_SESSION[
'dbx'][
'cache'][$bereich][$section]) || !is_array($_SESSION[
'dbx'][
'cache'][$bereich][$section])) {
2140 $_SESSION[
'dbx'][
'cache'][$bereich][$section] = array();
2143 return $_SESSION[
'dbx'][
'cache'][$bereich][$section];
2169 public function get_dd(
string $dd,
string $fld,
string $var) {
2170 if ($dd ===
'' || $dd ===
'dd') {
2178 $cache_key = md5($dd .
"\0" . $fld);
2179 $field_cache =& $this->session_cache_section(
'form',
'runtime_field');
2181 if (isset($field_cache[$cache_key]) && is_array($field_cache[$cache_key])) {
2182 $field = $field_cache[$cache_key];
2184 $fields = $this->get_dd_fields_source($dd);
2187 $field_cache[$cache_key] = array();
2197 $field_cache[$cache_key] =
$field;
2208 return $field[$var] ??
'';
2232 private function sql_dd_file_exists($modul, $dd) {
2233 $modul = trim((
string) $modul);
2234 $dd = trim((
string) $dd);
2240 if ($modul ===
'') {
2241 $modul =
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
2247 return file_exists($file1) || file_exists($file2);
2250 private function normalize_sql_dd_name($modul, $source) {
2251 $source = trim((
string) $source);
2253 if ($source ===
'') {
2257 $candidates = array(
2259 str_replace(
'dbx_',
'dbx', $source),
2260 str_replace(
' ',
'', ucwords(str_replace(
'_',
' ', $source))),
2261 lcfirst(str_replace(
' ',
'', ucwords(str_replace(
'_',
' ', $source))))
2264 foreach ($candidates as $candidate) {
2265 if ($this->sql_dd_file_exists($modul, $candidate)) {
2273 private function sql_to_array($data) {
2282 $compact_sql_syntax =
false;
2284 $data = str_replace(
'sql:',
'', (
string) $data);
2285 $work = explode(
'|', $data);
2287 if (isset($work[0])) {
2291 if (isset($work[1])) {
2295 if ($dd && $xkey && strpos($xkey,
',') !==
false) {
2296 $sqlSource = array_map(
'trim', explode(
',', $xkey));
2297 $dd = $this->normalize_sql_dd_name($dd, $sqlSource[0] ??
'');
2298 $xkey = $sqlSource[1] ??
'id';
2299 $flds = $sqlSource[2] ?? $xkey;
2300 $compact_sql_syntax =
true;
2303 if (isset($work[2])) {
2304 if ($compact_sql_syntax) {
2311 if (isset($work[3])) {
2312 if ($compact_sql_syntax) {
2319 if (isset($work[4])) {
2320 if ($compact_sql_syntax) {
2321 if ((
int) $work[4] > 0) {
2322 $limit = (int) $work[4];
2329 if (!$compact_sql_syntax && isset($work[5]) && (
int) $work[5] > 0) {
2330 $limit = (int) $work[5];
2333 $xdata[0] =
'Bitte auswählen';
2335 if ($order && strpos($order,
' DESC') !==
false) {
2337 $order = str_replace(
' DESC',
'', $order);
2340 if ($order && strpos($order,
' ASC') !==
false) {
2342 $order = str_replace(
' ASC',
'', $order);
2352 if (strpos(
',' . $xflds .
',',
',' . $xkey .
',') ===
false && $xflds !==
'*') {
2353 $xflds .=
',' . $xkey;
2356 $data = $this->oDB->select($dd, $where, $xflds, $order, $asc_desc,
'', $limit, 0, 0);
2358 if (is_array($data)) {
2359 $displayFields = ($flds ===
'*') ? array() : array_map(
'trim', explode(
',', $flds));
2361 foreach ($data as $record) {
2364 foreach ($record as $fld => $val) {
2365 $use = ($flds ===
'*') || in_array($fld, $displayFields,
true);
2368 if ($value !==
'') {
2376 if (isset($record[$xkey])) {
2377 $xdata[$record[$xkey]] = $value;
2421 $source = $this->get_active_field_source($dd);
2423 if ($source ===
'' || $source ===
'dd') {
2427 $fields = $this->get_dd_fields_source($source);
2435 foreach (
$fields as $record) {
2436 if (!is_array($record)) {
2440 if (!isset($record[
'name']) || trim((
string) $record[
'name']) ===
'') {
2444 $name = trim((
string) $record[
'name']);
2445 $this->
add_fld($name, dd: $source);
2507 public function add_fld($name, $tpl =
'fd::', $label =
'fd::', $rules =
'fd::', $class =
'fd::', $data =
'fd::', $options =
'fd::', $tooltip =
'fd::', $placeholder =
'fd::', $errormsg =
'fd::', $dd =
'fd::', $remap =
'fd::') {
2508 $field_source = $this->get_active_field_source($dd);
2509 $dd_source = $this->get_active_field_source(
'dd::');
2510 $field_record = $field_source ? $this->
get_dd($field_source, $name,
'*') : array();
2511 $dd_record = $dd_source ? $this->get_dd($dd_source, $name,
'*') : array();
2512 $source_data = array();
2513 $source_options = array();
2515 $dd_options = array();
2517 if (is_array($field_record) && $field_record) {
2518 $source_data = $this->process_array($field_record[
'data'] ??
'');
2519 $source_options = $this->process_array($field_record[
'options'] ??
'');
2522 if (is_array($dd_record) && $dd_record) {
2523 $dd_data = $this->process_array($dd_record[
'data'] ??
'');
2524 $dd_options = $this->process_array($dd_record[
'options'] ??
'');
2527 if ($data ===
'fd::' || $data ===
'' || $data ===
null) {
2528 $data = $source_data;
2529 } elseif ($data ===
'dd::') {
2532 $data = $this->merge_arrays($this->process_array($data), $source_data);
2535 if ($options ===
'fd::' || $options ===
'' || $options ===
null) {
2536 $options = $source_options;
2537 } elseif ($options ===
'dd::') {
2538 $options = $dd_options;
2540 $options = $this->merge_arrays($this->process_array($options), $source_options);
2543 if (isset($data[
'dd'])) {
2544 $field_source = $this->get_active_field_source($data[
'dd']);
2545 $field_record = $field_source ? $this->get_dd($field_source, $name,
'*') : array();
2548 if ($label ===
'fd::' && isset($data[
'label'])) {
2549 $label = $data[
'label'];
2552 if ($rules ===
'fd::' && isset($data[
'rules'])) {
2553 $rules = $data[
'rules'];
2556 if ($class ===
'fd::' && isset($data[
'class'])) {
2557 $class = $data[
'class'];
2560 if ($tooltip ===
'fd::' && isset($data[
'tooltip'])) {
2561 $tooltip = $data[
'tooltip'];
2564 if ($placeholder ===
'fd::' && isset($data[
'placeholder'])) {
2565 $placeholder = $data[
'placeholder'];
2568 if ($errormsg ===
'fd::' && isset($data[
'errormsg'])) {
2569 $errormsg = $data[
'errormsg'];
2572 if ($remap ===
'fd::' && isset($data[
'remap'])) {
2573 $remap = $data[
'remap'];
2576 $data[
'name'] = $name;
2577 $data[
'tpl'] = $this->get_fld_marker_value_from_records($tpl,
'tpl', $field_record, $dd_record);
2578 $data[
'label'] = $this->get_fld_marker_value_from_records($label,
'label', $field_record, $dd_record);
2579 $data[
'rules'] = $this->get_fld_marker_value_from_records($rules,
'rules', $field_record, $dd_record);
2580 $data[
'class'] = $this->get_fld_marker_value_from_records($class,
'class', $field_record, $dd_record);
2581 $data[
'tooltip'] = $this->get_fld_marker_value_from_records($tooltip,
'tooltip', $field_record, $dd_record);
2582 $data[
'placeholder'] = $this->get_fld_marker_value_from_records($placeholder,
'placeholder', $field_record, $dd_record);
2583 $data[
'errormsg'] = $this->get_fld_marker_value_from_records($errormsg,
'errormsg', $field_record, $dd_record);
2584 $data[
'remap'] = $this->get_fld_marker_value_from_records($remap,
'remap', $field_record, $dd_record);
2589 'options' => $options,
2590 'label' => $data[
'label'],
2591 'tpl' => $data[
'tpl'],
2592 'rules' => $data[
'rules'],
2593 'remap' => $data[
'remap'],
2596 'errormsg' => $data[
'errormsg'],
2600 'dd' => $field_source,
2603 $this->_flds[$name] = $fld;
2604 $this->touch_request_state();
2620 private function process_array($input) {
2621 if (!is_array($input)) {
2623 $data_first = substr((
string) $input, 0, 4);
2625 if ($data_first ===
'sql:') {
2626 $input = $this->sql_to_array($input);
2628 $input = $this->url_to_array($input);
2635 return is_array($input) ? $input : array();
2651 private function merge_arrays($primary, $secondary) {
2652 if (!is_array($primary)) {
2656 if (!is_array($secondary)) {
2657 $secondary = array();
2660 foreach ($secondary as $key => $value) {
2661 if (!array_key_exists($key, $primary)) {
2662 $primary[$key] = $value;
2680 private function touch_request_state() {
2681 $this->_form_validate = -1;
2682 $this->_fld_changes = -1;
2683 $this->_form_submit = -1;
2702 if (($fld[
'verify'] ?? 0)) {
2706 $errormsg =
'Bitte Eingabe pruefen';
2707 $name = $fld[
'name'] ??
'';
2708 $fld_rules = $fld[
'rules'] ??
'';
2711 $resolved = $this->resolve_fld_val($name,
'',
'',
false,
true);
2713 $fld[
'value'] = $resolved[
'value'];
2714 $fld[
'origin'] = $resolved[
'origin'];
2715 $fld[
'changed'] = 0;
2722 $old = $this->resolve_fld_val($name,
'',
'',
false,
true);
2723 $old_value = $old[
'value'];
2725 $resolved = $this->resolve_fld_val($name,
'', $fld_rules,
true,
false);
2726 $value = $resolved[
'value'];
2727 $ok = (bool) $resolved[
'ok'];
2729 $fld[
'origin'] = $resolved[
'origin'];
2730 $fld[
'error'] = $ok ? 0 : 1;
2731 $fld[
'value'] = $value;
2733 if (!empty($fld[
'data'][
'errormsg'])) {
2734 $errormsg = $fld[
'data'][
'errormsg'];
2737 if ($fld[
'error']) {
2739 $fld[
'data'][
'errormsg'] = $errormsg;
2742 $value_compare = $value;
2744 if (is_array($value_compare)) {
2747 foreach ($value_compare as $keyval) {
2748 if ($values !==
'') {
2755 $value_compare = $values;
2758 $change = $this->_fld_change_state;
2760 if ($value_compare != $old_value || $change ==
'*') {
2761 $fld[
'changed'] = 1;
2763 $fld[
'changed'] = 0;
2766 if (!$fld[
'error'] && $fld[
'changed']) {
2767 $this->_post[$name] = $value_compare;
2789 if ($this->_form_validate == 1) {
2793 $this->_post = array();
2794 $this->_errors = array();
2795 $this->_warnings = array();
2797 foreach ($this->_flds as $no => $fld) {
2799 $this->_flds[$no] = $fld;
2802 $this->_form_validate = 1;
2803 $this->_fld_changes = -1;
2821 private function evaluate_request() {
2822 if ($this->_form_validate == 1 && $this->_form_submit > -1) {
2823 dbx()->debug(
"dbxForm submit cached: fid=({$this->_fid}) submit=({$this->_form_submit})");
2828 $fld = $this->secure_fld_name();
2829 $secure = $this->secure_token($fld);
2834 if ($fld !==
'' && isset($_POST[$fld])) {
2835 $posted = (string)$_POST[$fld];
2838 if ($secure !==
'' && hash_equals($secure, $posted)) {
2845 "dbxForm submit evaluate: fid=({$this->_fid}) field=($fld) post=($hasPost) match=($match) submit=($submit) sys=(" . substr($secure, 0, 8) .
") postval=(" . substr($posted, 0, 8) .
")"
2848 $this->_form_submit = $submit;
2849 $this->check_flds_data($submit);
2852 $this->rotate_secure_token($fld);
2854 $this->sync_secure_field($fld, $secure);
2871 $file = $this->_tpl_form_info;
2874 if ($mode ==
'success') {
2875 $file = $this->_tpl_form_success;
2878 if ($mode ==
'error') {
2879 $file = $this->_tpl_form_error;
2882 if ($mode ==
'info') {
2883 $file = $this->_tpl_form_info;
2886 if ($mode ==
'warning') {
2887 $file = $this->_tpl_form_warning;
2892 $tpl = str_replace(
'{msg}', $msg, $tpl);
2895 return str_replace(
'{class}', $mode, $tpl);
2910 if ($mode ==
'success') {
2911 $file = $this->_tpl_fld_success;
2914 if ($mode ==
'error') {
2915 $file = $this->_tpl_fld_error;
2918 if ($mode ==
'info') {
2919 $file = $this->_tpl_fld_info;
2922 if ($mode ==
'warning') {
2923 $file = $this->_tpl_fld_warning;
2928 $tpl = str_replace(
'{msg}', $msg, $tpl);
2953 if (trim((
string) $value) !==
'') {
2954 $timestamp = strtotime((
string) $value);
2956 if ($timestamp !==
false) {
2957 $value = date(
'd.m.Y', $timestamp);
2958 $value = substr($value, 0, 10);
2962 return (
string) $value;
2973 $raw = trim((
string) $value);
2978 if (preg_match(
'/\.(\d+)$/', $raw, $match)) {
2979 $ms =
'.' . $match[1];
2982 $timestamp = strtotime($raw);
2984 if ($timestamp !==
false) {
2985 if (preg_match(
'/^\d{2}:\d{2}(:\d{2})?(\.\d+)?$/', $raw)) {
2986 $value = date(
'H:i' . (substr_count($raw,
':') == 2 ?
':s' :
''), $timestamp) . $ms;
2987 } elseif (preg_match(
'/^\d{4}-\d{2}-\d{2}$|^\d{2}\.\d{2}\.\d{4}$/', $raw)) {
2988 $value = date(
'd.m.Y', $timestamp);
2990 $value = date(
'd.m.Y H:i' . (substr_count($raw,
':') >= 2 ?
':s' :
''), $timestamp) . $ms;
2995 return (
string) $value;
3007 if ($value !=
'today') {
3008 $timestamp = strtotime((
string) $value);
3010 $timestamp = time();
3013 $value = date(
'Y-m-d', $timestamp);
3016 return (
string) $value;
3028 $this->_css[] = $css;
3043 $this->evaluate_request();
3044 $submit = ($this->_form_submit == 1) ? 1 : 0;
3045 $submit = $this->
callback(
'submit', $submit);
3046 $result = ($submit == 1) ? 1 : 0;
3048 dbx()->debug(
"dbxForm submit result: fid=({$this->_fid}) result=($result)");
3068 $this->evaluate_request();
3070 if ($this->_general_error >
'') {
3071 $this->_errors[
'general'] = 1;
3074 return count($this->_errors);
3083 $this->evaluate_request();
3084 return count($this->_warnings);
3095 $this->evaluate_request();
3097 if ($this->_form_submit != 1) {
3098 $this->_fld_changes = 0;
3102 if ($this->_fld_changes != -1) {
3103 return $this->_fld_changes;
3106 foreach ($this->_flds as $fld) {
3107 $changed += (int) ($fld[
'changed'] ?? 0);
3110 $this->_fld_changes = $changed;
3122 $rid =
dbx()->get_modul_var(
'rid', -1,
'int');
3123 $dbx_view = $this->_dbx_view;
3124 $dbx_modul = $this->_dbx_modul;
3127 $viewsys =
dbx()->get_session_var($dbx_view, $empty,
'view-sys', $dbx_modul);
3129 if (isset($viewsys[
'value'])) {
3130 $rid = $viewsys[
'value'];
3134 $this->_rid = (int) $rid;
3149 $dbx_view = $this->_dbx_view;
3150 $dbx_modul = $this->_dbx_modul;
3153 $viewsys =
dbx()->get_session_var($dbx_view, $empty,
'view-sys', $dbx_modul);
3154 $viewsys[
'value'] = $rid;
3155 dbx()->set_session_var($dbx_view, $viewsys,
'view-sys', $dbx_modul);
3172 if (strpos((
string) $tpl,
'_wait') !==
false) {
3193 if ($key !=
'form-dd-field') {
3194 $this->_post[$key] = $val;
3197 $this->_fld_changes = -1;
3225 public function save_post($dd, $rid, $pv =
'', $reread = 1) {
3228 if ($rid ===
'new') {
3232 if (is_array($pv)) {
3233 foreach ($pv as $key => $value) {
3234 $this->_post[$key] = $value;
3235 $this->_data[$key] = $value;
3240 $this->_rid = (int) $rid;
3243 $rid = (int) $this->_rid;
3244 $post = $this->_post;
3246 $this->oDB->_fld_id = $this->_fld_id;
3247 $ok = $this->oDB->save($dd, $post, $rid);
3250 dbx()->debug(
"DB-Error=(" . $this->oDB->_error .
")\nQuery=(" . $this->oDB->_query .
")");
3256 $rid = (int) $this->oDB->_insert_id;
3264 if ($rid && $ok && $reread) {
3265 $new = $this->oDB->select1($dd, $rid);
3267 if (is_array($new)) {
3268 foreach ($new as $key => $value) {
3269 $this->_data[$key] = $value;
3272 $this->_reload_run = 1;
3274 foreach ($this->_flds as $no => $fld) {
3275 $key = $fld[
'name'] ??
'';
3277 if ($key !==
'' && array_key_exists($key, $this->_data)) {
3278 $this->_flds[$no][
'value'] = $this->_data[$key];
3279 $this->_flds[$no][
'origin'] =
'reload';
3280 $this->_flds[$no][
'verify'] = 1;
3281 $this->_flds[$no][
'error'] = 0;
3293 dbx()->debug(
"#DD FORM-save# Tab=($dd) rid=($rid)");
3306 $i = $this->_next_i;
3309 $i =
dbx()->next_id($add);
3310 $this->_next_i = $i;
3327 $this->_data[$fld_name] = $fld_val;
3328 $this->_sys[$fld_name] = $fld_val;
3330 if (isset($this->_flds[$fld_name])) {
3331 $this->_flds[$fld_name][
'value'] = $fld_val;
3332 $this->_flds[$fld_name][
'origin'] =
'set';
3333 $this->_flds[$fld_name][
'verify'] = 1;
3344 $this->
add_rep(
'dbx_search',
dbx()->search_html(
dbx()->search_defaults(array_merge(array(
3345 'extra_attrs' =>
'data-dbx="grid-search"',
3349 private function is_search_field_tpl($tpl): bool {
3350 $tpl = strtolower(trim((string) $tpl));
3352 return $tpl ===
'dbx|search' || $tpl ===
'search' || substr($tpl, -7) ===
'|search';
3363 private function prepare_report_search_fld($name, &$tpl, array &$data): void {
3364 if ($name !==
'dbx_rwhere') {
3368 $tpl =
'dbx|search';
3369 $defaults =
dbx()->search_defaults();
3371 $data[
'label'] =
'';
3372 $data[
'placeholder'] = $defaults[
'placeholder'];
3373 $data[
'title'] = trim((
string) ($data[
'tooltip'] ??
'')) !==
''
3374 ? (string) $data[
'tooltip']
3375 : $defaults[
'title'];
3376 $data[
'input_class'] = $defaults[
'input_class'];
3377 $data[
'wrap_class'] = $defaults[
'wrap_class'];
3378 $data[
'data_role'] = $defaults[
'data_role'];
3379 $data[
'extra_attrs'] = $defaults[
'extra_attrs'];
3399 $i = $this->_next_i;
3402 if (!($fld[
'verify'] ?? 0)) {
3406 $tpl = $fld[
'tpl'] ??
'';
3407 $data = is_array($fld[
'data'] ??
null) ? $fld[
'data'] : array();
3408 $options = is_array($fld[
'options'] ??
null) ? $fld[
'options'] : array();
3409 $fld_value = $fld[
'value'] ??
'';
3410 $error = (int) ($fld[
'error'] ?? 0);
3411 $name = $fld[
'name'] ??
'';
3414 $data[
'class'] = trim(($data[
'class'] ??
'') .
' fld-error');
3416 if (!isset($data[
'errormsg']) || $data[
'errormsg'] ===
'') {
3417 $data[
'errormsg'] =
'Eingabe bitte prüfen !';
3420 $data[
'errormsg'] =
'';
3423 if (!is_array($fld_value)) {
3424 $fld_value = htmlspecialchars((
string) $fld_value, ENT_QUOTES,
'UTF-8');
3426 if (!isset($data[
'checked']) && $fld_value !==
'' && $fld_value !==
'0') {
3427 $data[
'checked'] =
'checked';
3430 if (!isset($data[
'checked'])) {
3431 $data[
'checked'] =
'';
3438 $data[
'required'] = $required;
3439 $data[
'class'] = $data[
'class'] ??
'';
3440 $data[
'style'] = $data[
'style'] ??
'';
3441 $data[
'tooltip'] = $data[
'tooltip'] ??
'';
3442 $data[
'errormsg'] = $data[
'errormsg'] ??
'';
3444 foreach (array(
'placeholder') as $htmlKey) {
3445 if (isset($data[$htmlKey]) && !is_array($data[$htmlKey])) {
3446 $data[$htmlKey] = htmlspecialchars((
string)$data[$htmlKey], ENT_QUOTES,
'UTF-8');
3450 foreach (array(
'tooltip',
'errormsg') as $htmlAttributeKey) {
3451 if (isset($data[$htmlAttributeKey]) && !is_array($data[$htmlAttributeKey])) {
3452 $data[$htmlAttributeKey] = htmlspecialchars(str_replace(
'"',
"'", (
string)$data[$htmlAttributeKey]), ENT_QUOTES,
'UTF-8');
3456 $this->prepare_report_search_fld($name, $tpl, $data);
3458 if ($this->is_search_field_tpl($tpl)) {
3459 $tpl =
dbx()->search_html(
dbx()->search_defaults(array(
3461 'value' => is_array($fld_value) ?
'' : (
string) $fld_value,
3462 'placeholder' => (
string) ($data[
'placeholder'] ??
''),
3463 'title' => (
string) ($data[
'title'] ?? $data[
'tooltip'] ??
''),
3464 'tooltip' => (
string) ($data[
'tooltip'] ?? $data[
'title'] ??
''),
3465 'errormsg' => (
string) ($data[
'errormsg'] ??
''),
3466 'class' => (
string) ($data[
'class'] ??
''),
3467 'input_class' => (
string) ($data[
'input_class'] ??
''),
3468 'wrap_class' => (
string) ($data[
'wrap_class'] ??
''),
3469 'wrap_style' => (
string) ($data[
'wrap_style'] ?? ($data[
'style'] ??
'')),
3470 'data_role' => (
string) ($data[
'data_role'] ??
''),
3471 'extra_attrs' => (
string) ($data[
'extra_attrs'] ??
''),
3472 'label' => (
string) ($data[
'label'] ??
''),
3473 'style' => (
string) ($data[
'style'] ??
''),
3477 $tpl = $this->
get_tpl($tpl, $data);
3480 if (is_array($options)) {
3482 $oid = $name .
'_options';
3483 $options_vals = $fld_value;
3485 if (!is_array($options_vals)) {
3486 $options_vals = explode(
',', (
string) $options_vals);
3489 $selected_lookup = array();
3490 foreach ($options_vals as $keyval) {
3491 $selected_lookup[(string) $keyval] =
true;
3494 foreach ($options as $key => $description) {
3495 $selected = isset($selected_lookup[(
string) $key]) ?
'selected' :
'';
3497 $xoptions .=
'<option value="' . htmlspecialchars((
string) $key, ENT_QUOTES,
'UTF-8') .
'" ' . $selected .
'>' .
3498 htmlspecialchars((
string) $description, ENT_QUOTES,
'UTF-8') .
3502 $tpl = str_replace(
'{' . $oid .
'}', $xoptions, $tpl);
3505 $tpl = $this->oTPL->replaces($tpl, $this->_replaces);
3507 if (!is_array($fld_value)) {
3508 $tpl = str_replace(
'{src}', $fld_value, $tpl);
3509 $tpl = str_replace(
'{value}', $fld_value, $tpl);
3512 $tpl =
dbx()->norep($tpl, $i);
3516 if ($field_markers !==
'') {
3517 $tpl = $field_markers . $tpl;
3544 $editor =
dbx()->get_system_var(
'dbx_editor', 0,
'int');
3546 if (!$i && !$editor) {
3547 $i = $this->_next_i;
3550 foreach ($this->_flds as $fld_name => $fld) {
3553 if (!empty($fld[
'remap'])) {
3554 $slot = $fld[
'remap'];
3557 $fid =
'{obj:' . $slot .
'}';
3560 if (strpos($content, $fid) !==
false) {
3561 $content = str_replace($fid, $fld_content, $content);
3563 $form .= $fld_content .
"\n";
3567 if (strpos($content,
'[dbx:form]') !==
false) {
3568 $content = str_replace(
'[dbx:form]', $form, $content);
3570 $content = str_replace(
'</form>', $form .
'</form>', $content);
3588 $reset = $this->_try_reset;
3589 $max = $this->_try_max;
3590 $msg = $this->_try_msg;
3591 $now =
dbx()->timestamp();
3592 $self =
dbx()->get_self_url();
3593 $ip = (string)(
$_SERVER[
'REMOTE_ADDR'] ??
'');
3594 $sys = isset($this->_sys[
'_try_sys']) ? $this->_sys[
'_try_sys'] : array();
3596 if (($sys[
'dbx_try_ip'] ??
'') !== $ip) {
3598 'dbx_try_ip' => $ip,
3602 $sys[
'dbx_try_count'] = $sys[
'dbx_try_count'] ?? 0;
3603 $sys[
'dbx_run_count'] = $sys[
'dbx_run_count'] ?? 0;
3604 $sys[
'dbx_try_lock'] = $sys[
'dbx_try_lock'] ?? 0;
3605 $sys[
'dbx_try_ip'] = $ip;
3607 $sys[
'dbx_run_count']++;
3611 $sys[
'dbx_try_first'] = $sys[
'dbx_try_first'] ?? $now;
3612 $sys[
'dbx_try_last'] = $now;
3613 $sys[
'dbx_try_count']++;
3615 if ($sys[
'dbx_try_count'] >= $max) {
3616 if (!isset($sys[
'dbx_try_stop'])) {
3617 $sys[
'dbx_try_lock']++;
3619 for ($i = 1; $i < $sys[
'dbx_try_lock']; $i++) {
3620 $reset = (int) ($reset * 2);
3623 $sys[
'dbx_try_stop'] = $now;
3624 $sys[
'dbx_try_run'] =
dbx()->timestamp($reset);
3628 if (isset($sys[
'dbx_try_run']) && $now > $sys[
'dbx_try_run']) {
3636 if (($submit || $allways) && !$clear) {
3637 if (($sys[
'dbx_try_count'] ?? 0) >= $max && ($sys[
'dbx_try_run'] ?? 0) > 0) {
3638 $diff =
dbx()->time_diff($now, $sys[
'dbx_try_run']);
3642 'sec' => (
int) $diff,
3644 'try_count' => $sys[
'dbx_try_count'],
3645 'run_count' => $sys[
'dbx_run_count'],
3647 $data[
'msg'] = $this->oTPL->replaces((
string) $msg, $data);
3649 $content = $this->
get_tpl($this->_tpl_max_try, $data);
3657 unset($sys[
'dbx_try_stop'], $sys[
'dbx_try_run']);
3658 $sys[
'dbx_try_count'] = 0;
3661 $this->_sys[
'_try_sys'] = $sys;
3685 $editor =
dbx()->get_system_var(
'dbx_editor', 0,
'int');
3687 $this->evaluate_request();
3689 $submit = $this->
submit();
3690 $errors = $this->
errors();
3696 $this->_next_i = $i;
3701 $replaces = $this->_replaces;
3702 $replaces[
'form-id'] = $this->_dbx_modul .
'-' . $this->_fid;
3703 foreach (array(
'form_shell_class' =>
'',
'form_class' =>
'',
'form_attrs' =>
'') as $shellKey => $shellDefault) {
3704 if (!isset($replaces[$shellKey]) || (
string)$replaces[$shellKey] ===
'') {
3705 $replaces[$shellKey] = $shellDefault;
3708 foreach (array(
'shell_panel_class' =>
'',
'shell_panel_attrs' =>
'',
'shell_body_class' =>
'') as $shellKey => $shellDefault) {
3709 if (!isset($replaces[$shellKey]) || (
string)$replaces[$shellKey] ===
'') {
3710 $replaces[$shellKey] = $shellDefault;
3714 $content = $this->
get_tpl(
'modul|' . $this->_tpl, $replaces,
'htm', $i);
3717 $content = $this->
merge_obj($content, $i);
3723 $form_msg = $this->
get_form_msg(
'error', $this->_msg_error);
3725 $form_msg = $this->
get_form_msg(
'warning', $this->_msg_warning);
3727 $form_msg = $this->
get_form_msg(
'success', $this->_msg_success);
3730 $form_msg = $this->
get_form_msg(
'info', $this->_msg_info);
3733 $content = str_replace(
'{obj:form_msg}', $form_msg, $content);
3737 if (is_array($this->_js)) {
3738 foreach ($this->_js as $javascript) {
3739 $javascript = str_replace(
'{i}', $this->_next_i, $javascript);
3740 $norep =
'<script>' . $javascript .
'</script> ';
3741 $norep_ids .=
dbx()->norep($norep, $i);
3745 $content = str_replace(
'[dbx:js]', $norep_ids, $content);
3747 if (!$editor && $content && $i) {
3748 $content = str_replace(
'{i}', $i, $content);
3752 $content = $this->
callback(
'run', $content);
3769 $source = trim($source);
3771 if ($source ===
'') {
3778 foreach (array(
'cfg:',
'def:',
'mod:',
'fd:',
'dd:') as $prefix) {
3779 if (strpos($source, $prefix) === 0) {
3780 $mod = substr($prefix, 0, -1);
3781 $name = substr($source, strlen($prefix));
3786 if ($mod ===
'dd' && strpos($source,
'|') !==
false) {
3791 if ($mod ===
'dd') {
3792 if (method_exists($this->oDB,
'get_dd_file')) {
3793 return (
string) $this->oDB->get_dd_file($name);
3796 $modul = $this->_dbx_modul ? $this->_dbx_modul :
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
3813 $modul =
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
3818 $fd_modul = $this->_dbx_modul ? $this->_dbx_modul :
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
3821 if (strpos($name,
'|') !==
false) {
3822 $parts = explode(
'|', $name, 2);
3823 $fd_modul = trim($parts[0]);
3824 $fd_name = trim($parts[1]);
3827 if ($fd_modul ===
'') {
3828 $fd_modul =
dbx()->get_system_var(
'dbx_activ_modul',
'dbx');
3831 $dd_file = function_exists(
'dbx_lng_resolve_file')
3832 ? dbx_lng_resolve_file(
3840 if ($dd_file ===
'' || !is_file($dd_file)) {
3841 $dd_file =
dbx_get_base_dir() .
"dbx/modules/$fd_modul/fd/$fd_name.fd.php";
3846 if ($dd_file ===
'') {
3852 return $real_file ? $real_file : $dd_file;
3863 foreach (array(
'fd' => $this->_fd,
'dd' => $this->_dd) as $kind => $source) {
3870 $marker =
dbx()->editor_marker($kind, $file);
3872 if ($marker !==
'' && strpos($markers, trim($marker)) ===
false) {
3873 $markers .= $marker;
3888 public function init($fid, $tpl =
'') {
3924 $this->_workflow_scope = trim($scope);
3934 return $this->_workflow_scope;
3944 private function normalize_state_token(
string $token): string {
3945 $token = trim($token);
3947 if ($token ===
'') {
3951 return preg_replace(
'/[^a-zA-Z0-9._-]+/',
'_', $token);
3970 $modul = $this->normalize_state_token((string) $this->_dbx_modul);
3971 $scope = $this->normalize_state_token((
string) $this->_workflow_scope);
3972 $fid = $this->normalize_state_token((
string) $this->_fid);
3974 return 'dbx.form.state.' . $modul .
'.' . $scope .
'.' . $fid;
3982 private function get_default_workflow_state(): array {
3991 'depends_on' => array(),
3992 'depends_version' => array(),
4003 $state =
dbx()->get_remember_var($key, $this->get_default_workflow_state(),
'dbx');
4005 if (!is_array($state)) {
4006 $state = $this->get_default_workflow_state();
4009 $this->_workflow_state = array_merge($this->get_default_workflow_state(), $state);
4011 if ((
int) ($this->_workflow_state[
'rid'] ?? 0) > 0 && !$this->_rid) {
4012 $this->_rid = (int) $this->_workflow_state[
'rid'];
4015 return $this->_workflow_state;
4025 dbx()->set_remember_var($key, $this->_workflow_state,
'dbx');
4034 $this->_workflow_state = $this->get_default_workflow_state();
4047 $this->_workflow_state[$key] = $value;
4060 if (!array_key_exists($key, $this->_workflow_state)) {
4064 return $this->_workflow_state[$key] ?? $default;
4083 if ($draftId ===
'' && $createIfMissing) {
4084 $draftId = $this->create_draft_id();
4107 private function create_draft_id(): string {
4108 return
'dft_' . md5($this->_dbx_modul .
'|' . $this->_fid .
'|' . microtime(true) .
'|' . mt_rand());
4232 foreach ($formIds as $formId) {
4233 $deps[] = $this->normalize_state_token((
string) $formId);
4252 if ($formIds ===
null) {
4256 $versions = array();
4258 foreach ($formIds as $formId) {
4260 $versions[$formId] = (int) ($state[
'version'] ?? 0);
4280 if (!is_array($dependsOn) || !$dependsOn) {
4284 foreach ($dependsOn as $formId) {
4285 $state = $this->get_external_form_state((
string) $formId);
4286 $currentVersion = (int) ($state[
'version'] ?? 0);
4287 $savedVersion = (int) ($dependsVersion[$formId] ?? -1);
4289 if ($currentVersion !== $savedVersion) {
4293 if ((
int) ($state[
'is_valid'] ?? 0) !== 1) {
4309 $modul = $this->normalize_state_token((string) $this->_dbx_modul);
4310 $scope = $this->normalize_state_token((
string) $this->_workflow_scope);
4311 $fid = $this->normalize_state_token($fid);
4313 $key =
'dbx.form.state.' . $modul .
'.' . $scope .
'.' . $fid;
4314 $state =
dbx()->get_remember_var($key, $this->get_default_workflow_state(),
'dbx');
4316 return is_array($state) ? $state : $this->get_default_workflow_state();
Gemeinsame Basisklasse fuer dbXapp-System-, Modul- und Include-Objekte.
set_callback_id(string $id)
Setzt den Namenspraefix fuer konventionelle Callback-Methoden.
set_callback(string $event, string $callback)
Ordnet einem Event einen konkreten Methodennamen zu.
set_callback_owner($owner)
Setzt ein explizites Owner-Objekt fuer Callback-Aufrufe.
callback(string $event, mixed $value)
Fuehrt einen Callback aus und gibt dessen Rueckgabewert zurueck.
dbx_os_path_file($path_file)
dbx_get_base_dir($cut_Data=0)
DBX schema administration.
if(! $db->connect_db_server($server)) $result
foreach( $topics as $file=> $html)