ProjectControllerJson::locations()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 14
ccs 9
cts 9
cp 1
crap 2
rs 10
1
<?php
2
3
namespace App\Controller;
4
5
use Exception;
6
use Symfony\Bundle\FrameworkBundle\Console\Application;
7
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
8
use Symfony\Component\Console\Exception\CommandNotFoundException;
9
use Symfony\Component\Console\Input\ArrayInput;
10
use Symfony\Component\Console\Output\BufferedOutput;
11
use Symfony\Component\Console\Output\NullOutput;
12
use Symfony\Component\HttpFoundation\JsonResponse;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\Response;
15
use Symfony\Component\HttpFoundation\Session\SessionInterface;
16
use Symfony\Component\HttpKernel\KernelInterface;
17
use Symfony\Component\Routing\Annotation\Route;
18
use Doctrine\Persistence\ManagerRegistry;
19
use Doctrine\ORM\EntityManagerInterface;
20
use App\Adventure\Log;
21
use App\Entity\Game\Connection;
22
use App\Entity\Game\Item;
23
use App\Entity\Game\Location;
24
use App\Repository\Game\ConnectionRepository;
25
use App\Repository\Game\ItemRepository;
26
use App\Repository\Game\LocationRepository;
27
28
class ProjectControllerJson extends AbstractController
29
{
30 2
    #[Route("/proj/api/locations", name: "proj_api_locations")]
31
    public function locations(LocationRepository $locationRepository): Response
32
    {
33 2
        $locations = $locationRepository->findAll();
34
35 2
        if (empty($locations)) {
36 1
            return $this->json(['error' => 'No locations found'], Response::HTTP_NOT_FOUND);
37
        }
38
39 1
        $response = $this->json($locations);
40 1
        $response->setEncodingOptions(
41 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
42 1
        );
43 1
        return $response;
44
    }
45
46 2
    #[Route("/proj/api/locations/{id}", name: "proj_api_locations_by_id")]
47
    public function locationById(int $id, LocationRepository $locationRepository): JsonResponse
48
    {
49 2
        $location = $locationRepository->find($id);
50
51 2
        if (!$location) {
52 1
            return $this->json(['error' => "No location found with ID {$id}"], Response::HTTP_NOT_FOUND);
53
        }
54
55 1
        $response = $this->json($location);
56 1
        $response->setEncodingOptions(
57 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
58 1
        );
59 1
        return $response;
60
    }
61
62 2
    #[Route("/proj/api/items", name: "proj_api_items")]
63
    public function items(ItemRepository $itemRepository): Response
64
    {
65 2
        $items = $itemRepository->findAll();
66
67 2
        if (empty($items)) {
68 1
            return $this->json(['error' => 'No items found'], Response::HTTP_NOT_FOUND);
69
        }
70
71 1
        $response = $this->json($items);
72 1
        $response->setEncodingOptions(
73 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
74 1
        );
75 1
        return $response;
76
    }
77
78 2
    #[Route("/proj/api/items/{id}", name: "proj_api_items_by_id")]
79
    public function itemById(int $id, ItemRepository $itemRepository): JsonResponse
80
    {
81 2
        $item = $itemRepository->find($id);
82
83 2
        if (!$item) {
84 1
            return $this->json(['error' => "No item found with ID {$id}"], Response::HTTP_NOT_FOUND);
85
        }
86
87 1
        $response = $this->json($item);
88 1
        $response->setEncodingOptions(
89 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
90 1
        );
91 1
        return $response;
92
    }
93
94 2
    #[Route("/proj/api/log", name: "proj_api_log")]
95
    public function log(SessionInterface $session): JsonResponse
96
    {
97
        /** @var Log */
98 2
        $log = $session->get('game_log', new Log());
99
100 2
        $entries = $log->getEntries();
101 2
        if (empty($entries)) {
102 1
            return $this->json(['error' => 'No logged entries found'], Response::HTTP_NOT_FOUND);
103
        }
104
105 1
        $response = $this->json($entries);
106 1
        $response->setEncodingOptions(
107 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
108 1
        );
109 1
        return $response;
110
    }
111
112 3
    #[Route("/proj/api/connect", name: "proj_api_connect", methods: ['POST'])]
113
    public function connect(Request $request, ManagerRegistry $doctrine, ConnectionRepository $connectionRepository): JsonResponse
114
    {
115
        // Retrieve request data
116
        /** @var int */
117 3
        $fromId = intval($request->request->get('from_location'));
118
        /** @var int */
119 3
        $toId = intval($request->request->get('to_location'));
120
        /** @var string */
121 3
        $direction = $request->request->get('direction');
122
123
        // Exit early with error message if locations are the same
124 3
        if ($fromId ===  $toId) {
125 1
            return $this->json(['error' => 'Cannot connect a location to itself'], Response::HTTP_BAD_REQUEST);
126
        }
127
128
        // Try to find if connection already exists
129 2
        $existingConnection = $connectionRepository->findOneBy([
130 2
            'fromLocationId' => $fromId,
131 2
            'toLocationId' => $toId,
132 2
            'direction' => $direction,
133 2
        ]);
134
135
        // Exit early with error message if connection already exists
136 2
        if ($existingConnection !== null) {
137 1
            return $this->json(['error' => 'Locations are already connected in the specified direction'], Response::HTTP_BAD_REQUEST);
138
        }
139
140
        try {
141
            // Find the highest ID among existing connections
142 1
            $highestId = $connectionRepository->findHighestId();
143
144
            // Create the connection
145 1
            $connection = new Connection();
146 1
            $connection->setId($highestId + 1);
147 1
            $connection->setFromLocationId($fromId);
148 1
            $connection->setToLocationId($toId);
149 1
            $connection->setDirection($direction);
150
151
            // Persist new connection in the database
152 1
            $entityManager = $doctrine->getManager('game');
153 1
            $entityManager->persist($connection);
154 1
            $entityManager->flush();
155
        } catch (Exception $exception) {
156
            return $this->json(['error' => $exception->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
157
        }
158
159 1
        $response = [
160 1
            'message' => 'Locations connected successfully',
161 1
            'from_location_id' => $fromId,
162 1
            'to_location_id' => $toId,
163 1
            'direction' => $direction,
164 1
        ];
165
166 1
        $response = $this->json($response, Response::HTTP_CREATED);
167 1
        $response->setEncodingOptions(
168 1
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
169 1
        );
170
171 1
        return $response;
172
    }
173
174
175
    /**
176
     * Reset the game database by running the reset-database command.
177
     */
178
    #[Route("/proj/api/reset", name: "proj_api_reset", methods: ['POST'])]
179
    public function resetDatabase(KernelInterface $kernel): JsonResponse
180
    {
181
        $application = new Application($kernel);
182
        $application->setAutoExit(false);
183
184
        $command = 'app:reset-database';
185
186
        $input = new ArrayInput([
187
            'command' => $command,
188
        ]);
189
190
        $output = new NullOutput();
191
192
        try {
193
            if (!$application->has($command)) {
194
                throw new CommandNotFoundException("The command {$command} does not exist.");
195
            }
196
197
            $statusCode = $application->run($input, $output);
198
199
            if ($statusCode === 0) {
200
                $response = $this->json([
201
                    'status' => 'success',
202
                    'message' => 'Database reset data import completed!',
203
                ], Response::HTTP_OK);
204
205
                $response->setEncodingOptions(
206
                    $response->getEncodingOptions() | JSON_PRETTY_PRINT,
207
                );
208
209
                return $response;
210
            }
211
212
            $errorMessage = 'Database reset and data import failed.';
213
            $errorStatusCode = Response::HTTP_INTERNAL_SERVER_ERROR;
214
        } catch (CommandNotFoundException $exception) {
215
            $errorMessage = $exception->getMessage();
216
            $errorStatusCode = Response::HTTP_NOT_FOUND;
217
        } catch (Exception $exception) {
218
            $errorMessage = $exception->getMessage();
219
            $errorStatusCode = Response::HTTP_BAD_REQUEST;
220
        }
221
222
        $response = $this->json([
223
            'status' => 'error',
224
            'message' => $errorMessage,
225
        ], $errorStatusCode);
226
227
        $response->setEncodingOptions(
228
            $response->getEncodingOptions() | JSON_PRETTY_PRINT,
229
        );
230
231
        return $response;
232
    }
233
}
234