Completed
Pull Request — master (#387)
by Paul
06:54
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, $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