Completed
Push — master ( 15d87d...7defa9 )
by WEBEWEB
14:36
created

AbstractController::getDataTablesSerializer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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