Completed
Pull Request — master (#387)
by Paul
06:54
created

WidgetFormBuilder::buildEntityForms()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 18
rs 9.4285
cc 1
eloc 9
nc 1
nop 8

How to fix   Many Parameters   

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