$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 { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $processId = $_POST['process_id'] ?? null; $name = $_POST['name'] ?? ''; $definition_json = $_POST['definition_json'] ?? ''; validate_definition_json($definition_json); // Generate a simple code from the name $code = strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $name))); if (empty($name)) { throw new WorkflowRuleFailedException('Process name is required.'); } $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, start_node_id, is_active, version, is_latest) VALUES (?, ?, ?, ?, 1, 1, 1)'; $params = [$name, $code, $definition_json, $start_node]; $message = 'Process created successfully.'; $stmt = $pdo->prepare($sql); $stmt->execute($params); } else { // "Update" existing process by creating a new version $stmt_old = $pdo->prepare('SELECT code, version, sort_order, is_active FROM process_definitions WHERE id = ?'); $stmt_old->execute([$processId]); $old = $stmt_old->fetch(); if ($old) { $is_active = isset($_POST['is_active']) ? (int)$_POST['is_active'] : $old['is_active']; $new_version = $old['version'] + 1; $db_code = $old['code']; // Mark all previous versions as not latest $stmt_update = $pdo->prepare('UPDATE process_definitions SET is_latest = 0 WHERE code = ?'); $stmt_update->execute([$db_code]); // Insert new version $sql = 'INSERT INTO process_definitions (name, code, definition_json, start_node_id, is_active, version, supersedes_definition_id, is_latest, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?)'; $params = [$name, $db_code, $definition_json, $start_node, $is_active, $new_version, $processId, $old['sort_order']]; $stmt = $pdo->prepare($sql); $stmt->execute($params); $message = 'Process updated successfully (new version created).'; } else { throw new WorkflowRuleFailedException('Process not found.'); } } if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false) { header('Content-Type: application/json'); echo json_encode(['message' => $message]); } else { $_SESSION['success_message'] = $message; header('Location: process_definitions.php'); exit(); } } } catch (WorkflowRuleFailedException $e) { header('Content-Type: application/json'); echo json_encode(['error' => $e->getMessage()]); }