*/ protected $helpers = ['security']; /** @var ApiClient */ protected ApiClient $api; /** * Be sure to declare properties for any property fetch you initialized. * The creation of dynamic property is deprecated in PHP 8.2. */ // protected $session; /** * @return void */ public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { // Do Not Edit This Line parent::initController($request, $response, $logger); // Preload any models, libraries, etc, here. // E.g.: $this->session = \Config\Services::session(); session(); $this->syncSchoolYearPropertyFromContext(); $this->injectSchoolYearViewData(); // Shared API client available to all controllers $this->api = service('apiClient'); } /** * Get the user role from the session or database * * @return string|null */ protected function getUserRole() { // Assuming the user role is stored in the session return session()->get('role'); } protected function validated(array $rules, ?array $data = null): array { $validation = service('validation'); $payload = $data ?? ($this->request->getJSON(true) ?: $this->request->getPost()); $payload = sanitize_request_value($payload); $validation->setRules($rules); if (! $validation->run($payload)) { throw new \InvalidArgumentException(json_encode($validation->getErrors(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: 'Validation failed'); } return $payload; } protected function resolveSchoolYearContext(?int $routeSchoolYearId = null): SchoolYearContext { try { return service('schoolYearContext')->resolve($this->request, $routeSchoolYearId); } catch (Throwable $e) { log_message('warning', 'School-year resolution failed: {message}', [ 'message' => $e->getMessage(), ]); throw $e; } } protected function currentSchoolYearName(?string $fallback = null): string { try { return $this->resolveSchoolYearContext()->yearName(); } catch (Throwable $e) { if ($fallback !== null && $fallback !== '') { return $fallback; } try { return (string) ((new \App\Models\ConfigurationModel())->getConfig('school_year') ?? ''); } catch (Throwable) { return ''; } } } protected function assertSchoolYearWritable( SchoolYearContext $context, bool $allowDraftForAdmin = false, bool $isAdmin = false ): void { service('schoolYearWriteGuard')->assertWritable($context, $allowDraftForAdmin, $isAdmin); } private function syncSchoolYearPropertyFromContext(): void { if (! property_exists($this, 'schoolYear')) { return; } if (! $this->request instanceof IncomingRequest || is_cli()) { return; } if (! session()->get('user_id')) { return; } try { $this->schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? '')); } catch (Throwable $e) { log_message('warning', 'Unable to sync controller school-year property: {message}', [ 'message' => $e->getMessage(), ]); } } private function injectSchoolYearViewData(): void { if (! config('Feature')->globalSchoolYearSelector) { return; } if (! $this->request instanceof IncomingRequest || is_cli()) { return; } if (! session()->get('user_id')) { return; } if (! $this->shouldShowSchoolYearSelector()) { return; } $accept = strtolower($this->request->getHeaderLine('Accept')); if ($this->request->isAJAX() || str_contains($accept, 'application/json')) { return; } try { service('renderer')->setData(service('schoolYearViewData')->forCurrentRequest($this->request)); } catch (SchoolYearConfigurationException $e) { throw $e; } catch (Throwable $e) { log_message('warning', 'Unable to inject school-year view data: {message}', [ 'message' => $e->getMessage(), ]); } } private function shouldShowSchoolYearSelector(): bool { $roles = (array) session()->get('roles'); $singleRole = session()->get('role'); if ($singleRole !== null && $singleRole !== '') { $roles[] = $singleRole; } $roles = array_map( static fn ($role): string => strtolower(trim((string) $role)), $roles ); return (bool) array_intersect($roles, [ 'admin', 'administrator', 'administrative staff', 'principal', 'vice principal', ]); } } ?>