requestStack->getCurrentRequest(); if (!$request) { return new Response('Missing request.', Response::HTTP_BAD_REQUEST); } $from = $request->query->get('from'); $to = $request->query->get('to'); if (!$from || !$to) { return new Response('Missing from/to query params.', Response::HTTP_BAD_REQUEST); } $fromDate = DateTimeImmutable::createFromFormat('Y-m-d', $from); $toDate = DateTimeImmutable::createFromFormat('Y-m-d', $to); $siteIds = $this->parseIds($request->query->get('sites')); $workContractIds = $this->parseIds($request->query->get('workContracts')); $contractNatures = $this->parseContractNatures($request->query->get('contractNatures')); $employees = $this->loadEmployees($siteIds, $contractNatures, $workContractIds); $absences = $this->loadAbsences($fromDate, $toDate, $employees); $days = $this->buildDays($fromDate, $toDate); $absenceMap = $this->buildAbsenceMap($absences, $fromDate, $toDate); $holidayMap = $this->buildHolidayMap($fromDate, $toDate); $options = new Options(); $options->set('isRemoteEnabled', true); $dompdf = new Dompdf($options); $html = $this->twig->render('absence/print.html.twig', [ 'from' => $fromDate, 'to' => $toDate, 'days' => $days, 'employees' => $employees, 'absenceMap' => $absenceMap, 'holidayMap' => $holidayMap, ]); $dompdf->loadHtml($html); $dompdf->setPaper('A3', 'landscape'); $dompdf->render(); $filename = sprintf( 'absences_du_%s_au_%s.pdf', $fromDate->format('d-m-Y'), $toDate->format('d-m-Y') ); return new Response($dompdf->output(), Response::HTTP_OK, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$filename.'"', ]); } private function parseIds(?string $value): array { if (null === $value || '' === trim($value)) { return []; } $ids = []; foreach (explode(',', $value) as $part) { $id = (int) trim($part); if ($id > 0) { $ids[] = $id; } } return array_values(array_unique($ids)); } private function loadEmployees(array $siteIds, array $contractNatures, array $workContractIds): array { $employees = $this->employeeRepository->findForPrintBySiteIds($siteIds); return array_values(array_filter($employees, static function ($employee) use ($contractNatures, $workContractIds): bool { $employeeNature = (string) $employee->getCurrentContractNature(); $employeeContractId = $employee->getContract()?->getId(); $natureMatches = [] === $contractNatures || in_array($employeeNature, $contractNatures, true); $contractMatches = [] === $workContractIds || (null !== $employeeContractId && in_array($employeeContractId, $workContractIds, true)); return $natureMatches && $contractMatches; })); } private function loadAbsences(DateTimeImmutable $from, DateTimeImmutable $to, array $employees): array { return $this->absenceRepository->findForPrint($from, $to, $employees); } private function buildDays(DateTimeImmutable $from, DateTimeImmutable $to): array { $days = []; $current = $from; while ($current <= $to) { $days[] = [ 'date' => $current->format('Y-m-d'), 'label' => $current->format('d'), ]; $current = $current->add(new DateInterval('P1D')); } return $days; } private function buildAbsenceMap(array $absences, DateTimeImmutable $from, DateTimeImmutable $to): array { $map = []; foreach ($absences as $absence) { $employeeId = $absence->getEmployee()?->getId(); $type = $absence->getType(); if (!$employeeId || !$type) { continue; } $absenceStart = DateTimeImmutable::createFromInterface($absence->getStartDate()); $absenceEnd = DateTimeImmutable::createFromInterface($absence->getEndDate()); $startHalf = $absence->getStartHalf(); $endHalf = $absence->getEndHalf(); $start = max($absenceStart, $from); $end = min($absenceEnd, $to); $current = $start; while ($current <= $end) { $dateKey = $current->format('Y-m-d'); $isSameDay = $absenceStart->format('Y-m-d') === $absenceEnd->format('Y-m-d'); $isStartDay = $current->format('Y-m-d') === $absenceStart->format('Y-m-d'); $isEndDay = $current->format('Y-m-d') === $absenceEnd->format('Y-m-d'); $halfLabel = null; if ($isSameDay) { if ($startHalf === $endHalf) { $halfLabel = $startHalf->value; } } else { if ($isStartDay && HalfDay::PM === $startHalf) { $halfLabel = 'PM'; } if ($isEndDay && HalfDay::AM === $endHalf) { $halfLabel = 'AM'; } } $map[$employeeId][$dateKey] = [ 'code' => (string) $type->getCode(), 'color' => (string) $type->getColor(), 'half' => null !== $halfLabel, 'halfLabel' => $halfLabel, ]; $current = $current->add(new DateInterval('P1D')); } } return $map; } private function buildHolidayMap(DateTimeImmutable $from, DateTimeImmutable $to): array { $map = []; $startYear = (int) $from->format('Y'); $endYear = (int) $to->format('Y'); try { for ($year = $startYear; $year <= $endYear; ++$year) { $holidays = $this->publicHolidayService->getHolidaysDayByYears('metropole', (string) $year); foreach ($holidays as $date => $label) { $map[$date] = (string) $label; } } } catch (Throwable) { return []; } return $map; } /** * @return list */ private function parseContractNatures(?string $value): array { if (null === $value || '' === trim($value)) { return []; } $values = []; foreach (explode(',', $value) as $part) { $nature = strtoupper(trim($part)); if (null !== ContractNature::tryFrom($nature)) { $values[] = $nature; } } return array_values(array_unique($values)); } }