Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 74
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 / 74
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 / 8
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 Doctrine\ORM\EntityManagerInterface;
37use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
38// utilisés dynamiquements pour revert duplication, ne pas supprimer
39use Symfony\Component\HttpFoundation\JsonResponse;
40use Symfony\Component\HttpFoundation\RequestStack;
41use Symfony\Component\HttpFoundation\Response;
42use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
43use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
44use Symfony\Contracts\Translation\TranslatorInterface;
45
46class DuplicationController extends AbstractController
47{
48    /**
49     * @var RequestStack
50     */
51    private $requestStack;
52
53    /**
54     * @var AdminRepository\Duplication
55     */
56    private $duplicationRepository;
57
58    /**
59     * @var UserRepository\Collectivity
60     */
61    private $collectivityRepository;
62
63    /**
64     * @var DuplicationHydrator
65     */
66    private $duplicationHydrator;
67
68    /**
69     * @var DuplicationFormDTOTransformer
70     */
71    private $dtoTransformer;
72
73    /**
74     * @var ClonerProvider
75     */
76    private $clonerProvider;
77    private TranslatorInterface $translator;
78    private EntityManagerInterface $entityManager;
79
80    public function __construct(
81        RequestStack $requestStack,
82        TranslatorInterface $translator,
83        AdminRepository\Duplication $duplicationRepository,
84        UserRepository\Collectivity $collectivityRepository,
85        DuplicationHydrator $duplicationHydrator,
86        DuplicationFormDTOTransformer $dtoTransformer,
87        ClonerProvider $clonerProvider,
88        EntityManagerInterface $entityManager,
89    ) {
90        $this->translator             = $translator;
91        $this->requestStack           = $requestStack;
92        $this->duplicationRepository  = $duplicationRepository;
93        $this->collectivityRepository = $collectivityRepository;
94        $this->duplicationHydrator    = $duplicationHydrator;
95        $this->dtoTransformer         = $dtoTransformer;
96        $this->clonerProvider         = $clonerProvider;
97        $this->entityManager          = $entityManager;
98    }
99
100    /**
101     * Show new duplication page form.
102     *
103     * @throws \Exception
104     */
105    public function newAction(): Response
106    {
107        $request = $this->requestStack->getMainRequest();
108
109        $dto  = new DuplicationFormDTO();
110        $form = $this->createForm(
111            DuplicationType::class,
112            $dto,
113            [
114                'validation_groups' => [
115                    'default',
116                ],
117            ]
118        );
119
120        $form->handleRequest($request);
121        if ($form->isSubmitted() && $form->isValid()) {
122            $model = $this->dtoTransformer->toModelObject($dto);
123            $this->duplicationRepository->insert($model);
124            // An improvement would be to persist DuplicationDTO object in database and only send DuplicationDTO ID
125
126            return $this->redirectToRoute('admin_duplication_processing', [
127                'duplicationId' => $model->getId()->toString(),
128            ]);
129        }
130
131        return $this->render('Admin/Duplication/new.html.twig', [
132            'form' => $form->createView(),
133        ]);
134    }
135
136    /**
137     * Show duplication processing page.
138     */
139    public function processingAction(string $duplicationId): Response
140    {
141        $duplication = $this->duplicationRepository->findOneById($duplicationId);
142        if (null === $duplication) {
143            throw new NotFoundHttpException('No duplication found for ID ' . $duplicationId);
144        }
145
146        $this->duplicationHydrator->hydrate($duplication);
147
148        return $this->render('Admin/Duplication/processing.html.twig', [
149            'duplication' => $duplication,
150        ]);
151    }
152
153    /**
154     * Action called with AJAX call
155     * Make duplication thanks to specified in duplication model.
156     */
157    public function duplicateAction(string $duplicationId, string $targetCollectivityId): JsonResponse
158    {
159        // Prefill objects
160        $targetCollectivity = $this->collectivityRepository->findOneById($targetCollectivityId);
161        if (null === $targetCollectivity) {
162            throw new NotFoundHttpException('No collectivity found for ID ' . $targetCollectivityId);
163        }
164        $duplication = $this->duplicationRepository->findOneById($duplicationId);
165        if (null === $duplication) {
166            throw new NotFoundHttpException('No duplication found for ID ' . $duplicationId);
167        }
168        $this->duplicationHydrator->hydrate($duplication);
169
170        // Check that targetCollectivity is a valid Duplication target
171        if (!\in_array($targetCollectivity, \iterable_to_array($duplication->getTargetCollectivities()))) {
172            throw new BadRequestHttpException('Collectivity with ID ' . $targetCollectivity->getId()->toString() . ' was not found in Duplication ' . $duplication->getId()->toString());
173        }
174
175        $this->clonerProvider->getCloner($duplication->getType())->cloneToSpecifiedTarget($duplication, $targetCollectivity);
176
177        return new JsonResponse();
178    }
179
180    public function revertAction()
181    {
182        $entityManager = $this->entityManager;
183
184        $d = $entityManager->getRepository(Duplication::class)->findBy([], ['createdAt' => 'DESC'], 1);
185        if (0 === count($d)) {
186            $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
187
188            return $this->redirectToRoute('admin_duplication_new');
189        }
190        $duplicationId = $d[0];
191
192        if ($duplicationId) {
193            $duplication = $entityManager->getRepository(Duplication::class)->find($duplicationId);
194
195            $objectIdsToDelete = $duplication->getDataIds();
196
197            try {
198                $typeToDelete = DuplicationTypeDictionary::getClassName($duplication->getType());
199            } catch (\Exception $e) {
200                $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.cancel'));
201
202                return $this->redirectToRoute('admin_duplication_new');
203            }
204
205            // Aller chercher puis supprimer tous les objets liés à la duplication
206            if ($objectIdsToDelete) {
207                foreach ($objectIdsToDelete as $objectId) {
208                    $duplicatedObjects = $entityManager
209                    ->getRepository(DuplicatedObject::class)
210                    ->findBy(['duplication' => $duplication, 'originObjectId' => $objectId]);
211
212                    foreach ($duplicatedObjects as $duplicatedObject) {
213                        $objectToDelete = $entityManager->getRepository($typeToDelete)->find($duplicatedObject->getDuplicatId());
214
215                        $entityManager->remove($objectToDelete);
216                    }
217                }
218                $entityManager->remove($duplication);
219
220                $entityManager->flush();
221
222                $this->addFlash('success', $this->translator->trans('admin.duplication.flashbag.success.cancel'));
223            } else {
224                $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
225            }
226        } else {
227            $this->addFlash('error', $this->translator->trans('admin.duplication.flashbag.error.no_data'));
228        }
229
230        return $this->redirectToRoute('admin_duplication_new');
231    }
232}