Completed
Push — 1.x ( e997bd )
by Sullivan
19:38
created

FormContractor::fixFieldDescription()   C

Complexity

Conditions 8
Paths 15

Size

Total Lines 37
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 37
rs 5.3846
cc 8
eloc 20
nc 15
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sonata 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\DoctrinePHPCRAdminBundle\Builder;
13
14
use Sonata\AdminBundle\Admin\AdminInterface;
15
use Sonata\AdminBundle\Admin\FieldDescriptionInterface;
16
use Sonata\AdminBundle\Builder\FormContractorInterface;
17
18
use Symfony\Component\Form\FormBuilder;
19
use Symfony\Component\Form\FormFactoryInterface;
20
21
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;
22
23
class FormContractor implements FormContractorInterface
24
{
25
    /**
26
     * @var FormFactoryInterface
27
     */
28
    protected $formFactory;
29
30
    /**
31
     * @param FormFactoryInterface $formFactory
32
     */
33
    public function __construct(FormFactoryInterface $formFactory)
34
    {
35
        $this->formFactory = $formFactory;
36
    }
37
38
    /**
39
     * The method defines the correct default settings for the provided FieldDescription
40
     *
41
     * {@inheritDoc}
42
     *
43
     * @throws \RuntimeException if the $fieldDescription does not specify a type.
44
     */
45
    public function fixFieldDescription(AdminInterface $admin, FieldDescriptionInterface $fieldDescription)
46
    {
47
        $metadata = null;
48
        if ($admin->getModelManager()->hasMetadata($admin->getClass())) {
49
            /** @var \Doctrine\ODM\PHPCR\Mapping\ClassMetadata $metadata */
50
            $metadata = $admin->getModelManager()->getMetadata($admin->getClass());
51
52
            // set the default field mapping
53
            if (isset($metadata->mappings[$fieldDescription->getName()])) {
54
                $fieldDescription->setFieldMapping($metadata->mappings[$fieldDescription->getName()]);
55
            }
56
57
            // set the default association mapping
58
            if ($metadata->hasAssociation($fieldDescription->getName())) {
59
                $fieldDescription->setAssociationMapping($metadata->getAssociation($fieldDescription->getName()));
60
            }
61
        }
62
63
        if (!$fieldDescription->getType()) {
64
            throw new \RuntimeException(sprintf('Please define a type for field `%s` in `%s`', $fieldDescription->getName(), get_class($admin)));
65
        }
66
67
        $fieldDescription->setAdmin($admin);
68
        $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'standard'));
69
70
        $mappingTypes = array(
71
            ClassMetadata::MANY_TO_ONE,
72
            ClassMetadata::MANY_TO_MANY,
73
            'children',
74
            'child', 'parent',
75
            'referrers',
76
        );
77
78
        if ($metadata && $metadata->hasAssociation($fieldDescription->getName()) && in_array($fieldDescription->getMappingType(), $mappingTypes)) {
79
            $admin->attachAdminClass($fieldDescription);
80
        }
81
    }
82
83
    /**
84
     * @return FormFactoryInterface
85
     */
86
    public function getFormFactory()
87
    {
88
        return $this->formFactory;
89
    }
90
91
    /**
92
     * {@inheritDoc}
93
     */
94
    public function getFormBuilder($name, array $options = array())
95
    {
96
        return $this->getFormFactory()->createNamedBuilder($name, 'form', null, $options);
97
    }
98
99
    /**
100
     * {@inheritDoc}
101
     *
102
     * @throws \LogicException if a sonata_type_model field does not have a
103
     *                         target model configured.
104
     */
105
    public function getDefaultOptions($type, FieldDescriptionInterface $fieldDescription)
106
    {
107
        $options = array();
108
        $options['sonata_field_description'] = $fieldDescription;
109
110
        switch ($type) {
111
            case 'Sonata\DoctrinePHPCRAdminBundle\Form\Type\TreeModelType':
112
            case 'doctrine_phpcr_odm_tree':
113
                $options['class']         = $fieldDescription->getTargetEntity();
114
                $options['model_manager'] = $fieldDescription->getAdmin()->getModelManager();
115
116
                break;
117
            case 'Sonata\AdminBundle\Form\Type\Modeltype':
118
            case 'sonata_type_model':
119
            case 'Sonata\AdminBundle\Form\Type\ModelTypeList':
120
            case 'sonata_type_model_list':
121
                if (!$fieldDescription->getTargetEntity()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldDescription->getTargetEntity() 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...
122
                    throw new \LogicException(sprintf(
123
                        'The field "%s" in class "%s" does not have a target model defined. ' .
124
                        'Please specify the "targetDocument" attribute in the mapping for this class.',
125
                        $fieldDescription->getName(),
126
                        $fieldDescription->getAdmin()->getClass()
127
                    ));
128
                }
129
130
                $options['class']         = $fieldDescription->getTargetEntity();
131
                $options['model_manager'] = $fieldDescription->getAdmin()->getModelManager();
132
133
                break;
134
            case 'Sonata\AdminBundle\Form\Type\AdminType':
135
            case 'sonata_type_admin':
136
                if (!$fieldDescription->getAssociationAdmin()) {
137
                    throw $this->getAssociationAdminException($fieldDescription);
138
                }
139
140
                $options['data_class'] = $fieldDescription->getAssociationAdmin()->getClass();
141
                $fieldDescription->setOption('edit', $fieldDescription->getOption('edit', 'admin'));
142
143
                break;
144
            case 'Sonata\CoreBundle\Form\Type\CollectionType':
145
            case 'sonata_type_collection':
146
                if (!$fieldDescription->getAssociationAdmin()) {
147
                    throw $this->getAssociationAdminException($fieldDescription);
148
                }
149
150
                $options['type']         = 'sonata_type_admin';
151
                $options['modifiable']   = true;
152
                $options['type_options'] = array(
153
                    'sonata_field_description' => $fieldDescription,
154
                    'data_class'               => $fieldDescription->getAssociationAdmin()->getClass()
155
                );
156
157
                break;
158
        }
159
160
        return $options;
161
    }
162
163
    /**
164
     * @param FieldDescriptionInterface $fieldDescription
165
     *
166
     * @return \LogicException
167
     */
168
    protected function getAssociationAdminException(FieldDescriptionInterface $fieldDescription)
169
    {
170
        $msg = sprintf('The current field `%s` is not linked to an admin. Please create one', $fieldDescription->getName());
171
        if (in_array($fieldDescription->getMappingType(), array(ClassMetadata::MANY_TO_ONE, ClassMetadata::MANY_TO_MANY, 'referrers'))) {
172
            if ($fieldDescription->getTargetEntity()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $fieldDescription->getTargetEntity() of type string|null is loosely compared to true; 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...
173
                $msg .= " for the target document: `{$fieldDescription->getTargetEntity()}`";
174
            }
175
            $msg .= ", specify the `targetDocument` in the Reference, or the `referringDocument` in the Referrers or use the option `admin_code` to link it.";
176
        } else {
177
            $msg .= ' and use the option `admin_code` to link it.';
178
        }
179
180
        return new \LogicException($msg);
181
    }
182
}
183