Completed
Pull Request — 3.x (#606)
by Arkadiusz
15:55
created

FormContractor::fixFieldDescription()   C

Complexity

Conditions 7
Paths 15

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 27
rs 6.7272
cc 7
eloc 13
nc 15
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\DoctrineORMAdminBundle\Builder;
13
14
use Doctrine\ORM\Mapping\ClassMetadataInfo;
15
use Sonata\AdminBundle\Admin\AdminInterface;
16
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
17
use Sonata\AdminBundle\Builder\FormContractorInterface;
18
use Symfony\Component\Form\FormFactoryInterface;
19
20
class FormContractor implements FormContractorInterface
21
{
22
    /**
23
     * @deprecated since version 3.0.4, to be removed in 4.0
24
     *
25
     * @var FormFactoryInterface
26
     */
27
    protected $fieldFactory;
28
29
    /**
30
     * @var FormFactoryInterface
31
     */
32
    protected $formFactory;
33
34
    /**
35
     * @param FormFactoryInterface $formFactory
36
     */
37
    public function __construct(FormFactoryInterface $formFactory)
38
    {
39
        $this->formFactory = $formFactory;
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
46
    {
47
        if ($admin->getModelManager()->hasMetadata($admin->getClass())) {
48
            $metadata = $admin->getModelManager()->getMetadata($admin->getClass());
49
50
            // set the default field mapping
51
            if (isset($metadata->fieldMappings[$fieldDescription->getName()])) {
52
                $fieldDescription->setFieldMapping($metadata->fieldMappings[$fieldDescription->getName()]);
53
            }
54
55
            // set the default association mapping
56
            if (isset($metadata->associationMappings[$fieldDescription->getName()])) {
57
                $fieldDescription->setAssociationMapping($metadata->associationMappings[$fieldDescription->getName()]);
58
            }
59
        }
60
61
        if (!$fieldDescription->getType()) {
62
            throw new \RuntimeException(sprintf('Please define a type for field `%s` in `%s`', $fieldDescription->getName(), get_class($admin)));
63
        }
64
65
        $fieldDescription->setAdmin($admin);
66
        $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'standard'));
67
68
        if ($this->hasAssociation($fieldDescription) || $fieldDescription->getOption('admin_code')) {
69
            $admin->attachAdminClass($fieldDescription);
70
        }
71
    }
72
73
    /**
74
     * @param FieldDescriptionInterface $fieldDescription
75
     *
76
     * @return bool
77
     */
78
    private function hasAssociation(FieldDescriptionInterface $fieldDescription)
79
    {
80
        return in_array($fieldDescription->getMappingType(), [
81
            ClassMetadataInfo::ONE_TO_MANY,
82
            ClassMetadataInfo::MANY_TO_MANY,
83
            ClassMetadataInfo::MANY_TO_ONE,
84
            ClassMetadataInfo::ONE_TO_ONE
85
        ]);
86
    }
87
88
    /**
89
     * @return FormFactoryInterface
90
     */
91
    public function getFormFactory()
92
    {
93
        return $this->formFactory;
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function getFormBuilder($name, array $options = array())
100
    {
101
        // NEXT_MAJOR: Remove this line when drop Symfony <2.8 support
102
        $formType = method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
103
            ? 'Symfony\Component\Form\Extension\Core\Type\FormType' : 'form';
104
105
        return $this->getFormFactory()->createNamedBuilder($name, $formType, null, $options);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function getDefaultOptions($type, FieldDescriptionInterface $fieldDescription)
112
    {
113
        $options = array();
114
        $options['sonata_field_description'] = $fieldDescription;
115
116
        // NEXT_MAJOR: Check only against FQCNs when dropping support for Symfony <2.8
117
        if (in_array($type, array(
118
            'sonata_type_model',
119
            'Sonata\AdminBundle\Form\Type\ModelType',
120
            'sonata_type_model_list',
121
            'Sonata\AdminBundle\Form\Type\ModelTypeList',
122
            'sonata_type_model_hidden',
123
            'Sonata\AdminBundle\Form\Type\ModelHiddenType',
124
            'sonata_type_model_autocomplete',
125
            'Sonata\AdminBundle\Form\Type\ModelAutocompleteType',
126
        ), true)) {
127
            if ($fieldDescription->getOption('edit') === 'list') {
128
                throw new \LogicException('The ``sonata_type_model`` type does not accept an ``edit`` option anymore, please review the UPGRADE-2.1.md file from the SonataAdminBundle');
129
            }
130
131
            $options['class'] = $fieldDescription->getTargetEntity();
132
            $options['model_manager'] = $fieldDescription->getAdmin()->getModelManager();
133
134
            if (in_array($type, array(
135
                'sonata_type_model_autocomplete',
136
                'Sonata\AdminBundle\Form\Type\ModelAutocompleteType',
137
            ), true)) {
138
                if (!$fieldDescription->getAssociationAdmin()) {
139
                    throw new \RuntimeException(sprintf('The current field `%s` is not linked to an admin. Please create one for the target entity: `%s`', $fieldDescription->getName(), $fieldDescription->getTargetEntity()));
140
                }
141
            }
142
        } elseif (in_array($type, array(
143
            'sonata_type_admin',
144
            'Sonata\AdminBundle\Form\Type\AdminType',
145
        ), true)) {
146
            if (!$fieldDescription->getAssociationAdmin()) {
147
                throw new \RuntimeException(sprintf('The current field `%s` is not linked to an admin. Please create one for the target entity : `%s`', $fieldDescription->getName(), $fieldDescription->getTargetEntity()));
148
            }
149
150
            if (!in_array($fieldDescription->getMappingType(), array(ClassMetadataInfo::ONE_TO_ONE, ClassMetadataInfo::MANY_TO_ONE))) {
151
                throw new \RuntimeException(sprintf('You are trying to add `sonata_type_admin` field `%s` which is not One-To-One or  Many-To-One. Maybe you want `sonata_model_list` instead?', $fieldDescription->getName()));
152
            }
153
154
            // set sensitive default value to have a component working fine out of the box
155
            $options['btn_add'] = false;
156
            $options['delete'] = false;
157
158
            $options['data_class'] = $fieldDescription->getAssociationAdmin()->getClass();
159
            $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'admin'));
160
        } elseif (in_array($type, array(
161
            'sonata_type_collection',
162
            'Sonata\CoreBundle\Form\Type\CollectionType',
163
        ), true)) {
164
            if (!$fieldDescription->getAssociationAdmin()) {
165
                throw new \RuntimeException(sprintf('The current field `%s` is not linked to an admin. Please create one for the target entity : `%s`', $fieldDescription->getName(), $fieldDescription->getTargetEntity()));
166
            }
167
168
            $options['type'] = 'sonata_type_admin';
169
            $options['modifiable'] = true;
170
            $options['type_options'] = array(
171
                'sonata_field_description' => $fieldDescription,
172
                'data_class' => $fieldDescription->getAssociationAdmin()->getClass(),
173
            );
174
        }
175
176
        return $options;
177
    }
178
}
179