docs: consolidate documentation into organized structure

- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
This commit is contained in:
2025-10-05 11:05:04 +02:00
parent 887847dde6
commit 5050c7d73a
36686 changed files with 196456 additions and 12398919 deletions

View File

@@ -0,0 +1,241 @@
<?php
declare(strict_types=1);
namespace App\Framework\Console;
/**
* Executes command workflows
*/
final readonly class WorkflowExecutor
{
public function __construct(
private CommandRegistry $commandRegistry,
private CommandGroupRegistry $groupRegistry,
private ConsoleOutputInterface $output
) {}
/**
* Execute workflow by name
*/
public function executeWorkflow(string $workflowName, array $context = []): WorkflowResult
{
$workflow = $this->groupRegistry->getWorkflow($workflowName);
if ($workflow === null) {
return WorkflowResult::error("Workflow '{$workflowName}' not found");
}
return $this->executeWorkflowSteps($workflow, $context);
}
/**
* Execute workflow steps
*/
public function executeWorkflowSteps(array $workflow, array $context = []): WorkflowResult
{
$this->output->writeLine("🔄 Starting workflow: {$workflow['name']}", ConsoleColor::BRIGHT_CYAN);
if (!empty($workflow['description'])) {
$this->output->writeLine($workflow['description'], ConsoleColor::GRAY);
}
$this->output->newLine();
// Check prerequisites
if (!$this->checkPrerequisites($workflow['prerequisites'], $context)) {
return WorkflowResult::error('Prerequisites not met');
}
$results = [];
$stepNumber = 1;
$totalSteps = count($workflow['steps']);
foreach ($workflow['steps'] as $step) {
$workflowStep = $step instanceof WorkflowStep ? $step : WorkflowStep::fromArray($step);
$this->output->writeLine(
"Step {$stepNumber}/{$totalSteps}: {$workflowStep->getDescription() ?: $workflowStep->getCommand()}",
ConsoleColor::BRIGHT_WHITE
);
// Check if step should be executed
if (!$workflowStep->shouldExecute($context)) {
$this->output->writeLine(' ⏭️ Skipped (condition not met)', ConsoleColor::YELLOW);
$stepNumber++;
continue;
}
$stepResult = $this->executeStep($workflowStep, $context);
$results[] = $stepResult;
if ($stepResult->isSuccess()) {
$this->output->writeLine(' ✅ Success', ConsoleColor::GREEN);
} else {
$message = " ❌ Failed: {$stepResult->getError()}";
if ($workflowStep->isOptional()) {
$this->output->writeLine("{$message} (optional step)", ConsoleColor::YELLOW);
} else {
$this->output->writeLine($message, ConsoleColor::RED);
if ($workflow['stopOnError']) {
$this->output->newLine();
$this->output->writeLine('🛑 Workflow stopped due to error', ConsoleColor::RED);
// Execute rollback if configured
if (!empty($workflow['rollbackSteps'])) {
$this->executeRollback($workflow['rollbackSteps'], $context);
}
return WorkflowResult::error("Step failed: {$stepResult->getError()}");
}
}
}
$stepNumber++;
}
$this->output->newLine();
$this->output->writeLine('🎉 Workflow completed successfully!', ConsoleColor::BRIGHT_GREEN);
return WorkflowResult::success($results);
}
/**
* Execute a single workflow step
*/
private function executeStep(WorkflowStep $step, array $context): StepResult
{
$retryCount = 0;
$maxRetries = $step->getRetryCount();
do {
try {
// Merge step environment with context
$stepContext = array_merge($context, $step->getEnvironment());
// Build command arguments
$args = ['console', $step->getCommand()];
foreach ($step->getParameters() as $param) {
// Simple parameter substitution
$args[] = $this->substituteVariables($param, $stepContext);
}
$exitCode = $this->commandRegistry->execute($args);
if ($exitCode->value === 0) {
return StepResult::success($step->getCommand());
} else {
$error = "Command exited with code {$exitCode->value}";
if ($retryCount < $maxRetries) {
$retryCount++;
$this->output->writeLine(
" ⏳ Retrying ({$retryCount}/{$maxRetries})...",
ConsoleColor::YELLOW
);
continue;
}
return StepResult::error($error);
}
} catch (\Exception $e) {
$error = "Exception: {$e->getMessage()}";
if ($retryCount < $maxRetries) {
$retryCount++;
$this->output->writeLine(
" ⏳ Retrying ({$retryCount}/{$maxRetries})...",
ConsoleColor::YELLOW
);
continue;
}
return StepResult::error($error);
}
} while ($retryCount <= $maxRetries);
return StepResult::error('Max retries exceeded');
}
/**
* Execute rollback steps
*/
private function executeRollback(array $rollbackSteps, array $context): void
{
$this->output->writeLine('🔄 Executing rollback...', ConsoleColor::YELLOW);
foreach ($rollbackSteps as $step) {
$workflowStep = $step instanceof WorkflowStep ? $step : WorkflowStep::fromArray($step);
$this->output->writeLine(" Rolling back: {$workflowStep->getCommand()}", ConsoleColor::GRAY);
$result = $this->executeStep($workflowStep, $context);
if ($result->isSuccess()) {
$this->output->writeLine(' ✅ Rollback success', ConsoleColor::GREEN);
} else {
$this->output->writeLine(' ❌ Rollback failed', ConsoleColor::RED);
}
}
}
/**
* Check workflow prerequisites
*/
private function checkPrerequisites(array $prerequisites, array $context): bool
{
if (empty($prerequisites)) {
return true;
}
$this->output->writeLine('🔍 Checking prerequisites...', ConsoleColor::YELLOW);
foreach ($prerequisites as $prerequisite) {
// Simple prerequisite checking - can be extended
if ($prerequisite === 'database') {
$result = $this->checkDatabaseConnection();
} elseif ($prerequisite === 'migrations') {
$result = $this->checkMigrations();
} else {
$result = true;
}
if (!$result) {
$this->output->writeLine("❌ Prerequisite failed: {$prerequisite}", ConsoleColor::RED);
return false;
}
$this->output->writeLine("{$prerequisite}", ConsoleColor::GREEN);
}
return true;
}
/**
* Substitute variables in parameters
*/
private function substituteVariables(string $value, array $context): string
{
// Simple variable substitution: {{variable}}
return preg_replace_callback('/\{\{(\w+)\}\}/', function($matches) use ($context) {
return $context[$matches[1]] ?? $matches[0];
}, $value);
}
/**
* Check database connection (placeholder)
*/
private function checkDatabaseConnection(): bool
{
// Implementation would check actual database connection
return true;
}
/**
* Check migrations (placeholder)
*/
private function checkMigrations(): bool
{
// Implementation would check migration status
return true;
}
}