Completed
Pull Request — 2.x (#540)
by Grégoire
03:24 queued 01:39
created

src/Builder/ListBuilder.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\DoctrinePHPCRAdminBundle\Builder;
15
16
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\FieldDescriptionCollection;
19
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
20
use Sonata\AdminBundle\Builder\ListBuilderInterface;
21
use Sonata\AdminBundle\Guesser\TypeGuesserInterface;
22
23
class ListBuilder implements ListBuilderInterface
24
{
25
    /**
26
     * @var TypeGuesserInterface
27
     */
28
    protected $guesser;
29
30
    /**
31
     * @var array
32
     */
33
    protected $templates;
34
35
    /**
36
     * @param TypeGuesserInterface $guesser
37
     * @param array                $templates
38
     */
39
    public function __construct(TypeGuesserInterface $guesser, array $templates = [])
40
    {
41
        $this->guesser = $guesser;
42
        $this->templates = $templates;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function getBaseList(array $options = [])
49
    {
50
        return new FieldDescriptionCollection();
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function buildField($type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin)
57
    {
58
        if (null == $type) {
59
            $guessType = $this->guesser->guessType($admin->getClass(), $fieldDescription->getName(), $admin->getModelManager());
60
            $fieldDescription->setType($guessType->getType());
61
        } else {
62
            $fieldDescription->setType($type);
63
        }
64
65
        $this->fixFieldDescription($admin, $fieldDescription);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function addField(FieldDescriptionCollection $list, $type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin)
72
    {
73
        $this->buildField($type, $fieldDescription, $admin);
74
        $admin->addListFieldDescription($fieldDescription->getName(), $fieldDescription);
75
76
        $list->add($fieldDescription);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     *
82
     * @throws \RuntimeException if the $fieldDescription does not have a type
83
     */
84
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
85
    {
86
        if ('_action' == $fieldDescription->getName() || 'actions' === $fieldDescription->getType()) {
87
            $this->buildActionFieldDescription($fieldDescription);
88
        }
89
90
        $fieldDescription->setAdmin($admin);
91
        $metadata = null;
92
93
        if ($admin->getModelManager()->hasMetadata($admin->getClass())) {
94
            /** @var ClassMetadata $metadata */
95
            $metadata = $admin->getModelManager()->getMetadata($admin->getClass());
96
97
            // TODO sort on parent associations or node name
98
            $defaultSortable = true;
99
            if ($metadata->hasAssociation($fieldDescription->getName())
100
                || $metadata->nodename === $fieldDescription->getName()
101
            ) {
102
                $defaultSortable = false;
103
            }
104
105
            // TODO get and set parent association mappings, see
106
            // https://github.com/sonata-project/SonataDoctrinePhpcrAdminBundle/issues/106
107
            //$fieldDescription->setParentAssociationMappings($parentAssociationMappings);
108
109
            // set the default field mapping
110
            if (isset($metadata->mappings[$fieldDescription->getName()])) {
111
                $fieldDescription->setFieldMapping($metadata->mappings[$fieldDescription->getName()]);
112
                if (false !== $fieldDescription->getOption('sortable')) {
113
                    $fieldDescription->setOption(
114
                        'sortable',
115
                        $fieldDescription->getOption('sortable', $defaultSortable)
116
                    );
117
                    $fieldDescription->setOption(
118
                        'sort_parent_association_mappings',
119
                        $fieldDescription->getOption(
120
                            'sort_parent_association_mappings',
121
                            $fieldDescription->getParentAssociationMappings()
122
                        )
123
                    );
124
                    $fieldDescription->setOption(
125
                        'sort_field_mapping',
126
                        $fieldDescription->getOption(
127
                            'sort_field_mapping',
128
                            $fieldDescription->getFieldMapping()
129
                        )
130
                    );
131
                }
132
            }
133
134
            // set the default association mapping
135
            if (isset($metadata->associationMappings[$fieldDescription->getName()])) {
0 ignored issues
show
The property associationMappings does not seem to exist. Did you mean mappings?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
136
                $fieldDescription->setAssociationMapping($metadata->associationMappings[$fieldDescription->getName()]);
0 ignored issues
show
The property associationMappings does not seem to exist. Did you mean mappings?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
137
            }
138
139
            $fieldDescription->setOption(
140
                '_sort_order',
141
                $fieldDescription->getOption('_sort_order', 'ASC')
142
            );
143
        }
144
145
        if (!$fieldDescription->getType()) {
146
            throw new \RuntimeException(sprintf(
147
                'Please define a type for field `%s` in `%s`',
148
                $fieldDescription->getName(),
149
                \get_class($admin)
150
            ));
151
        }
152
153
        $fieldDescription->setOption(
154
            'code',
155
            $fieldDescription->getOption('code', $fieldDescription->getName())
156
        );
157
        $fieldDescription->setOption(
158
            'label',
159
            $fieldDescription->getOption('label', $fieldDescription->getName())
160
        );
161
162
        if (!$fieldDescription->getTemplate()) {
163
            $fieldDescription->setTemplate($this->getTemplate($fieldDescription->getType()));
164
165
            if (ClassMetadata::MANY_TO_ONE == $fieldDescription->getMappingType()) {
166
                $fieldDescription->setTemplate('@SonataAdmin/CRUD/Association/list_many_to_one.html.twig');
167
            }
168
169
            if (ClassMetadata::MANY_TO_MANY == $fieldDescription->getMappingType()) {
170
                $fieldDescription->setTemplate('@SonataAdmin/CRUD/Association/list_many_to_many.html.twig');
171
            }
172
173
            if ('child' == $fieldDescription->getMappingType() || 'parent' == $fieldDescription->getMappingType()) {
174
                $fieldDescription->setTemplate('@SonataAdmin/CRUD/Association/list_one_to_one.html.twig');
175
            }
176
177
            if ('children' == $fieldDescription->getMappingType() || 'referrers' == $fieldDescription->getMappingType()) {
178
                $fieldDescription->setTemplate('@SonataAdmin/CRUD/Association/list_one_to_many.html.twig');
179
            }
180
        }
181
182
        $mappingTypes = [
183
            ClassMetadata::MANY_TO_ONE,
184
            ClassMetadata::MANY_TO_MANY,
185
            'children',
186
            'child',
187
            'parent',
188
            'referrers',
189
        ];
190
191
        if ($metadata
192
            && $metadata->hasAssociation($fieldDescription->getName())
193
            && \in_array($fieldDescription->getMappingType(), $mappingTypes)
194
        ) {
195
            $admin->attachAdminClass($fieldDescription);
196
        }
197
    }
198
199
    /**
200
     * @param FieldDescriptionInterface $fieldDescription
201
     *
202
     * @return FieldDescriptionInterface
203
     */
204
    public function buildActionFieldDescription(FieldDescriptionInterface $fieldDescription)
205
    {
206
        if (null === $fieldDescription->getTemplate()) {
207
            $fieldDescription->setTemplate('@SonataAdmin/CRUD/list__action.html.twig');
208
        }
209
210
        if (null === $fieldDescription->getType()) {
211
            $fieldDescription->setType('actions');
212
        }
213
214
        if (null === $fieldDescription->getOption('name')) {
215
            $fieldDescription->setOption('name', 'Action');
216
        }
217
218
        if (null === $fieldDescription->getOption('code')) {
219
            $fieldDescription->setOption('code', 'Action');
220
        }
221
222
        if (null !== $fieldDescription->getOption('actions')) {
223
            $actions = $fieldDescription->getOption('actions');
224
            foreach ($actions as $k => $action) {
225
                if (!isset($action['template'])) {
226
                    $actions[$k]['template'] = sprintf('@SonataAdmin/CRUD/list__action_%s.html.twig', $k);
227
                }
228
            }
229
230
            $fieldDescription->setOption('actions', $actions);
231
        }
232
233
        return $fieldDescription;
234
    }
235
236
    /**
237
     * @param string $type
238
     *
239
     * @return string
240
     */
241
    private function getTemplate($type)
242
    {
243
        if (!isset($this->templates[$type])) {
244
            return;
245
        }
246
247
        return $this->templates[$type];
248
    }
249
}
250