Issues (3627)

FormBundle/Controller/Api/FormApiController.php (2 issues)

1
<?php
2
3
/*
4
 * @copyright   2014 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\FormBundle\Controller\Api;
13
14
use Mautic\ApiBundle\Controller\CommonApiController;
15
use Mautic\FormBundle\Entity\Action;
16
use Mautic\FormBundle\Model\FormModel;
17
use Symfony\Component\Form\FormInterface;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
20
21
/**
22
 * Class FormApiController.
23
 */
24
class FormApiController extends CommonApiController
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function initialize(FilterControllerEvent $event)
30
    {
31
        $this->model            = $this->getModel('form');
32
        $this->entityClass      = 'Mautic\FormBundle\Entity\Form';
33
        $this->entityNameOne    = 'form';
34
        $this->entityNameMulti  = 'forms';
35
        $this->serializerGroups = ['formDetails', 'categoryList', 'publishDetails'];
36
37
        parent::initialize($event);
38
    }
39
40
    /**
41
     * {@inheritdoc}
42
     */
43
    protected function preSerializeEntity(&$entity, $action = 'view')
44
    {
45
        $entity->automaticJs = '<script type="text/javascript" src="'.$this->generateUrl('mautic_form_generateform', ['id' => $entity->getId()], true).'"></script>';
46
    }
47
48
    /**
49
     * Delete fields from a form.
50
     *
51
     * @return \Symfony\Component\HttpFoundation\Response
52
     */
53
    public function deleteFieldsAction($formId)
54
    {
55
        if (!$this->security->isGranted(['form:forms:editown', 'form:forms:editother'], 'MATCH_ONE')) {
56
            return $this->accessDenied();
57
        }
58
59
        $entity = $this->model->getEntity($formId);
60
61
        if (null === $entity) {
62
            return $this->notFound();
63
        }
64
65
        $fieldsToDelete = $this->request->get('fields');
66
67
        if (!is_array($fieldsToDelete)) {
68
            return $this->badRequest('The fields attribute must be array.');
69
        }
70
71
        $this->model->deleteFields($entity, $fieldsToDelete);
72
73
        $view = $this->view([$this->entityNameOne => $entity]);
74
75
        return $this->handleView($view);
76
    }
77
78
    /**
79
     * Delete fields from a form.
80
     *
81
     * @return \Symfony\Component\HttpFoundation\Response
82
     */
83
    public function deleteActionsAction($formId)
84
    {
85
        if (!$this->security->isGranted(['form:forms:editown', 'form:forms:editother'], 'MATCH_ONE')) {
86
            return $this->accessDenied();
87
        }
88
89
        $entity = $this->model->getEntity($formId);
90
91
        if (null === $entity) {
92
            return $this->notFound();
93
        }
94
95
        $actionsToDelete = $this->request->get('actions');
96
97
        if (!is_array($actionsToDelete)) {
98
            return $this->badRequest('The actions attribute must be array.');
99
        }
100
101
        $this->model->deleteActions($entity, $actionsToDelete);
0 ignored issues
show
The method deleteActions() does not exist on Mautic\CoreBundle\Model\AbstractCommonModel. It seems like you code against a sub-type of Mautic\CoreBundle\Model\AbstractCommonModel such as Mautic\FormBundle\Model\FormModel. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

101
        $this->model->/** @scrutinizer ignore-call */ 
102
                      deleteActions($entity, $actionsToDelete);
Loading history...
102
103
        $view = $this->view([$this->entityNameOne => $entity]);
104
105
        return $this->handleView($view);
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
112
    {
113
        $method      = $this->request->getMethod();
114
        $fieldModel  = $this->getModel('form.field');
115
        $actionModel = $this->getModel('form.action');
116
        $isNew       = false;
117
        $alias       = $entity->getAlias();
118
119
        if (empty($alias)) {
120
            // Set clean alias to prevent SQL errors
121
            $alias = $this->model->cleanAlias($entity->getName(), '', 10);
122
            $entity->setAlias($alias);
123
        }
124
125
        // Set timestamps
126
        $this->model->setTimestamps($entity, true, false);
127
128
        if (!$entity->getId()) {
129
            $isNew = true;
130
131
            // Save the form first to get the form ID.
132
            // Using the repository function to not trigger the listeners twice.
133
            $this->model->getRepository()->saveEntity($entity);
134
        }
135
136
        $formId           = $entity->getId();
137
        $requestFieldIds  = [];
138
        $requestActionIds = [];
139
        $currentFields    = $entity->getFields();
140
        $currentActions   = $entity->getActions();
141
142
        // Add fields from the request
143
        if (!empty($parameters['fields']) && is_array($parameters['fields'])) {
144
            $aliases = $entity->getFieldAliases();
145
146
            foreach ($parameters['fields'] as &$fieldParams) {
147
                if (empty($fieldParams['id'])) {
148
                    // Create an unique ID if not set - the following code requires one
149
                    $fieldParams['id'] = 'new'.hash('sha1', uniqid(mt_rand()));
150
                    $fieldEntity       = $fieldModel->getEntity();
151
                } else {
152
                    $fieldEntity       = $fieldModel->getEntity($fieldParams['id']);
153
                    $requestFieldIds[] = $fieldParams['id'];
154
                }
155
156
                if (is_null($fieldEntity)) {
157
                    $msg = $this->translator->trans(
158
                        'mautic.core.error.entity.not.found',
159
                        [
160
                            '%entity%' => $this->translator->trans('mautic.form.field'),
161
                            '%id%'     => $fieldParams['id'],
162
                        ],
163
                        'flashes'
164
                    );
165
166
                    return $this->returnError($msg, Response::HTTP_NOT_FOUND);
167
                }
168
169
                $fieldEntityArray           = $fieldEntity->convertToArray();
170
                $fieldEntityArray['formId'] = $formId;
171
172
                if (!empty($fieldParams['alias'])) {
173
                    $fieldParams['alias'] = $fieldModel->cleanAlias($fieldParams['alias'], '', 25);
174
175
                    if (!in_array($fieldParams['alias'], $aliases)) {
176
                        $fieldEntityArray['alias'] = $fieldParams['alias'];
177
                    }
178
                }
179
180
                if (empty($fieldEntityArray['alias'])) {
181
                    $fieldEntityArray['alias'] = $fieldParams['alias'] = $fieldModel->generateAlias($fieldEntityArray['label'], $aliases);
182
                }
183
184
                $fieldForm = $this->createFieldEntityForm($fieldEntityArray);
185
                $fieldForm->submit($fieldParams, 'PATCH' !== $method);
186
187
                if (!$fieldForm->isValid()) {
188
                    $formErrors = $this->getFormErrorMessages($fieldForm);
189
                    $msg        = $this->getFormErrorMessage($formErrors);
190
191
                    return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
192
                }
193
            }
194
195
            $this->model->setFields($entity, $parameters['fields']);
196
        }
197
198
        // Remove fields which weren't in the PUT request
199
        if (!$isNew && 'PUT' === $method) {
200
            $fieldsToDelete = [];
201
202
            foreach ($currentFields as $currentField) {
203
                if (!in_array($currentField->getId(), $requestFieldIds)) {
204
                    $fieldsToDelete[] = $currentField->getId();
205
                }
206
            }
207
208
            if ($fieldsToDelete) {
209
                $this->model->deleteFields($entity, $fieldsToDelete);
210
            }
211
        }
212
213
        // Add actions from the request
214
        if (!empty($parameters['actions']) && is_array($parameters['actions'])) {
215
            $actions = [];
216
            foreach ($parameters['actions'] as &$actionParams) {
217
                if (empty($actionParams['id'])) {
218
                    $actionParams['id'] = 'new'.hash('sha1', uniqid(mt_rand()));
219
                    $actionEntity       = $actionModel->getEntity();
220
                } else {
221
                    $actionEntity       = $actionModel->getEntity($actionParams['id']);
222
                    $requestActionIds[] = $actionParams['id'];
223
                }
224
225
                $actionEntity->setForm($entity);
226
227
                $actionForm = $this->createActionEntityForm($actionEntity, $actionParams);
228
                $actionForm->submit($actionParams, 'PATCH' !== $method);
229
230
                if (!$actionForm->isValid()) {
231
                    $formErrors = $this->getFormErrorMessages($actionForm);
232
                    $msg        = $this->getFormErrorMessage($formErrors);
233
234
                    return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
235
                }
236
                $actions[] = $actionForm->getNormData();
237
            }
238
239
            // Save the form first and new actions so that new fields are available to actions.
240
            // Using the repository function to not trigger the listeners twice.
241
            $this->model->getRepository()->saveEntity($entity);
242
            $this->model->setActions($entity, $actions);
0 ignored issues
show
The method setActions() does not exist on Mautic\CoreBundle\Model\AbstractCommonModel. It seems like you code against a sub-type of Mautic\CoreBundle\Model\AbstractCommonModel such as Mautic\FormBundle\Model\FormModel. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

242
            $this->model->/** @scrutinizer ignore-call */ 
243
                          setActions($entity, $actions);
Loading history...
243
        }
244
245
        // Remove actions which weren't in the PUT request
246
        if (!$isNew && 'PUT' === $method) {
247
            $actionsToDelete = [];
248
249
            foreach ($currentActions as $currentAction) {
250
                if (!in_array($currentAction->getId(), $requestActionIds)) {
251
                    $actionsToDelete[] = $currentAction->getId();
252
                }
253
            }
254
255
            if ($actionsToDelete) {
256
                $this->model->deleteActions($entity, $actionsToDelete);
257
            }
258
        }
259
    }
260
261
    /**
262
     * Creates the form instance.
263
     *
264
     * @param $entity
265
     *
266
     * @return FormInterface
267
     */
268
    protected function createActionEntityForm(Action $entity, array $action)
269
    {
270
        /** @var FormModel $formModel */
271
        $formModel  = $this->getModel('form');
272
        $components = $formModel->getCustomComponents();
273
        $type       = $action['type'] ?? $entity->getType();
274
275
        return $this->getModel('form.action')->createForm(
276
            $entity,
277
            $this->get('form.factory'),
278
            null,
279
            [
280
                'csrf_protection'    => false,
281
                'allow_extra_fields' => true,
282
                'settings'           => $components['actions'][$type],
283
            ]
284
        );
285
    }
286
287
    /**
288
     * Creates the form instance.
289
     *
290
     * @param $entity
291
     *
292
     * @return FormInterface
293
     */
294
    protected function createFieldEntityForm($entity)
295
    {
296
        return $this->getModel('form.field')->createForm(
297
            $entity,
298
            $this->get('form.factory'),
299
            null,
300
            [
301
                'csrf_protection'    => false,
302
                'allow_extra_fields' => true,
303
            ]
304
        );
305
    }
306
}
307