FormContractor   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 3
dl 0
loc 157
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B fixFieldDescription() 0 31 6
A getFormFactory() 0 4 1
A getFormBuilder() 0 4 1
C getDefaultOptions() 0 79 10
A checkFormClass() 0 6 1
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\DoctrineMongoDBAdminBundle\Builder;
15
16
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
17
use Sonata\AdminBundle\Admin\AdminInterface;
18
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
19
use Sonata\AdminBundle\Builder\FormContractorInterface;
20
use Sonata\AdminBundle\Form\Type\AdminType;
21
use Sonata\AdminBundle\Form\Type\ModelAutocompleteType;
22
use Sonata\AdminBundle\Form\Type\ModelHiddenType;
23
use Sonata\AdminBundle\Form\Type\ModelListType;
24
use Sonata\AdminBundle\Form\Type\ModelType;
25
use Sonata\AdminBundle\Form\Type\ModelTypeList;
26
use Sonata\CoreBundle\Form\Type\CollectionType as DeprecatedCollectionType;
27
use Sonata\Form\Type\CollectionType;
28
use Symfony\Component\Form\Extension\Core\Type\FormType;
29
use Symfony\Component\Form\FormFactoryInterface;
30
31
class FormContractor implements FormContractorInterface
32
{
33
    /**
34
     * @deprecated since version 3.1.0, to be removed in 4.0
35
     *
36
     * @var FormFactoryInterface
37
     */
38
    protected $fieldFactory;
39
40
    /**
41
     * @var FormFactoryInterface
42
     */
43
    private $formFactory;
44
45
    public function __construct(FormFactoryInterface $formFactory)
46
    {
47
        $this->formFactory = $formFactory;
48
    }
49
50
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription): void
51
    {
52
        if ($admin->getModelManager()->hasMetadata($admin->getClass())) {
53
            $metadata = $admin->getModelManager()->getMetadata($admin->getClass());
54
55
            // set the default field mapping
56
            if (isset($metadata->fieldMappings[$fieldDescription->getName()])) {
57
                $fieldDescription->setFieldMapping($metadata->fieldMappings[$fieldDescription->getName()]);
58
            }
59
60
            // set the default association mapping
61
            if (isset($metadata->associationMappings[$fieldDescription->getName()])) {
62
                $fieldDescription->setAssociationMapping($metadata->associationMappings[$fieldDescription->getName()]);
63
            }
64
        }
65
66
        if (!$fieldDescription->getType()) {
67
            throw new \RuntimeException(sprintf(
68
                'Please define a type for field `%s` in `%s`',
69
                $fieldDescription->getName(),
70
                \get_class($admin)
71
            ));
72
        }
73
74
        $fieldDescription->setAdmin($admin);
75
        $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'standard'));
76
77
        if (\in_array($fieldDescription->getMappingType(), [ClassMetadata::ONE, ClassMetadata::MANY], true)) {
78
            $admin->attachAdminClass($fieldDescription);
79
        }
80
    }
81
82
    /**
83
     * @return FormFactoryInterface
84
     */
85
    public function getFormFactory()
86
    {
87
        return $this->formFactory;
88
    }
89
90
    public function getFormBuilder($name, array $options = [])
91
    {
92
        return $this->getFormFactory()->createNamedBuilder($name, FormType::class, null, $options);
93
    }
94
95
    public function getDefaultOptions($type, FieldDescriptionInterface $fieldDescription)
96
    {
97
        $options = [];
98
        $options['sonata_field_description'] = $fieldDescription;
99
100
        if ($this->checkFormClass($type, [
101
            ModelType::class,
102
            ModelTypeList::class,
103
            ModelListType::class,
104
            ModelHiddenType::class,
105
            ModelAutocompleteType::class,
106
        ])) {
107
            if ('list' === $fieldDescription->getOption('edit')) {
108
                throw new \LogicException(
109
                    'The ``Sonata\AdminBundle\Form\Type\ModelType`` type does not accept an ``edit`` option anymore,'
110
                    .' please review the UPGRADE-2.1.md file from the SonataAdminBundle'
111
                );
112
            }
113
114
            $options['class'] = $fieldDescription->getTargetEntity();
115
            $options['model_manager'] = $fieldDescription->getAdmin()->getModelManager();
116
117
            if ($this->checkFormClass($type, [ModelAutocompleteType::class])) {
118
                if (!$fieldDescription->getAssociationAdmin()) {
119
                    throw new \RuntimeException(sprintf(
120
                        'The current field `%s` is not linked to an admin.'
121
                        .' Please create one for the target entity: `%s`',
122
                        $fieldDescription->getName(),
123
                        $fieldDescription->getTargetEntity()
124
                    ));
125
                }
126
            }
127
        } elseif ($this->checkFormClass($type, [AdminType::class])) {
128
            if (!$fieldDescription->getAssociationAdmin()) {
129
                throw new \RuntimeException(sprintf(
130
                    'The current field `%s` is not linked to an admin.'
131
                    .' Please create one for the target entity : `%s`',
132
                    $fieldDescription->getName(),
133
                    $fieldDescription->getTargetEntity()
134
                ));
135
            }
136
137
            if (!\in_array($fieldDescription->getMappingType(), [ClassMetadata::ONE, ClassMetadata::MANY], true)) {
138
                throw new \RuntimeException(sprintf(
139
                    'You are trying to add `sonata_type_admin` field `%s` which is not One-To-One or  Many-To-One.'
140
                    .' Maybe you want `sonata_type_collection` instead?',
141
                    $fieldDescription->getName()
142
                ));
143
            }
144
145
            // set sensitive default value to have a component working fine out of the box
146
            $options['btn_add'] = false;
147
            $options['delete'] = false;
148
149
            $options['data_class'] = $fieldDescription->getAssociationAdmin()->getClass();
150
            $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'admin'));
151
        } elseif ($this->checkFormClass($type, [
152
            CollectionType::class,
153
            DeprecatedCollectionType::class,
154
        ])) {
155
            if (!$fieldDescription->getAssociationAdmin()) {
156
                throw new \RuntimeException(sprintf(
157
                    'The current field `%s` is not linked to an admin.'
158
                    .' Please create one for the target entity : `%s`',
159
                    $fieldDescription->getName(),
160
                    $fieldDescription->getTargetEntity()
161
                ));
162
            }
163
164
            $options['type'] = AdminType::class;
165
            $options['modifiable'] = true;
166
            $options['type_options'] = [
167
                'sonata_field_description' => $fieldDescription,
168
                'data_class' => $fieldDescription->getAssociationAdmin()->getClass(),
169
            ];
170
        }
171
172
        return $options;
173
    }
174
175
    /**
176
     * @param string $type
177
     * @param array  $classes
178
     *
179
     * @return array
180
     */
181
    private function checkFormClass($type, $classes)
182
    {
183
        return array_filter($classes, static function ($subclass) use ($type) {
184
            return is_a($type, $subclass, true);
185
        });
186
    }
187
}
188