Passed
Push — develop ( 002f70...7908ff )
by Ludwig
05:19
created

AbstractGrid::addSearch()   D

Complexity

Conditions 10
Paths 16

Size

Total Lines 45
Code Lines 28

Duplication

Lines 8
Ratio 17.78 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 8
loc 45
rs 4.8196
cc 10
eloc 28
nc 16
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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