] [--no-lock] [--json] Options: --apply Mutierender Lauf (Zuweisungen anlegen/entfernen) --dry-run Nur Vorschau, keine DB-Änderungen --task_id Optional: nur eine Aufgabe verarbeiten --no-lock Locking deaktivieren (nur Debug) --json JSON-Ausgabe zusätzlich auf stdout --help Diese Hilfe anzeigen TXT; try { $options = TaskCertCronRuntime::parseOptions($argv, true); } catch (InvalidArgumentException $exception) { TaskCertCronRuntime::printOptionError($exception->getMessage(), $usage); exit(2); } if ((bool) ($options['help'] ?? false)) { TaskCertCronRuntime::printUsage($usage); exit(0); } $exitCode = TaskCertCronRuntime::runWithHandling( 'sync_assignments', $options, static function (array $context) use ($options): array { require_once dirname(__DIR__) . '/bootstrap.php'; $services = task_cert_services(); $resolver = $services['assignmentResolverService'] ?? null; if (!$resolver instanceof AssignmentResolverService) { throw new RuntimeException('AssignmentResolverService nicht verfügbar.'); } $apply = (bool) ($options['apply'] ?? false); $taskId = (int) ($options['task_id'] ?? 0); $auditContext = [ 'changed_by' => 0, 'trigger' => 'cron_cli', 'job_run_id' => (string) ($context['job_run_id'] ?? ''), ]; if ($taskId > 0) { $results = [$resolver->syncAssignmentsForTask($taskId, $apply, 'current_cycle', $auditContext)]; } else { $results = $resolver->syncAssignmentsForAllActiveTasks($apply, 'current_cycle', $auditContext); } $totals = [ 'task_count' => 0, 'target_count' => 0, 'existing_count' => 0, 'create_count' => 0, 'update_count' => 0, 'stale_count' => 0, 'protected_completed_count' => 0, 'protected_certificate_count' => 0, 'remove_count' => 0, 'remove_with_submissions_count' => 0, ]; foreach ($results as $result) { if (!is_array($result)) { continue; } $totals['task_count']++; foreach ([ 'target_count', 'existing_count', 'create_count', 'update_count', 'stale_count', 'protected_completed_count', 'protected_certificate_count', 'remove_count', 'remove_with_submissions_count', ] as $key) { $totals[$key] += (int) ($result[$key] ?? 0); } } if ($apply && $taskId <= 0) { CronHeartbeat::record('sync_assignments', [ 'task_count' => (int) ($totals['task_count'] ?? 0), 'create_count' => (int) ($totals['create_count'] ?? 0), 'remove_count' => (int) ($totals['remove_count'] ?? 0), ]); } return [ 'job' => 'sync_assignments', 'mode' => $apply ? 'apply' : 'dry_run', 'scope' => 'current_cycle', 'task_id' => $taskId > 0 ? $taskId : null, 'totals' => $totals, ]; } ); exit($exitCode);