Completed
Pull Request — master (#375)
by Paul
06:22
created

WidgetFormBuilder::buildWidgetForm()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 83
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 2 Features 0
Metric Value
c 7
b 2
f 0
dl 0
loc 83
rs 8.3634
cc 6
eloc 54
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('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('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
     * Generates new forms for each available business entities.
118
     *
119
     * @param string           $slot
120
     * @param View             $view
121
     * @param Widget           $widget
0 ignored issues
show
Documentation introduced by
There is no parameter named $widget. Did you maybe mean $widgets?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
122
     * @param BusinessEntity[] $classes
123
     * @param int              $position
124
     *
125
     * @throws \Exception
126
     *
127
     * @return Form[]
128
     */
129
    public function renderNewQuantumForms($slot, View $view, $widgets, $activeWidget, $classes, $position = null, $parentWidgetMap = null)
130
    {
131
        $forms = [];
132
        foreach ($widgets as $key => $widget) {
133
            $forms[$key] = $this->renderNewWidgetForms($slot, $view, $widget, $classes, $position, $parentWidgetMap);
134
            if ($widget === $activeWidget) {
135
                $forms[$key]['active'] = true;
136
            }
137
        }
138
139
        return $forms;
140
    }
141
142
    /**
143
     * @param Widget $widget
144
     * @param View   $view
145
     * @param string $businessEntityId
146
     * @param string $namespace
147
     * @param int    $position
148
     * @param string $slot
149
     *
150
     * @return array
151
     */
152
    protected function buildEntityForms($widget, View $view, $businessEntityId = null, $namespace = null, $position = null, $parentWidgetMap = null, $slot = null)
153
    {
154
        $forms = [];
155
156
        //get the entity form
157
        $entityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_ENTITY, $slot, $position, $parentWidgetMap);
158
        $forms[Widget::MODE_ENTITY] = $entityForm;
159
160
        //get the query form
161
        $queryForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_QUERY, $slot, $position, $parentWidgetMap);
162
        $forms[Widget::MODE_QUERY] = $queryForm;
163
164
        //get the query form
165
        $businessEntityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_BUSINESS_ENTITY, $slot, $position, $parentWidgetMap);
166
        $forms[Widget::MODE_BUSINESS_ENTITY] = $businessEntityForm;
167
168
        return $forms;
169
    }
170
171
    /**
172
     * create a form with given widget.
173
     *
174
     * @param Widget $widget
175
     * @param View   $view
176
     * @param string $businessEntityId
177
     * @param string $namespace
178
     * @param string $formMode
179
     * @param int    $position
180
     *
181
     * @throws \Exception
182
     *
183
     * @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...
184
     */
185
    public function buildWidgetForm(Widget $widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $position = null, $parentWidgetMap = null, $slotId = null)
186
    {
187
        $router = $this->container->get('router');
188
189
        //test parameters
190
        if ($businessEntityId !== null) {
191
            if ($namespace === null) {
192
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
193
            }
194
            if (in_array($formMode, [Widget::MODE_STATIC, null])) {
195
                throw new \Exception('The formMode cannot be null or static if the businessEntityId is given');
196
            }
197
        }
198
199
        $container = $this->container;
200
        $formFactory = $container->get('form.factory');
201
202
        //are we updating or creating the widget?
203
        if ($widget->getId() === null) {
204
            $viewReference = $view->getReference();
205
            $actionParams = [
206
                'viewReference'      => $viewReference->getId(),
207
                'slot'               => $slotId,
208
                'type'               => $widget->getType(), // @todo: use the config
209
                'position'           => $position,
210
                'parentWidgetMap'    => $parentWidgetMap,
211
            ];
212
            $action = 'victoire_core_widget_create';
213
            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...
214
                $actionParams['businessEntityId'] = $businessEntityId;
215
                $actionParams['mode'] = $formMode;
216
            } else {
217
                $action = 'victoire_core_widget_create_static';
218
            }
219
            $formUrl = $router->generate($action, $actionParams);
220
        } else {
221
            $viewReference = $this->container->get('victoire_core.current_view')->getCurrentView()->getReference();
222
            $formUrl = $router->generate('victoire_core_widget_update',
223
                [
224
                    'id'               => $widget->getId(),
225
                    'viewReference'    => $viewReference->getId(),
226
                    'businessEntityId' => $businessEntityId,
227
                    'mode'             => $formMode,
228
                ]
229
            );
230
        }
231
232
        $widgetName = $this->container->get('victoire_widget.widget_helper')->getWidgetName($widget);
233
234
        $widgetFormTypeClass = ClassUtils::getClass(
235
            $this->container->get(
236
                sprintf(
237
                    'victoire.widget.form.%s',
238
                    strtolower($widgetName)
239
                )
240
            )
241
        );
242
243
        $optionsContainer = new WidgetOptionsContainer([
244
            'businessEntityId' => $businessEntityId,
245
            'namespace'        => $namespace,
246
            'mode'             => $formMode,
247
            'action'           => $formUrl,
248
            'method'           => 'POST',
249
            'dataSources'           => $this->container->get('victoire_criteria.chain.data_source_chain'),
250
        ]);
251
252
        $event = new WidgetFormCreateEvent($optionsContainer, $widgetFormTypeClass);
253
        $this->container->get('event_dispatcher')->dispatch(WidgetFormEvents::PRE_CREATE, $event);
254
        $this->container->get('event_dispatcher')->dispatch(WidgetFormEvents::PRE_CREATE.'_'.strtoupper($widgetName), $event);
255
256
        /** @var Form $mockForm Get the base form to get the name */
257
        $mockForm = $formFactory->create($widgetFormTypeClass, $widget, $optionsContainer->getOptions());
258
        //Prefix base name with form mode to avoid to have unique form fields ids
259
        $form = $formFactory->createNamed(
260
            sprintf('%s_%s_%s', $businessEntityId, $formMode, $mockForm->getName()),
261
            $widgetFormTypeClass,
262
            $widget,
263
            $optionsContainer->getOptions()
264
        );
265
266
        return $form;
267
    }
268
269
    /**
270
     * create a form with given widget.
271
     *
272
     * @param Widget $widget           the widget
273
     * @param View   $view             the page
274
     * @param string $businessEntityId the entity class
275
     * @param string $namespace        the namespace
276
     * @param string $formMode         the form mode
277
     * @param int    $position
278
     *
279
     * @throws \Exception
280
     *
281
     * @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...
282
     */
283
    public function buildForm($widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $slotId = null, $position = null, $parentWidgetMap = null)
284
    {
285
        //test parameters
286
        if ($businessEntityId !== null) {
287
            if ($namespace === null) {
288
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
289
            }
290
            if ($formMode === null) {
291
                throw new \Exception('The formMode is mandatory if the businessEntityId is given');
292
            }
293
        }
294
295
        $form = $this->buildWidgetForm($widget, $view, $businessEntityId, $namespace, $formMode, $position, $parentWidgetMap, $slotId);
296
297
        //send event
298
        $dispatcher = $this->container->get('event_dispatcher');
299
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_BUILD_FORM, new WidgetBuildFormEvent($widget, $form));
300
301
        return $form;
302
    }
303
304
    /**
305
     * Call the build form with selected parameter switch the parameters
306
     * The call is not the same if an entity is provided or not.
307
     *
308
     * @param Widget $widget
309
     * @param View   $view
310
     * @param string $businessEntityId
311
     * @param int    $position
312
     * @param string $slotId
313
     *
314
     * @throws \Exception
315
     *
316
     * @return \Symfony\Component\Form\Form
317
     */
318
    public function callBuildFormSwitchParameters(Widget $widget, $view, $businessEntityId, $position, $parentWidgetMap, $slotId)
319
    {
320
        $entityClass = null;
321
        //if there is an entity
322
        if ($businessEntityId) {
323
            //get the businessClasses for the widget
324
            $classes = $this->container->get('victoire_core.helper.business_entity_helper')->getBusinessClassesForWidget($widget);
325
326
            //test the result
327
            if (!isset($classes[$businessEntityId])) {
328
                throw new \Exception('The entity '.$businessEntityId.' was not found int the business classes.');
329
            }
330
            //get the class of the entity name
331
            $entityClass = $classes[$businessEntityId]->getClass();
332
        }
333
334
        $form = $this->buildForm($widget, $view, $businessEntityId, $entityClass, $widget->getMode(), $slotId, $position, $parentWidgetMap);
335
336
        return $form;
337
    }
338
}
339