Completed
Push — master ( 7b108e...bec163 )
by Paul
11s
created

WidgetFormBuilder::convertToString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
326
327
        return $form;
328
    }
329
330
    /**
331
     * Call the build form with selected parameter switch the parameters
332
     * The call is not the same if an entity is provided or not.
333
     *
334
     * @param Widget $widget
335
     * @param View   $view
336
     * @param string $businessEntityId
337
     * @param int    $position
338
     * @param string $slotId
339
     *
340
     * @throws \Exception
341
     *
342
     * @return \Symfony\Component\Form\Form
343
     */
344
    public function callBuildFormSwitchParameters(Widget $widget, $view, $businessEntityId, $position, $parentWidgetMap, $slotId, $quantum)
345
    {
346
        $entityClass = null;
347
        //if there is an entity
348
        if ($businessEntityId) {
349
            //get the businessClasses for the widget
350
            $classes = $this->container->get('victoire_core.helper.business_entity_helper')->getBusinessClassesForWidget($widget);
351
352
            //test the result
353
            if (!isset($classes[$businessEntityId])) {
354
                throw new \Exception('The entity '.$businessEntityId.' was not found int the business classes.');
355
            }
356
            //get the class of the entity name
357
            $entityClass = $classes[$businessEntityId]->getClass();
358
        }
359
360
        $form = $this->buildForm($widget, $view, $businessEntityId, $entityClass, $widget->getMode(), $slotId, $position, $parentWidgetMap, $quantum);
361
362
        return $form;
363
    }
364
}
365