EntityType::buildColumnOptions()   B
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 16
nc 3
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\Column;
12
13
use Doctrine\Common\Persistence\ObjectManager;
14
use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader;
15
use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader;
16
use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader;
17
use Symfony\Bridge\Doctrine\ManagerRegistry;
18
use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
19
use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
20
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
21
use Symfony\Component\OptionsResolver\Options;
22
use Symfony\Component\OptionsResolver\OptionsResolver;
23
24
/**
25
 * Class EntityType
26
 * @package Cwd\FancyGridBundle\Column
27
 * @author Ludwig Ruderstaler <[email protected]>
28
 */
29
class EntityType extends AbstractColumn
30
{
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public function configureOptions(OptionsResolver $resolver)
35
    {
36
        parent::configureOptions($resolver);
37
38
        $choiceLoader = function (Options $options) {
39
            // Unless the choices are given explicitly, load them on demand
40
            if (null === $options['data']) {
41
42
                if (null !== $options['query_builder']) {
43
                    $entityLoader = $this->getLoader($options['em'], $options['query_builder'], $options['class']);
44
                } else {
45
                    $queryBuilder = $options['em']->getRepository($options['class'])->createQueryBuilder('e');
46
                    $entityLoader = $this->getLoader($options['em'], $queryBuilder, $options['class']);
47
                }
48
49
                $doctrineChoiceLoader = new DoctrineChoiceLoader(
50
                    $options['em'],
51
                    $options['class'],
52
                    $options['id_reader'],
53
                    $entityLoader
54
                );
55
56
                return $doctrineChoiceLoader;
57
            }
58
        };
59
60
        $emNormalizer = function (Options $options, $em) {
61
            /* @var ManagerRegistry $registry */
62
            if (null !== $em && $em instanceof ObjectManager) {
63
                return $em;
64
            }
65
66
            if ($this->getOption('em') === null) {
67
                throw new \RuntimeException(sprintf(
68
                    'Object Manager not set'.
69
                    'Did you forget to set it? "em"'
70
                ));
71
            }
72
73
            $em = $this->getOption('em')->getManagerForClass($options['class']);
74
75
            if (null === $em) {
76
                throw new \RuntimeException(sprintf(
77
                    'Class "%s" seems not to be a managed Doctrine entity. '.
78
                    'Did you forget to map it?',
79
                    $options['class']
80
                ));
81
            }
82
83
            return $em;
84
        };
85
86
        // Invoke the query builder closure so that we can cache choice lists
87
        // for equal query builders
88
        $queryBuilderNormalizer = function (Options $options, $queryBuilder) {
89
            if (is_callable($queryBuilder)) {
90
                $queryBuilder = call_user_func($queryBuilder, $options['em']->getRepository($options['class']));
91
            }
92
93
            return $queryBuilder;
94
        };
95
96
        // Set the "id_reader" option via the normalizer. This option is not
97
        // supposed to be set by the user.
98
        $idReaderNormalizer = function (Options $options) {
99
            $classMetadata = $options['em']->getClassMetadata($options['class']);
100
            return new IdReader($options['em'], $classMetadata);
101
        };
102
103
        $resolver->setDefaults(array(
104
            'align' => 'left',
105
            'cellAlign' => 'left',
106
            'type' => 'combo',
107
            'data' => null,
108
            'class' => null,
109
            'query_builder' => null,
110
            'choice_loader' => $choiceLoader,
111
            'choice_label'  => null,
112
            'id_reader' => null,
113
            'em' => null,
114
        ));
115
        $resolver->setRequired(['class']);
116
117
        $resolver->setNormalizer('em', $emNormalizer);
118
        $resolver->setNormalizer('query_builder', $queryBuilderNormalizer);
119
        $resolver->setNormalizer('id_reader', $idReaderNormalizer);
120
121
        $resolver->setAllowedTypes('attr', 'array');
122
        $resolver->setAllowedTypes('data', ['array', 'null']);
123
    }
124
125
126
    public function buildColumnOptions() : array
127
    {
128
        $printOptions = parent::buildColumnOptions();
129
130
        if (is_array($this->getOption('data')) && count($this->getOption('data')) > 0) {
131
            return $printOptions;
132
        }
133
134
        $list = $this->getOption('choice_loader');
135
        $viewFactory = new DefaultChoiceListFactory();
136
        $views = $viewFactory->createView($list->loadChoiceList(), null, $this->getOption('choice_label'));
137
138
        $printOptions['data'] = [];
139
        $printOptions['displayKey'] = 'label';
140
        $printOptions['valueKey'] = 'name';
141
142
        foreach ($views->choices as $view) {
143
            $printOptions['data'][] = [
144
                'id' => $view->value,
145
                'label' => $view->label,
146
                'name' => $view->data->getName()
147
            ];
148
        }
149
150
        return $printOptions;
151
    }
152
153
154
    /**
155
     * We consider two query builders with an equal SQL string and
156
     * equal parameters to be equal.
157
     *
158
     * @param QueryBuilder $queryBuilder
159
     *
160
     * @return array
161
     *
162
     * @internal This method is public to be usable as callback. It should not
163
     *           be used in user code.
164
     */
165
    public function getQueryBuilderPartsForCachingHash($queryBuilder)
166
    {
167
        return array(
168
            $queryBuilder->getQuery()->getSQL(),
169
            array_map(array($this, 'parameterToArray'), $queryBuilder->getParameters()->toArray()),
170
        );
171
    }
172
173
    /**
174
     * Converts a query parameter to an array.
175
     *
176
     * @return array The array representation of the parameter
177
     */
178
    private function parameterToArray(Parameter $parameter)
179
    {
180
        return array($parameter->getName(), $parameter->getType(), $parameter->getValue());
181
    }
182
183
    /**
184
     * Return the default loader object.
185
     *
186
     * @param ObjectManager $manager
187
     * @param QueryBuilder  $queryBuilder
188
     * @param string        $class
189
     *
190
     * @return ORMQueryBuilderLoader
191
     */
192
    public function getLoader(ObjectManager $manager, $queryBuilder, $class)
193
    {
194
        return new ORMQueryBuilderLoader($queryBuilder);
195
    }
196
}
197