Completed
Push — master ( 5a36be...3fd68a )
by WEBEWEB
01:29
created

AbstractController   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 380
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 30

Importance

Changes 0
Metric Value
wmc 31
lcom 2
cbo 30
dl 0
loc 380
rs 9.92
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A buildDataTablesResponse() 0 28 5
A dispatchDataTablesEvent() 0 14 3
A exportCallback() 0 48 3
A getDataTablesColumn() 0 19 2
A getDataTablesCSVExporter() 0 19 2
A getDataTablesEditor() 0 19 2
A getDataTablesEntityById() 0 20 2
A getDataTablesManager() 0 3 1
A getDataTablesNotification() 0 3 1
A getDataTablesProvider() 0 14 1
A getDataTablesRepository() 0 17 2
A getDataTablesSerializer() 0 3 1
A getDataTablesWrapper() 0 26 3
A handleDataTablesException() 0 13 2
A prepareActionResponse() 0 10 1
1
<?php
2
3
/*
4
 * This file is part of the jquery-datatables-bundle package.
5
 *
6
 * (c) 2018 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Bundle\JQuery\DataTablesBundle\Controller;
13
14
use Doctrine\ORM\EntityNotFoundException;
15
use Doctrine\ORM\EntityRepository;
16
use Exception;
17
use Symfony\Component\EventDispatcher\Event;
18
use Symfony\Component\HttpFoundation\JsonResponse;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\Serializer\Encoder\JsonEncoder;
22
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
23
use Symfony\Component\Serializer\Serializer;
24
use WBW\Bundle\BootstrapBundle\Controller\AbstractController as BaseController;
25
use WBW\Bundle\JQuery\DataTablesBundle\API\DataTablesColumnInterface;
26
use WBW\Bundle\JQuery\DataTablesBundle\API\DataTablesWrapperInterface;
27
use WBW\Bundle\JQuery\DataTablesBundle\Event\DataTablesEvent;
28
use WBW\Bundle\JQuery\DataTablesBundle\Event\DataTablesEvents;
29
use WBW\Bundle\JQuery\DataTablesBundle\Exception\BadDataTablesColumnException;
30
use WBW\Bundle\JQuery\DataTablesBundle\Exception\BadDataTablesCSVExporterException;
31
use WBW\Bundle\JQuery\DataTablesBundle\Exception\BadDataTablesEditorException;
32
use WBW\Bundle\JQuery\DataTablesBundle\Exception\BadDataTablesRepositoryException;
33
use WBW\Bundle\JQuery\DataTablesBundle\Exception\UnregisteredDataTablesProviderException;
34
use WBW\Bundle\JQuery\DataTablesBundle\Factory\DataTablesFactory;
35
use WBW\Bundle\JQuery\DataTablesBundle\Manager\DataTablesManager;
36
use WBW\Bundle\JQuery\DataTablesBundle\Provider\DataTablesCSVExporterInterface;
37
use WBW\Bundle\JQuery\DataTablesBundle\Provider\DataTablesEditorInterface;
38
use WBW\Bundle\JQuery\DataTablesBundle\Provider\DataTablesProviderInterface;
39
use WBW\Bundle\JQuery\DataTablesBundle\Repository\DataTablesRepositoryInterface;
40
use WBW\Library\Core\Database\PaginateHelper;
41
use WBW\Library\Core\Model\Response\ActionResponse;
42
43
/**
44
 * Abstract controller.
45
 *
46
 * @author webeweb <https://github.com/webeweb/>
47
 * @package WBW\Bundle\JQuery\DataTablesBundle\Controller
48
 * @abstract
49
 */
50
abstract class AbstractController extends BaseController {
51
52
    /**
53
     * Build a response.
54
     *
55
     * @param Request $request The request.
56
     * @param string $name The provider name.
57
     * @param ActionResponse $output The output.
58
     * @return Response Returns the response.
59
     */
60
    protected function buildDataTablesResponse(Request $request, $name, ActionResponse $output) {
61
62
        // Determines if the request is an XML HTTP request.
63
        if (true === $request->isXmlHttpRequest()) {
64
65
            // Return the response.
66
            return new JsonResponse($output);
67
        }
68
69
        // Notify the user.
70
        switch ($output->getStatus()) {
71
72
            case 200:
73
                $this->notifySuccess($output->getNotify());
74
                break;
75
76
            case 404:
77
                $this->notifyDanger($output->getNotify());
78
                break;
79
80
            case 500:
81
                $this->notifyWarning($output->getNotify());
82
                break;
83
        }
84
85
        // Return the response.
86
        return $this->redirectToRoute("jquery_datatables_index", ["name" => $name]);
87
    }
88
89
    /**
90
     * Dispatch an event.
91
     *
92
     * @param string $eventName The event name.
93
     * @param array $entities The entities.
94
     * @return Event Returns the event in case of succes, null otherwise.
95
     */
96
    protected function dispatchDataTablesEvent($eventName, array $entities) {
97
98
        // Get and check the event dispatcher.
99
        $eventDispatcher = $this->getEventDispatcher();
100
        if (null !== $eventDispatcher && false === $eventDispatcher->hasListeners($eventName)) {
101
            return null;
102
        }
103
104
        // Log a debug trace.
105
        $this->getLogger()->debug(sprintf("DataTables controller dispatch a DataTables event with name \"%s\"", $eventName));
106
107
        // Dispatch the event.
108
        return $eventDispatcher->dispatch($eventName, new DataTablesEvent($eventName, $entities));
109
    }
110
111
    /**
112
     * Export callback.
113
     *
114
     * @param DataTablesProviderInterface $dtProvider The provider.
115
     * @param DataTablesRepositoryInterface $repository The repository.
116
     * @param DataTablesCSVExporterInterface $dtExporter The exporter.
117
     * @return void
118
     */
119
    protected function exportCallback(DataTablesProviderInterface $dtProvider, DataTablesRepositoryInterface $repository, DataTablesCSVExporterInterface $dtExporter) {
120
121
        // Get the entities manager.
122
        $em = $this->getDoctrine()->getManager();
123
124
        // Open the file.
125
        $stream = fopen("php://output", "w+");
126
127
        // Export the columns.
128
        fputcsv($stream, $dtExporter->exportColumns(), ";");
129
130
        // Paginates.
131
        $total = $repository->dataTablesCountExported($dtProvider);
132
        $pages = PaginateHelper::getPagesCount($total, DataTablesRepositoryInterface::REPOSITORY_LIMIT);
133
134
        // Handle each page.
135
        for ($i = 0; $i < $pages; ++$i) {
136
137
            // Get the offset and limit.
138
            list($offset, $limit) = PaginateHelper::getPageOffsetAndLimit($i, DataTablesRepositoryInterface::REPOSITORY_LIMIT, $total);
139
140
            // Get the export query with offset and limit.
141
            $result = $repository->dataTablesExportAll($dtProvider)
142
                ->setFirstResult($offset)
143
                ->setMaxResults($limit)
144
                ->getQuery()
145
                ->iterate();
146
147
            // Handle each entity.
148
            while (false !== ($row = $result->next())) {
149
150
                // Dispatch an event.
151
                $this->dispatchDataTablesEvent(DataTablesEvents::DATATABLES_PRE_EXPORT, [$row[0]]);
152
153
                // Export the entity.
154
                fputcsv($stream, $dtExporter->exportRow($row[0]), ";");
155
156
                // Detach the entity to avoid memory consumption.
157
                $em->detach($row[0]);
158
159
                // Dispatch an event.
160
                $this->dispatchDataTablesEvent(DataTablesEvents::DATATABLES_PRE_EXPORT, [$row[0]]);
161
            }
162
        }
163
164
        // Close the file.
165
        fclose($stream);
166
    }
167
168
    /**
169
     * Get a column.
170
     *
171
     * @param DataTablesProviderInterface $dtProvider The provider.
172
     * @param string $data The data.
173
     * @return DataTablesColumnInterface Returns the column.
174
     * @throws BadDataTablesColumnException Throws a bad column exception.
175
     */
176
    protected function getDataTablesColumn(DataTablesProviderInterface $dtProvider, $data) {
177
178
        // Get the column.
179
        $dtColumn = $this->getDataTablesWrapper($dtProvider)->getColumn($data);
180
181
        // Log a debug trace.
182
        $this->getLogger()->debug(sprintf("DataTables controller search for a column with name \"%s\"", $data));
183
184
        // Check the column.
185
        if (null === $dtColumn) {
186
            throw new BadDataTablesColumnException($data);
187
        }
188
189
        // Log a debug trace.
190
        $this->getLogger()->debug(sprintf("DataTables controller found a column with name \"%s\"", $data));
191
192
        // Return the column.
193
        return $dtColumn;
194
    }
195
196
    /**
197
     * Get a CSV exporter.
198
     *
199
     * @param DataTablesProviderInterface $dtProvider The provider.
200
     * @return DataTablesCSVExporterInterface Returns the CSV exporter.
201
     * @throws UnregisteredDataTablesProviderException Throws an unregistered provider exception.
202
     * @throws BadDataTablesCSVExporterException Throws a bad CSV exporter exception.
203
     */
204
    protected function getDataTablesCSVExporter(DataTablesProviderInterface $dtProvider) {
205
206
        // Get the provider.
207
        $dtExporter = $dtProvider->getCSVExporter();
208
209
        // Log a debug trace.
210
        $this->getLogger()->debug(sprintf("DataTables controller search for a CSV exporter with name \"%s\"", $dtProvider->getName()));
211
212
        // Check the CSV exporter.
213
        if (false === ($dtExporter instanceOf DataTablesCSVExporterInterface)) {
214
            throw new BadDataTablesCSVExporterException($dtExporter);
215
        }
216
217
        // Log a debug trace.
218
        $this->getLogger()->debug(sprintf("DataTables controller found a CSV exporter with name \"%s\"", $dtProvider->getName()));
219
220
        // Return the exporter.
221
        return $dtExporter;
222
    }
223
224
    /**
225
     * Get an editor.
226
     *
227
     * @param DataTablesProviderInterface $dtProvider The provider.
228
     * @return DataTablesEditorInterface Returns the editor.
229
     * @throws UnregisteredDataTablesProviderException Throws an unregistered provider exception.
230
     * @throws BadDataTablesEditorException Throws a bad editor exception.
231
     */
232
    protected function getDataTablesEditor(DataTablesProviderInterface $dtProvider) {
233
234
        // Get the editor.
235
        $dtEditor = $dtProvider->getEditor();
236
237
        // Log a debug trace.
238
        $this->getLogger()->debug(sprintf("DataTables controller search for an editor with name \"%s\"", $dtProvider->getName()));
239
240
        // Check the CSV exporter.
241
        if (false === ($dtEditor instanceOf DataTablesEditorInterface)) {
242
            throw new BadDataTablesEditorException($dtEditor);
243
        }
244
245
        // Log a debug trace.
246
        $this->getLogger()->debug(sprintf("DataTables controller found an editor with name \"%s\"", $dtProvider->getName()));
247
248
        // Return the exporter.
249
        return $dtEditor;
250
    }
251
252
    /**
253
     * Get an entity by id.
254
     *
255
     * @param DataTablesProviderInterface $dtProvider The provider.
256
     * @param int $id The entity id.
257
     * @return object Returns the entity.
258
     * @throws BadDataTablesRepositoryException Throws a bad repository exception.
259
     * @throws EntityNotFoundException Throws an Entity not found exception.
260
     */
261
    protected function getDataTablesEntityById(DataTablesProviderInterface $dtProvider, $id) {
262
263
        // Get the repository.
264
        $repository = $this->getDataTablesRepository($dtProvider);
265
266
        // Log a debug trace.
267
        $this->getLogger()->debug(sprintf("DataTables controller search for an entity [%s]", $id));
268
269
        // Find and check the entity.
270
        $entity = $repository->find($id);
271
        if (null === $entity) {
272
            throw EntityNotFoundException::fromClassNameAndIdentifier($dtProvider->getEntity(), [$id]);
273
        }
274
275
        // Log a debug trace.
276
        $this->getLogger()->debug(sprintf("DataTables controller found an entity [%s]", $id));
277
278
        // Return the entity.
279
        return $entity;
280
    }
281
282
    /**
283
     * Get the manager.
284
     *
285
     * @return DataTablesManager Returns the manager.
286
     */
287
    protected function getDataTablesManager() {
288
        return $this->get(DataTablesManager::SERVICE_NAME);
289
    }
290
291
    /**
292
     * Get a notification.
293
     *
294
     * @param string $notificationId The notification id.
295
     * @return string Returns the notification.
296
     */
297
    protected function getDataTablesNotification($notificationId) {
298
        return $this->getTranslator()->trans($notificationId, [], "JQueryDataTablesBundle");
299
    }
300
301
    /**
302
     * Get the provider.
303
     *
304
     * @param string $name The provider name.
305
     * @return DataTablesProviderInterface Returns the provider.
306
     * @throws UnregisteredDataTablesProviderException Throws an unregistered provider exception.
307
     */
308
    protected function getDataTablesProvider($name) {
309
310
        // Log a debug trace.
311
        $this->getLogger()->debug(sprintf("DataTables controller search for a provider with name \"%s\"", $name));
312
313
        // Get the provider.
314
        $dtProvider = $this->getDataTablesManager()->getProvider($name);
315
316
        // Log a debug trace.
317
        $this->getLogger()->debug(sprintf("DataTables controller found a provider with name \"%s\"", $name));
318
319
        // Return the provider.
320
        return $dtProvider;
321
    }
322
323
    /**
324
     * Get a repository.
325
     *
326
     * @param DataTablesProviderInterface $dtProvider The provider.
327
     * @return EntityRepository Returns the repository.
328
     * @throws BadDataTablesRepositoryException Throws a bad repository exception.
329
     */
330
    protected function getDataTablesRepository(DataTablesProviderInterface $dtProvider) {
331
332
        // Log a debug trace.
333
        $this->getLogger()->debug(sprintf("DataTables controller search for a repository with name \"%s\"", $dtProvider->getName()));
334
335
        // Get the entities manager.
336
        $em = $this->getDoctrine()->getManager();
337
338
        // Get and check the entities repository.
339
        $repository = $em->getRepository($dtProvider->getEntity());
340
        if (false === ($repository instanceOf DataTablesRepositoryInterface)) {
341
            throw new BadDataTablesRepositoryException($repository);
342
        }
343
344
        // Return the repository.
345
        return $repository;
346
    }
347
348
    /**
349
     * Get a serializer.
350
     *
351
     * @return Serializer Returns the serializer.
352
     */
353
    protected function getDataTablesSerializer() {
354
        return new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
355
    }
356
357
    /**
358
     * Get a wrapper.
359
     *
360
     * @param DataTablesProviderInterface $dtProvider The provider.
361
     * @return DataTablesWrapperInterface Returns the wrapper.
362
     */
363
    protected function getDataTablesWrapper(DataTablesProviderInterface $dtProvider) {
364
365
        // Initialize the URL.
366
        $url = $this->getRouter()->generate("jquery_datatables_index", ["name" => $dtProvider->getName()]);
367
368
        // Initialize the wrapper.
369
        $dtWrapper = DataTablesFactory::newWrapper($url, $dtProvider);
370
371
        // Handle each column.
372
        foreach ($dtProvider->getColumns() as $dtColumn) {
373
374
            // Log a debug trace.
375
            $this->getLogger()->debug(sprintf("DataTables provider add a column \"%s\"", $dtColumn->getData()));
376
377
            // Add the column.
378
            $dtWrapper->addColumn($dtColumn);
379
        }
380
381
        // Set the options.
382
        if (null !== $dtProvider->getOptions()) {
383
            $dtWrapper->setOptions($dtProvider->getOptions());
384
        }
385
386
        // Return the wrapper.
387
        return $dtWrapper;
388
    }
389
390
    /**
391
     * Handle an exception.
392
     *
393
     * @param Exception $ex The exception.
394
     * @param string $notificationBaseId The notification base id.
395
     * @return ActionResponse Returns the action response.
396
     */
397
    protected function handleDataTablesException(Exception $ex, $notificationBaseId) {
398
399
        // Log a debug trace.
400
        $this->getLogger()->debug($ex->getMessage());
401
402
        // Check the exception.
403
        if (true === ($ex instanceof EntityNotFoundException)) {
404
            return $this->prepareActionResponse(404, $notificationBaseId . ".danger");
405
        }
406
407
        // Return a default action response.
408
        return $this->prepareActionResponse(500, $notificationBaseId . ".warning");
409
    }
410
411
    /**
412
     * Prepare an action response.
413
     *
414
     * @param int $status The status.
415
     * @param string $notificationId The notification id.
416
     * @return ActionResponse Returns the action response.
417
     */
418
    protected function prepareActionResponse($status, $notificationId) {
419
420
        // Initialize the action response.
421
        $response = new ActionResponse();
422
        $response->setStatus($status);
423
        $response->setNotify($this->getDataTablesNotification($notificationId));
424
425
        // Return the action response.
426
        return $response;
427
    }
428
429
}
430