Completed
Pull Request — master (#387)
by Paul
07:40
created

WidgetFormBuilder::buildWidgetForm()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 86
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 1
Metric Value
c 6
b 1
f 1
dl 0
loc 86
rs 8.3234
cc 6
eloc 56
nc 8
nop 9

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, $quantum = null)
0 ignored issues
show
Unused Code introduced by
The parameter $quantum is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

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