Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
ImportController
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
5 / 5
20
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
6
 storeWayPoints
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 findExistingWaypoint
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 updateExistingWaypoint
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5namespace App\Controller;
6
7use App\Entity\Waypoint;
8use App\Form\ImportFormType;
9use App\Parser\WayPointParser;
10use App\Repository\WaypointRepository;
11use App\Service\WayPointHelper;
12use Doctrine\ORM\EntityManagerInterface;
13use Exception;
14use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
15use Symfony\Component\HttpFoundation\Request;
16use Symfony\Component\HttpFoundation\Response;
17use Symfony\Component\Routing\Attribute\Route;
18use Symfony\Component\Security\Http\Attribute\IsGranted;
19
20#[IsGranted('ROLE_ADMIN')]
21class ImportController extends AbstractController
22{
23    public function __construct(
24        private readonly WaypointRepository $waypointRepo,
25        private readonly WayPointParser $wayPointParser,
26        private readonly WayPointHelper $wayPointHelper,
27        private readonly EntityManagerInterface $entityManager,
28    ) {}
29
30    #[Route(path: '/import', name: 'import', methods: ['GET', 'POST'])]
31    public function index(
32        Request $request,
33    ): Response
34    {
35        $form = $this->createForm(ImportFormType::class);
36        $form->handleRequest($request);
37        if ($form->isSubmitted() && $form->isValid()) {
38            try {
39                /** @var array<string> $data */
40                $data = $form->getData();
41                $waypoints = $this->wayPointParser->parse($data);
42                $count = $this->storeWayPoints(
43                    $waypoints,
44                    $this->waypointRepo,
45                    $this->wayPointHelper,
46                    $this->entityManager,
47                    isset($data['forceUpdate']) && (bool) $data['forceUpdate'],
48                );
49                if ($count !== 0) {
50                    $this->addFlash('success', $count.' Waypoint(s) imported!');
51                } else {
52                    $this->addFlash('warning', 'No Waypoints imported!');
53                }
54
55                return $this->redirectToRoute('default');
56            } catch (Exception $exception) {
57                $this->addFlash('danger', $exception->getMessage());
58            }
59        }
60
61        return $this->render(
62            'import/index.html.twig',
63            [
64                'form' => $form,
65            ]
66        );
67    }
68
69    /**
70     * @param array<Waypoint> $wayPoints
71     */
72    private function storeWayPoints(
73        array $wayPoints,
74        WaypointRepository $repository,
75        WayPointHelper $wayPointHelper,
76        EntityManagerInterface $entityManager,
77        bool $forceUpdate = false,
78    ): int
79    {
80        $currentWayPoints = $repository->findAll();
81        $cnt = 0;
82
83        foreach ($wayPoints as $wayPoint) {
84            $existing = $this->findExistingWaypoint($wayPoint, $currentWayPoints);
85
86            if ($existing instanceof Waypoint) {
87                if ($this->updateExistingWaypoint($existing, $wayPoint, $wayPointHelper, $entityManager, $forceUpdate)) {
88                    ++$cnt;
89                }
90
91                continue;
92            }
93
94            $wayPoint->setName($wayPointHelper->cleanName((string)$wayPoint->getName()));
95            $entityManager->persist($wayPoint);
96            ++$cnt;
97        }
98
99        $entityManager->flush();
100
101        return $cnt;
102    }
103
104    /**
105     * @param Waypoint[] $existingWayPoints
106     */
107    private function findExistingWaypoint(Waypoint $newWayPoint, array $existingWayPoints): ?Waypoint
108    {
109        foreach ($existingWayPoints as $currentWayPoint) {
110            if ($newWayPoint->getLat() === $currentWayPoint->getLat()
111                && $newWayPoint->getLon() === $currentWayPoint->getLon()
112            ) {
113                return $currentWayPoint;
114            }
115        }
116
117        return null;
118    }
119
120    private function updateExistingWaypoint(
121        Waypoint $existing,
122        Waypoint $newWayPoint,
123        WayPointHelper $wayPointHelper,
124        EntityManagerInterface $entityManager,
125        bool $forceUpdate
126    ): bool {
127        if ($existing->getGuid() === $newWayPoint->getGuid()) {
128            if ($forceUpdate) {
129                $existing
130                    ->setName($wayPointHelper->cleanName((string)$newWayPoint->getName()))
131                    ->setLat($newWayPoint->getLat() ?? 0.0)
132                    ->setLon($newWayPoint->getLon() ?? 0.0)
133                    ->setImage($newWayPoint->getImage());
134
135                $entityManager->persist($existing);
136                return true;
137            }
138
139            return false;
140        }
141
142        if (!$existing->getGuid() && $newWayPoint->getGuid()) {
143            $existing->setGuid($newWayPoint->getGuid());
144            $entityManager->persist($existing);
145        }
146
147        return false;
148    }
149}