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

WidgetFormBuilder::buildWidgetForm()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 79
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 2 Features 0
Metric Value
c 6
b 2
f 0
dl 0
loc 79
rs 8.4178
cc 6
eloc 51
nc 8
nop 8

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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 Victoire\Bundle\BusinessEntityBundle\Entity\BusinessEntity;
9
use Victoire\Bundle\CoreBundle\Entity\View;
10
use Victoire\Bundle\CoreBundle\Event\WidgetBuildFormEvent;
11
use Victoire\Bundle\CoreBundle\VictoireCmsEvents;
12
use Victoire\Bundle\WidgetBundle\Entity\Widget;
13
use Victoire\Bundle\WidgetBundle\Event\WidgetFormCreateEvent;
14
use Victoire\Bundle\WidgetBundle\Event\WidgetFormEvents;
15
use Victoire\Bundle\WidgetBundle\Form\WidgetOptionsContainer;
16
17
class WidgetFormBuilder
18
{
19
    private $container;
20
21
    public function __construct(Container $container)
22
    {
23
        $this->container = $container;
24
    }
25
26
    /**
27
     * create form new for a widget.
28
     *
29
     * @param Form   $form
30
     * @param Widget $widget
31
     * @param string $slot
32
     * @param View   $view
33
     * @param string $entity
34
     *
35
     * @return string
36
     */
37
    public function renderNewForm($form, $widget, $slot, View $view, $entity = null)
38
    {
39
        //the template displayed is in the widget bundle
40
        $templateName = $this->container->get('victoire_widget.widget_helper')->getTemplateName('new', $widget);
41
42
        return $this->container->get('victoire_templating')->render(
43
            $templateName,
44
            [
45
                'widget' => $widget,
46
                'form'   => $form->createView(),
47
                'slot'   => $slot,
48
                'entity' => $entity,
49
                'view'   => $view,
50
            ]
51
        );
52
    }
53
54
    /**
55
     * render Widget form.
56
     *
57
     * @param Form   $form
58
     * @param Widget $widget
59
     * @param object $entity
60
     *
61
     * @return form
62
     */
63
    public function renderForm(Form $form, Widget $widget, $entity = null)
64
    {
65
        //the template displayed is in the widget bundle
66
        $templateName = $this->container->get('victoire_widget.widget_helper')->getTemplateName('edit', $widget);
67
68
        return $this->container->get('victoire_templating')->render(
69
            $templateName,
70
            [
71
                'widget' => $widget,
72
                'view'   => $this->container->get('victoire_core.current_view')->getCurrentView(),
73
                'form'   => $form->createView(),
74
                'id'     => $widget->getId(),
75
                'entity' => $entity,
76
            ]
77
        );
78
    }
79
80
    /**
81
     * Generates new forms for each available business entities.
82
     *
83
     * @param string           $slot
84
     * @param View             $view
85
     * @param Widget           $widget
86
     * @param BusinessEntity[] $classes
87
     * @param int              $position
88
     *
89
     * @throws \Exception
90
     *
91
     * @return Form[]
92
     */
93
    public function renderNewWidgetForms($slot, View $view, Widget $widget, $classes, $position = null, $parentWidgetMap = null)
94
    {
95
        //the static form
96
        $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...
97
        $forms['static']['main'] = $this->renderNewForm($this->buildForm($widget, $view, null, null, Widget::MODE_STATIC, $slot, $position, $parentWidgetMap), $widget, $slot, $view, null);
98
99
        // Build each form relative to business entities
100
        foreach ($classes as $businessEntity) {
101
            //get the forms for the business entity (entity/query/businessEntity)
102
            $entityForms = $this->buildEntityForms($widget, $view, $businessEntity->getId(), $businessEntity->getClass(), $position, $parentWidgetMap, $slot);
103
104
            //the list of forms
105
            $forms[$businessEntity->getId()] = [];
106
107
            //foreach of the entity form
108
            foreach ($entityForms as $formMode => $entityForm) {
109
                //we add the form
110
                $forms[$businessEntity->getId()][$formMode] = $this->renderNewForm($entityForm, $widget, $slot, $view, $businessEntity->getId());
111
            }
112
        }
113
114
        return $forms;
115
    }
116
117
    /**
118
     * @param Widget $widget
119
     * @param View   $view
120
     * @param string $businessEntityId
121
     * @param string $namespace
122
     * @param int    $position
123
     * @param string $slot
124
     *
125
     * @return array
126
     */
127
    protected function buildEntityForms($widget, View $view, $businessEntityId = null, $namespace = null, $position = null, $parentWidgetMap = null, $slot = null)
128
    {
129
        $forms = [];
130
131
        //get the entity form
132
        $entityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_ENTITY, $slot, $position, $parentWidgetMap);
133
        $forms[Widget::MODE_ENTITY] = $entityForm;
134
135
        //get the query form
136
        $queryForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_QUERY, $slot, $position, $parentWidgetMap);
137
        $forms[Widget::MODE_QUERY] = $queryForm;
138
139
        //get the query form
140
        $businessEntityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_BUSINESS_ENTITY, $slot, $position, $parentWidgetMap);
141
        $forms[Widget::MODE_BUSINESS_ENTITY] = $businessEntityForm;
142
143
        return $forms;
144
    }
145
146
    /**
147
     * create a form with given widget.
148
     *
149
     * @param Widget $widget
150
     * @param View   $view
151
     * @param string $businessEntityId
152
     * @param string $namespace
153
     * @param string $formMode
154
     * @param int    $position
155
     *
156
     * @throws \Exception
157
     *
158
     * @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...
159
     */
160
    public function buildWidgetForm(Widget $widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $position = null, $parentWidgetMap = null, $slotId = null)
161
    {
162
        $router = $this->container->get('router');
163
164
        //test parameters
165
        if ($businessEntityId !== null) {
166
            if ($namespace === null) {
167
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
168
            }
169
            if (in_array($formMode, [Widget::MODE_STATIC, null])) {
170
                throw new \Exception('The formMode cannot be null or static if the businessEntityId is given');
171
            }
172
        }
173
174
        $container = $this->container;
175
        $formFactory = $container->get('form.factory');
176
177
        //are we updating or creating the widget?
178
        if ($widget->getId() === null) {
179
            $viewReference = $view->getReference();
180
            $actionParams = [
181
                'viewReference'      => $viewReference->getId(),
182
                'slot'               => $slotId,
183
                'type'               => $widget->getType(), // @todo: use the config
184
                'position'           => $position,
185
                'parentWidgetMap'    => $parentWidgetMap,
186
            ];
187
            $action = 'victoire_core_widget_create';
188
            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...
189
                $actionParams['businessEntityId'] = $businessEntityId;
190
                $actionParams['mode'] = $formMode;
191
            } else {
192
                $action = 'victoire_core_widget_create_static';
193
            }
194
            $formUrl = $router->generate($action, $actionParams);
195
        } else {
196
            $viewReference = $widget->getCurrentView()->getReference();
197
            $formUrl = $router->generate('victoire_core_widget_update',
198
                [
199
                    'id'               => $widget->getId(),
200
                    'viewReference'    => $viewReference->getId(),
201
                    'businessEntityId' => $businessEntityId,
202
                    'mode'             => $formMode,
203
                ]
204
            );
205
        }
206
207
        $widgetFormTypeClass = ClassUtils::getClass(
208
            $this->container->get(
209
                sprintf(
210
                    'victoire.widget.form.%s',
211
                    strtolower($this->container->get('victoire_widget.widget_helper')->getWidgetName($widget))
212
                )
213
            )
214
        );
215
216
        $optionsContainer = new WidgetOptionsContainer([
217
            'businessEntityId' => $businessEntityId,
218
            'namespace'        => $namespace,
219
            'mode'             => $formMode,
220
            'action'           => $formUrl,
221
            'method'           => 'POST',
222
        ]);
223
224
        $event = new WidgetFormCreateEvent($optionsContainer, $widgetFormTypeClass);
225
        $this->container->get('event_dispatcher')->dispatch(WidgetFormEvents::PRE_CREATE, $event);
226
227
        /** @var Form $mockForm Get the base form to get the name */
228
        $mockForm = $formFactory->create($widgetFormTypeClass, $widget, $optionsContainer->getOptions());
229
        //Prefix base name with form mode to avoid to have unique form fields ids
230
        $form = $formFactory->createNamed(
231
            sprintf('%s_%s_%s', $businessEntityId, $formMode, $mockForm->getName()),
232
            $widgetFormTypeClass,
233
            $widget,
234
            $optionsContainer->getOptions()
235
        );
236
237
        return $form;
238
    }
239
240
    /**
241
     * create a form with given widget.
242
     *
243
     * @param Widget $widget           the widget
244
     * @param View   $view             the page
245
     * @param string $businessEntityId the entity class
246
     * @param string $namespace        the namespace
247
     * @param string $formMode         the form mode
248
     * @param int    $position
249
     *
250
     * @throws \Exception
251
     *
252
     * @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...
253
     */
254
    public function buildForm($widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $slotId = null, $position = null, $parentWidgetMap = null)
255
    {
256
        //test parameters
257
        if ($businessEntityId !== null) {
258
            if ($namespace === null) {
259
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
260
            }
261
            if ($formMode === null) {
262
                throw new \Exception('The formMode is mandatory if the businessEntityId is given');
263
            }
264
        }
265
266
        $form = $this->buildWidgetForm($widget, $view, $businessEntityId, $namespace, $formMode, $position, $parentWidgetMap, $slotId);
267
268
        //send event
269
        $dispatcher = $this->container->get('event_dispatcher');
270
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_BUILD_FORM, new WidgetBuildFormEvent($widget, $form));
271
272
        return $form;
273
    }
274
275
    /**
276
     * Call the build form with selected parameter switch the parameters
277
     * The call is not the same if an entity is provided or not.
278
     *
279
     * @param Widget $widget
280
     * @param View   $view
281
     * @param string $businessEntityId
282
     * @param int    $position
283
     * @param string $slotId
284
     *
285
     * @throws \Exception
286
     *
287
     * @return \Symfony\Component\Form\Form
288
     */
289
    public function callBuildFormSwitchParameters(Widget $widget, $view, $businessEntityId, $position, $parentWidgetMap, $slotId)
290
    {
291
        $entityClass = null;
292
        //if there is an entity
293
        if ($businessEntityId) {
294
            //get the businessClasses for the widget
295
            $classes = $this->container->get('victoire_core.helper.business_entity_helper')->getBusinessClassesForWidget($widget);
296
297
            //test the result
298
            if (!isset($classes[$businessEntityId])) {
299
                throw new \Exception('The entity '.$businessEntityId.' was not found int the business classes.');
300
            }
301
            //get the class of the entity name
302
            $entityClass = $classes[$businessEntityId]->getClass();
303
        }
304
305
        $form = $this->buildForm($widget, $view, $businessEntityId, $entityClass, $widget->getMode(), $slotId, $position, $parentWidgetMap);
306
307
        return $form;
308
    }
309
}
310