From cca62198706921bb5d7b57cd23585cc10079a4ff Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 1 Mar 2026 20:13:59 +0000 Subject: [PATCH] =?UTF-8?q?Poprawki=20b=C5=82=C4=99d=C3=B3w?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WorkflowEngine.php | 35 ++++++++++++++----------- _save_process_definition.php | 51 +++++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/WorkflowEngine.php b/WorkflowEngine.php index c5185f5..718aa11 100644 --- a/WorkflowEngine.php +++ b/WorkflowEngine.php @@ -181,7 +181,8 @@ class WorkflowEngine { } public function startProcess(string $processCode, int $personId, int $userId): int { - $this->pdo->beginTransaction(); + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } try { // 1. Find active process definition by code. $stmt_def = $this->pdo->prepare("SELECT * FROM process_definitions WHERE code = ? AND is_active = 1"); @@ -224,10 +225,10 @@ class WorkflowEngine { // 3. Create a system event for process start. $this->addEvent($instanceId, 'system', 'Process started.', $startNodeId, [], $userId); - $this->pdo->commit(); + if (!$inTransaction) { $this->pdo->commit(); } return (int)$instanceId; } catch (Exception $e) { - $this->pdo->rollBack(); + if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } @@ -257,7 +258,8 @@ class WorkflowEngine { } public function applyTransition(int $instanceId, string $transitionId, array $inputPayload, int $userId): array { - $this->pdo->beginTransaction(); + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } try { $state = $this->getProcessState($instanceId); if (!$state) { @@ -298,7 +300,7 @@ class WorkflowEngine { } } - $this->pdo->commit(); + if (!$inTransaction) { $this->pdo->commit(); } // Refetch the final state of the instance to return the correct status $finalState = $this->getProcessState($instanceId)['instance']; @@ -314,7 +316,7 @@ class WorkflowEngine { ]; } catch (Exception $e) { - $this->pdo->rollBack(); + if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } @@ -384,7 +386,8 @@ class WorkflowEngine { } public function applyManualStatus(int $instanceId, string $status, string $reasonOrNote, int $userId): bool { - $this->pdo->beginTransaction(); + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } try { $state = $this->getProcessState($instanceId); if (!$state) { @@ -404,10 +407,10 @@ class WorkflowEngine { $this->addEvent($instanceId, 'manual_status_change', $message, $currentNodeId, ['status' => $status, 'reason' => $reasonOrNote], $userId); - $this->pdo->commit(); + if (!$inTransaction) { $this->pdo->commit(); } return true; } catch (Exception $e) { - $this->pdo->rollBack(); + if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } @@ -442,7 +445,8 @@ class WorkflowEngine { public function updateChecklistStatus(int $instanceId, string $taskCode, bool $isChecked, int $userId): array { - $this->pdo->beginTransaction(); + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } try { // Get current data_json $stmt = $this->pdo->prepare("SELECT data_json, process_definition_id FROM process_instances WHERE id = ?"); @@ -475,7 +479,7 @@ class WorkflowEngine { $totalTasks = count($definition['tasks'] ?? []); $completedTasks = count(array_filter($data)); - $this->pdo->commit(); + if (!$inTransaction) { $this->pdo->commit(); } return [ 'success' => true, @@ -487,7 +491,7 @@ class WorkflowEngine { ]; } catch (Exception $e) { - $this->pdo->rollBack(); + if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } @@ -754,7 +758,8 @@ class WorkflowEngine { } public function deleteInstance(int $instanceId): void { - $this->pdo->beginTransaction(); + $inTransaction = $this->pdo->inTransaction(); + if (!$inTransaction) { $this->pdo->beginTransaction(); } try { // Delete events $stmt_events = $this->pdo->prepare("DELETE FROM process_events WHERE process_instance_id = ?"); @@ -764,9 +769,9 @@ class WorkflowEngine { $stmt_instance = $this->pdo->prepare("DELETE FROM process_instances WHERE id = ?"); $stmt_instance->execute([$instanceId]); - $this->pdo->commit(); + if (!$inTransaction) { $this->pdo->commit(); } } catch (Exception $e) { - $this->pdo->rollBack(); + if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } diff --git a/_save_process_definition.php b/_save_process_definition.php index 094a75c..0693dd5 100644 --- a/_save_process_definition.php +++ b/_save_process_definition.php @@ -8,7 +8,8 @@ session_start(); function validate_definition_json($json) { if (empty($json)) { - return; // No validation for empty json + http_response_code(422); + throw new WorkflowRuleFailedException('Process definition JSON cannot be empty.'); } $data = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { @@ -48,6 +49,43 @@ function validate_definition_json($json) { } } } + + if (!isset($data['start_node_id'])) { + http_response_code(422); + throw new WorkflowRuleFailedException('Process definition is missing start_node_id.'); + } + + $start_node_id = $data['start_node_id']; + + if (!isset($data['nodes']) || !is_array($data['nodes'])) { + http_response_code(422); + throw new WorkflowRuleFailedException('Process definition is missing a valid "nodes" object.'); + } + + if (!isset($data['nodes'][$start_node_id])) { + http_response_code(422); + throw new WorkflowRuleFailedException("start_node_id '{$start_node_id}' does not exist in nodes."); + } + + if (!isset($data['transitions']) || !is_array($data['transitions'])) { + http_response_code(422); + throw new WorkflowRuleFailedException('Process definition is missing a valid "transitions" array.'); + } + + foreach ($data['transitions'] as $index => $transition) { + if (!isset($transition['from']) || !isset($transition['to'])) { + http_response_code(422); + throw new WorkflowRuleFailedException("Transition at index {$index} is missing 'from' or 'to' property."); + } + if (!isset($data['nodes'][$transition['from']])) { + http_response_code(422); + throw new WorkflowRuleFailedException("Transition from an unknown node: '{$transition['from']}'."); + } + if (!isset($data['nodes'][$transition['to']])) { + http_response_code(422); + throw new WorkflowRuleFailedException("Transition to an unknown node: '{$transition['to']}'."); + } + } } try { @@ -66,17 +104,18 @@ try { } $pdo = db(); + $start_node = json_decode($definition_json, true)['start_node_id'] ?? null; if (empty($processId)) { // Create new process - $sql = 'INSERT INTO process_definitions (name, code, definition_json, is_active) VALUES (?, ?, ?, 1)'; - $params = [$name, $code, $definition_json]; + $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active) VALUES (?, ?, ?, ?, 1)'; + $params = [$name, $code, $definition_json, $start_node]; $message = 'Process created successfully.'; } else { // Update existing process $is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : 0; - $sql = 'UPDATE process_definitions SET name = ?, definition_json = ?, is_active = ? WHERE id = ?'; - $params = [$name, $definition_json, $is_active, $processId]; + $sql = 'UPDATE process_definitions SET name = ?, definition_json = ?, start_node_id = ?, is_active = ? WHERE id = ?'; + $params = [$name, $definition_json, $start_node, $is_active, $processId]; $message = 'Process updated successfully.'; } @@ -94,4 +133,4 @@ try { } catch (WorkflowRuleFailedException $e) { header('Content-Type: application/json'); echo json_encode(['error' => $e->getMessage()]); -} \ No newline at end of file +}