Hydrator::hydrate()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 46
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 11.174

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 25
c 1
b 0
f 0
nc 7
nop 2
dl 0
loc 46
ccs 14
cts 25
cp 0.56
crap 11.174
rs 8.5866
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Helper;
26
27
use LogicException;
28
use ReflectionClass;
29
30
/**
31
 * Hidratador básico para actualización de atributos en instancias de clases.
32
 */
33
class Hydrator
34
{
35
    /**
36
     * Hidrata un objeto con los datos proporcionados.
37
     *
38
     * @param object $instance Instancia de la clase que se hidratará.
39
     * @param array $data Datos con los atributos que se deben asignar.
40
     * @return object Instancia hidratada.
41
     */
42 5
    public static function hydrate(object $instance, array $data): object
43
    {
44 5
        $reflectionClass = new ReflectionClass($instance);
45
46 5
        foreach ($data as $attribute => $value) {
47 5
            $assigned = false;
48
49
            // Si la propiedad existe, se configura directamente.
50 5
            if ($reflectionClass->hasProperty($attribute)) {
51 3
                $property = $reflectionClass->getProperty($attribute);
52 3
                $property->setAccessible(true);
53 3
                $property->setValue($instance, $value);
54 3
                $assigned = true;
55
            }
56
            // Si no existe, intentar usar algún método genérico.
57
            else {
58
                // Probar primero con setAttribute().
59 2
                if (method_exists($instance, 'setAttribute')) {
60 2
                    $instance->setAttribute($attribute, $value);
61 2
                    $assigned = true;
62
                }
63
                // Probar con setXyz() y setXyzAttribute().
64
                else {
65
                    // Tratar de asignar
66
                    $methods = ['set' . Str::studly($attribute)];
67
                    $methods[] = $methods[0] . 'Attribute';
68
                    foreach ($methods as $method) {
69
                        if (method_exists($instance, $method)) {
70
                            $instance->$method($value);
71
                            $assigned = true;
72
                        }
73
                    }
74
                }
75
            }
76
77
            // Si no fue posible asignar el atributo error.
78 5
            if (!$assigned) {
79
                throw new LogicException(sprintf(
80
                    'No se puede asignar el atributo %s porque la clase %s no define la propiedad ni un método setAttribute().',
81
                    $attribute,
82
                    get_class($instance)
83
                ));
84
            }
85
        }
86
87 5
        return $instance;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $instance could return the type object which is incompatible with the type-hinted return object. Consider adding an additional type-check to rule them out.
Loading history...
88
    }
89
}
90