ListBuilder::fixFieldDescription()   D
last analyzed

Complexity

Conditions 15
Paths 210

Size

Total Lines 83

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 83
rs 4.3375
c 0
b 0
f 0
cc 15
nc 210
nop 2

How to fix   Long Method    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
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\DoctrineORMAdminBundle\Builder;
15
16
use Doctrine\ORM\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
use Sonata\DoctrineORMAdminBundle\Guesser\TypeGuesser;
23
24
class ListBuilder implements ListBuilderInterface
25
{
26
    /**
27
     * @var TypeGuesserInterface
28
     */
29
    protected $guesser;
30
31
    /**
32
     * @var string[]
33
     */
34
    protected $templates = [];
35
36
    /**
37
     * @param string[] $templates
38
     */
39
    public function __construct(TypeGuesserInterface $guesser, array $templates = [])
40
    {
41
        $this->guesser = $guesser;
42
        $this->templates = $templates;
43
    }
44
45
    public function getBaseList(array $options = [])
46
    {
47
        return new FieldDescriptionCollection();
48
    }
49
50
    public function buildField($type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin): void
51
    {
52
        if (null === $type) {
53
            $guessType = $this->guesser->guessType(
54
                $admin->getClass(),
55
                $fieldDescription->getName(),
56
                $admin->getModelManager()
57
            );
58
            $fieldDescription->setType($guessType->getType() ? $guessType->getType() : '_action');
59
        } else {
60
            $fieldDescription->setType($type);
61
        }
62
63
        $this->fixFieldDescription($admin, $fieldDescription);
64
    }
65
66
    public function addField(FieldDescriptionCollection $list, $type, FieldDescriptionInterface $fieldDescription, AdminInterface $admin): void
67
    {
68
        $this->buildField($type, $fieldDescription, $admin);
69
        $admin->addListFieldDescription($fieldDescription->getName(), $fieldDescription);
70
71
        $list->add($fieldDescription);
72
    }
73
74
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription): void
75
    {
76
        if ('_action' === $fieldDescription->getName() || 'actions' === $fieldDescription->getType()) {
77
            $this->buildActionFieldDescription($fieldDescription);
78
        }
79
80
        $fieldDescription->setAdmin($admin);
81
82
        if ($admin->getModelManager()->hasMetadata($admin->getClass())) {
83
            list($metadata, $lastPropertyName, $parentAssociationMappings) = $admin->getModelManager()->getParentMetadataForProperty($admin->getClass(), $fieldDescription->getName());
84
            $fieldDescription->setParentAssociationMappings($parentAssociationMappings);
85
86
            // set the default field mapping
87
            if (isset($metadata->fieldMappings[$lastPropertyName])) {
88
                $fieldDescription->setFieldMapping($metadata->fieldMappings[$lastPropertyName]);
89
                if (false !== $fieldDescription->getOption('sortable')) {
90
                    $fieldDescription->setOption('sortable', $fieldDescription->getOption('sortable', true));
91
                    $fieldDescription->setOption('sort_parent_association_mappings', $fieldDescription->getOption('sort_parent_association_mappings', $fieldDescription->getParentAssociationMappings()));
92
                    $fieldDescription->setOption('sort_field_mapping', $fieldDescription->getOption('sort_field_mapping', $fieldDescription->getFieldMapping()));
93
                }
94
            }
95
96
            // set the default association mapping
97
            if (isset($metadata->associationMappings[$lastPropertyName])) {
98
                $fieldDescription->setAssociationMapping($metadata->associationMappings[$lastPropertyName]);
99
            }
100
101
            $fieldDescription->setOption('_sort_order', $fieldDescription->getOption('_sort_order', 'ASC'));
102
        }
103
104
        if (!$fieldDescription->getType()) {
105
            throw new \RuntimeException(sprintf(
106
                'Please define a type for field `%s` in `%s`',
107
                $fieldDescription->getName(),
108
                \get_class($admin)
109
            ));
110
        }
111
112
        $fieldDescription->setOption('code', $fieldDescription->getOption('code', $fieldDescription->getName()));
113
        $fieldDescription->setOption('label', $fieldDescription->getOption('label', $fieldDescription->getName()));
114
115
        if (!$fieldDescription->getTemplate()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldDescription->getTemplate() of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
116
            $fieldDescription->setTemplate($this->getTemplate($fieldDescription->getType()));
117
118
            if (!$fieldDescription->getTemplate()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldDescription->getTemplate() of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
119
                switch ($fieldDescription->getMappingType()) {
120
                    case ClassMetadata::MANY_TO_ONE:
121
                        $fieldDescription->setTemplate(
122
                            '@SonataAdmin/CRUD/Association/list_many_to_one.html.twig'
123
                        );
124
125
                        break;
126
                    case ClassMetadata::ONE_TO_ONE:
127
                        $fieldDescription->setTemplate(
128
                            '@SonataAdmin/CRUD/Association/list_one_to_one.html.twig'
129
                        );
130
131
                        break;
132
                    case ClassMetadata::ONE_TO_MANY:
133
                        $fieldDescription->setTemplate(
134
                            '@SonataAdmin/CRUD/Association/list_one_to_many.html.twig'
135
                        );
136
137
                        break;
138
                    case ClassMetadata::MANY_TO_MANY:
139
                        $fieldDescription->setTemplate(
140
                            '@SonataAdmin/CRUD/Association/list_many_to_many.html.twig'
141
                        );
142
143
                        break;
144
                }
145
            }
146
        }
147
148
        if (\in_array($fieldDescription->getMappingType(), [
149
            ClassMetadata::MANY_TO_ONE,
150
            ClassMetadata::ONE_TO_ONE,
151
            ClassMetadata::ONE_TO_MANY,
152
            ClassMetadata::MANY_TO_MANY,
153
        ], true)) {
154
            $admin->attachAdminClass($fieldDescription);
155
        }
156
    }
157
158
    /**
159
     * @return FieldDescriptionInterface
160
     */
161
    public function buildActionFieldDescription(FieldDescriptionInterface $fieldDescription)
162
    {
163
        if (null === $fieldDescription->getTemplate()) {
164
            $fieldDescription->setTemplate('@SonataAdmin/CRUD/list__action.html.twig');
165
        }
166
167
        if (\in_array($fieldDescription->getType(), [null, '_action'], true)) {
168
            $fieldDescription->setType('actions');
169
        }
170
171
        if (null === $fieldDescription->getOption('name')) {
172
            $fieldDescription->setOption('name', 'Action');
173
        }
174
175
        if (null === $fieldDescription->getOption('code')) {
176
            $fieldDescription->setOption('code', 'Action');
177
        }
178
179
        if (null !== $fieldDescription->getOption('actions')) {
180
            $actions = $fieldDescription->getOption('actions');
181
            foreach ($actions as $k => $action) {
182
                if (!isset($action['template'])) {
183
                    $actions[$k]['template'] = sprintf('@SonataAdmin/CRUD/list__action_%s.html.twig', $k);
184
                }
185
            }
186
187
            $fieldDescription->setOption('actions', $actions);
188
        }
189
190
        return $fieldDescription;
191
    }
192
193
    private function getTemplate(string $type): ?string
194
    {
195
        if (!isset($this->templates[$type])) {
196
            // NEXT_MAJOR: Remove the check for deprecated type and always return null.
197
            if (isset(TypeGuesser::DEPRECATED_TYPES[$type])) {
198
                return $this->getTemplate(TypeGuesser::DEPRECATED_TYPES[$type]);
199
            }
200
201
            return null;
202
        }
203
204
        // NEXT_MAJOR: Remove the deprecation.
205
        if (isset(TypeGuesser::DEPRECATED_TYPES[$type])) {
206
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
207
                'Overriding %s list template is deprecated since sonata-project/doctrine-orm-admin-bundle 3.19.'
208
                .' You should override %s list template instead.',
209
                $type,
210
                TypeGuesser::DEPRECATED_TYPES[$type]
211
            ), E_USER_DEPRECATED);
212
        }
213
214
        return $this->templates[$type];
215
    }
216
}
217