Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
30.09% covered (danger)
30.09%
34 / 113
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ReviewController
30.09% covered (danger)
30.09%
34 / 113
16.67% covered (danger)
16.67%
1 / 6
156.68
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 indexAction
72.41% covered (warning)
72.41%
21 / 29
0.00% covered (danger)
0.00%
0 / 1
12.10
 zipAction
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
42
 zipConfirmAction
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 listDataTables
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLabelAndKeysArray
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
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\Reporting\Controller;
25
26use App\Application\Symfony\Security\UserProvider;
27use App\Application\Traits\ServersideDatatablesTrait;
28use App\Domain\Maturity\Repository as MaturityRepository;
29use App\Domain\Registry\Repository;
30use App\Domain\Reporting\Handler\WordHandler;
31use App\Infrastructure\ORM\Registry\Repository\ConformiteOrganisation\Evaluation;
32use App\Infrastructure\ORM\User\Repository\Collectivity as CollectivityRepository;
33use PhpOffice\PhpWord\PhpWord;
34use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
35use Symfony\Component\HttpFoundation\BinaryFileResponse;
36use Symfony\Component\HttpFoundation\JsonResponse;
37use Symfony\Component\HttpFoundation\Request;
38use Symfony\Component\HttpFoundation\Response;
39use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
40use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
41use Symfony\Component\Security\Core\Security;
42use Symfony\Component\String\Slugger\AsciiSlugger;
43
44class ReviewController extends AbstractController
45{
46    use ServersideDatatablesTrait;
47    /**
48     * @var WordHandler
49     */
50    private $wordHandler;
51
52    /**
53     * @var UserProvider
54     */
55    private $userProvider;
56
57    /**
58     * @var AuthorizationCheckerInterface
59     */
60    private $authorizationChecker;
61
62    /**
63     * @var Repository\Treatment;
64     */
65    private $treatmentRepository;
66
67    /**
68     * @var Repository\Contractor;
69     */
70    private $contractorRepository;
71
72    /**
73     * @var Repository\Tool;
74     */
75    private $toolRepository;
76
77    /**
78     * @var Repository\Mesurement;
79     */
80    private $mesurementRepository;
81
82    /**
83     * @var Repository\Request
84     */
85    private $requestRepository;
86
87    /**
88     * @var MaturityRepository\Survey;
89     */
90    private $surveyRepository;
91
92    /**
93     * @var Repository\Violation
94     */
95    private $violationRepository;
96
97    /**
98     * @var Evaluation
99     */
100    private $evaluationRepository;
101
102    /**
103     * @var Security
104     */
105    protected $security;
106
107    public function __construct(
108        WordHandler $wordHandler,
109        UserProvider $userProvider,
110        AuthorizationCheckerInterface $authorizationChecker,
111        Repository\Treatment $treatmentRepository,
112        Repository\Contractor $contractorRepository,
113        Repository\Mesurement $mesurementRepository,
114        Repository\Request $requestRepository,
115        Repository\Violation $violationRepository,
116        Repository\Tool $toolRepository,
117        MaturityRepository\Survey $surveyRepository,
118        CollectivityRepository $repository,
119        Repository\ConformiteOrganisation\Evaluation $evaluationRepository,
120        Security $security,
121    ) {
122        $this->wordHandler          = $wordHandler;
123        $this->userProvider         = $userProvider;
124        $this->authorizationChecker = $authorizationChecker;
125        $this->treatmentRepository  = $treatmentRepository;
126        $this->contractorRepository = $contractorRepository;
127        $this->mesurementRepository = $mesurementRepository;
128        $this->requestRepository    = $requestRepository;
129        $this->violationRepository  = $violationRepository;
130        $this->surveyRepository     = $surveyRepository;
131        $this->repository           = $repository;
132        $this->evaluationRepository = $evaluationRepository;
133        $this->toolRepository       = $toolRepository;
134        $this->security             = $security;
135    }
136
137    /**
138     * Download an entire review.
139     *
140     * @throws \PhpOffice\PhpWord\Exception\Exception
141     * @throws \Exception
142     */
143    public function indexAction(string $id): BinaryFileResponse
144    {
145        /**
146         * @var CollectivityRepository $repo
147         */
148        $repo = $this->repository;
149        $user = $this->userProvider->getAuthenticatedUser();
150        // By default get the users collectivity, ignoring the ID passed in the URL
151        $collectivity = $user->getCollectivity();
152
153        if ($id && $this->security->isGranted('ROLE_REFERENT') && !$this->security->isGranted('ROLE_ADMIN')) {
154            // If the user is a referent and they are part of this collectivity
155            foreach ($user->getCollectivitesReferees() as $col) {
156                if ($col->getId() === $id) {
157                    $collectivity = $repo->findOneById($id);
158                }
159            }
160        }
161
162        if ($this->security->isGranted('ROLE_ADMIN')) {
163            $collectivity = $repo->findOneById($id);
164        }
165
166        if (!$collectivity) {
167            throw new NotFoundHttpException('No collectivity found');
168        }
169
170        $maturity = [];
171        // Get most recent maturity index that has a referentiel
172        $objects = $this->surveyRepository->findAllByCollectivity($collectivity, ['createdAt' => 'DESC'], 1, ['o.referentiel is not null']);
173
174        if (1 <= \count($objects)) {
175            $maturity['new'] = $objects[0];
176
177            $previous = $this->surveyRepository->findAllByCollectivity($collectivity, ['createdAt' => 'DESC'], 2, ['referentiel' => $maturity['new']->getReferentiel()]);
178            if (2 <= \count($previous)) {
179                $maturity['old'] = $previous[1];
180            }
181        }
182
183        $this->wordHandler->setCollectivity($collectivity);
184
185        return $this->wordHandler->generateOverviewReport(
186            $this->treatmentRepository->findAllActiveByCollectivity($collectivity),
187            $this->contractorRepository->findAllByCollectivity($collectivity),
188            $this->mesurementRepository->findAllByCollectivity($collectivity),
189            $maturity,
190            $this->requestRepository->findAllArchivedByCollectivity($collectivity, false),
191            $this->violationRepository->findAllArchivedByCollectivity($collectivity, false),
192            $this->toolRepository->findAllByCollectivity($collectivity),
193            $this->evaluationRepository->findLastByOrganisation($collectivity)
194        );
195    }
196
197    /**
198     * Download a zip of all visible reviews.
199     *
200     * @throws \PhpOffice\PhpWord\Exception\Exception
201     * @throws \Exception
202     */
203    public function zipAction(Request $request): Response
204    {
205        $ids = $request->get('ids');
206        /** @var CollectivityRepository $repository */
207        $repository     = $this->repository;
208        $collectivities = $repository->findByIds($ids);
209
210        $files = [];
211        foreach ($collectivities as $collectivity) {
212            $maturity = [];
213            // Get most recent maturity index that has a referentiel
214            $objects = $this->surveyRepository->findAllByCollectivity($collectivity, ['createdAt' => 'DESC'], 1, ['o.referentiel is not null']);
215
216            if (1 <= \count($objects)) {
217                $maturity['new'] = $objects[0];
218
219                $previous = $this->surveyRepository->findAllByCollectivity($collectivity, ['createdAt' => 'DESC'], 2, ['referentiel' => $maturity['new']->getReferentiel()]);
220                if (2 <= \count($previous)) {
221                    $maturity['old'] = $previous[1];
222                }
223            }
224            $this->wordHandler->setCollectivity($collectivity);
225            $this->wordHandler->setDocument(new PhpWord());
226            $response = $this->wordHandler->generateOverviewReport(
227                $this->treatmentRepository->findAllActiveByCollectivity($collectivity),
228                $this->contractorRepository->findAllByCollectivity($collectivity),
229                $this->mesurementRepository->findAllByCollectivity($collectivity),
230                $maturity,
231                $this->requestRepository->findAllArchivedByCollectivity($collectivity, false),
232                $this->violationRepository->findAllArchivedByCollectivity($collectivity, false),
233                $this->toolRepository->findAllByCollectivity($collectivity),
234                $this->evaluationRepository->findLastByOrganisation($collectivity),
235            );
236
237            $files[] = ['file' => $response->getFile(), 'collectivity' => $collectivity];
238        }
239
240        // Zip all files
241
242        // Create new Zip Archive.
243        $zip = new \ZipArchive();
244
245        // The name of the Zip documents.
246        $currentDate = (new \DateTimeImmutable())->format('Ymd');
247        $zipName     = "bilans-{$currentDate}.zip";
248        @unlink($zipName);
249        $zip->open($zipName, \ZipArchive::CREATE);
250        $used = [];
251        foreach ($files as $file) {
252            $slugger = new AsciiSlugger();
253            $cname   = $slugger->slug($file['collectivity']->getShortName())->lower()->toString();
254            $newname = $cname;
255            $i       = 1;
256            while (in_array($newname, $used)) {
257                $newname = $cname . '-' . $i;
258                ++$i;
259            }
260            $used[]      = $newname;
261            $zipFileName = "{$currentDate}-bilan-{$newname}.doc";
262            $zip->addFromString($zipFileName, file_get_contents($file['file']->getRealPath()));
263        }
264        $zip->close();
265
266        $response = new Response(file_get_contents($zipName));
267
268        $response->headers->set('Content-Type', 'application/zip');
269        $response->headers->set('Content-length', filesize($zipName));
270        $response->headers->set('Content-Disposition', 'attachment; filename="' . basename($zipName) . '";');
271
272        @unlink($zipName);
273
274        return $response;
275    }
276
277    /**
278     * Download a zip of all visible reviews.
279     *
280     * @throws \PhpOffice\PhpWord\Exception\Exception
281     * @throws \Exception
282     */
283    public function zipConfirmAction(Request $request): Response
284    {
285        $ids = $request->get('ids');
286        /** @var CollectivityRepository $repository */
287        $repository     = $this->repository;
288        $collectivities = $repository->findByIds($ids);
289
290        return $this->render('User/Collectivity/confirm_generate_bilans.html.twig', [ // delete_all
291            'collectivities' => $collectivities,
292        ]);
293    }
294
295    public function listDataTables(Request $request): JsonResponse
296    {
297        // Do nothing here
298        return new JsonResponse();
299    }
300
301    protected function getLabelAndKeysArray(): array
302    {
303        return [
304            'nom',
305            'nom_court',
306            'type',
307            'informations_complementaires',
308            'statut',
309            'date_maj',
310            'population',
311            'nbr_agents',
312            'nbr_cnil',
313            'createdAt',
314            'updatedAt',
315            'actions',
316            'id',
317        ];
318    }
319}