ProofAdminController   A
last analyzed

Complexity

Total Complexity 37

Size/Duplication

Total Lines 279
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 123
dl 0
loc 279
rs 9.44
c 1
b 0
f 0
wmc 37

9 Methods

Rating   Name   Duplication   Size   Complexity  
B editAction() 0 81 11
A __construct() 0 2 1
A statsAction() 0 17 2
B handleProofValidation() 0 28 8
A isProofValidationSubmission() 0 17 5
A getProofValidationMessage() 0 25 4
A handleProofAccepted() 0 10 2
A handleProofRefused() 0 7 2
A getNextProofRedirect() 0 37 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace VideoGamesRecords\CoreBundle\Controller\Admin;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
use Sonata\AdminBundle\Controller\CRUDController;
9
use Symfony\Component\HttpFoundation\RedirectResponse;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response;
12
use VideoGamesRecords\CoreBundle\ValueObject\ProofStatus;
13
14
class ProofAdminController extends CRUDController
15
{
16
    public function __construct(private readonly EntityManagerInterface $em)
17
    {
18
    }
19
20
    /**
21
     * @return Response
22
     */
23
    public function statsAction(): Response
24
    {
25
        $stats = $this->em->getRepository('VideoGamesRecords\CoreBundle\Entity\Player')->getProofStats();
26
27
        // Formatage
28
        $months = [];
29
30
31
        // MONTH
32
        foreach ($stats as $row) {
33
            $months[$row['month']][] = $row;
34
        }
35
36
        return $this->render(
37
            '@VideoGamesRecordsCore/Admin/Object/Proof/stats.html.twig',
38
            [
39
                'stats' => $months,
40
            ]
41
        );
42
    }
43
44
    /**
45
     * Action d'édition personnalisée pour gérer la validation des preuves
46
     */
47
    public function editAction(Request $request): Response
48
    {
49
        $object = $this->assertObjectExists($request, true);
50
        $this->checkParentChildAssociation($request, $object);
0 ignored issues
show
Bug introduced by
It seems like $object can also be of type null; however, parameter $object of Sonata\AdminBundle\Contr...arentChildAssociation() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

50
        $this->checkParentChildAssociation($request, /** @scrutinizer ignore-type */ $object);
Loading history...
51
52
        $this->admin->checkAccess('edit', $object);
53
54
        $preResponse = $this->preEdit($request, $object);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $preResponse is correct as $this->preEdit($request, $object) targeting Sonata\AdminBundle\Contr...UDController::preEdit() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
55
        if (null !== $preResponse) {
0 ignored issues
show
introduced by
The condition null !== $preResponse is always false.
Loading history...
56
            return $preResponse;
57
        }
58
59
        $this->admin->setSubject($object);
60
        $form = $this->admin->getForm();
61
        $form->setData($object);
62
        $form->handleRequest($request);
63
64
        if ($form->isSubmitted()) {
65
            $isFormValid = $form->isValid();
66
67
            // Gestion spéciale pour la validation des preuves
68
            if ($isFormValid && $this->isProofValidationSubmission($request, $object)) {
69
                $this->handleProofValidation($object, $request);
70
            }
71
72
            // Validation et redirection si tout est OK
73
            if ($isFormValid) {
74
                $submittedObject = $form->getData();
75
                $this->admin->setSubject($submittedObject);
76
77
                try {
78
                    $submittedObject = $this->admin->update($submittedObject);
79
80
                    if ($this->isXmlHttpRequest($request)) {
81
                        return $this->handleXmlHttpRequestSuccessResponse($request, $submittedObject);
82
                    }
83
84
                    $this->addFlash(
85
                        'sonata_flash_success',
86
                        $this->getProofValidationMessage($submittedObject)
87
                    );
88
89
                    // Redirection après succès vers la prochaine preuve
90
                    $nextProofRedirect = $this->getNextProofRedirect($submittedObject);
91
                    if ($nextProofRedirect) {
0 ignored issues
show
introduced by
$nextProofRedirect is of type Symfony\Component\HttpFoundation\RedirectResponse, thus it always evaluated to true.
Loading history...
92
                        return $nextProofRedirect;
93
                    }
94
95
                    if (null !== ($response = $this->redirectTo($request, $submittedObject))) {
96
                        return $response;
97
                    }
98
                } catch (\Throwable $e) {
99
                    $this->handleModelManagerThrowable($e);
100
101
                    $isFormValid = false;
102
                }
103
            }
104
105
            // Message d'erreur si la validation a échoué
106
            if (!$isFormValid) {
0 ignored issues
show
introduced by
The condition $isFormValid is always false.
Loading history...
107
                $this->addFlash(
108
                    'sonata_flash_error',
109
                    $this->trans(
110
                        'flash_edit_error',
111
                        ['%name%' => $this->escapeHtml($this->admin->toString($object))],
112
                        'SonataAdminBundle'
113
                    )
114
                );
115
            }
116
        }
117
118
        $formView = $form->createView();
119
        $this->setFormTheme($formView, $this->admin->getFormTheme());
120
121
        return $this->render(
122
            $this->admin->getTemplateRegistry()->getTemplate('edit'),
123
            [
124
                'action' => 'edit',
125
                'form' => $formView,
126
                'object' => $object,
127
                'objectId' => $this->admin->getNormalizedIdentifier($object),
128
            ]
129
        );
130
    }
131
132
    /**
133
     * Vérifie si la soumission concerne une validation de preuve
134
     */
135
    private function isProofValidationSubmission(Request $request, $proof): bool
136
    {
137
        $formData = $request->request->all();
138
139
        // Cherche le champ status dans les données du formulaire
140
        foreach ($formData as $key => $data) {
141
            if (is_array($data) && isset($data['status'])) {
142
                $newStatus = $data['status'];
143
                $currentStatus = $proof->getStatus()->getValue();
144
145
                // Vérifie si c'est un changement de IN_PROGRESS vers ACCEPTED ou REFUSED
146
                return $currentStatus === ProofStatus::IN_PROGRESS &&
147
                    in_array($newStatus, [ProofStatus::ACCEPTED, ProofStatus::REFUSED]);
148
            }
149
        }
150
151
        return false;
152
    }
153
154
    /**
155
     * Gère la logique de validation de preuve
156
     */
157
    private function handleProofValidation($proof, Request $request): void
158
    {
159
        // Récupère le nouveau statut depuis la requête
160
        $formData = $request->request->all();
161
        $newStatus = null;
162
163
        foreach ($formData as $key => $data) {
164
            if (is_array($data) && isset($data['status'])) {
165
                $newStatus = $data['status'];
166
                break;
167
            }
168
        }
169
170
        if (!$newStatus) {
171
            return;
172
        }
173
174
        try {
175
            // Logique spécifique selon le statut
176
            if ($newStatus === ProofStatus::ACCEPTED) {
177
                $this->handleProofAccepted($proof);
178
            } elseif ($newStatus === ProofStatus::REFUSED) {
179
                $this->handleProofRefused($proof);
180
            }
181
        } catch (\Exception $e) {
182
            $this->addFlash(
183
                'sonata_flash_error',
184
                'Erreur lors de la validation de la preuve : ' . $e->getMessage()
185
            );
186
        }
187
    }
188
189
    /**
190
     * Logique à exécuter quand une preuve est acceptée
191
     */
192
    private function handleProofAccepted($proof): void
193
    {
194
        // La logique est déjà gérée dans ProofListener::postUpdate()
195
        // Mais vous pouvez ajouter ici des traitements supplémentaires comme :
196
        // - Logging spécifique
197
        // - Notifications custom
198
        // - Mise à jour de statistiques
199
200
        $playerChart = $proof->getPlayerChart();
201
        if ($playerChart) {
202
            // Le statut du PlayerChart sera automatiquement mis à jour par le listener
203
            // à PlayerChartStatus::ID_STATUS_PROOVED
204
        }
205
    }
206
207
    /**
208
     * Logique à exécuter quand une preuve est refusée
209
     */
210
    private function handleProofRefused($proof): void
211
    {
212
        // La logique est déjà gérée dans ProofListener::postUpdate()
213
        // Mais vous pouvez ajouter ici des traitements supplémentaires
214
215
        $playerChart = $proof->getPlayerChart();
216
        if ($playerChart) {
217
            // Le statut du PlayerChart sera automatiquement ajusté par le listener
218
        }
219
    }
220
221
    /**
222
     * Génère le message de confirmation selon le statut
223
     */
224
    private function getProofValidationMessage($proof): string
225
    {
226
        $status = $proof->getStatus()->getValue();
227
        $playerName = $proof->getPlayerChart() ?
228
            $proof->getPlayerChart()->getPlayer()->getPseudo() :
229
            $this->trans('proof.unknown.player', [], 'VgrCoreAdmin');
230
231
        switch ($status) {
232
            case ProofStatus::ACCEPTED:
233
                return $this->trans(
234
                    'proof.success.accepted',
235
                    ['%player%' => $playerName],
236
                    'VgrCoreAdmin'
237
                );
238
            case ProofStatus::REFUSED:
239
                return $this->trans(
240
                    'proof.success.refused',
241
                    ['%player%' => $playerName],
242
                    'VgrCoreAdmin'
243
                );
244
            default:
245
                return $this->trans(
246
                    'flash_edit_success',
247
                    ['%name%' => $this->escapeHtml($this->admin->toString($proof))],
248
                    'SonataAdminBundle'
249
                );
250
        }
251
    }
252
253
    /**
254
     * Trouve la prochaine preuve à valider dans le même jeu
255
     */
256
    private function getNextProofRedirect($currentProof): ?RedirectResponse
257
    {
258
        // Récupère le jeu de la preuve actuelle
259
        $currentGame = $currentProof->getChart()->getGroup()->getGame();
260
261
        $proofRepository = $this->em->getRepository('VideoGamesRecords\CoreBundle\Entity\Proof');
262
263
        $nextProof = $proofRepository->findNextInProgressByGame(
264
            $currentGame,
265
            $currentProof->getId()
266
        );
267
268
        if ($nextProof) {
269
            // Message informatif sur le nombre de preuves restantes
270
            $remainingCount = $proofRepository->countInProgressByGame($currentGame);
271
            $this->addFlash(
272
                'sonata_flash_info',
273
                $this->trans(
274
                    'proof.next.redirect.info',
275
                    [
276
                        '%game%' => $currentGame->getName(),
277
                        '%count%' => $remainingCount - 1, // -1 car on vient de traiter une preuve
278
                        '%next_id%' => $nextProof->getId()
279
                    ],
280
                    'VgrCoreAdmin'
281
                )
282
            );
283
284
            // Redirection vers la prochaine preuve
285
            return new RedirectResponse(
286
                $this->admin->generateUrl('edit', ['id' => $nextProof->getId()])
287
            );
288
        }
289
290
        // Aucune autre preuve dans le même jeu, redirection vers la liste
291
        return new RedirectResponse(
292
            $this->admin->generateUrl('list')
293
        );
294
    }
295
}
296