ContentPipelineController.php
- Pfad:
src/Controller/ContentPipelineController.php - Namespace: Controller
- Zeilen: 381 | Größe: 10,542 Bytes
- Geändert: 2025-12-27 12:20:38 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 78
- Dependencies: 70 (25%)
- LOC: 59 (20%)
- Methods: 70 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 15
- extends Framework\Controller
- constructor Domain\Repository\PipelineRepositoryInterface
- constructor Application\PipelineStepService
- constructor UseCases\Pipeline\RunPipelineUseCase
- constructor UseCases\Pipeline\PipelineRunStatusUseCase
- constructor UseCases\Pipeline\UpdatePipelineConfigUseCase
- constructor Infrastructure\AI\ModelRegistry
- use Application\PipelineStepService
- use Domain\Repository\PipelineRepositoryInterface
- use Framework\Controller
- use Infrastructure\AI\ModelRegistry
- use Infrastructure\Config\PipelineStepConfig
- use UseCases\Pipeline\PipelineRunStatusUseCase
- use UseCases\Pipeline\RunPipelineUseCase
- use UseCases\Pipeline\UpdatePipelineConfigUseCase
Klassen 1
-
ContentPipelineControllerclass Zeile 18
Funktionen 18
-
__construct()public Zeile 20 -
index()public Zeile 33 -
import()public Zeile 45 -
pipelineNew()public Zeile 66 -
show()public Zeile 78 -
edit()public Zeile 100 -
store()public Zeile 118 -
update()public Zeile 146 -
run()public Zeile 178 -
status()public Zeile 194 -
runStatus()public Zeile 210 -
runStatusPoll()public Zeile 234 -
runCancel()public Zeile 250 -
toggleStep()public Zeile 286 -
updateStepModel()public Zeile 300 -
updateStepCollection()public Zeile 323 -
updateConfig()public Zeile 346 -
delete()public Zeile 365
Versionen 33
-
v33
2025-12-27 12:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v32
2025-12-27 12:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v31
2025-12-27 12:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v30
2025-12-27 12:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v29
2025-12-25 13:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v28
2025-12-25 13:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v27
2025-12-25 12:52 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v26
2025-12-23 07:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v25
2025-12-23 07:39 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v24
2025-12-23 04:39 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v23
2025-12-23 04:31 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v22
2025-12-23 04:31 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v21
2025-12-23 04:30 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v20
2025-12-23 04:30 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v19
2025-12-23 04:30 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v18
2025-12-23 04:30 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v17
2025-12-23 04:29 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v16
2025-12-23 04:24 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v15
2025-12-23 04:19 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v14
2025-12-23 04:11 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v13
2025-12-23 04:10 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v12
2025-12-22 19:03 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Write-Operation -
v11
2025-12-22 15:21 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v10
2025-12-22 15:21 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v9
2025-12-22 15:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v8
2025-12-22 15:19 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v7
2025-12-22 10:14 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v6
2025-12-22 10:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v5
2025-12-22 10:01 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v4
2025-12-22 10:01 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-22 09:55 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-22 09:42 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-22 09:35 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
Code
<?php
declare(strict_types=1);
namespace Controller;
// @responsibility: HTTP-Endpunkte für Content-Pipeline-Verwaltung
use Application\PipelineStepService;
use Domain\Repository\PipelineRepositoryInterface;
use Framework\Controller;
use Infrastructure\AI\ModelRegistry;
use Infrastructure\Config\PipelineStepConfig;
use UseCases\Pipeline\PipelineRunStatusUseCase;
use UseCases\Pipeline\RunPipelineUseCase;
use UseCases\Pipeline\UpdatePipelineConfigUseCase;
class ContentPipelineController extends Controller
{
public function __construct(
private PipelineRepositoryInterface $repository,
private PipelineStepService $stepService,
private RunPipelineUseCase $runUseCase,
private PipelineRunStatusUseCase $statusUseCase,
private UpdatePipelineConfigUseCase $configUseCase,
private ModelRegistry $modelRegistry
) {
}
/**
* GET /content-pipeline
*/
public function index(): void
{
$this->view('content-pipeline.index', [
'title' => 'Content Pipeline',
'pipelines' => $this->repository->findAll(),
'stats' => $this->repository->getStatistics(),
]);
}
/**
* GET /content-pipeline/import
*/
public function import(): void
{
$pipeline = $this->repository->findDefault();
if ($pipeline === null) {
$pipelines = $this->repository->findAll(1);
$pipeline = $pipelines[0] ?? null;
}
$this->view('content-pipeline.import', [
'title' => 'Import Pipeline',
'pipeline' => $pipeline,
'latestRun' => $pipeline !== null
? $this->repository->findLatestRun((int) $pipeline['id'])
: null,
]);
}
/**
* GET /content-pipeline/new
*/
public function pipelineNew(): void
{
$this->view('content-pipeline.form', [
'title' => 'Neue Pipeline',
'pipeline' => null,
'stepTypes' => PipelineStepConfig::getStepTypes(),
]);
}
/**
* GET /content-pipeline/{id}
*/
public function show(string $id): void
{
$pipeline = $this->repository->findById((int) $id);
if ($pipeline === null) {
$this->notFound('Pipeline nicht gefunden');
}
$this->view('content-pipeline.show', [
'title' => 'Pipeline: ' . $pipeline['name'],
'pipeline' => $pipeline,
'runs' => $this->repository->findRuns((int) $id, 10),
'stepTypes' => PipelineStepConfig::getStepTypes(),
'models' => $this->modelRegistry->getChatModels(),
'defaultModel' => $this->modelRegistry->getDefaultChatModel(),
'collections' => PipelineStepConfig::getCollections(),
]);
}
/**
* GET /content-pipeline/{id}/edit
*/
public function edit(string $id): void
{
$pipeline = $this->repository->findById((int) $id);
if ($pipeline === null) {
$this->notFound('Pipeline nicht gefunden');
}
$this->view('content-pipeline.form', [
'title' => 'Pipeline bearbeiten: ' . $pipeline['name'],
'pipeline' => $pipeline,
'stepTypes' => PipelineStepConfig::getStepTypes(),
]);
}
/**
* POST /content-pipeline
*/
public function store(): void
{
$this->requireCsrf();
$name = trim($_POST['name'] ?? '');
if ($name === '') {
$_SESSION['error'] = 'Name ist erforderlich.';
$this->redirect('/content-pipeline/new');
}
$pipelineId = $this->repository->create([
'name' => $name,
'description' => trim($_POST['description'] ?? ''),
'source_path' => trim($_POST['source_path'] ?? '/var/www/nextcloud/data/root/files/Documents'),
'extensions' => PipelineStepConfig::parseExtensions($_POST['extensions'] ?? ''),
'is_default' => isset($_POST['is_default']) ? 1 : 0,
]);
$this->stepService->createDefaultSteps($pipelineId);
$_SESSION['success'] = 'Pipeline erfolgreich erstellt.';
$this->redirect('/content-pipeline/' . $pipelineId);
}
/**
* POST /content-pipeline/{id}
*/
public function update(string $id): void
{
$this->requireCsrf();
$pipeline = $this->repository->findById((int) $id);
if ($pipeline === null) {
$this->notFound('Pipeline nicht gefunden');
}
$name = trim($_POST['name'] ?? '');
if ($name === '') {
$_SESSION['error'] = 'Name ist erforderlich.';
$this->redirect('/content-pipeline/' . $id . '/edit');
}
$this->repository->update((int) $id, [
'name' => $name,
'description' => trim($_POST['description'] ?? ''),
'source_path' => trim($_POST['source_path'] ?? ''),
'extensions' => PipelineStepConfig::parseExtensions($_POST['extensions'] ?? ''),
'is_default' => isset($_POST['is_default']) ? 1 : 0,
]);
$_SESSION['success'] = 'Pipeline aktualisiert.';
$this->redirect('/content-pipeline/' . $id);
}
/**
* POST /content-pipeline/{id}/run
*/
public function run(string $id): void
{
$this->requireCsrf();
$result = $this->runUseCase->start((int) $id);
if (!$result['success']) {
$this->notFound($result['error'] ?? 'Pipeline nicht gefunden');
}
$this->redirect('/content-pipeline/' . $id . '/run/' . $result['run_id'] . '/status');
}
/**
* GET /content-pipeline/{id}/status (AJAX)
*/
public function status(string $id): void
{
$result = $this->runUseCase->getStatus((int) $id);
if (!$result['success']) {
$this->json(['error' => $result['error']], 404);
return;
}
$this->json($result);
}
/**
* GET /content-pipeline/{id}/run/{runId}/status
*/
public function runStatus(string $id, string $runId): void
{
$pipeline = $this->repository->findById((int) $id);
if ($pipeline === null) {
$this->notFound('Pipeline nicht gefunden');
}
$run = $this->repository->findRunById((int) $runId);
if ($run === null || (int) $run['pipeline_id'] !== (int) $id) {
$this->notFound('Run nicht gefunden');
}
$this->view('content-pipeline.run-status', [
'title' => 'Pipeline Status: ' . $pipeline['name'],
'pipeline' => $pipeline,
'run' => $run,
]);
}
/**
* GET /content-pipeline/{id}/run/{runId}/poll (AJAX/HTMX)
*/
public function runStatusPoll(string $id, string $runId): void
{
$result = $this->statusUseCase->execute((int) $id, (int) $runId);
if (!$result['success']) {
$this->json(['error' => $result['error']], 404);
return;
}
$this->json($result['data']);
}
/**
* POST /content-pipeline/{id}/run/{runId}/cancel
*/
public function runCancel(string $id, string $runId): void
{
$this->requireCsrf();
$result = $this->runUseCase->cancel((int) $id, (int) $runId);
if (!$result['success']) {
if ($result['error'] === 'Run nicht gefunden') {
$this->notFound($result['error']);
}
if ($this->isHtmxRequest()) {
$this->htmxError($result['error']);
return;
}
$_SESSION['error'] = $result['error'];
} else {
// HTMX: Return disabled button
if ($this->isHtmxRequest()) {
$this->partial('content-pipeline.partials.cancel-button', [
'disabled' => true,
'label' => 'Abgebrochen',
]);
return;
}
$_SESSION['success'] = 'Pipeline-Run wurde abgebrochen.';
}
$this->redirect('/content-pipeline/' . $id . '/run/' . $runId . '/status');
}
/**
* POST /content-pipeline/{id}/steps/{stepId}/toggle
*/
public function toggleStep(string $id, string $stepId): void
{
$this->requireCsrf();
if (!$this->stepService->toggleStep((int) $id, (int) $stepId)) {
$this->notFound('Pipeline oder Schritt nicht gefunden');
}
$this->redirect('/content-pipeline/' . $id);
}
/**
* POST /content-pipeline/{id}/steps/{stepId}/model (HTMX)
*/
public function updateStepModel(string $id, string $stepId): void
{
$this->requireCsrf();
$result = $this->stepService->updateModel(
(int) $id,
(int) $stepId,
$_POST['model'] ?? ''
);
if (!$result['success']) {
$this->htmxError($result['error']);
return;
}
// hx-swap="none" erwartet nur Status 200
$this->text('OK');
}
/**
* POST /content-pipeline/{id}/steps/{stepId}/collection (HTMX)
*/
public function updateStepCollection(string $id, string $stepId): void
{
$this->requireCsrf();
$result = $this->stepService->updateCollection(
(int) $id,
(int) $stepId,
$_POST['collection'] ?? ''
);
if (!$result['success']) {
$this->htmxError($result['error']);
return;
}
// hx-swap="none" erwartet nur Status 200
$this->text('OK');
}
/**
* POST /content-pipeline/{id}/config (HTMX)
*/
public function updateConfig(string $id): void
{
$this->requireCsrf();
$result = $this->configUseCase->execute((int) $id, $_POST);
if (!$result['success']) {
$this->htmxError($result['error']);
return;
}
// hx-swap="none" erwartet nur Status 200
$this->text('OK');
}
/**
* POST /content-pipeline/{id}/delete
*/
public function delete(string $id): void
{
$this->requireCsrf();
$pipeline = $this->repository->findById((int) $id);
if ($pipeline === null) {
$this->notFound('Pipeline nicht gefunden');
}
$this->repository->delete((int) $id);
$_SESSION['success'] = 'Pipeline geloescht.';
$this->redirect('/content-pipeline');
}
}