Completed
Pull Request — master (#351)
by Leny
06:37
created

WidgetFormBuilder   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 293
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 8
Bugs 4 Features 0
Metric Value
wmc 20
c 8
b 4
f 0
lcom 1
cbo 10
dl 0
loc 293
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A renderNewForm() 0 16 1
A renderForm() 0 16 1
A renderNewWidgetForms() 0 23 3
A buildEntityForms() 0 18 1
B buildWidgetForm() 0 79 6
A buildForm() 0 20 4
A callBuildFormSwitchParameters() 0 20 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('victoire_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('victoire_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
     *
89
     * @throws \Exception
90
     *
91
     * @return Form[]
92
     */
93
    public function renderNewWidgetForms($slot, View $view, Widget $widget, $classes, $position = null, $parentWidgetMap = null)
94
    {
95
        //the static form
96
        $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...
97
        $forms['static']['main'] = $this->renderNewForm($this->buildForm($widget, $view, null, null, Widget::MODE_STATIC, $slot, $position, $parentWidgetMap), $widget, $slot, $view, null);
98
99
        // Build each form relative to business entities
100
        foreach ($classes as $businessEntity) {
101
            //get the forms for the business entity (entity/query/businessEntity)
102
            $entityForms = $this->buildEntityForms($widget, $view, $businessEntity->getId(), $businessEntity->getClass(), $position, $parentWidgetMap, $slot);
103
104
            //the list of forms
105
            $forms[$businessEntity->getId()] = [];
106
107
            //foreach of the entity form
108
            foreach ($entityForms as $formMode => $entityForm) {
109
                //we add the form
110
                $forms[$businessEntity->getId()][$formMode] = $this->renderNewForm($entityForm, $widget, $slot, $view, $businessEntity->getId());
111
            }
112
        }
113
114
        return $forms;
115
    }
116
117
    /**
118
     * @param Widget $widget
119
     * @param View   $view
120
     * @param string $businessEntityId
121
     * @param string $namespace
122
     * @param int    $position
123
     * @param string $slot
124
     *
125
     * @return array
126
     */
127
    protected function buildEntityForms($widget, View $view, $businessEntityId = null, $namespace = null, $position = null, $parentWidgetMap = null, $slot = null)
128
    {
129
        $forms = [];
130
131
        //get the entity form
132
        $entityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_ENTITY, $slot, $position, $parentWidgetMap);
133
        $forms[Widget::MODE_ENTITY] = $entityForm;
134
135
        //get the query form
136
        $queryForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_QUERY, $slot, $position, $parentWidgetMap);
137
        $forms[Widget::MODE_QUERY] = $queryForm;
138
139
        //get the query form
140
        $businessEntityForm = $this->buildForm($widget, $view, $businessEntityId, $namespace, Widget::MODE_BUSINESS_ENTITY, $slot, $position, $parentWidgetMap);
141
        $forms[Widget::MODE_BUSINESS_ENTITY] = $businessEntityForm;
142
143
        return $forms;
144
    }
145
146
    /**
147
     * create a form with given widget.
148
     *
149
     * @param Widget $widget
150
     * @param View   $view
151
     * @param string $businessEntityId
152
     * @param string $namespace
153
     * @param string $formMode
154
     * @param int    $position
155
     *
156
     * @throws \Exception
157
     *
158
     * @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...
159
     */
160
    public function buildWidgetForm(Widget $widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $position = null, $parentWidgetMap = null, $slotId = null)
161
    {
162
        $router = $this->container->get('router');
163
164
        //test parameters
165
        if ($businessEntityId !== null) {
166
            if ($namespace === null) {
167
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
168
            }
169
            if (in_array($formMode, [Widget::MODE_STATIC, null])) {
170
                throw new \Exception('The formMode cannot be null or static if the businessEntityId is given');
171
            }
172
        }
173
174
        $container = $this->container;
175
        $formFactory = $container->get('form.factory');
176
177
        //are we updating or creating the widget?
178
        if ($widget->getId() === null) {
179
            $viewReference = $view->getReference();
180
            $actionParams = [
181
                'viewReference'      => $viewReference->getId(),
182
                'slot'               => $slotId,
183
                'type'               => $widget->getType(), // @todo: use the config
184
                'position'           => $position,
185
                'parentWidgetMap'    => $parentWidgetMap,
186
            ];
187
            $action = 'victoire_core_widget_create';
188
            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...
189
                $actionParams['businessEntityId'] = $businessEntityId;
190
                $actionParams['mode'] = $formMode;
191
            } else {
192
                $action = 'victoire_core_widget_create_static';
193
            }
194
            $formUrl = $router->generate($action, $actionParams);
195
        } else {
196
            $viewReference = $widget->getCurrentView()->getReference();
197
            $formUrl = $router->generate('victoire_core_widget_update',
198
                [
199
                    'id'               => $widget->getId(),
200
                    'viewReference'    => $viewReference->getId(),
201
                    'businessEntityId' => $businessEntityId,
202
                    'mode'             => $formMode,
203
                ]
204
            );
205
        }
206
207
        $widgetFormTypeClass = ClassUtils::getClass(
208
            $this->container->get(
209
                sprintf(
210
                    'victoire.widget.form.%s',
211
                    strtolower($this->container->get('victoire_widget.widget_helper')->getWidgetName($widget))
212
                )
213
            )
214
        );
215
216
        $optionsContainer = new WidgetOptionsContainer([
217
            'businessEntityId' => $businessEntityId,
218
            'namespace'        => $namespace,
219
            'mode'             => $formMode,
220
            'action'           => $formUrl,
221
            'method'           => 'POST',
222
        ]);
223
224
        $event = new WidgetFormCreateEvent($optionsContainer, $widgetFormTypeClass);
225
        $this->container->get('event_dispatcher')->dispatch(WidgetFormEvents::PRE_CREATE, $event);
226
227
        /** @var Form $mockForm Get the base form to get the name */
228
        $mockForm = $formFactory->create($widgetFormTypeClass, $widget, $optionsContainer->getOptions());
229
        //Prefix base name with form mode to avoid to have unique form fields ids
230
        $form = $formFactory->createNamed(
231
            sprintf('%s_%s_%s', $businessEntityId, $formMode, $mockForm->getName()),
232
            $widgetFormTypeClass,
233
            $widget,
234
            $optionsContainer->getOptions()
235
        );
236
237
        return $form;
238
    }
239
240
    /**
241
     * create a form with given widget.
242
     *
243
     * @param Widget $widget           the widget
244
     * @param View   $view             the page
245
     * @param string $businessEntityId the entity class
246
     * @param string $namespace        the namespace
247
     * @param string $formMode         the form mode
248
     * @param int    $position
249
     *
250
     * @throws \Exception
251
     *
252
     * @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...
253
     */
254
    public function buildForm($widget, View $view, $businessEntityId = null, $namespace = null, $formMode = Widget::MODE_STATIC, $slotId = null, $position = null, $parentWidgetMap = null)
255
    {
256
        //test parameters
257
        if ($businessEntityId !== null) {
258
            if ($namespace === null) {
259
                throw new \Exception('The namespace is mandatory if the businessEntityId is given');
260
            }
261
            if ($formMode === null) {
262
                throw new \Exception('The formMode is mandatory if the businessEntityId is given');
263
            }
264
        }
265
266
        $form = $this->buildWidgetForm($widget, $view, $businessEntityId, $namespace, $formMode, $position, $parentWidgetMap, $slotId);
267
268
        //send event
269
        $dispatcher = $this->container->get('event_dispatcher');
270
        $dispatcher->dispatch(VictoireCmsEvents::WIDGET_BUILD_FORM, new WidgetBuildFormEvent($widget, $form));
271
272
        return $form;
273
    }
274
275
    /**
276
     * Call the build form with selected parameter switch the parameters
277
     * The call is not the same if an entity is provided or not.
278
     *
279
     * @param Widget $widget
280
     * @param View   $view
281
     * @param string $businessEntityId
282
     * @param int    $position
283
     * @param string $slotId
284
     *
285
     * @throws \Exception
286
     *
287
     * @return \Symfony\Component\Form\Form
288
     */
289
    public function callBuildFormSwitchParameters(Widget $widget, $view, $businessEntityId, $position, $parentWidgetMap, $slotId)
290
    {
291
        $entityClass = null;
292
        //if there is an entity
293
        if ($businessEntityId) {
294
            //get the businessClasses for the widget
295
            $classes = $this->container->get('victoire_core.helper.business_entity_helper')->getBusinessClassesForWidget($widget);
296
297
            //test the result
298
            if (!isset($classes[$businessEntityId])) {
299
                throw new \Exception('The entity '.$businessEntityId.' was not found int the business classes.');
300
            }
301
            //get the class of the entity name
302
            $entityClass = $classes[$businessEntityId]->getClass();
303
        }
304
305
        $form = $this->buildForm($widget, $view, $businessEntityId, $entityClass, $widget->getMode(), $slotId, $position, $parentWidgetMap);
306
307
        return $form;
308
    }
309
}
310