import re with open('WorkflowEngine.php', 'r') as f: content = f.read() new_method = """ public function getOrCreateInstanceBySubject(string $subjectType, int $subjectId, string $processCode, int $userId, string $mode='resume_or_create'): array { if (!in_array($subjectType, ['person', 'meeting', 'bni_group', 'organization'])) { throw new InvalidArgumentException("Invalid subjectType."); } if ($subjectId <= 0) { throw new InvalidArgumentException("subjectId must be > 0."); } if (empty($processCode)) { throw new InvalidArgumentException("processCode cannot be empty."); } $inTransaction = $this->pdo->inTransaction(); if (!$inTransaction) { $this->pdo->beginTransaction(); } try { $sql = "SELECT * FROM process_definitions WHERE code = ? AND is_active = 1 AND subject_scope = ? ORDER BY version DESC, id DESC LIMIT 1"; $stmt = $this->pdo->prepare($sql); $stmt->execute([$processCode, $subjectType]); $definition = $stmt->fetch(PDO::FETCH_ASSOC); if (!$definition) { $stmt = $this->pdo->prepare("SELECT * FROM process_definitions WHERE code = ? AND is_active = 1 ORDER BY version DESC, id DESC LIMIT 1"); $stmt->execute([$processCode]); $definition = $stmt->fetch(PDO::FETCH_ASSOC); if (!$definition) { throw new WorkflowNotFoundException("No active process definition found for code '$processCode'"); } } $defId = $definition['id']; $defJson = json_decode($definition['definition_json'], true); $startNodeId = $defJson['start_node_id'] ?? null; if (!$startNodeId) { throw new Exception("Process definition missing start_node_id"); } $instance = null; if ($mode === 'resume_or_create') { $stmt = $this->pdo->prepare( "SELECT pi.* FROM process_instances pi\n JOIN process_definitions pd ON pi.process_definition_id = pd.id\n WHERE pi.subject_type = ? AND pi.subject_id = ? AND pd.code = ?\n ORDER BY pi.id DESC LIMIT 1" ); $stmt->execute([$subjectType, $subjectId, $processCode]); $instance = $stmt->fetch(PDO::FETCH_ASSOC); } if (!$instance) { $stmt = $this->pdo->prepare( "SELECT MAX(pi.run_number) \n FROM process_instances pi\n JOIN process_definitions pd ON pi.process_definition_id = pd.id\n WHERE pi.subject_type = ? AND pi.subject_id = ? AND pd.code = ?" ); $stmt->execute([$subjectType, $subjectId, $processCode]); $maxRun = (int)$stmt->fetchColumn(); $runNumber = $maxRun + 1; $personIdVal = ($subjectType === 'person') ? $subjectId : null; $status = $defJson['nodes'][$startNodeId]['ui_hints']['status'] ?? 'in_progress'; $reason = $defJson['nodes'][$startNodeId]['ui_hints']['reason'] ?? ''; $nextStep = $defJson['nodes'][$startNodeId]['ui_hints']['next_step'] ?? ''; $stmt = $this->pdo->prepare( "INSERT INTO process_instances \n (subject_type, subject_id, person_id, process_definition_id, current_node_id, current_status, current_reason, suggested_next_step, run_number, last_activity_at, data_json)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), '{}')" ); $stmt->execute([ $subjectType, $subjectId, $personIdVal, $defId, $startNodeId, $status, $reason, $nextStep, $runNumber ]); $instanceId = $this->pdo->lastInsertId(); $this->addEvent($instanceId, 'system', 'Process started.', $startNodeId, [], $userId); $stmt = $this->pdo->prepare("SELECT * FROM process_instances WHERE id = ?"); $stmt->execute([$instanceId]); $instance = $stmt->fetch(PDO::FETCH_ASSOC); } if (!$inTransaction) { $this->pdo->commit(); } return [ 'instance_id' => $instance['id'], 'process_definition_id' => $instance['process_definition_id'], 'process_code' => $processCode, 'subject_type' => $instance['subject_type'], 'subject_id' => $instance['subject_id'], 'person_id' => $instance['person_id'], 'current_node_id' => $instance['current_node_id'], 'current_status' => $instance['current_status'], 'last_activity_at' => $instance['last_activity_at'], 'data_json' => $instance['data_json'] ]; } catch (Exception $e) { if (!$inTransaction) { $this->pdo->rollBack(); } throw $e; } } " if "function getOrCreateInstanceBySubject" not in content: last_brace_idx = content.rfind('}') content = content[:last_brace_idx] + new_method + "\n}\n" with open('WorkflowEngine.php', 'w') as f: f.write(content) print("Method added.") else: print("Method already exists.")