Passed
Push — develop ( a93deb...c2cf51 )
by Ludwig
04:39
created

AbstractGrid::getObjectManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/*
3
 * This file is part of cwdFancyGridBundle
4
 *
5
 * (c)2017 cwd.at GmbH <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
declare(strict_types=1);
11
namespace Cwd\FancyGridBundle\Grid;
12
13
use Cwd\FancyGridBundle\Column\AbstractColumn;
14
use Cwd\FancyGridBundle\Column\ColumnInterface;
15
use Doctrine\Common\Persistence\ObjectManager;
16
use Doctrine\ORM\QueryBuilder;
17
use JMS\Serializer\Serializer;
18
use JMS\Serializer\SerializerBuilder;
19
use Pagerfanta\Adapter\DoctrineORMAdapter;
20
use Pagerfanta\Pagerfanta;
21
use Symfony\Component\OptionsResolver\OptionsResolver;
22
use Symfony\Component\PropertyAccess\PropertyAccess;
23
use Symfony\Component\Translation\TranslatorInterface;
24
25
/**
26
 * Class AbstractGrid
27
 * @package Cwd\FancyGridBundle\Grid
28
 * @author Ludwig Ruderstaler <[email protected]>
29
 */
30
abstract class AbstractGrid implements GridInterface, \IteratorAggregate
31
{
32
    /**
33
     * @var array
34
     */
35
    protected $options;
36
37
    /**
38
     * @var array
39
     */
40
    protected $children = [];
41
42
    /**
43
     * @var ObjectManager
44
     */
45
    protected $objectManager;
46
47
    /**
48
     * @var TranslatorInterface
49
     */
50
    protected $translator;
51
52
    /**
53
     * @var \Symfony\Component\PropertyAccess\PropertyAccessor
54
     */
55
    protected $accessor;
56
57
    /**
58
     * @var null|string
59
     */
60
    protected $primary = null;
61
62
    /**
63
     * @var \Twig_Environment
64
     */
65
    protected $twig;
66
67
    /**
68
     * AbstractGrid constructor.
69
     * @param array $options
70
     */
71
    public function __construct(TranslatorInterface $translator, array $options = array())
72
    {
73
        $resolver = new OptionsResolver();
74
        $this->configureOptions($resolver);
75
76
        $this->options = $resolver->resolve($options);
77
        $this->translator = $translator;
78
        $this->accessor = PropertyAccess::createPropertyAccessor();
79
    }
80
81
    /**
82
     * @param \Twig_Environment $twig
83
     */
84
    public function setTwig(\Twig_Environment $twig)
85
    {
86
        $this->twig = $twig;
87
    }
88
89
    /**
90
     * @param ObjectManager $objectManager
91
     * @return $this
92
     */
93
    public function setObjectManager($objectManager)
94
    {
95
        $this->objectManager = $objectManager;
96
97
        return $this;
98
    }
99
100
    public function getObjectManager()
101
    {
102
        return $this->objectManager;
103
    }
104
105
    /**
106
     * generate gridid
107
     * @return string
108
     */
109
    public function getId()
110
    {
111
        $data = [
112
            $this->getOption('data_route'),
113
            $this->getOption('data_route_options'),
114
            $this->getOption('template'),
115
        ];
116
117
        return md5(serialize($data));
118
    }
119
120
    /**
121
     * @return array
122
     */
123
    public function getOptions() : array
124
    {
125
        return $this->options;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function buildGrid(GridBuilderInterface $builder, array $options)
132
    {
133
    }
134
135
    /**
136
     * @return array
137
     */
138
    public function getData() : array
139
    {
140
        $queryBuilder = $this->getQueryBuilder($this->objectManager, $this->getOptions());
141
142
        if ($this->getOption('sortField') !== null) {
143
            $field = $this->getOption('sortField');
144
            if ($this->has($field)) {
145
                $column = $this->get($field);
146
                $queryBuilder->orderBy($column->getField(), $this->getOption('sortDir'));
147
            }
148
        }
149
150
        if ($this->getOption('filter', false)) {
151
            $this->addSearch($queryBuilder, $this->all());
152
        }
153
154
        $pager = $this->getPager($queryBuilder);
155
156
        return [
157
            'totalCount' => $pager->getNbResults(),
158
            'data'  => $this->parseData($pager->getCurrentPageResults()),
159
            'success' => true,
160
        ];
161
    }
162
163
    /**
164
     * @param QueryBuilder      $queryBuilder
165
     * @param ColumnInterface[] $columns
166
     */
167
    protected function addSearch(QueryBuilder $queryBuilder, $columns)
0 ignored issues
show
Unused Code introduced by
The parameter $columns is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
    {
169
        $filter = json_decode($this->getOption('filter'));
170
        $where = $queryBuilder->expr()->andX();
171
        $i = 0;
172
173
        foreach ($filter as $filterSearch) {
174
            if (!$this->has($filterSearch->property)) {
175
                continue;
176
            }
177
178
            $property = sprintf(':%s%s', $filterSearch->property, $i);
179
180
            $column = $this->get($filterSearch->property);
181
182
            switch ($filterSearch->operator) {
183
                case 'eq':
184
                    $where->add($queryBuilder->expr()->eq($column->getField(), $property));
185
                    $queryBuilder->setParameter($property, $filterSearch->value);
186
                    break;
187
                case 'like':
188
                    $value = $filterSearch->value;
189
190
                    if ($value == 'true' || $value == 'false') {
191
                        $value = $value == 'true' ? 1 : 0;
192
                    }
193
194
                    $where->add($queryBuilder->expr()->like($column->getField(), $property));
195
                    $queryBuilder->setParameter($property, sprintf('%%%s%%',$value));
196
                    break;
197 View Code Duplication
                case 'gteq':
198
                    $where->add($queryBuilder->expr()->gte($column->getField(), $property));
199
                    $queryBuilder->setParameter($property, $filterSearch->value);
200
                    break;
201 View Code Duplication
                case 'lteq':
202
                    $where->add($queryBuilder->expr()->lte($column->getField(), $property));
203
                    $queryBuilder->setParameter($property, $filterSearch->value);
204
                    break;
205
206
            }
207
208
209
            $i++;
210
        }
211
212
        if (count($where->getParts()) > 0) {
213
            $queryBuilder->having($where);
214
        }
215
    }
216
217
    /**
218
     * @param array|\Traversable $rows
219
     * @return array
220
     */
221
    protected function parseData($rows)
222
    {
223
        $data = [];
224
        foreach ($rows as $row) {
225
            $rowData = [];
226
227
            foreach ($this->all() as $column) {
228
                /** @var ColumnInterface $column */
229
                $value = $column->getValue($row, $column->getField(), $this->findPrimary(), $this->accessor);
230
                $value = $column->render($value, $row, $this->getPrimaryValue($row), $this->twig);
231
232
                // FancyGrid doesnt like null
233
                if (null === $value) {
234
                    $value = '';
235
                }
236
237
                if ($column->getOption('translatable', false)) {
238
                    $value = $this->translator->trans($value, [], $column->getOption('translation_domain'));
239
                }
240
241
                // FancyGrid does not like . in index name
242
                $name = str_replace('.', '_', $column->getName());
243
244
                $rowData[$name] = $value;
245
            }
246
247
            $data[] = $rowData;
248
        }
249
250
        return $data;
251
    }
252
253
    /**
254
     * @param QueryBuilder $queryBuilder
255
     * @return Pagerfanta
256
     */
257
    public function getPager(QueryBuilder $queryBuilder)
258
    {
259
        $adapter = new DoctrineORMAdapter($queryBuilder, false);
260
        $pager = new Pagerfanta($adapter);
261
        $page = $this->getOption('page', 1);
262
        if ($page < 1) {
263
            $page = 1;
264
        }
265
266
        $pager->setCurrentPage($page)
267
              ->setMaxPerPage($this->getOption('limit', 10));
268
269
        return $pager;
270
    }
271
272
    /**
273
     * Get value of primary column
274
     *
275
     * @param mixed $object
276
     *
277
     * @return mixed
278
     */
279
    public function getPrimaryValue($object)
280
    {
281
        if ($this->primary === null) {
282
            $this->primary = $this->findPrimary();
283
        }
284
285
        /** special case when counting */
286
        if (is_array($object)) {
287
            $object = $object[0];
288
        }
289
290
        return $this->accessor->getValue($object, $this->primary);
291
    }
292
293
    /**
294
     * @return null|string
295
     */
296
    public function findPrimary()
297
    {
298
        foreach ($this->all() as $column) {
299
            if (true === $column->getOption('identifier')) {
300
                return $column->getName();
301
            }
302
        }
303
304
        return null;
305
    }
306
307
    /**
308
     * @param OptionsResolver $resolver
309
     */
310
    public function configureOptions(OptionsResolver $resolver)
311
    {
312
        $resolver->setDefaults([
313
            'template' => 'CwdFancyGridBundle:Grid:template.html.twig',
314
            'current' => 1,
315
            'filter' => null,
316
            'sortField' => null,
317
            'sortDir' => null,
318
            'data_route_options' => [],
319
            'page' => 1,
320
            'limit' => 20,
321
        ]);
322
323
        $resolver->setRequired([
324
            'template',
325
            'data_route',
326
        ]);
327
    }
328
329
    public function getColumnDefinition()
330
    {
331
        $columns = [];
332
        /** @var AbstractColumn $column */
333
        foreach ($this->children as $column) {
334
            $column->setTranslator($this->translator);
335
            $columns[] = $column->buildColumnOptions();
336
        }
337
338
        return $columns;
339
    }
340
341
    /**
342
     * @param string $name
343
     * @return bool
344
     */
345
    public function hasOption(string $name)
346
    {
347
        return array_key_exists($name, $this->options);
348
    }
349
350
    /**
351
     * @param string     $name
352
     * @param mixed|null $default
353
     * @return mixed
354
     */
355
    public function getOption(string $name, $default = null)
356
    {
357
        return array_key_exists($name, $this->options) ? $this->options[$name] : $default;
358
    }
359
360
    /**
361
     * @param string $name
362
     * @return ColumnInterface
363
     */
364 View Code Duplication
    public function get(string $name) : ColumnInterface
365
    {
366
        if (isset($this->children[$name])) {
367
            return $this->children[$name];
368
        }
369
370
        throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name));
371
    }
372
373
    /**
374
     * @param string $name
375
     * @return $this
376
     */
377
    public function remove(string $name)
378
    {
379
        unset($this->children[$name]);
380
381
        return $this;
382
    }
383
384
    /**
385
     * @param string $name
386
     * @return bool
387
     */
388
    public function has(string $name)
389
    {
390
        return isset($this->children[$name]);
391
    }
392
393
    /**
394
     * @return \Cwd\FancyGridBundle\Column\ColumnInterface[]
395
     */
396
    public function all()
397
    {
398
        return $this->children;
399
    }
400
401
    /**
402
     * @param array<ColumnInterface> $children
403
     * @return $this
404
     */
405
    public function setChildren($children)
406
    {
407
        $this->children = $children;
408
409
        return $this;
410
    }
411
412
    /**
413
     *
414
     * @return \ArrayIterator
415
     */
416
    public function getIterator()
417
    {
418
        return new \ArrayIterator($this->all());
419
    }
420
}
421