Passed
Push — develop ( 98d07f...258763 )
by Ludwig
01:42
created

AbstractGrid::addSearch()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 39
Code Lines 25

Duplication

Lines 12
Ratio 30.77 %

Importance

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