Issues (3627)

LeadBundle/Entity/CustomFieldEntityTrait.php (5 issues)

1
<?php
2
3
/*
4
 * @copyright   2016 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\LeadBundle\Entity;
13
14
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
15
use Mautic\LeadBundle\Helper\CustomFieldHelper;
16
use Mautic\LeadBundle\Helper\CustomFieldValueHelper;
17
use Mautic\LeadBundle\Model\FieldModel;
18
19
trait CustomFieldEntityTrait
20
{
21
    /**
22
     * Used by Mautic to populate the fields pulled from the DB.
23
     *
24
     * @var array
25
     */
26
    protected $fields = [];
27
28
    /**
29
     * Just a place to store updated field values so we don't have to loop through them again comparing.
30
     *
31
     * @var array
32
     */
33
    protected $updatedFields = [];
34
35
    /**
36
     * A place events can use to pass data around on the object to prevent issues like creating a contact and having it processed to be sent back
37
     * to the origin of creation in a webhook (like Pipedrive).
38
     *
39
     * @var array
40
     */
41
    protected $eventData = [];
42
43
    /**
44
     * @param $name
45
     *
46
     * @return bool
47
     */
48
    public function __get($name)
49
    {
50
        return $this->getFieldValue(strtolower($name));
51
    }
52
53
    /**
54
     * @param $name
55
     * @param $value
56
     *
57
     * @return $this
58
     */
59
    public function __set($name, $value)
60
    {
61
        return $this->addUpdatedField(strtolower($name), $value);
62
    }
63
64
    /**
65
     * @param string $name
66
     * @param        $arguments
67
     *
68
     * @return mixed
69
     */
70
    public function __call($name, $arguments)
71
    {
72
        $isSetter = 0 === strpos($name, 'set');
73
        $isGetter = 0 === strpos($name, 'get');
74
75
        if (($isSetter && array_key_exists(0, $arguments)) || $isGetter) {
76
            $fieldRequested = mb_strtolower(mb_substr($name, 3));
77
            $fields         = $this->getProfileFields();
78
79
            if (array_key_exists($fieldRequested, $fields)) {
80
                return ($isSetter) ? $this->addUpdatedField($fieldRequested, $arguments[0]) : $this->getFieldValue($fieldRequested);
81
            }
82
        }
83
84
        return parent::__call($name, $arguments);
85
    }
86
87
    /**
88
     * @param $fields
89
     */
90
    public function setFields($fields)
91
    {
92
        $this->fields = CustomFieldValueHelper::normalizeValues($fields);
93
    }
94
95
    /**
96
     * @param bool $ungroup
97
     *
98
     * @return array
99
     */
100
    public function getFields($ungroup = false)
101
    {
102
        if ($ungroup && isset($this->fields['core'])) {
103
            $return = [];
104
            foreach ($this->fields as $fields) {
105
                $return += $fields;
106
            }
107
108
            return $return;
109
        }
110
111
        return $this->fields;
112
    }
113
114
    /**
115
     * Add an updated field to persist to the DB and to note changes.
116
     *
117
     * @param        $alias
118
     * @param        $value
119
     * @param string $oldValue
120
     *
121
     * @return $this
122
     */
123
    public function addUpdatedField($alias, $value, $oldValue = null)
124
    {
125
        // Don't allow overriding ID
126
        if ('id' === $alias) {
127
            return $this;
128
        }
129
130
        $property = (defined('self::FIELD_ALIAS')) ? str_replace(self::FIELD_ALIAS, '', $alias) : $alias;
0 ignored issues
show
The constant Mautic\LeadBundle\Entity...ntityTrait::FIELD_ALIAS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
131
        $field    = $this->getField($alias);
132
        $setter   = 'set'.ucfirst($property);
133
134
        if (null == $oldValue) {
0 ignored issues
show
It seems like you are loosely comparing $oldValue of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
135
            $oldValue = $this->getFieldValue($alias);
136
        } elseif ($field) {
137
            $oldValue = CustomFieldHelper::fixValueType($field['type'], $oldValue);
138
        }
139
140
        if (property_exists($this, $property) && method_exists($this, $setter)) {
141
            // Fixed custom field so use the setter but don't get caught in a loop such as a custom field called "notes"
142
            // Set empty value as null
143
            if ('' === $value) {
144
                $value = null;
145
            }
146
            $this->$setter($value);
147
        }
148
149
        if (is_string($value)) {
150
            $value = trim($value);
151
            if ('' === $value) {
152
                // Ensure value is null for consistency
153
                $value = null;
154
155
                if ('' === $oldValue) {
156
                    $oldValue = null;
157
                }
158
            }
159
        } elseif (is_array($value)) {
160
            // Flatten the array
161
            $value = implode('|', $value);
162
        }
163
164
        if ($field) {
165
            $value = CustomFieldHelper::fixValueType($field['type'], $value);
166
        }
167
168
        if ($oldValue !== $value && !(('' === $oldValue && null === $value) || (null === $oldValue && '' === $value))) {
169
            $this->addChange('fields', [$alias => [$oldValue, $value]]);
0 ignored issues
show
The method addChange() does not exist on Mautic\LeadBundle\Entity\CustomFieldEntityTrait. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

169
            $this->/** @scrutinizer ignore-call */ 
170
                   addChange('fields', [$alias => [$oldValue, $value]]);
Loading history...
170
            $this->updatedFields[$alias] = $value;
171
        }
172
173
        return $this;
174
    }
175
176
    /**
177
     * Get the array of updated fields.
178
     *
179
     * @return array
180
     */
181
    public function getUpdatedFields()
182
    {
183
        return $this->updatedFields;
184
    }
185
186
    /**
187
     * Get field value.
188
     *
189
     * @param string $field
190
     * @param string $group
191
     *
192
     * @return mixed
193
     */
194
    public function getFieldValue($field, $group = null)
195
    {
196
        if (property_exists($this, $field)) {
197
            $value = $this->{'get'.ucfirst($field)}();
198
199
            if (null !== $value) {
200
                return $value;
201
            }
202
        }
203
204
        if (array_key_exists($field, $this->updatedFields)) {
205
            return $this->updatedFields[$field];
206
        }
207
208
        if ($field = $this->getField($field, $group)) {
209
            return CustomFieldHelper::fixValueType($field['type'], $field['value']);
210
        }
211
212
        return null;
213
    }
214
215
    /**
216
     * Get field details.
217
     *
218
     * @param string $key
219
     * @param string $group
220
     *
221
     * @return array|false
222
     */
223
    public function getField($key, $group = null)
224
    {
225
        if ($group && isset($this->fields[$group][$key])) {
226
            return $this->fields[$group][$key];
227
        }
228
229
        foreach ($this->fields as $groupFields) {
230
            foreach ($groupFields as $name => $details) {
231
                if ($name == $key) {
232
                    return $details;
233
                }
234
            }
235
        }
236
237
        return false;
238
    }
239
240
    /**
241
     * Get profile values.
242
     *
243
     * @return array
244
     */
245
    public function getProfileFields()
246
    {
247
        if (isset($this->fields['core'])) {
248
            $fieldValues = [
249
                'id' => $this->id,
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on Mautic\LeadBundle\Entity\CustomFieldEntityTrait. Since you implemented __get, consider adding a @property annotation.
Loading history...
250
            ];
251
252
            foreach ($this->fields as $group => $fields) {
253
                if ('all' === $group) {
254
                    continue;
255
                }
256
257
                foreach ($fields as $alias => $field) {
258
                    $fieldValues[$alias] = $field['value'];
259
                }
260
            }
261
262
            return array_merge($fieldValues, $this->updatedFields);
263
        } else {
264
            // The fields are already flattened
265
266
            return $this->fields;
267
        }
268
    }
269
270
    /**
271
     * @return bool
272
     */
273
    public function hasFields()
274
    {
275
        return !empty($this->fields);
276
    }
277
278
    /**
279
     * @param $key
280
     */
281
    public function getEventData($key)
282
    {
283
        return (isset($this->eventData[$key])) ? $this->eventData[$key] : null;
284
    }
285
286
    /**
287
     * @param $key
288
     * @param $value
289
     *
290
     * @return $this
291
     */
292
    public function setEventData($key, $value)
293
    {
294
        $this->eventData[$key] = $value;
295
296
        return $this;
297
    }
298
299
    protected static function loadFixedFieldMetadata(ClassMetadataBuilder $builder, array $fields, array $customFieldDefinitions)
300
    {
301
        foreach ($fields as $fieldProperty) {
302
            $field = (defined('self::FIELD_ALIAS')) ? self::FIELD_ALIAS.$fieldProperty : $fieldProperty;
0 ignored issues
show
The constant Mautic\LeadBundle\Entity...ntityTrait::FIELD_ALIAS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
303
304
            $type = 'text';
305
            if (isset($customFieldDefinitions[$field]) && !empty($customFieldDefinitions[$field]['type'])) {
306
                $type = $customFieldDefinitions[$field]['type'];
307
            }
308
309
            $builder->addNamedField(
310
                $fieldProperty,
311
                FieldModel::getSchemaDefinition($field, $type, !empty($customFieldDefinitions[$field]['unique']))['type'],
312
                $field,
313
                true
314
            );
315
        }
316
    }
317
}
318