handler instance (must implement ScheduledJobHandlerInterface). * * To register a new job: * 1. Create lib/Service/Scheduler/Handler/YourJobHandler.php implementing the interface. * 2. Add a public const for the job key above. * 3. Add one line in __construct(): self::YOUR_JOB_KEY => new YourJobHandler(...), * * No other file needs to be changed. * * @var array */ private array $handlers; public function __construct( UserLifecycleService $userLifecycleService, SystemAuditService $systemAuditService ) { $this->handlers = [ self::USER_LIFECYCLE_RUN => new UserLifecycleJobHandler($userLifecycleService), self::SYSTEM_AUDIT_PURGE => new SystemAuditPurgeJobHandler($systemAuditService), ]; } /** * Returns all job definitions keyed by job_key. * Consumed by ScheduledJobService->ensureSystemJobs() to sync registry with the database. */ public function definitions(): array { $result = []; foreach ($this->handlers as $jobKey => $handler) { $result[$jobKey] = $handler->definition(); } return $result; } /** * Returns the definition for a single job key, or null if not registered. */ public function get(string $jobKey): ?array { $jobKey = trim($jobKey); if ($jobKey === '') { return null; } return isset($this->handlers[$jobKey]) ? $this->handlers[$jobKey]->definition() : null; } /** * Dispatches execution to the registered handler for the given job key and returns * a normalized result envelope. Unknown job keys return status 'failed' with * error_code 'job_not_supported' rather than throwing an exception. * * @param string $jobKey Registered job identifier (see class constants). * @param int|null $actorUserId Null for scheduler-triggered runs; user ID for manual runs. * @return array{status:string,error_code:?string,error_message:?string,result:array} */ public function execute(string $jobKey, ?int $actorUserId): array { if (!isset($this->handlers[$jobKey])) { return [ 'status' => 'failed', 'error_code' => 'job_not_supported', 'error_message' => null, 'result' => [], ]; } return $this->handlers[$jobKey]->execute($actorUserId); } }