dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
workflow_roundtrip_test.php
Go to the documentation of this file.
1<?php
2
3require_once dirname(__DIR__) . '/include/dbxWorkflowAdmin.class.php';
4require_once dirname(__DIR__, 2) . '/dbxWorkflow/include/dbxWorkflowEngine.class.php';
5
7 public function select($dd, $where, $fields = '*', $order = '', $dir = '', $group = '', $limit = 0, $pos = 0, $flag = 0) {
8 $key = (string)($where['workflow_key'] ?? '');
9 $rows = array(
10 'active_flow' => array(
11 'id' => 1,
12 'workflow_key' => 'active_flow',
13 'title' => 'Aktiver Ablauf',
14 'result_label' => 'Aktives Ergebnis',
15 'description' => 'Test',
16 'active' => 1,
17 'definition_json' => '{"needs":[{"key":"value","label":"Wert","actions":["form"]}]}',
18 ),
19 'inactive_flow' => array(
20 'id' => 2,
21 'workflow_key' => 'inactive_flow',
22 'title' => 'Inaktiver Ablauf',
23 'result_label' => 'Inaktives Ergebnis',
24 'description' => 'Test',
25 'active' => 0,
26 'definition_json' => '{"needs":[{"key":"value","label":"Wert","actions":["form"]}]}',
27 ),
28 );
29 if (!isset($rows[$key])) return array();
30 if (isset($where['active']) && (int)$where['active'] !== (int)$rows[$key]['active']) return array();
31 return array($rows[$key]);
32 }
33}
34
36 public function enrichDefinition(array $definition, array $values = array()): array {
37 return $definition;
38 }
39}
40
42 public $db;
43 public $module;
44
45 public function __construct() {
46 $this->db = new WorkflowDefinitionDbStub();
47 $this->module = new WorkflowDefinitionModuleStub();
48 }
49
50 public function get_config($modul = 'dbx', $key = '', $default = null) {
51 return $key === 'default_workflow' ? 'active_flow' : $default;
52 }
53
54 public function get_system_obj($name) {
55 return $name === 'dbxDB' ? $this->db : null;
56 }
57
58 public function get_include_obj($name, $modul = '') {
59 return $name === 'dbxWorkflowModule' ? $this->module : null;
60 }
61}
62
63if (!function_exists('dbx')) {
64 function dbx() {
65 static $api;
67 return $api;
68 }
69}
70
72 private $values;
73
74 public function __construct(array $values) {
75 $this->values = $values;
76 }
77
78 public function get_post($name, $default = '', $rules = '') {
79 return $this->values[$name] ?? $default;
80 }
81
82 public function get_post_data($name, $default = '', $rules = '') {
83 return $this->values[$name] ?? $default;
84 }
85}
86
87function workflow_test_assert($condition, string $message): void {
88 if ($condition) return;
89 fwrite(STDERR, "FEHLER: " . $message . PHP_EOL);
90 exit(1);
91}
92
94 'key' => 'customer',
95 'label' => 'Kunde',
96 'kind' => 'input',
97 'mode' => 'single',
98 'required' => true,
99 'actions' => array('create', 'select'),
100 'preferred' => 'select',
101 'event' => 'Alter Ereignistext',
102 'resolver' => array(
103 'type' => 'select',
104 'label' => 'Kunde auswählen',
105 'adapter' => 'customer_v2',
106 ),
107 'source' => array('dd' => 'dbxContact|contact'),
108 'complete_label' => 'Kunde wurde im Fachformular gespeichert.',
109 'future_extension' => array('keep' => true),
110);
111
113 'workflow_key' => 'customer_flow',
114 'title' => 'Kundenablauf',
115 'result' => 'Kunde bearbeitet',
116 'description' => 'Ausgangsbeschreibung',
117 'schema_version' => 3,
118 'custom_root' => array('owner_module' => 'dbxContact'),
119 'bind_ref' => 'dbxContact|customer_flow',
120 'needs' => array($originalNeed),
121 'checks' => array(array(
122 'key' => 'customer',
123 'severity' => 'blocking',
124 )),
125 'finish' => array(
126 'label' => 'Kunde abschließen',
127 'strategy' => 'atomic',
128 'custom_finish' => array('keep' => true),
129 ),
130);
131
132$_POST = array(
133 'workflow_step_present' => array(0 => '1'),
134 'workflow_step_active' => array(0 => '1'),
135 'workflow_step_original' => array(0 => json_encode($originalNeed, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
136 'workflow_step_action_contract' => array(0 => '1'),
137 // Die Checkbox-Reihenfolge entspricht der UI, nicht der Definition. Der
138 // Merge muss die bestehende Reihenfolge create/select dennoch erhalten.
139 'workflow_step_actions' => array(0 => array('select', 'create')),
140 'workflow_step_action' => array(0 => 'select'),
141 'workflow_step_kind' => array(0 => 'input'),
142 'workflow_step_automation' => array(0 => 'manual'),
143 'workflow_step_mode' => array(0 => 'single'),
144 'workflow_step_required' => array(0 => '1'),
145 'workflow_step_label' => array(0 => 'Kunde auswählen'),
146 'workflow_step_key' => array(0 => 'primary_customer'),
147 'workflow_step_question' => array(0 => 'Welcher Kunde wird verwendet?'),
148 'workflow_step_validation' => array(0 => 'exactly_one'),
149 'workflow_step_missing_message' => array(0 => 'Kunde fehlt.'),
150 'workflow_step_resolver_label' => array(0 => 'Kundenauswahl öffnen'),
151 'workflow_step_hint' => array(0 => 'Vorhandenen Kunden auswählen oder neu anlegen.'),
152 'workflow_step_event' => array(0 => ''),
153 'workflow_step_depends_on' => array(0 => ''),
154 'workflow_step_depends_value' => array(0 => ''),
155 'workflow_step_options' => array(0 => ''),
156 'workflow_step_complete_label' => array(0 => 'Kunde wurde im Fachformular gespeichert.'),
157 'workflow_step_source' => array(0 => json_encode($originalNeed['source'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)),
158 'workflow_step_bind' => array(0 => ''),
159 'workflow_step_module_links' => array(0 => ''),
160 'workflow_finish_label' => 'Kunde abschließen',
161 'workflow_bind_ref' => '',
162);
163
165 'workflow_key' => 'customer_flow',
166 'title' => 'Kundenablauf aktualisiert',
167 'result_label' => 'Kunde vollständig bearbeitet',
168 'description' => 'Aktualisierte Beschreibung',
169));
170$admin = new \dbx\dbxWorkflow_admin\dbxWorkflowAdmin();
171$merge = new ReflectionMethod($admin, 'workflow_definition_from_post');
173$need = $definition['needs'][0];
174
175workflow_test_assert(($definition['schema_version'] ?? null) === 3, 'Unbekanntes Top-Level-Feld wurde entfernt.');
176workflow_test_assert(($definition['custom_root']['owner_module'] ?? '') === 'dbxContact', 'Top-Level-Erweiterung wurde verändert.');
177workflow_test_assert(($definition['finish']['strategy'] ?? '') === 'atomic', 'Finish-Erweiterung wurde entfernt.');
178workflow_test_assert(!isset($definition['bind_ref']), 'Ein sichtbar geleertes bind_ref wurde nicht entfernt.');
179workflow_test_assert(($definition['checks'][0]['key'] ?? '') === 'primary_customer', 'Check-Erweiterung wurde bei einer Key-Umbenennung nicht mitgeführt.');
180workflow_test_assert(($need['future_extension']['keep'] ?? false) === true, 'Unbekannte Need-Erweiterung wurde entfernt.');
181workflow_test_assert(($need['resolver']['adapter'] ?? '') === 'customer_v2', 'Resolver-Erweiterung wurde entfernt.');
182workflow_test_assert(($need['source']['dd'] ?? '') === 'dbxContact|contact', 'Datenquelle wurde nicht erhalten.');
183workflow_test_assert(($need['complete_label'] ?? '') === 'Kunde wurde im Fachformular gespeichert.', 'complete_label wurde nicht erhalten.');
184workflow_test_assert(($need['actions'] ?? array()) === array('create', 'select'), 'Mehrfachaktionen oder deren Reihenfolge wurden verändert.');
185workflow_test_assert(($need['preferred'] ?? '') === 'select', 'Standardaktion wurde nicht erhalten.');
186workflow_test_assert(!isset($need['event']), 'Ein sichtbar geleertes Ereignis wurde nicht entfernt.');
187
188// Wird eine entfernte Zeile im Designer als neuer Schritt wiederverwendet,
189// darf sie keine unbekannten Eigenschaften des früheren Needs erben.
190$_POST['workflow_step_original'][0] = '';
191$_POST['workflow_step_actions'][0] = array('form');
192$_POST['workflow_step_action'][0] = 'form';
193$_POST['workflow_step_label'][0] = 'Neue Notiz';
194$_POST['workflow_step_key'][0] = 'new_note';
195$_POST['workflow_step_complete_label'][0] = '';
196$_POST['workflow_step_source'][0] = '';
199workflow_test_assert(!isset($newNeed['future_extension']), 'Ein neuer Schritt hat Erweiterungen der wiederverwendeten alten Zeile geerbt.');
200workflow_test_assert(!isset($newNeed['source']), 'Ein neuer Schritt hat die Datenquelle der wiederverwendeten alten Zeile geerbt.');
201workflow_test_assert(($newNeed['actions'] ?? array()) === array('form'), 'Aktionen eines neuen Schritts wurden nicht sauber initialisiert.');
202
203// Falls das transportierte Original-JSON beschädigt wird, dient der stabile
204// Ursprungsindex als serverseitiger Fallback. Leere neue Zeilen besitzen ihn
205// absichtlich nicht.
206$_POST['workflow_step_original'][0] = '{ungueltig';
207$_POST['workflow_step_original_index'][0] = '0';
210workflow_test_assert(($fallbackNeed['future_extension']['keep'] ?? false) === true, 'Serverseitiger Round-Trip-Fallback hat Need-Erweiterungen verloren.');
211
212$engine = new \dbx\dbxWorkflow\dbxWorkflowEngine();
213$normalized = $engine->normalize_definition(array(
214 'workflow_key' => 'check_extensions',
215 'title' => 'Check-Erweiterungen',
216 'result' => 'Geprüft',
217 'needs' => array(array(
218 'key' => 'readiness',
219 'label' => 'Bereitschaft',
220 'actions' => array('form'),
221 'resolver' => array('type' => 'form', 'label' => 'Prüfung öffnen'),
222 )),
223 'checks' => array(array(
224 'key' => 'readiness',
225 'severity' => 'blocking',
226 'resolver' => array('telemetry_key' => 'ready-v2'),
227 )),
228));
229$check = $normalized['checks'][0];
230workflow_test_assert(($check['severity'] ?? '') === 'blocking', 'Check-Erweiterung wurde beim Ableiten entfernt.');
231workflow_test_assert(($check['resolver']['telemetry_key'] ?? '') === 'ready-v2', 'Resolver-Erweiterung des Checks wurde entfernt.');
232workflow_test_assert(($check['label'] ?? '') === 'Bereitschaft', 'Abgeleitetes Check-Feld wurde nicht aktualisiert.');
233
234$applicable = new ReflectionMethod($engine, 'need_is_applicable');
236 'depends_on' => 'channels',
237 'depends_value' => 'ebay',
238), array(
239 'channels' => array('shop', 'ebay'),
240)) === true, 'Ein Schritt hinter einer gültigen Mehrfachauswahl bleibt gesperrt.');
242 'depends_on' => 'optional_note',
243), array(
244 'optional_note' => array('skipped' => 1),
245)) === false, 'Ein übersprungener Abhängigkeitsschritt wurde als Wert behandelt.');
246
247workflow_test_assert(($engine->load_definition('active_flow')['workflow_key'] ?? '') === 'active_flow', 'Aktive Admin-Definition wurde nicht geladen.');
248workflow_test_assert($engine->load_definition('inactive_flow') === array(), 'Inaktive Definition kann einen neuen Lauf starten.');
249workflow_test_assert(($engine->load_definition('inactive_flow', false)['workflow_key'] ?? '') === 'inactive_flow', 'Inaktive Definition kann für eine bestehende Instanz nicht geladen werden.');
250workflow_test_assert($engine->load_definition('unknown_flow') === array(), 'Unbekannter Key wurde durch eine Fallback-Definition ersetzt.');
251
252echo "OK: Workflow-Definitionen bleiben round-trip-sicher." . PHP_EOL;
253
254?>
get_config($modul='dbx', $key='', $default=null)
select($dd, $where, $fields=' *', $order='', $dir='', $group='', $limit=0, $pos=0, $flag=0)
enrichDefinition(array $definition, array $values=array())
get_post($name, $default='', $rules='')
get_post_data($name, $default='', $rules='')
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
exit
Definition index.php:146
DBX schema administration.
workflow_test_assert($condition, string $message)