Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
87.84% |
65 / 74 |
|
57.14% |
4 / 7 |
CRAP | |
0.00% |
0 / 1 |
SyncSolvEventsCommand | |
87.84% |
65 / 74 |
|
57.14% |
4 / 7 |
21.79 | |
0.00% |
0 / 1 |
getAllowedAppEnvs | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
configure | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setSolvEventParser | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
handle | |
71.43% |
5 / 7 |
|
0.00% |
0 / 1 |
3.21 | |||
syncSolvEventsForYear | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
importSolvEventsForYear | |
88.46% |
46 / 52 |
|
0.00% |
0 / 1 |
13.26 |
1 | <?php |
2 | |
3 | namespace Olz\Command; |
4 | |
5 | use Olz\Command\Common\OlzCommand; |
6 | use Olz\Entity\SolvEvent; |
7 | use Olz\Entity\Termine\Termin; |
8 | use Olz\Parsers\SolvEventParser; |
9 | use Symfony\Component\Console\Attribute\AsCommand; |
10 | use Symfony\Component\Console\Command\Command; |
11 | use Symfony\Component\Console\Input\InputArgument; |
12 | use Symfony\Component\Console\Input\InputInterface; |
13 | use Symfony\Component\Console\Output\OutputInterface; |
14 | |
15 | #[AsCommand(name: 'olz:sync-solv-events')] |
16 | class SyncSolvEventsCommand extends OlzCommand { |
17 | /** @return array<string> */ |
18 | protected function getAllowedAppEnvs(): array { |
19 | return ['dev', 'test', 'staging', 'prod']; |
20 | } |
21 | |
22 | protected function configure(): void { |
23 | $this->addArgument('year', InputArgument::REQUIRED, 'Year (YYYY; 1996 or later)'); |
24 | } |
25 | |
26 | protected SolvEventParser $solvEventParser; |
27 | |
28 | public function __construct() { |
29 | parent::__construct(); |
30 | $this->solvEventParser = new SolvEventParser(); |
31 | } |
32 | |
33 | public function setSolvEventParser(SolvEventParser $solvEventParser): void { |
34 | $this->solvEventParser = $solvEventParser; |
35 | } |
36 | |
37 | protected function handle(InputInterface $input, OutputInterface $output): int { |
38 | $year = $input->getArgument('year'); |
39 | if (!preg_match('/^[0-9]{4}$/', $year) || intval($year) < 1996) { |
40 | $this->logAndOutput("Invalid year: {$year}. Must be in format YYYY and 1996 or later.", level: 'notice'); |
41 | return Command::INVALID; |
42 | } |
43 | $year = intval($year); |
44 | $this->syncSolvEventsForYear($year); |
45 | return Command::SUCCESS; |
46 | } |
47 | |
48 | public function syncSolvEventsForYear(int $year): void { |
49 | $this->logAndOutput("Syncing SOLV events for {$year}..."); |
50 | |
51 | $csv = $this->solvFetcher()->fetchEventsCsvForYear($year); |
52 | $this->generalUtils()->checkNotNull($csv, "No events CSV for year {$year}"); |
53 | |
54 | $csv_excerpt = mb_substr($csv, 0, 255); |
55 | $csv_length = mb_strlen($csv); |
56 | $this->logAndOutput("Successfully read CSV: {$csv_excerpt}... ({$csv_length})."); |
57 | |
58 | $solv_events = $this->solvEventParser->parse_solv_events_csv($csv); |
59 | |
60 | $solv_event_count = count($solv_events); |
61 | $this->logAndOutput("Parsed {$solv_event_count} events out of CSV."); |
62 | |
63 | $this->importSolvEventsForYear($solv_events, $year); |
64 | } |
65 | |
66 | /** @param array<SolvEvent> $solv_events */ |
67 | private function importSolvEventsForYear(array $solv_events, int $year): void { |
68 | $solv_event_repo = $this->entityManager()->getRepository(SolvEvent::class); |
69 | $termin_repo = $this->entityManager()->getRepository(Termin::class); |
70 | $existing_solv_events = $solv_event_repo->getSolvEventsForYear($year); |
71 | $existing_solv_events_index = []; |
72 | foreach ($existing_solv_events as $existing_solv_event) { |
73 | $solv_uid = $existing_solv_event->getSolvUid(); |
74 | $existing_solv_events_index[$solv_uid] = $existing_solv_event; |
75 | } |
76 | $solv_uid_still_exists = []; |
77 | foreach ($existing_solv_events_index as $solv_uid => $existing_solv_event) { |
78 | $solv_uid_still_exists[$solv_uid] = false; |
79 | } |
80 | foreach ($solv_events as $solv_event) { |
81 | $solv_uid = $solv_event->getSolvUid(); |
82 | $solv_uid_still_exists[$solv_uid] = true; |
83 | $existing_solv_event = $existing_solv_events_index[$solv_uid] ?? null; |
84 | $outdated = $existing_solv_event ? $solv_event->getLastModification() > $existing_solv_event->getLastModification() : false; |
85 | if (!$existing_solv_event) { |
86 | try { |
87 | $this->entityManager()->persist($solv_event); |
88 | $this->entityManager()->flush(); |
89 | $this->logAndOutput("INSERTED {$solv_uid}"); |
90 | } catch (\Exception $e) { |
91 | $this->logAndOutput("INSERT FAILED {$solv_uid}: {$e}"); |
92 | } |
93 | } elseif ($outdated) { |
94 | $existing_solv_event->setDate($solv_event->getDate()); |
95 | $existing_solv_event->setDuration($solv_event->getDuration()); |
96 | $existing_solv_event->setKind($solv_event->getKind()); |
97 | $existing_solv_event->setDayNight($solv_event->getDayNight()); |
98 | $existing_solv_event->setNational($solv_event->getNational()); |
99 | $existing_solv_event->setRegion($solv_event->getRegion()); |
100 | $existing_solv_event->setType($solv_event->getType()); |
101 | $existing_solv_event->setName($solv_event->getName()); |
102 | $existing_solv_event->setLink($solv_event->getLink()); |
103 | $existing_solv_event->setClub($solv_event->getClub()); |
104 | $existing_solv_event->setMap($solv_event->getMap()); |
105 | $existing_solv_event->setLocation($solv_event->getLocation()); |
106 | $existing_solv_event->setCoordX($solv_event->getCoordX()); |
107 | $existing_solv_event->setCoordY($solv_event->getCoordY()); |
108 | $existing_solv_event->setDeadline($solv_event->getDeadline()); |
109 | $existing_solv_event->setEntryportal($solv_event->getEntryportal()); |
110 | $existing_solv_event->setLastModification($solv_event->getLastModification()); |
111 | |
112 | $termine = $termin_repo->findBy(['solv_uid' => $solv_uid]); |
113 | foreach ($termine as $termin) { |
114 | $this->termineUtils()->updateTerminFromSolvEvent($termin, $solv_event); |
115 | } |
116 | |
117 | try { |
118 | $this->entityManager()->flush(); |
119 | $this->logAndOutput("UPDATED {$solv_uid}"); |
120 | } catch (\Exception $e) { |
121 | $this->logAndOutput("UPDATE FAILED {$solv_uid}: {$e}"); |
122 | } |
123 | } |
124 | } |
125 | foreach ($solv_uid_still_exists as $solv_uid => $still_exists) { |
126 | if (!$still_exists) { |
127 | try { |
128 | $solv_event_repo->deleteBySolvUid($solv_uid); |
129 | $this->logAndOutput("DELETED {$solv_uid}"); |
130 | } catch (\Exception $e) { |
131 | $this->logAndOutput("DELETE FAILED {$solv_uid}: {$e}"); |
132 | } |
133 | } |
134 | } |
135 | } |
136 | } |