where('is_current', true)->orderByDesc('id')->first(); if ($year && trim((string) $year->name) !== '') { return (string) $year->name; } } return ''; } public function currentSemester(?string $requested = null): string { $requested = trim((string) $requested); if ($requested !== '') { return $requested; } return trim((string) (Configuration::getConfig('semester') ?? '')); } public function options(?string $selectedSchoolYear = null, ?string $selectedSemester = null): array { if (Schema::hasTable('school_years')) { $this->resolver->ensureCurrentTracked(); } $currentSchoolYear = $this->currentSchoolYear($selectedSchoolYear); $currentSemester = $this->currentSemester($selectedSemester); $schoolYears = $this->schoolYears($currentSchoolYear); $semesters = $this->semesters($currentSemester); return [ 'school_year' => $currentSchoolYear !== '' ? $currentSchoolYear : null, 'current_school_year' => $currentSchoolYear !== '' ? $currentSchoolYear : null, 'semester' => $currentSemester !== '' ? $currentSemester : null, 'current_semester' => $currentSemester !== '' ? $currentSemester : null, 'school_years' => $schoolYears, 'semesters' => $semesters, ]; } public function schoolYears(?string $include = null): array { $years = []; if (Schema::hasTable('school_years')) { $years = SchoolYear::query() ->orderByDesc('start_date') ->orderByDesc('id') ->get() ->map(fn (SchoolYear $year) => [ 'id' => (int) $year->id, 'name' => (string) $year->name, 'label' => (string) $year->name, 'start_date' => $year->start_date ? $year->start_date->format('Y-m-d') : null, 'end_date' => $year->end_date ? $year->end_date->format('Y-m-d') : null, 'status' => (string) $year->status, 'is_current' => (bool) $year->is_current, 'is_editable' => $year->status === SchoolYear::STATUS_ACTIVE, ]) ->all(); } $seen = []; foreach ($years as $row) { $seen[$row['name']] = true; } foreach ($this->legacySchoolYearNames() as $name) { if (! isset($seen[$name])) { $years[] = [ 'id' => null, 'name' => $name, 'label' => $name, 'start_date' => null, 'end_date' => null, 'status' => 'legacy', 'is_current' => false, 'is_editable' => true, ]; $seen[$name] = true; } } $include = trim((string) $include); if ($include !== '' && ! isset($seen[$include])) { array_unshift($years, [ 'id' => null, 'name' => $include, 'label' => $include, 'start_date' => null, 'end_date' => null, 'status' => 'selected', 'is_current' => true, 'is_editable' => true, ]); } return $years; } public function semesters(?string $include = null): array { $names = ['Fall', 'Spring']; $current = trim((string) $include); if ($current !== '' && ! in_array($current, $names, true)) { array_unshift($names, $current); } return array_map(fn (string $name) => [ 'name' => $name, 'label' => $name, 'is_current' => $current !== '' && strcasecmp($name, $current) === 0, ], $names); } private function legacySchoolYearNames(): array { $tables = [ 'student_class', 'teacher_class', 'events', 'calendar_events', 'exam_drafts', 'certificate_records', 'semester_scores', 'final_score', 'student_decisions', 'below_sixty_decisions', 'whatsapp_group_links', ]; $names = []; foreach ($tables as $table) { if (! SchoolYearTableRegistry::isYearScoped($table) || ! Schema::hasTable($table) || ! Schema::hasColumn($table, 'school_year')) { continue; } try { $rows = DB::table($table) ->whereNotNull('school_year') ->where('school_year', '!=', '') ->distinct() ->orderByDesc('school_year') ->limit(20) ->pluck('school_year') ->all(); } catch (\Throwable $e) { continue; } foreach ($rows as $row) { $name = trim((string) $row); if ($name !== '') { $names[$name] = true; } } } $configured = trim((string) (Configuration::getConfig('school_year') ?? '')); if ($configured !== '') { $names[$configured] = true; } $out = array_keys($names); rsort($out, SORT_NATURAL); return $out; } }