Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
DuplicationController
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 5
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 newAction
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
12
 processingAction
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 duplicateAction
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 revertAction
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3/**
4 * This file is part of the MADIS - RGPD Management application.
5 *
6 * @copyright Copyright (c) 2018-2019 Soluris - Solutions Numériques Territoriales Innovantes
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22declare(strict_types=1);
23
24namespace App\Domain\Admin\Controller;
25
26use App\Domain\Admin\Cloner\ClonerProvider;
27use App\Domain\Admin\Dictionary\DuplicationTypeDictionary;
28use App\Domain\Admin\DTO\DuplicationFormDTO;
29use App\Domain\Admin\Form\Type\DuplicationType;
30use App\Domain\Admin\Hydrator\DuplicationHydrator;
31use App\Domain\Admin\Model\DuplicatedObject;
32use App\Domain\Admin\Model\Duplication;
33use App\Domain\Admin\Repository as AdminRepository;
34use App\Domain\Admin\Transformer\DuplicationFormDTOTransformer;
35use App\Domain\User\Repository as UserRepository;
36use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
37// utilisés dynamiquements pour revert duplication, ne pas supprimer
38use Symfony\Component\HttpFoundation\JsonResponse;
39use Symfony\Component\HttpFoundation\RequestStack;
40use Symfony\Component\HttpFoundation\Response;
41use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
42use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
43use Symfony\Contracts\Translation\TranslatorInterface;
44
45class DuplicationController extends AbstractController
46{
47    /**
48     * @var RequestStack
49     */
50    private $requestStack;
51
52    /**
53     * @var AdminRepository\Duplication
54     */
55    private $duplicationRepository;
56
57    /**
58     * @var UserRepository\Collectivity
59     */
60    private $collectivityRepository;
61
62    /**
63     * @var DuplicationHydrator
64     */
65    private $duplicationHydrator;
66
67    /**
68     * @var DuplicationFormDTOTransformer
69     */
70    private $dtoTransformer;
71
72    /**
73     * @var ClonerProvider
74     */
75    private $clonerProvider;
76    private TranslatorInterface $translator;
77
78    public function __construct(
79        RequestStack $requestStack,
80        TranslatorInterface $translator,
81        AdminRepository\Duplication $duplicationRepository,
82        UserRepository\Collectivity $collectivityRepository,
83        DuplicationHydrator $duplicationHydrator,
84        DuplicationFormDTOTransformer $dtoTransformer,
85        ClonerProvider $clonerProvider,
86    ) {
87        $this->translator             = $translator;
88        $this->requestStack           = $requestStack;
89        $this->duplicationRepository  = $duplicationRepository;
90        $this->collectivityRepository = $collectivityRepository;
91        $this->duplicationHydrator    = $duplicationHydrator;
92        $this->dtoTransformer         = $dtoTransformer;
93        $this->clonerProvider         = $clonerProvider;
94    }
95
96    /**
97     * Show new duplication page form.
98     *
99     * @throws \Exception
100     */
101    public function newAction(): Response
102    {
103        $request = $this->requestStack->getMasterRequest();
104
105        $dto  = new DuplicationFormDTO();
106        $form = $this->createForm(
107            DuplicationType::class,
108            $dto,
109            [
110                'validation_groups' => [
111                    'default',
112                ],
113            ]
114        );
115
116        $form->handleRequest($request);
117        if ($form->isSubmitted() && $form->isValid()) {
118            $model = $this->dtoTransformer->toModelObject($dto);
119            $this->duplicationRepository->insert($model);
120            // An improvement would be to persist DuplicationDTO object in database and only send DuplicationDTO ID
121
122            return $this->redirectToRoute('admin_duplication_processing', [
123                'duplicationId' => $model->getId()->toString(),
124            ]);
125        }
126
127        return $this->render('Admin/Duplication/new.html.twig', [
128            'form' => $form->createView(),
129        ]);
130    }
131
132    /**
133     * Show duplication processing page.
134     */
135    public function processingAction(string $duplicationId): Response
136    {
137        $duplication = $this->duplicationRepository->findOneById($duplicationId);
138        if (null === $duplication) {
139            throw new NotFoundHttpException('No duplication found for ID ' . $duplicationId);
140        }
141
142        $this->duplicationHydrator->hydrate($duplication);
143
144        return $this->render('Admin/Duplication/processing.html.twig', [
145            'duplication' => $duplication,
146        ]);
147    }
148
149    /**
150     * Action called with AJAX call
151     * Make duplication thanks to specified in duplication model.
152     */
153    public function duplicateAction(string $duplicationId, string $targetCollectivityId): JsonResponse
154    {
155        // Prefill objects
156        $targetCollectivity = $this->collectivityRepository->findOneById($targetCollectivityId);
157        if (null === $targetCollectivity) {
158            throw new NotFoundHttpException('No collectivity found for ID ' . $targetCollectivityId);
159        }
160        $duplication = $this->duplicationRepository->findOneById($duplicationId);
161        if (null === $duplication) {
162            throw new NotFoundHttpException('No duplication found for ID ' . $duplicationId);
163        }
164        $this->duplicationHydrator->hydrate($duplication);
165
166        // Check that targetCollectivity is a valid Duplication target
167        if (!\in_array($targetCollectivity, \iterable_to_array($duplication->getTargetCollectivities()))) {
168            throw new BadRequestHttpException('Collectivity with ID ' . $targetCollectivity->getId()->toString() . ' was not found in Duplication ' . $duplication->getId()->toString());
169        }
170
171        $this->clonerProvider->getCloner($duplication->getType())->cloneToSpecifiedTarget($duplication, $targetCollectivity);
172
173        return new JsonResponse();
174    }
175
176    public function revertAction()
177    {
178        $entityManager = $this->getDoctrine()->getManager();
179
180        $d = $entityManager->getRepository(Duplication::class)->findBy([], ['createdAt' => 'DESC'], 1);
181        if (0 === count($d)) {
182            $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
183
184            return $this->redirectToRoute('admin_duplication_new');
185        }
186        $duplicationId = $d[0];
187
188        if ($duplicationId) {
189            $duplication = $entityManager->getRepository(Duplication::class)->find($duplicationId);
190
191            $objectIdsToDelete = $duplication->getDataIds();
192
193            try {
194                $typeToDelete = DuplicationTypeDictionary::getClassName($duplication->getType());
195            } catch (\Exception $e) {
196                $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.cancel'));
197
198                return $this->redirectToRoute('admin_duplication_new');
199            }
200
201            // Aller chercher puis supprimer tous les objets liés à la duplication
202            if ($objectIdsToDelete) {
203                foreach ($objectIdsToDelete as $objectId) {
204                    $duplicatedObjects = $entityManager
205                    ->getRepository(DuplicatedObject::class)
206                    ->findBy(['duplication' => $duplication, 'originObjectId' => $objectId]);
207
208                    foreach ($duplicatedObjects as $duplicatedObject) {
209                        $objectToDelete = $entityManager->getRepository($typeToDelete)->find($duplicatedObject->getDuplicatId());
210
211                        $entityManager->remove($objectToDelete);
212                    }
213                }
214                $entityManager->remove($duplication);
215
216                $entityManager->flush();
217
218                $this->addFlash('success', $this->translator->trans('admin.duplication.flashbag.success.cancel'));
219            } else {
220                $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
221            }
222        } else {
223            $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
224        }
225
226        return $this->redirectToRoute('admin_duplication_new');
227    }
228}