This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Sofa\Eloquence\Metable; |
||
4 | |||
5 | use InvalidArgumentException; |
||
6 | use Illuminate\Database\Eloquent\Model; |
||
7 | use Sofa\Eloquence\Contracts\Attribute as AttributeContract; |
||
8 | use Sofa\Eloquence\Mutator\Mutator; |
||
9 | |||
10 | /** |
||
11 | * @property array $attributes |
||
12 | */ |
||
13 | class Attribute extends Model implements AttributeContract |
||
14 | { |
||
15 | /** |
||
16 | * Attribute mutator instance. |
||
17 | * |
||
18 | * @var \Sofa\Eloquence\Contracts\Mutator |
||
19 | */ |
||
20 | protected static $attributeMutator; |
||
21 | |||
22 | /** |
||
23 | * Custom table name. |
||
24 | * |
||
25 | * @var string |
||
26 | */ |
||
27 | protected static $customTable; |
||
28 | |||
29 | /** |
||
30 | * The database table used by the model. |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $table = 'meta_attributes'; |
||
35 | |||
36 | /** |
||
37 | * Indicates if the model should be timestamped. |
||
38 | * |
||
39 | * @var bool |
||
40 | */ |
||
41 | public $timestamps = false; |
||
42 | |||
43 | /** |
||
44 | * The primary key for the model. |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | protected $primaryKey = 'meta_id'; |
||
49 | |||
50 | /** |
||
51 | * @var array |
||
52 | */ |
||
53 | protected $getterMutators = [ |
||
54 | 'array' => 'json_decode', |
||
55 | 'StdClass' => 'json_decode', |
||
56 | 'DateTime' => 'asDateTime', |
||
57 | Model::class => 'unserialize', |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * @var array |
||
62 | */ |
||
63 | protected $setterMutators = [ |
||
64 | 'array' => 'json_encode', |
||
65 | 'StdClass' => 'json_encode', |
||
66 | 'DateTime' => 'fromDateTime', |
||
67 | Model::class => 'serialize', |
||
68 | ]; |
||
69 | |||
70 | /** |
||
71 | * The attributes included in the model's JSON and array form. |
||
72 | * |
||
73 | * @var array |
||
74 | */ |
||
75 | protected $visible = ['meta_key', 'meta_value', 'meta_type', 'meta_group']; |
||
76 | |||
77 | /** |
||
78 | * Create new attribute instance. |
||
79 | * |
||
80 | * @param string|array $key |
||
81 | * @param mixed $value |
||
82 | */ |
||
83 | public function __construct($key = null, $value = null, $group = null) |
||
84 | { |
||
85 | // default behaviour |
||
86 | if (is_array($key)) { |
||
87 | parent::__construct($key); |
||
88 | } else { |
||
89 | parent::__construct(); |
||
90 | |||
91 | if (is_string($key)) { |
||
92 | $this->set($key, $value, $group); |
||
93 | } |
||
94 | } |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Boot this model. |
||
99 | * |
||
100 | * @codeCoverageIgnore |
||
101 | * |
||
102 | * @return void |
||
103 | */ |
||
104 | protected static function boot() |
||
105 | { |
||
106 | parent::boot(); |
||
107 | |||
108 | if (!isset(static::$attributeMutator)) { |
||
109 | if (function_exists('app') && app()->bound('eloquence.mutator')) { |
||
110 | static::$attributeMutator = app('eloquence.mutator'); |
||
111 | } else { |
||
112 | static::$attributeMutator = new Mutator; |
||
113 | } |
||
114 | } |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Set the meta attribute. |
||
119 | * |
||
120 | * @param string $key |
||
121 | * @param mixed $value |
||
122 | * @param string $group |
||
123 | */ |
||
124 | protected function set($key, $value, $group = 'default') |
||
125 | { |
||
126 | $this->setMetaKey($key); |
||
127 | $this->setValue($value); |
||
128 | $this->setMetaGroup($group); |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Create new AttributeBag. |
||
133 | * |
||
134 | * @param array $models |
||
135 | * @return \Sofa\Eloquence\Metable\AttributeBag |
||
136 | */ |
||
137 | public function newBag(array $models = []) |
||
138 | { |
||
139 | return new AttributeBag($models); |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get the meta attribute value. |
||
144 | * |
||
145 | * @return mixed |
||
146 | */ |
||
147 | public function getValue() |
||
148 | { |
||
149 | if ($this->hasMutator($this->attributes['meta_value'], 'getter', $this->attributes['meta_type'])) { |
||
150 | return $this->mutateValue($this->attributes['meta_value'], 'getter'); |
||
151 | } |
||
152 | |||
153 | return $this->castValue(); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Get the meta attribute key. |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | public function getMetaKey() |
||
162 | { |
||
163 | return $this->attributes['meta_key']; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Get the meta attribute group. |
||
168 | * |
||
169 | * @return string |
||
170 | */ |
||
171 | public function getMetaGroup() |
||
172 | { |
||
173 | return $this->attributes['meta_group']; |
||
174 | } |
||
175 | |||
176 | /** |
||
177 | * Cast value to proper type. |
||
178 | * |
||
179 | * @return mixed |
||
180 | */ |
||
181 | protected function castValue() |
||
182 | { |
||
183 | $value = $this->attributes['meta_value']; |
||
184 | |||
185 | $validTypes = ['boolean', 'integer', 'float', 'double', 'array', 'object', 'null']; |
||
186 | |||
187 | if (in_array($this->attributes['meta_type'], $validTypes)) { |
||
188 | settype($value, $this->attributes['meta_type']); |
||
189 | } |
||
190 | |||
191 | return $value; |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Set key of the meta attribute. |
||
196 | * |
||
197 | * @param string $key |
||
198 | * |
||
199 | * @throws \InvalidArgumentException |
||
200 | */ |
||
201 | protected function setMetaKey($key) |
||
202 | { |
||
203 | if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $key)) { |
||
204 | throw new InvalidArgumentException("Provided key [{$key}] is not valid variable name."); |
||
205 | } |
||
206 | |||
207 | $this->attributes['meta_key'] = $key; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Set group of the meta attribute. |
||
212 | * |
||
213 | * @param string $group |
||
214 | * |
||
215 | * @throws \InvalidArgumentException |
||
216 | */ |
||
217 | public function setMetaGroup($group = null) |
||
218 | { |
||
219 | if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $group) && $group !== null) { |
||
220 | throw new InvalidArgumentException("Provided group [{$group}] is not valid variable name."); |
||
221 | } |
||
222 | |||
223 | $this->attributes['meta_group'] = $group; |
||
224 | } |
||
225 | |||
226 | /** |
||
227 | * Set type of the meta attribute. |
||
228 | * |
||
229 | * @param mixed $value |
||
230 | */ |
||
231 | protected function setType($value) |
||
232 | { |
||
233 | $this->attributes['meta_type'] = $this->hasMutator($value, 'setter') |
||
234 | ? $this->getMutatedType($value, 'setter') |
||
235 | : $this->getValueType($value); |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Set value of the meta attribute. |
||
240 | * |
||
241 | * @param mixed $value |
||
242 | * |
||
243 | * @throws \Sofa\Eloquence\Metable\InvalidTypeException |
||
244 | */ |
||
245 | public function setValue($value) |
||
246 | { |
||
247 | $this->setType($value); |
||
248 | |||
249 | if ($this->hasMutator($value, 'setter')) { |
||
250 | $value = $this->mutateValue($value, 'setter'); |
||
251 | } elseif (!$this->isStringable($value) && !is_null($value)) { |
||
252 | throw new InvalidTypeException( |
||
253 | "Unsupported meta value type [{$this->getValueType($value)}]." |
||
254 | ); |
||
255 | } |
||
256 | |||
257 | $this->attributes['meta_value'] = $value; |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Mutate attribute value. |
||
262 | * |
||
263 | * @param mixed $value |
||
264 | * @param string $dir |
||
265 | * @return mixed |
||
266 | */ |
||
267 | protected function mutateValue($value, $dir = 'setter') |
||
268 | { |
||
269 | $mutator = $this->getMutator($value, $dir, $this->attributes['meta_type']); |
||
270 | |||
271 | if (method_exists($this, $mutator)) { |
||
272 | return $this->{$mutator}($value); |
||
273 | } |
||
274 | |||
275 | return static::$attributeMutator->mutate($value, $mutator); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * Determine whether the value type can be set to string. |
||
280 | * |
||
281 | * @param mixed $value |
||
282 | * @return bool |
||
283 | */ |
||
284 | protected function isStringable($value) |
||
285 | { |
||
286 | return is_scalar($value); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Get the value type. |
||
291 | * |
||
292 | * @param mixed $value |
||
293 | * @return string |
||
294 | */ |
||
295 | protected function getValueType($value) |
||
296 | { |
||
297 | $type = is_object($value) ? get_class($value) : gettype($value); |
||
298 | |||
299 | // use float instead of deprecated double |
||
300 | return ($type == 'double') ? 'float' : $type; |
||
301 | } |
||
302 | |||
303 | /** |
||
304 | * Get the mutated type. |
||
305 | * |
||
306 | * @param mixed $value |
||
307 | * @param string $dir |
||
308 | * @return string |
||
309 | */ |
||
310 | protected function getMutatedType($value, $dir = 'setter') |
||
311 | { |
||
312 | View Code Duplication | foreach ($this->{"{$dir}Mutators"} as $mutated => $mutator) { |
|
0 ignored issues
–
show
|
|||
313 | if ($this->getValueType($value) == $mutated || $value instanceof $mutated) { |
||
314 | return $mutated; |
||
315 | } |
||
316 | } |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Determine whether a mutator exists for the value type. |
||
321 | * |
||
322 | * @param mixed $value |
||
323 | * @param string $dir |
||
324 | * @return bool |
||
325 | */ |
||
326 | protected function hasMutator($value, $dir = 'setter', $type = null) |
||
327 | { |
||
328 | return (bool) $this->getMutator($value, $dir, $type); |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Get mutator for the type. |
||
333 | * |
||
334 | * @param mixed $value |
||
335 | * @param string $dir |
||
336 | * @return string |
||
337 | */ |
||
338 | protected function getMutator($value, $dir = 'setter', $type = null) |
||
339 | { |
||
340 | $type = $type ?: $this->getValueType($value); |
||
341 | |||
342 | View Code Duplication | foreach ($this->{"{$dir}Mutators"} as $mutated => $mutator) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
343 | if ($type == $mutated || $value instanceof $mutated) { |
||
344 | return $mutator; |
||
345 | } |
||
346 | } |
||
347 | } |
||
348 | |||
349 | /** |
||
350 | * Allow custom table name for meta attributes via config. |
||
351 | * |
||
352 | * @return string |
||
353 | */ |
||
354 | public function getTable() |
||
355 | { |
||
356 | return isset(static::$customTable) ? static::$customTable : parent::getTable(); |
||
357 | } |
||
358 | |||
359 | /** |
||
360 | * Set custom table for the meta attributes. Allows doing it only once |
||
361 | * in order to mimic protected behaviour, most likely in the service |
||
362 | * provider, which in turn gets the table name from configuration. |
||
363 | * |
||
364 | * @param string $table |
||
365 | */ |
||
366 | public static function setCustomTable($table) |
||
367 | { |
||
368 | if (!isset(static::$customTable)) { |
||
369 | static::$customTable = $table; |
||
370 | } |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Handle casting value to string. |
||
375 | * |
||
376 | * @return string |
||
377 | */ |
||
378 | public function castToString() |
||
379 | { |
||
380 | if ($this->attributes['meta_type'] == 'array') { |
||
381 | return $this->attributes['meta_value']; |
||
382 | } |
||
383 | |||
384 | $value = $this->getValue(); |
||
385 | |||
386 | if ($this->isStringable($value) || is_object($value) && method_exists($value, '__toString')) { |
||
387 | return (string) $value; |
||
388 | } |
||
389 | |||
390 | return ''; |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Handle dynamic casting to string. |
||
395 | * |
||
396 | * @return string |
||
397 | */ |
||
398 | public function __toString() |
||
399 | { |
||
400 | return $this->castToString(); |
||
401 | } |
||
402 | } |
||
403 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.