128 lines
3.7 KiB
PHP
128 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Parents;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class ParentAttendanceReportCalendarService
|
|
{
|
|
public function __construct(private ParentConfigService $configService)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @return array{0: array<int, array{value:string,label:string}>, 1: string}
|
|
*/
|
|
public function computeSundays(int $weeksBefore = 4, int $weeksAfter = 26): array
|
|
{
|
|
$today = new \DateTime('today');
|
|
$dow = (int) $today->format('w');
|
|
|
|
$thisSunday = clone $today;
|
|
if ($dow !== 0) {
|
|
$thisSunday->modify('last sunday');
|
|
}
|
|
|
|
$default = clone $today;
|
|
if ($dow !== 0) {
|
|
$default->modify('next sunday');
|
|
}
|
|
|
|
$schoolYear = (string) ($this->configService->context()['school_year'] ?? '');
|
|
$cap = $this->firstSundayOfJune($schoolYear);
|
|
|
|
$dates = [];
|
|
for ($i = $weeksBefore; $i >= 1; $i--) {
|
|
$dates[] = (clone $thisSunday)->modify('-' . $i . ' week');
|
|
}
|
|
|
|
$cursor = clone $thisSunday;
|
|
while ($cursor <= $cap) {
|
|
$dates[] = clone $cursor;
|
|
$cursor->modify('+1 week');
|
|
}
|
|
|
|
$rangeStart = reset($dates);
|
|
$rangeEnd = end($dates);
|
|
$rangeStartStr = $rangeStart instanceof \DateTime ? $rangeStart->format('Y-m-d') : null;
|
|
$rangeEndStr = $rangeEnd instanceof \DateTime ? $rangeEnd->format('Y-m-d') : null;
|
|
|
|
$noSchool = [];
|
|
if ($rangeStartStr && $rangeEndStr) {
|
|
$rows = DB::table('calendar_events')
|
|
->select('date')
|
|
->where('no_school', 1)
|
|
->groupStart()
|
|
->where('school_year', $schoolYear)
|
|
->orWhere('school_year IS NULL', null, false)
|
|
->groupEnd()
|
|
->where('date >=', $rangeStartStr)
|
|
->where('date <=', $rangeEndStr)
|
|
->get()
|
|
->toArray();
|
|
|
|
foreach ($rows as $row) {
|
|
$d = substr((string) ($row->date ?? ''), 0, 10);
|
|
if ($d !== '') {
|
|
$noSchool[$d] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
$filtered = [];
|
|
foreach ($dates as $d) {
|
|
$ymd = $d->format('Y-m-d');
|
|
if (!isset($noSchool[$ymd]) && $d >= $today && $d <= $cap) {
|
|
$filtered[] = $d;
|
|
}
|
|
}
|
|
|
|
$defaultYmd = $default->format('Y-m-d');
|
|
if (!empty($filtered)) {
|
|
$defaultYmd = $filtered[0]->format('Y-m-d');
|
|
}
|
|
|
|
$out = [];
|
|
foreach ($filtered as $d) {
|
|
$out[] = [
|
|
'value' => $d->format('Y-m-d'),
|
|
'label' => $d->format('m-d-Y'),
|
|
];
|
|
}
|
|
|
|
return [$out, $defaultYmd];
|
|
}
|
|
|
|
public function normalizeCutoffTime(string $raw, string $default = '09:00'): string
|
|
{
|
|
$raw = trim($raw);
|
|
if ($raw === '') {
|
|
return $default;
|
|
}
|
|
if (preg_match('/^(\\d{1,2}):(\\d{2})$/', $raw, $m)) {
|
|
$hh = str_pad((string) ((int) $m[1]), 2, '0', STR_PAD_LEFT);
|
|
return $hh . ':' . $m[2];
|
|
}
|
|
return $default;
|
|
}
|
|
|
|
public function firstSundayOfJune(string $schoolYear): \DateTime
|
|
{
|
|
$today = new \DateTime('today');
|
|
$endYear = null;
|
|
if (preg_match('/^(\\d{4})\\D(\\d{4})$/', $schoolYear, $m)) {
|
|
$endYear = (int) $m[2];
|
|
}
|
|
if ($endYear === null) {
|
|
$y = (int) $today->format('Y');
|
|
$endYear = ((int) $today->format('n') > 6) ? ($y + 1) : $y;
|
|
}
|
|
|
|
$juneFirst = new \DateTime(sprintf('%04d-06-01', $endYear));
|
|
if ((int) $juneFirst->format('w') !== 0) {
|
|
$juneFirst->modify('next sunday');
|
|
}
|
|
return $juneFirst;
|
|
}
|
|
}
|