Completed
Push — master ( 51c220...46929e )
by WEBEWEB
01:13
created

AbstractController::getDataTablesEditor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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