Files
espocrm/custom/scripts/workflow_manager.php

288 lines
9.8 KiB
PHP

<?php
/**
* Workflow Manager Script for EspoCRM
*
* Manages both BPM Flowcharts and Simple Workflows
*
* Usage: php workflow_manager.php <action> [options]
*
* Actions:
* list - List all workflows (BPM and Simple)
* read <id> - Read workflow details
* delete <id> - Delete a workflow
* import <file> - Import workflow from JSON file
* export <id> <file> - Export workflow to JSON file
*/
$config = require '/var/www/html/data/config-internal.php';
$dsn = 'mysql:host=' . $config['database']['host'] . ';dbname=' . $config['database']['dbname'];
$user = $config['database']['user'];
$pass = $config['database']['password'];
function connectDB() {
global $dsn, $user, $pass;
try {
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch (PDOException $e) {
die("DB Fehler: " . $e->getMessage() . "\n");
}
}
function listWorkflows($pdo) {
// Load categories
$categories = [];
$stmt = $pdo->query("SELECT id, name FROM workflow_category WHERE deleted = 0 ORDER BY `order`, name");
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $cat) {
$categories[$cat['id']] = $cat['name'];
}
echo "=== BPM Flowcharts ===\n";
$stmt = $pdo->query("SELECT id, name, target_type, is_active FROM bpmn_flowchart WHERE deleted = 0 ORDER BY name");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($results as $row) {
$active = $row['is_active'] ? '[AKTIV]' : '[INAKTIV]';
echo " {$active} ID: {$row['id']}, Name: {$row['name']}, Entity: {$row['target_type']}\n";
}
echo "\n=== Simple Workflows ===\n";
$stmt = $pdo->query("SELECT id, name, entity_type, type, is_active, category_id FROM workflow WHERE deleted = 0 ORDER BY category_id, name");
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
$currentCategory = null;
foreach ($results as $row) {
$catId = $row['category_id'];
if ($catId !== $currentCategory) {
$currentCategory = $catId;
$catName = $catId && isset($categories[$catId]) ? $categories[$catId] : 'Ohne Kategorie';
echo "\n [Kategorie: {$catName}]\n";
}
$active = $row['is_active'] ? '[AKTIV]' : '[INAKTIV]';
$name = $row['name'] ?: '(unnamed)';
echo " {$active} ID: {$row['id']}, Name: {$name}, Entity: {$row['entity_type']}, Type: {$row['type']}\n";
}
}
function readWorkflow($pdo, $id) {
// Try BPM first
$stmt = $pdo->prepare("SELECT * FROM bpmn_flowchart WHERE id = ? AND deleted = 0");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
echo "=== BPM Flowchart ===\n";
echo json_encode($row, JSON_PRETTY_PRINT) . "\n";
return;
}
// Try Simple Workflow
$stmt = $pdo->prepare("SELECT * FROM workflow WHERE id = ? AND deleted = 0");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
echo "=== Simple Workflow ===\n";
echo json_encode($row, JSON_PRETTY_PRINT) . "\n";
return;
}
echo "Workflow nicht gefunden.\n";
}
function deleteWorkflow($pdo, $id) {
echo "Bist du sicher, dass du den Workflow $id löschen möchtest? (ja/nein): ";
$input = trim(fgets(STDIN));
if (strtolower($input) !== 'ja') {
echo "Abgebrochen.\n";
return;
}
// Try BPM first
$stmt = $pdo->prepare("UPDATE bpmn_flowchart SET deleted = 1 WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
echo "BPM Flowchart gelöscht.\n";
return;
}
// Try Simple Workflow
$stmt = $pdo->prepare("UPDATE workflow SET deleted = 1 WHERE id = ?");
$stmt->execute([$id]);
if ($stmt->rowCount() > 0) {
echo "Simple Workflow gelöscht.\n";
return;
}
echo "Workflow nicht gefunden.\n";
}
function importWorkflow($pdo, $file) {
if (!file_exists($file)) {
die("Datei nicht gefunden: $file\n");
}
$json = file_get_contents($file);
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
die("Ungültiges JSON in Datei.\n");
}
$type = $data['type'] ?? 'unknown';
$now = date('Y-m-d H:i:s');
if ($type === 'simple') {
// Import Simple Workflow
$id = substr(bin2hex(random_bytes(12)), 0, 17);
// Resolve category by name if provided
$categoryId = null;
if (isset($data['category'])) {
$stmt = $pdo->prepare("SELECT id FROM workflow_category WHERE name = ? AND deleted = 0");
$stmt->execute([$data['category']]);
$cat = $stmt->fetch(PDO::FETCH_ASSOC);
$categoryId = $cat ? $cat['id'] : null;
}
$stmt = $pdo->prepare("
INSERT INTO workflow (
id, name, entity_type, type, is_active, is_internal,
description, conditions_all, conditions_any, conditions_formula,
actions, portal_only, scheduling, scheduling_apply_timezone,
process_order, category_id, created_at, modified_at, deleted
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)
");
$stmt->execute([
$id,
$data['name'],
$data['entity_type'],
$data['trigger_type'],
$data['is_active'] ?? 1,
0,
$data['description'] ?? null,
json_encode($data['conditions_all'] ?? []),
json_encode($data['conditions_any'] ?? []),
$data['conditions_formula'] ?? null,
json_encode($data['actions'] ?? []),
0,
'0 0 * * *',
1,
10,
$categoryId,
$now,
$now
]);
$catInfo = $categoryId ? " (Kategorie: {$data['category']})" : "";
echo "✓ Simple Workflow importiert: $id - {$data['name']}{$catInfo}\n";
} elseif ($type === 'bpm') {
// Import BPM Flowchart
$id = substr(bin2hex(random_bytes(12)), 0, 17);
$stmt = $pdo->prepare("
INSERT INTO bpmn_flowchart (
id, name, target_type, is_active,
created_at, modified_at, data, elements_data_hash,
deleted, has_none_start_event, event_start_id_list, event_start_all_id_list
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, 0, '[]', ?)
");
$stmt->execute([
$id,
$data['name'],
$data['target_type'],
$data['is_active'] ?? 1,
$now,
$now,
json_encode($data['data']),
json_encode($data['elements_data_hash']),
json_encode($data['event_start_all_id_list'] ?? [])
]);
echo "✓ BPM Flowchart importiert: $id - {$data['name']}\n";
} else {
die("Unbekannter Workflow-Typ: $type\n");
}
}
function exportWorkflow($pdo, $id, $file) {
// Try BPM first
$stmt = $pdo->prepare("SELECT * FROM bpmn_flowchart WHERE id = ? AND deleted = 0");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
$export = [
'type' => 'bpm',
'name' => $row['name'],
'target_type' => $row['target_type'],
'is_active' => (bool)$row['is_active'],
'description' => $row['description'],
'data' => json_decode($row['data'], true),
'elements_data_hash' => json_decode($row['elements_data_hash'], true),
'event_start_all_id_list' => json_decode($row['event_start_all_id_list'], true)
];
file_put_contents($file, json_encode($export, JSON_PRETTY_PRINT));
echo "✓ BPM Flowchart exportiert nach: $file\n";
return;
}
// Try Simple Workflow
$stmt = $pdo->prepare("SELECT w.*, wc.name as category_name FROM workflow w LEFT JOIN workflow_category wc ON w.category_id = wc.id WHERE w.id = ? AND w.deleted = 0");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row) {
$export = [
'type' => 'simple',
'name' => $row['name'],
'entity_type' => $row['entity_type'],
'trigger_type' => $row['type'],
'is_active' => (bool)$row['is_active'],
'description' => $row['description'],
'conditions_all' => json_decode($row['conditions_all'], true),
'conditions_any' => json_decode($row['conditions_any'], true),
'conditions_formula' => $row['conditions_formula'],
'actions' => json_decode($row['actions'], true)
];
// Add category name if exists
if ($row['category_name']) {
$export['category'] = $row['category_name'];
}
file_put_contents($file, json_encode($export, JSON_PRETTY_PRINT));
echo "✓ Simple Workflow exportiert nach: $file\n";
return;
}
echo "Workflow nicht gefunden.\n";
}
$pdo = connectDB();
$action = $argv[1] ?? 'list';
switch ($action) {
case 'list':
listWorkflows($pdo);
break;
case 'read':
if (!isset($argv[2])) die("Usage: read <id>\n");
readWorkflow($pdo, $argv[2]);
break;
case 'delete':
if (!isset($argv[2])) die("Usage: delete <id>\n");
deleteWorkflow($pdo, $argv[2]);
break;
case 'import':
if (!isset($argv[2])) die("Usage: import <file>\n");
importWorkflow($pdo, $argv[2]);
break;
case 'export':
if (!isset($argv[2]) || !isset($argv[3])) die("Usage: export <id> <file>\n");
exportWorkflow($pdo, $argv[2], $argv[3]);
break;
default:
echo "Unbekannte Aktion.\n";
echo "Verfügbare Aktionen: list, read, delete, import, export\n";
}
?>