Passed
Push — master ( 6fb22a...49a409 )
by Esteban De La Fuente
03:21
created

Factory::create()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 39
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 18.2613

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 21
nc 5
nop 2
dl 0
loc 39
ccs 4
cts 21
cp 0.1905
crap 18.2613
rs 9.2728
c 1
b 0
f 0
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 Error;
28
use LogicException;
29
use ReflectionClass;
30
use stdClass;
31
32
/**
33
 * Fábrica básica para creación de instancias de clases a partir de los datos y
34
 * el nombre de la clase.
35
 */
36
class Factory
37
{
38
    /**
39
     * Crea una instancia de una clase.
40
     *
41
     * @param array $data Datos con los atributos que se deben asignar.
42
     * @param string|null $class Si la clase no se especifica se usará stdClass.
43
     * @return object Instancia de la clase solicitada con sus atributos.
44
     */
45 5
    public static function create(array $data, ?string $class = null): object
46
    {
47 5
        $class = $class ?? stdClass::class;
48
49
        // Si no se indicó una clase se retorna como objeto stdClass.
50 5
        if ($class === stdClass::class) {
51 5
            return (object) $data;
52
        }
53
54
        // Crear la instancia de la clase y asignar los datos.
55
        $reflectionClass = new ReflectionClass($class);
56
        $instance = $reflectionClass->newInstanceWithoutConstructor();
57
        foreach ($data as $column => $value) {
58
            // Si la propiedad existe se configura.
59
            if ($reflectionClass->hasProperty($column)) {
60
                $property = $reflectionClass->getProperty($column);
61
                $property->setAccessible(true);
62
                $property->setValue($instance, $value);
63
            }
64
            // Si la propiedad no existe se tratará de asignar mediante el
65
            // método setAttribute(). Si este método no está disponible se
66
            // generará inmediatamente un error.
67
            else {
68
                try {
69
                    $instance->setAttribute($column, $value);
70
                } catch (Error $e) {
71
                    throw new LogicException(sprintf(
72
                        'No fue posible asignar el atributo %s de la clase %s. Probablemente no existe el método %s::setAttribute() requerido cuando la propiedad %s no está definida explícitamente en la clase.',
73
                        $column,
74
                        $class,
75
                        $class,
76
                        $column
77
                    ));
78
                }
79
            }
80
        }
81
82
        // Entregar la instancia de la clase.
83
        return $instance;
84
    }
85
}
86