Completed
Pull Request — master (#351)
by Leny
06:31
created

WidgetFormBuilder   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 293
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 8
Bugs 4 Features 0
Metric Value
wmc 20
c 8
b 4
f 0
lcom 1
cbo 10
dl 0
loc 293
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A renderNewForm() 0 16 1
A renderForm() 0 16 1
A renderNewWidgetForms() 0 23 3
A buildEntityForms() 0 18 1
B buildWidgetForm() 0 79 6
A buildForm() 0 20 4
A callBuildFormSwitchParameters() 0 20 3
1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Builder;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Symfony\Component\DependencyInjection\Container;
7
use Symfony\Component\Form\Form;
8
use Symfony\Component\OptionsResolver\OptionsResolver;
9
use Victoire\Bundle\BusinessEntityBundle\Entity\BusinessEntity;
10
use Victoire\Bundle\CoreBundle\Entity\View;
11
use Victoire\Bundle\CoreBundle\Event\WidgetBuildFormEvent;
12
use Victoire\Bundle\CoreBundle\VictoireCmsEvents;
13
use Victoire\Bundle\WidgetBundle\Entity\Widget;
14
use Victoire\Bundle\WidgetBundle\Event\WidgetFormCreateEvent;
15
use Victoire\Bundle\WidgetBundle\Event\WidgetFormEvents;
16
use Victoire\Bundle\WidgetBundle\Form\WidgetOptionsContainer;
17
18
class WidgetFormBuilder
19
{
20
    private $container;
21
22
    public function __construct(Container $container)
23
    {
24
        $this->container = $container;
25
    }
26
27
    /**
28
     * create form new for a widget.
29
     *
30
     * @param Form   $form
31
     * @param Widget $widget
32
     * @param string $slot
33
     * @param View   $view
34
     * @param string $entity
35
     *
36
     * @return string
37
     */
38
    public function renderNewForm($form, $widget, $slot, View $view, $entity = null)
39
    {
40
        //the template displayed is in the widget bundle
41
        $templateName = $this->container->get('victoire_widget.widget_helper')->getTemplateName('new', $widget);
42
43
        return $this->container->get('victoire_templating')->render(
44
            $templateName,
45
            [
46
                'widget' => $widget,
47
                'form'   => $form->createView(),
48
                'slot'   => $slot,
49
                'entity' => $entity,
50
                'view'   => $view,
51
            ]
52
        );
53
    }
54
55
    /**
56
     * render Widget form.
57
     *
58
     * @param Form   $form
59
     * @param Widget $widget
60
     * @param object $entity
61
     *
62
     * @return form
63
     */
64
    public function renderForm(Form $form, Widget $widget, $entity = null)
65
    {
66
        //the template displayed is in the widget bundle
67
        $templateName = $this->container->get('victoire_widget.widget_helper')->getTemplateName('edit', $widget);
68
69
        return $this->container->get('victoire_templating')->render(
70
            $templateName,
71
            [
72
                'widget' => $widget,
73
                'view'   => $this->container->get('victoire_core.current_view')->getCurrentView(),
74
                'form'   => $form->createView(),
75
                'id'     => $widget->getId(),
76
                'entity' => $entity,
77
            ]
78
        );
79
    }
80
81
    /**
82
     * Generates new forms for each available business entities.
83
     *
84
     * @param string           $slot
85
     * @param View             $view
86
     * @param Widget           $widget
87
     * @param BusinessEntity[] $classes
88
     * @param int              $position
89
     *
90
     * @throws \Exception
91
     *
92
     * @return Form[]
93
     */
94
    public function renderNewWidgetForms($slot, View $view, Widget $widget, $classes, $position = null, $parentWidgetMap = null)
95
    {
96
        //the static form
97
        $forms['static'] = [];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$forms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $forms = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
98
        $forms['static']['main'] = $this->renderNewForm($this->buildForm($widget, $view, null, null, Widget::MODE_STATIC, $slot, $position, $parentWidgetMap), $widget, $slot, $view, null);
99
100
        // Build each form relative to business entities
101
        foreach ($classes as $businessEntity) {
102
            //get the forms for the business entity (entity/query/businessEntity)
103
            $entityForms = $this->buildEntityForms($widget, $view, $businessEntity->getId(), $businessEntity->getClass(), $position, $parentWidgetMap, $slot);
104
105
            //the list of forms
106
            $forms[$businessEntity->getId()] = [];
107
108
            //foreach of the entity form
109
            foreach ($entityForms as $formMode => $entityForm) {
110
                //we add the form
111
                $forms[$businessEntity->getId()][$formMode] = $this->renderNewForm($entityForm, $widget, $slot, $view, $businessEntity->getId());
112
            }
113
        }
114
115
        return $forms;
116
    }
117
118
    /**
119
     * @param Widget $widget
120
     * @param View   $view
121
     * @param string $businessEntityId
122
     * @param string $namespace
123
     * @param int    $position
124
     * @param string $slot
125
     *
126
     * @return array
127
     */
128
    protected function buildEntityForms($widget, View $view, $businessEntityId = null, $namespace = null, $position = null, $parentWidgetMap = null, $slot = null)
129
    {
130
        $forms = [];
131
132
        //get the entity form
133
        $entityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_ENTITY, $slot, $position, $parentWidgetMap);
134
        $forms[Widget::MODE_ENTITY] = $entityForm;
135
136
        //get the query form
137
        $queryForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_QUERY, $slot, $position, $parentWidgetMap);
138
        $forms[Widget::MODE_QUERY] = $queryForm;
139
140
        //get the query form
141
        $businessEntityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_BUSINESS_ENTITY, $slot, $position, $parentWidgetMap);
142
        $forms[Widget::MODE_BUSINESS_ENTITY] = $businessEntityForm;
143
144
        return $forms;
145
    }
146
147
    /**
148
     * create a form with given widget.
149
     *
150
     * @param Widget $widget
151
     * @param View   $view
152
     * @param string $businessEntityId
153
     * @param string $namespace
154
     * @param string $formMode
155
     * @param int    $position
156
     *
157
     * @throws \Exception
158
     *
159
     * @return $form
0 ignored issues
show
Documentation introduced by
The doc-type $form could not be parsed: Unknown type name "$form" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
160
     */
161
    public function buildWidgetForm(Widget $widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $position = null, $parentWidgetMap = null, $slotId = null)
162
    {
163
        $router = $this->container->get('router');
164
165
        //test parameters
166
        if ($businessEntityId !== null) {
167
            if ($namespace === null) {
168
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
169
            }
170
            if (in_array($formMode, [Widget::MODE_STATIC, null])) {
171
                throw new \Exception('The formMode cannot be null or static if the businessEntityId is given');
172
            }
173
        }
174
175
        $container = $this->container;
176
        $formFactory = $container->get('form.factory');
177
178
        //are we updating or creating the widget?
179
        if ($widget->getId() === null) {
180
            $viewReference = $view->getReference();
181
            $actionParams = [
182
                'viewReference'      => $viewReference->getId(),
183
                'slot'               => $slotId,
184
                'type'               => $widget->getType(), // @todo: use the config
185
                'position'           => $position,
186
                'parentWidgetMap'    => $parentWidgetMap,
187
            ];
188
            $action = 'victoire_core_widget_create';
189
            if ($businessEntityId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $businessEntityId 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...
190
                $actionParams['businessEntityId'] = $businessEntityId;
191
                $actionParams['mode'] = $formMode;
192
            } else {
193
                $action = 'victoire_core_widget_create_static';
194
            }
195
            $formUrl = $router->generate($action, $actionParams);
196
        } else {
197
            $viewReference = $widget->getCurrentView()->getReference();
198
            $formUrl = $router->generate('victoire_core_widget_update',
199
                [
200
                    'id'               => $widget->getId(),
201
                    'viewReference'    => $viewReference->getId(),
202
                    'businessEntityId' => $businessEntityId,
203
                    'mode'             => $formMode,
204
                ]
205
            );
206
        }
207
208
        $widgetFormTypeClass = ClassUtils::getClass(
209
            $this->container->get(
210
                sprintf(
211
                    'victoire.widget.form.%s',
212
                    strtolower($this->container->get('victoire_widget.widget_helper')->getWidgetName($widget))
213
                )
214
            )
215
        );
216
217
        $optionsContainer = new WidgetOptionsContainer([
218
            'businessEntityId' => $businessEntityId,
219
            'namespace'        => $namespace,
220
            'mode'             => $formMode,
221
            'action'           => $formUrl,
222
            'method'           => 'POST',
223
        ]);
224
225
        $event = new WidgetFormCreateEvent($optionsContainer, $widgetFormTypeClass);
226
        $this->container->get('event_dispatcher')->dispatch(WidgetFormEvents::PRE_CREATE, $event);
227
228
        /** @var Form $mockForm Get the base form to get the name */
229
        $mockForm = $formFactory->create($widgetFormTypeClass, $widget, $optionsContainer->getOptions());
230
        //Prefix base name with form mode to avoid to have unique form fields ids
231
        $form = $formFactory->createNamed(
232
            sprintf('%s_%s_%s', $businessEntityId, $formMode, $mockForm->getName()),
233
            $widgetFormTypeClass,
234
            $widget,
235
            $params
0 ignored issues
show
Bug introduced by
The variable $params does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
236
        );
237
238
        return $form;
239
    }
240
241
    /**
242
     * create a form with given widget.
243
     *
244
     * @param Widget $widget           the widget
245
     * @param View   $view             the page
246
     * @param string $businessEntityId the entity class
247
     * @param string $namespace        the namespace
248
     * @param string $formMode         the form mode
249
     * @param int    $position
250
     *
251
     * @throws \Exception
252
     *
253
     * @return $form
0 ignored issues
show
Documentation introduced by
The doc-type $form could not be parsed: Unknown type name "$form" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
254
     */
255
    public function buildForm($widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $slotId = null, $position = null, $parentWidgetMap = null)
256
    {
257
        //test parameters
258
        if ($businessEntityId !== null) {
259
            if ($namespace === null) {
260
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
261
            }
262
            if ($formMode === null) {
263
                throw new \Exception('The formMode is mandatory if the businessEntityId is given');
264
            }
265
        }
266
267
        $form = $this->buildWidgetForm($widget, $view, $businessEntityId, $namespace, $formMode, $position, $parentWidgetMap, $slotId);
268
269
        //send event
270
        $dispatcher = $this->container->get('event_dispatcher');
271
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_BUILD_FORM, new WidgetBuildFormEvent($widget, $form));
272
273
        return $form;
274
    }
275
276
    /**
277
     * Call the build form with selected parameter switch the parameters
278
     * The call is not the same if an entity is provided or not.
279
     *
280
     * @param Widget $widget
281
     * @param View   $view
282
     * @param string $businessEntityId
283
     * @param int    $position
284
     * @param string $slotId
285
     *
286
     * @throws \Exception
287
     *
288
     * @return \Symfony\Component\Form\Form
289
     */
290
    public function callBuildFormSwitchParameters(Widget $widget, $view, $businessEntityId, $position, $parentWidgetMap, $slotId)
291
    {
292
        $entityClass = null;
293
        //if there is an entity
294
        if ($businessEntityId) {
295
            //get the businessClasses for the widget
296
            $classes = $this->container->get('victoire_core.helper.business_entity_helper')->getBusinessClassesForWidget($widget);
297
298
            //test the result
299
            if (!isset($classes[$businessEntityId])) {
300
                throw new \Exception('The entity '.$businessEntityId.' was not found int the business classes.');
301
            }
302
            //get the class of the entity name
303
            $entityClass = $classes[$businessEntityId]->getClass();
304
        }
305
306
        $form = $this->buildForm($widget, $view, $businessEntityId, $entityClass, $widget->getMode(), $slotId, $position, $parentWidgetMap);
307
308
        return $form;
309
    }
310
}
311