• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

webeweb / jquery-datatables-bundle / 9657863695

25 Jun 2024 06:54AM UTC coverage: 99.814% (+0.001%) from 99.813%
9657863695

push

github

webeweb
Add DataTables service

3750 of 3757 relevant lines covered (99.81%)

213.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.84
/src/Controller/AbstractController.php
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
declare(strict_types = 1);
13

14
namespace WBW\Bundle\DataTablesBundle\Controller;
15

16
use Doctrine\ORM\EntityNotFoundException;
17
use Doctrine\ORM\EntityRepository;
18
use Symfony\Component\HttpFoundation\JsonResponse;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpFoundation\Response;
21
use Throwable;
22
use WBW\Bundle\BootstrapBundle\Controller\AbstractController as BaseController;
23
use WBW\Bundle\DataTablesBundle\Event\DataTablesEvent;
24
use WBW\Bundle\DataTablesBundle\Exception\BadDataTablesColumnException;
25
use WBW\Bundle\DataTablesBundle\Exception\BadDataTablesCsvExporterException;
26
use WBW\Bundle\DataTablesBundle\Exception\BadDataTablesEditorException;
27
use WBW\Bundle\DataTablesBundle\Exception\BadDataTablesRepositoryException;
28
use WBW\Bundle\DataTablesBundle\Exception\UnregisteredDataTablesProviderException;
29
use WBW\Bundle\DataTablesBundle\Factory\DataTablesFactory;
30
use WBW\Bundle\DataTablesBundle\Helper\DataTablesExportHelper;
31
use WBW\Bundle\DataTablesBundle\Manager\DataTablesManagerTrait;
32
use WBW\Bundle\DataTablesBundle\Model\DataTablesColumnInterface;
33
use WBW\Bundle\DataTablesBundle\Model\DataTablesEntityInterface;
34
use WBW\Bundle\DataTablesBundle\Model\DataTablesWrapperInterface;
35
use WBW\Bundle\DataTablesBundle\Provider\DataTablesCsvExporterInterface;
36
use WBW\Bundle\DataTablesBundle\Provider\DataTablesEditorInterface;
37
use WBW\Bundle\DataTablesBundle\Provider\DataTablesProviderInterface;
38
use WBW\Bundle\DataTablesBundle\Provider\DataTablesRouterInterface;
39
use WBW\Bundle\DataTablesBundle\Repository\DataTablesRepositoryInterface;
40
use WBW\Bundle\DataTablesBundle\WBWDataTablesBundle;
41
use WBW\Library\Common\Database\Paginator;
42
use WBW\Library\Common\Model\Response\SimpleJsonResponseData;
43
use WBW\Library\Common\Model\Response\SimpleJsonResponseDataInterface;
44

45
/**
46
 * Abstract controller.
47
 *
48
 * @author webeweb <https://github.com/webeweb>
49
 * @package WBW\Bundle\DataTablesBundle\Controller
50
 * @abstract
51
 */
52
abstract class AbstractController extends BaseController {
53

54
    use DataTablesManagerTrait {
55
        setDataTablesManager as public;
56
    }
57

58
    /**
59
     * Build a response.
60
     *
61
     * @param Request $request The request.
62
     * @param string $name The provider name.
63
     * @param SimpleJsonResponseDataInterface $output The output.
64
     * @return Response Returns the response.
65
     * @throws Throwable Throws an exception if an error occurs.
66
     */
67
    protected function buildDataTablesResponse(Request $request, string $name, SimpleJsonResponseDataInterface $output): Response {
68

69
        if (true === $request->isXmlHttpRequest()) {
84✔
70
            return new JsonResponse($output);
42✔
71
        }
72

73
        switch ($output->getStatus()) {
42✔
74

75
            case 200:
42✔
76
                $this->notifySuccess($output->getNotify());
21✔
77
                break;
21✔
78

79
            case 404:
21✔
80
                $this->notifyDanger($output->getNotify());
21✔
81
                break;
21✔
82

83
            case 500:
×
84
                $this->notifyWarning($output->getNotify());
×
85
                break;
×
86
        }
87

88
        return $this->redirectToRoute("wbw_datatables_index", ["name" => $name]);
42✔
89
    }
90

91
    /**
92
     * Dispatch an event.
93
     *
94
     * @param object[] $entities The entities.
95
     * @param string $eventName The event name.
96
     * @param DataTablesProviderInterface|null $provider The provider.
97
     * @return DataTablesEvent Returns the event.
98
     * @throws Throwable Throws an exception if an error occurs.
99
     */
100
    protected function dispatchDataTablesEvent(array $entities, string $eventName, ?DataTablesProviderInterface $provider = null): DataTablesEvent {
101

102
        $event = new DataTablesEvent($entities, $eventName, $provider);
336✔
103
        $this->dispatchEvent($event, $eventName);
336✔
104

105
        return $event;
336✔
106
    }
107

108
    /**
109
     * Export callback.
110
     *
111
     * @param DataTablesWrapperInterface $dtWrapper The wrapper.
112
     * @param DataTablesRepositoryInterface $repository The repository.
113
     * @param DataTablesCsvExporterInterface $dtExporter The exporter.
114
     * @param bool $windows Windows ?
115
     * @return void
116
     * @throws Throwable Throws an exception if an error occurs.
117
     */
118
    protected function exportDataTablesCallback(DataTablesWrapperInterface $dtWrapper, DataTablesRepositoryInterface $repository, DataTablesCsvExporterInterface $dtExporter, bool $windows): void {
119

120
        $stream = fopen("php://output", "w+");
21✔
121
        fputcsv($stream, DataTablesExportHelper::convert($dtExporter->exportColumns(), $windows), ";");
21✔
122

123
        // Paginates.
124
        $total = $repository->dataTablesCountExported($dtWrapper);
21✔
125
        $pages = Paginator::countPages($total, DataTablesRepositoryInterface::REPOSITORY_LIMIT);
21✔
126

127
        $em = $this->getEntityManager();
21✔
128

129
        for ($i = 0; $i < $pages; ++$i) {
21✔
130

131
            // Get the offset and limit.
132
            [$offset, $limit] = Paginator::offsetLimit($i, DataTablesRepositoryInterface::REPOSITORY_LIMIT, $total);
21✔
133

134
            // Get the export query with offset and limit.
135
            $query = $repository->dataTablesExportAll($dtWrapper)
21✔
136
                ->setFirstResult($offset)
21✔
137
                ->setMaxResults($limit)
21✔
138
                ->getQuery();
21✔
139

140
            foreach ($query->toIterable() as $entity) {
21✔
141

142
                $this->dispatchDataTablesEvent([$entity], DataTablesEvent::PRE_EXPORT, $dtWrapper->getProvider());
21✔
143

144
                fputcsv($stream, DataTablesExportHelper::convert($dtExporter->exportRow($entity), $windows), ";");
21✔
145

146
                $this->dispatchDataTablesEvent([$entity], DataTablesEvent::POST_EXPORT, $dtWrapper->getProvider());
21✔
147
            }
148

149
            $em->clear(); // Detach the entity to avoid memory consumption.
21✔
150
        }
151

152
        fclose($stream);
21✔
153
    }
8✔
154

155
    /**
156
     * Get a column.
157
     *
158
     * @param DataTablesProviderInterface $dtProvider The provider.
159
     * @param string $data The data.
160
     * @return DataTablesColumnInterface Returns the column.
161
     * @throws BadDataTablesColumnException Throws a bad column exception.
162
     * @throws Throwable Throws an exception if an error occurs.
163
     */
164
    protected function getDataTablesColumn(DataTablesProviderInterface $dtProvider, string $data): DataTablesColumnInterface {
165

166
        $dtWrapper = $this->getDataTablesWrapper($dtProvider);
84✔
167

168
        $context = [
52✔
169
            "_controller" => get_class($this),
84✔
170
            "_provider"   => get_class($dtProvider),
84✔
171
            "_wrapper"    => get_class($dtWrapper),
84✔
172
        ];
52✔
173

174
        $this->logInfo(sprintf('DataTables controller search for a column with name "%s"', $data), $context);
84✔
175

176
        $dtColumn = $dtWrapper->getColumn($data);
84✔
177
        if (null === $dtColumn) {
84✔
178
            throw new BadDataTablesColumnException($data);
21✔
179
        }
180

181
        $context["_column"] = get_class($dtColumn);
63✔
182

183
        $this->logInfo(sprintf('DataTables controller found a column with name "%s"', $data), $context);
63✔
184

185
        return $dtColumn;
63✔
186
    }
187

188
    /**
189
     * Get a CSV exporter.
190
     *
191
     * @param DataTablesProviderInterface $dtProvider The provider.
192
     * @return DataTablesCsvExporterInterface Returns the CSV exporter.
193
     * @throws BadDataTablesCsvExporterException Throws a bad CSV exporter exception.
194
     * @throws Throwable Throws an exception if an error occurs.
195
     */
196
    protected function getDataTablesCsvExporter(DataTablesProviderInterface $dtProvider): DataTablesCsvExporterInterface {
197

198
        $context = [
26✔
199
            "_controller" => get_class($this),
42✔
200
            "_provider"   => get_class($dtProvider),
42✔
201
        ];
26✔
202

203
        $this->logInfo(sprintf('DataTables controller search for a CSV exporter with name "%s"', $dtProvider->getName()), $context);
42✔
204

205
        $dtExporter = $dtProvider->getCsvExporter();
42✔
206
        if (false === ($dtExporter instanceof DataTablesCsvExporterInterface)) {
42✔
207
            throw new BadDataTablesCsvExporterException($dtExporter);
21✔
208
        }
209

210
        $context["_exporter"] = get_class($dtExporter);
21✔
211

212
        $this->logInfo(sprintf('DataTables controller found a CSV exporter with name "%s"', $dtProvider->getName()), $context);
21✔
213

214
        return $dtExporter;
21✔
215
    }
216

217
    /**
218
     * Get an editor.
219
     *
220
     * @param DataTablesProviderInterface $dtProvider The provider.
221
     * @return DataTablesEditorInterface Returns the editor.
222
     * @throws BadDataTablesEditorException Throws a bad editor exception.
223
     * @throws Throwable Throws an exception if an error occurs.
224
     */
225
    protected function getDataTablesEditor(DataTablesProviderInterface $dtProvider): DataTablesEditorInterface {
226

227
        $context = [
65✔
228
            "_controller" => get_class($this),
105✔
229
            "_provider"   => get_class($dtProvider),
105✔
230
        ];
65✔
231

232
        $this->logInfo(sprintf('DataTables controller search for an editor with name "%s"', $dtProvider->getName()), $context);
105✔
233

234
        $dtEditor = $dtProvider->getEditor();
105✔
235
        if (false === ($dtEditor instanceof DataTablesEditorInterface)) {
105✔
236
            throw new BadDataTablesEditorException($dtEditor);
21✔
237
        }
238

239
        $context["_editor"] = get_class($dtEditor);
84✔
240

241
        $this->logInfo(sprintf('DataTables controller found an editor with name "%s"', $dtProvider->getName()), $context);
84✔
242

243
        return $dtEditor;
84✔
244
    }
245

246
    /**
247
     * Get an entity by id.
248
     *
249
     * @param DataTablesProviderInterface $dtProvider The provider.
250
     * @param mixed $id The entity id.
251
     * @return object Returns the entity.
252
     * @throws BadDataTablesRepositoryException Throws a bad repository exception.
253
     * @throws EntityNotFoundException Throws an Entity not found exception.
254
     * @throws Throwable Throws an exception if an error occurs.
255
     */
256
    protected function getDataTablesEntityById(DataTablesProviderInterface $dtProvider, $id) {
257

258
        /** @var EntityRepository<DataTablesEntityInterface> $repository */
259
        $repository = $this->getDataTablesRepository($dtProvider);
231✔
260

261
        $context = [
143✔
262
            "_controller" => get_class($this),
231✔
263
            "_provider"   => get_class($dtProvider),
231✔
264
            "_repository" => get_class($repository),
231✔
265
        ];
143✔
266

267
        $this->logInfo(sprintf("DataTables controller search for an entity with id [%s]", $id), $context);
231✔
268

269
        $entity = $repository->find($id);
231✔
270
        if (null === $entity) {
231✔
271
            throw EntityNotFoundException::fromClassNameAndIdentifier($dtProvider->getEntity(), [$id]);
105✔
272
        }
273

274
        $context["_entity"] = get_class($entity);
126✔
275

276
        $this->logInfo(sprintf("DataTables controller found an entity with id [%s]", $id), $context);
126✔
277

278
        return $entity;
126✔
279
    }
280

281
    /**
282
     * Get the provider.
283
     *
284
     * @param string $name The provider name.
285
     * @return DataTablesProviderInterface Returns the provider.
286
     * @throws Throwable Throws an exception if an error occurs.
287
     * @throws UnregisteredDataTablesProviderException Throws an unregistered provider exception.
288
     */
289
    protected function getDataTablesProvider(string $name): DataTablesProviderInterface {
290

291
        $dtManager = $this->getDataTablesManager();
630✔
292

293
        $context = [
390✔
294
            "_controller" => get_class($this),
630✔
295
            "_manager"    => get_class($dtManager),
630✔
296
        ];
390✔
297

298
        $this->logInfo(sprintf('DataTables controller search for a provider with name "%s"', $name), $context);
630✔
299

300
        $dtProvider = $dtManager->getProvider($name);
630✔
301

302
        $context["_provider"] = get_class($dtProvider);
630✔
303

304
        $this->logInfo(sprintf('DataTables controller found a provider with name "%s"', $name), $context);
630✔
305

306
        return $dtProvider;
630✔
307
    }
308

309
    /**
310
     * Get a repository.
311
     *
312
     * @param DataTablesProviderInterface $dtProvider The provider.
313
     * @return DataTablesRepositoryInterface Returns the repository.
314
     * @throws BadDataTablesRepositoryException Throws a bad repository exception.
315
     * @throws Throwable Throws an exception if an error occurs.
316
     */
317
    protected function getDataTablesRepository(DataTablesProviderInterface $dtProvider): DataTablesRepositoryInterface {
318

319
        $em = $this->getEntityManager();
462✔
320

321
        $context = [
286✔
322
            "_controller" => get_class($this),
462✔
323
            "_provider"   => get_class($dtProvider),
462✔
324
            "_entity"     => $dtProvider->getEntity(),
462✔
325
        ];
286✔
326

327
        $this->logInfo(sprintf('DataTables controller search for a repository with name "%s"', $dtProvider->getName()), $context);
462✔
328

329
        /** @var EntityRepository<DataTablesEntityInterface> $repository */
330
        $repository = $em->getRepository($dtProvider->getEntity());
462✔
331
        if (false === ($repository instanceof DataTablesRepositoryInterface)) {
462✔
332
            throw new BadDataTablesRepositoryException($repository);
21✔
333
        }
334

335
        $context["_repository"] = get_class($repository);
441✔
336

337
        $this->logInfo(sprintf('DataTables controller found a repository with name "%s"', $dtProvider->getName()), $context);
441✔
338

339
        /** @var DataTablesRepositoryInterface $repository */
340
        return $repository;
441✔
341
    }
342

343
    /**
344
     * Get a URL.
345
     *
346
     * @param DataTablesProviderInterface $dtProvider The provider.
347
     * @return string Returns the URL.
348
     * @throws Throwable Throws an exception if an error occurs.
349
     */
350
    protected function getDataTablesUrl(DataTablesProviderInterface $dtProvider): string {
351

352
        $context = [
273✔
353
            "_controller" => get_class($this),
441✔
354
            "_provider"   => get_class($dtProvider),
441✔
355
        ];
273✔
356

357
        $this->logInfo(sprintf('DataTables controller search for an URL with name "%s"', $dtProvider->getName()), $context);
441✔
358

359
        if (true === ($dtProvider instanceof DataTablesRouterInterface)) {
441✔
360
            $url = $dtProvider->getUrl();
21✔
361
        } else {
362
            $url = $this->getRouter()->generate("wbw_datatables_index", ["name" => $dtProvider->getName()]);
420✔
363
        }
364

365
        $context["_url"] = $url;
441✔
366

367
        $this->logInfo(sprintf('DataTables controller found for an URL with name "%s"', $dtProvider->getName()), $context);
441✔
368

369
        return $url;
441✔
370
    }
371

372
    /**
373
     * Get a wrapper.
374
     *
375
     * @param DataTablesProviderInterface $dtProvider The provider.
376
     * @return DataTablesWrapperInterface Returns the wrapper.
377
     * @throws Throwable Throws an exception if an error occurs.
378
     */
379
    protected function getDataTablesWrapper(DataTablesProviderInterface $dtProvider): DataTablesWrapperInterface {
380

381
        $dtWrapper = DataTablesFactory::newWrapper($this->getDataTablesUrl($dtProvider), $dtProvider, $this->getUser());
441✔
382

383
        $context = [
273✔
384
            "_controller" => get_class($this),
441✔
385
            "_provider"   => get_class($dtProvider),
441✔
386
            "_wrapper"    => get_class($dtWrapper),
441✔
387
        ];
273✔
388

389
        foreach ($dtProvider->getColumns() as $dtColumn) {
441✔
390

391
            $this->logInfo(sprintf('DataTables controller add a column "%s" with the provider "%s"', $dtColumn->getData(), $dtProvider->getName()), $context);
441✔
392

393
            $dtWrapper->addColumn($dtColumn);
441✔
394
        }
395

396
        if (null !== $dtProvider->getOptions()) {
441✔
397
            $dtWrapper->setOptions($dtProvider->getOptions());
420✔
398
        }
399

400
        return $dtWrapper;
441✔
401
    }
402

403
    /**
404
     * Handle an exception.
405
     *
406
     * @param Throwable $ex The exception.
407
     * @param string $notificationBaseId The notification base id.
408
     * @return SimpleJsonResponseDataInterface Returns the action response.
409
     * @throws Throwable Throws an exception if an error occurs.
410
     */
411
    protected function handleDataTablesException(Throwable $ex, string $notificationBaseId): SimpleJsonResponseDataInterface {
412

413
        $this->logInfo($ex->getMessage());
84✔
414

415
        if (true === ($ex instanceof EntityNotFoundException)) {
84✔
416
            return $this->prepareActionResponse(404, $notificationBaseId . ".danger");
63✔
417
        }
418

419
        return $this->prepareActionResponse(500, $notificationBaseId . ".warning");
21✔
420
    }
421

422
    /**
423
     * Log an info.
424
     *
425
     * @param string $message The message.
426
     * @param mixed[] $context The context.
427
     * @return AbstractController Returns this controller.
428
     * @throws Throwable Throws an exception if an error occurs.
429
     */
430
    protected function logInfo(string $message, array $context = []): AbstractController {
431
        $this->getLogger()->info($message, $context);
630✔
432
        return $this;
630✔
433
    }
434

435
    /**
436
     * Prepare an action response.
437
     *
438
     * @param int $status The status.
439
     * @param string $notificationId The notification id.
440
     * @return SimpleJsonResponseDataInterface Returns the action response.
441
     * @throws Throwable Throws an exception if an error occurs.
442
     */
443
    protected function prepareActionResponse(int $status, string $notificationId): SimpleJsonResponseDataInterface {
444

445
        $notify = $this->getTranslator()->trans($notificationId, [], WBWDataTablesBundle::getTranslationDomain());
147✔
446

447
        $response = new SimpleJsonResponseData();
147✔
448
        $response->setStatus($status);
147✔
449
        $response->setNotify($notify);
147✔
450

451
        return $response;
147✔
452
    }
453
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc