Lines
96.87%
31 / 32
Methods
80.00%
4 / 5
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __invoke | 100.00% | 11 / 11 | 100.00% | 1 / 1 | 5 | ||
| importStats | 80.00% | 4 / 5 | 0.00% | 0 / 1 | 2.03 | ||
| statsImported | 100.00% | 5 / 5 | 100.00% | 1 / 1 | 2 | ||
| medalsImported | 100.00% | 6 / 6 | 100.00% | 1 / 1 | 2 | ||
| flashErrors | 100.00% | 5 / 5 | 100.00% | 1 / 1 | 2 | ||
| 28 | final class Import extends BaseController | |
| 29 | { | |
| 30 | /** At most this many rows that were not imported are listed. */ | |
| 31 | private const int SHOWN_ERRORS = 10; | |
| 32 | ||
| 33 | public function __invoke( | |
| 34 | Request $request, | |
| 35 | AgentStatCsvImporter $importer, | |
| 36 | CustomMedalsJsonImporter $medalsImporter, | |
| 37 | TranslatorInterface $translator, | |
| 38 | ChatActivity $chatActivity, | |
| 39 | ): Response { | |
| 40 | $form = $this->createForm(StatsImportType::class); | |
| 41 | $form->handleRequest($request); | |
| 42 | ||
| 43 | $file = $form->get('file')->getData(); | |
| 44 | ||
| 45 | // The form, again with what is wrong (render() answers 422 for an invalid one) | |
| 46 | if (!$form->isSubmitted() || !$form->isValid() || !$file instanceof UploadedFile) { | |
| 47 | return $this->render('agent_stat/import.html.twig', ['form' => $form]); | |
| 48 | } | |
| 49 | ||
| 50 | if ('json' === \strtolower($file->getClientOriginalExtension())) { | |
| 51 | $this->medalsImported($medalsImporter->import($this->getUser(), (string) \file_get_contents($file->getPathname())), $translator); | |
| 52 | } else { | |
| 53 | $result = $this->importStats($importer, $file); | |
| 54 | $chatActivity->statsImported($this->getUser(), $result->imported); | |
| 55 | $this->statsImported($result, $translator); | |
| 56 | } | |
| 57 | ||
| 58 | return $this->redirectToRoute('app_agent_stat_index', [], Response::HTTP_SEE_OTHER); | |
| 59 | } | |
| 60 | ||
| 61 | private function importStats(AgentStatCsvImporter $importer, UploadedFile $file): CsvImportResult | |
| 62 | { | |
| 63 | $csv = \fopen($file->getPathname(), 'r'); | |
| 64 | if (false === $csv) { | |
| 65 | throw new \RuntimeException('The uploaded file cannot be read.'); | |
| 66 | } | |
| 67 | ||
| 68 | try { | |
| 69 | return $importer->import($this->getUser(), $csv); | |
| 70 | } finally { | |
| 71 | \fclose($csv); | |
| 72 | } | |
| 73 | } | |
| 74 | ||
| 75 | private function statsImported(CsvImportResult $result, TranslatorInterface $translator): void | |
| 76 | { | |
| 77 | $this->addFlash($result->imported > 0 ? 'success' : 'info', $translator->trans('stats_import.done', [ | |
| 78 | '%imported%' => $result->imported, | |
| 79 | '%skipped%' => $result->skipped, | |
| 80 | ])); | |
| 81 | $this->flashErrors($result->errors, $translator); | |
| 82 | } | |
| 83 | ||
| 84 | private function medalsImported(CustomMedalsImportResult $result, TranslatorInterface $translator): void | |
| 85 | { | |
| 86 | $this->addFlash($result->added + $result->upgraded > 0 ? 'success' : 'info', $translator->trans('stats_import.medals_done', [ | |
| 87 | '%added%' => $result->added, | |
| 88 | '%upgraded%' => $result->upgraded, | |
| 89 | '%kept%' => $result->kept, | |
| 90 | ])); | |
| 91 | $this->flashErrors($result->errors, $translator); | |
| 92 | } | |
| 93 | ||
| 94 | /** | |
| 95 | * @param list<string> $errors what was not imported | |
| 96 | */ | |
| 97 | private function flashErrors(array $errors, TranslatorInterface $translator): void | |
| 98 | { | |
| 99 | if ([] === $errors) { | |
| 100 | return; | |
| 101 | } | |
| 102 | ||
| 103 | // The texts come from the file: escaped, flashes are shown as HTML | |
| 104 | $lines = \array_map(\htmlspecialchars(...), \array_slice($errors, 0, self::SHOWN_ERRORS)); | |
| 105 | $this->addFlash('warning', $translator->trans('stats_import.errors', ['%count%' => \count($errors)]) | |
| 106 | .'<ul class="mb-0"><li>'.\implode('</li><li>', $lines).'</li></ul>'); | |
| 107 | } | |
| 108 | } |