Completed
Push — master ( 60cb50...a9988a )
by WEBEWEB
01:18
created

AbstractController::getDataTablesRepository()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

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