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

WidgetFormBuilder::convertToString()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 2
eloc 6
nc 1
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
                '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