Issues (3627)

app/bundles/CoreBundle/Form/RequestTrait.php (2 issues)

1
<?php
2
3
/*
4
 * @copyright   2016 Mautic Contributors. All rights reserved
5
 * @author      Mautic, Inc.
6
 *
7
 * @link        https://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace Mautic\CoreBundle\Form;
13
14
use Mautic\CoreBundle\Form\Type\BooleanType;
15
use Mautic\CoreBundle\Form\Type\CountryType;
16
use Mautic\CoreBundle\Form\Type\LocaleType;
17
use Mautic\CoreBundle\Form\Type\MultiselectType;
18
use Mautic\CoreBundle\Form\Type\RegionType;
19
use Mautic\CoreBundle\Form\Type\SelectType;
20
use Mautic\CoreBundle\Form\Type\TimezoneType;
21
use Mautic\CoreBundle\Form\Type\YesNoButtonGroupType;
22
use Mautic\CoreBundle\Helper\ArrayHelper;
23
use Mautic\CoreBundle\Helper\InputHelper;
24
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
25
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
26
use Symfony\Component\Form\Extension\Core\Type\DateType;
27
use Symfony\Component\Form\Extension\Core\Type\TimeType;
28
use Symfony\Component\Form\Form;
29
use Symfony\Component\Form\ResolvedFormTypeInterface;
30
31
trait RequestTrait
32
{
33
    protected function prepareParametersFromRequest(Form $form, array &$params, $entity = null, $masks = [], $fields = [])
34
    {
35
        // ungroup fields if need it
36
        foreach ($fields as $key=>$field) {
37
            if (is_array($field)) {
38
                foreach ($field as $k=>$f) {
39
                    $fields[$k]=$f;
40
                }
41
                unset($fields[$key]);
42
                continue;
43
            }
44
        }
45
46
        // Special handling of some fields
47
        foreach ($form as $name => $child) {
48
            if (!isset($params[$name])) {
49
                continue;
50
            }
51
52
            $type = $child->getConfig()->getType();
53
            if ($type instanceof ResolvedFormTypeInterface) {
54
                $type = $type->getInnerType();
55
            }
56
            switch (get_class($type)) {
57
                case YesNoButtonGroupType::class:
58
                case BooleanType::class:
59
                    if (!is_object($entity)) {
60
                        break;
61
                    }
62
63
                    $setter = 'set'.ucfirst($name);
64
                    // Symfony fails to recognize true values on PATCH and add support for all boolean types (on, off, true, false, 1, 0)
65
                    // If value is array and count 1, return value of array as string
66
                    if (is_array($params[$name]) && 1 == count($params[$name])) {
67
                        $params[$name] = end($params[$name]);
68
                    }
69
70
                    if ('' === $params[$name]) {
71
                        break;
72
                    }
73
74
                    // find property by value
75
                    if (!empty($fields)) {
76
                        $properties = ArrayHelper::getValue('properties', $fields[$name]);
77
                        if (is_array($properties)) {
78
                            $valuesAsKeys = array_flip(array_values($properties));
79
                            if (isset($valuesAsKeys[$params[$name]])) {
80
                                $params[$name] = $valuesAsKeys[$params[$name]];
81
                            }
82
                        }
83
                    }
84
85
                    $data = filter_var($params[$name], FILTER_VALIDATE_BOOLEAN);
86
                    $data = (bool) $data;
87
                    try {
88
                        $entity->$setter($data);
89
                        // Manually handled so remove from form processing
90
                        unset($form[$name], $params[$name]);
91
                        break;
92
                    } catch (\InvalidArgumentException $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
93
                    }
94
95
                    // If not manually handled cast to int because Symfony form processing take false as empty
96
                    $params[$name] = (int) $data;
97
98
                    break;
99
                case ChoiceType::class:
100
                case CountryType::class:
101
                case LocaleType::class:
102
                case MultiselectType::class:
103
                case RegionType::class:
104
                case SelectType::class:
105
                case TimezoneType::class:
106
                    if (!$child->getConfig()->getOption('multiple')) {
107
                        break;
108
                    }
109
110
                    // Ensure the value is an array
111
                    if (!is_array($params[$name])) {
112
                        $params[$name] = (false !== strpos($params[$name], '|')) ? explode('|', $params[$name]) : [$params[$name]];
113
                    }
114
115
                    break;
116
                case DateTimeType::class:
117
                case DateType::class:
118
                case TimeType::class:
119
                    // Prevent zero based date placeholders
120
                    $dateTest = (int) str_replace(['/', '-', ' '], '', $params[$name]);
121
122
                    if (!$dateTest) {
123
                        // Date placeholder was used so just ignore it to allow import of the field
124
                        unset($params[$name]);
125
                        break;
126
                    }
127
128
                    if (false === ($timestamp = strtotime($params[$name]))) {
129
                        $timestamp = null;
130
                    }
131
132
                    if (!$timestamp) {
133
                        unset($params[$name]);
134
                        break;
135
                    }
136
137
                    switch ($type) {
138
                        case DateTimeType::class:
139
                            $params[$name] = (new \DateTime(date('Y-m-d H:i:s', $timestamp)))->format('Y-m-d H:i');
140
                            break;
141
                        case DateType::class:
142
                            $params[$name] = (new \DateTime(date('Y-m-d', $timestamp)))->format('Y-m-d');
143
                            break;
144
                        case TimeType::class:
145
                            $params[$name] = (new \DateTime(date('H:i:s', $timestamp)))->format('H:i:s');
146
                            break;
147
                    }
148
149
                    break;
150
            }
151
        }
152
153
        if (!isset($masks['description'])) {
154
            // Add description to support strict HTML
155
            $masks['description'] = 'strict_html';
156
        }
157
158
        if (!isset($masks['content'])) {
159
            // Assume HTML
160
            $masks['description'] = 'html';
161
        }
162
163
        $params = InputHelper::_($params, $masks);
164
    }
165
166
    /**
167
     * @param $fieldData
168
     * @param $leadField
169
     */
170
    public function cleanFields(&$fieldData, $leadField)
171
    {
172
        // This will catch null values or non-existent values to prevent null from converting to false/0
173
        if (!isset($fieldData[$leadField['alias']])) {
174
            return;
175
        }
176
177
        switch ($leadField['type']) {
178
            // Adjust the boolean values from text to boolean. Do not convert null to false.
179
            case 'boolean':
180
                $fieldData[$leadField['alias']] = (int) filter_var($fieldData[$leadField['alias']], FILTER_VALIDATE_BOOLEAN);
181
                break;
182
            // Ensure date/time entries match what symfony expects
183
            case 'datetime':
184
            case 'date':
185
            case 'time':
186
                // Prevent zero based date placeholders
187
                $dateTest = (int) str_replace(['/', '-', ' '], '', $fieldData[$leadField['alias']]);
188
                if (!$dateTest) {
189
                    // Date placeholder was used so just ignore it to allow import of the field
190
                    unset($fieldData[$leadField['alias']]);
191
                } else {
192
                    if (false === ($timestamp = strtotime($fieldData[$leadField['alias']]))) {
193
                        $timestamp = null;
194
                    }
195
                    if ($timestamp) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $timestamp of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
196
                        switch ($leadField['type']) {
197
                            case 'datetime':
198
                                $fieldData[$leadField['alias']] = (new \DateTime(date('Y-m-d H:i:s', $timestamp)))->format('Y-m-d H:i:s');
199
                                break;
200
                            case 'date':
201
                                $fieldData[$leadField['alias']] = (new \DateTime(date('Y-m-d', $timestamp)))->format('Y-m-d');
202
                                break;
203
                            case 'time':
204
                                $fieldData[$leadField['alias']] = (new \DateTime(date('H:i:s', $timestamp)))->format('H:i:s');
205
                                break;
206
                        }
207
                    }
208
                }
209
                break;
210
            case 'multiselect':
211
                if (!is_array($fieldData[$leadField['alias']])) {
212
                    if (false !== strpos($fieldData[$leadField['alias']], '|')) {
213
                        $fieldData[$leadField['alias']] = explode('|', $fieldData[$leadField['alias']]);
214
                    } else {
215
                        $fieldData[$leadField['alias']] = [$fieldData[$leadField['alias']]];
216
                    }
217
                }
218
                break;
219
            case 'number':
220
                $fieldData[$leadField['alias']] = (float) $fieldData[$leadField['alias']];
221
                break;
222
            case 'email':
223
                $fieldData[$leadField['alias']] = InputHelper::email($fieldData[$leadField['alias']]);
224
                break;
225
        }
226
    }
227
}
228