Passed
Branch master (0b4ab1)
by Esteban De La Fuente
74:02 queued 50:02
created

DataContainer::resolve()   B

Complexity

Conditions 9
Paths 50

Size

Total Lines 43
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 9

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 23
c 1
b 0
f 0
nc 50
nop 2
dl 0
loc 43
ccs 25
cts 25
cp 1
crap 9
rs 8.0555
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\Support\Store;
26
27
use Derafu\Lib\Core\Support\Store\Abstract\AbstractStore;
28
use Derafu\Lib\Core\Support\Store\Contract\DataContainerInterface;
29
use Symfony\Component\OptionsResolver\Options;
30
use Symfony\Component\OptionsResolver\OptionsResolver;
31
32
/**
33
 * Clase para contenedor de datos estructurados con schema.
34
 */
35
class DataContainer extends AbstractStore implements DataContainerInterface
36
{
37
    /**
38
     * Configuración del schema de datos.
39
     *
40
     * @var array
41
     */
42
    protected array $schema = [];
43
44
    /**
45
     * Constructor del contenedor.
46
     *
47
     * @param array $data Datos iniciales.
48
     * @param array $schema Schema inicial.
49
     */
50 11
    public function __construct(array $data = [], array $schema = [])
51
    {
52 11
        $this->setSchema($schema);
53 11
        $this->data = $this->resolve($data, $this->schema);
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59 11
    public function setSchema(array $schema): static
60
    {
61 11
        $this->schema = $schema;
62
63 11
        return $this;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69 1
    public function getSchema(): array
70
    {
71 1
        return $this->schema;
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function validate(): void
78
    {
79
        $this->resolve($this->data, $this->schema);
80
    }
81
82
    /**
83
     * Valida datos usando un esquema específico.
84
     *
85
     * @param array $data Datos a validar.
86
     * @param array $schema Esquema a usar.
87
     * @return array Datos validados y normalizados.
88
     */
89 11
    private function resolve(array $data, array $schema): array
90
    {
91 11
        if (empty($schema)) {
92 2
            return $data;
93
        }
94
95 9
        $resolver = new OptionsResolver();
96
97 9
        foreach ($schema as $key => $config) {
98
            // Configurar el nivel actual.
99 9
            if (!empty($config['types'])) {
100 9
                $resolver->setDefined([$key]);
101 9
                $resolver->setAllowedTypes($key, $config['types']);
102
            }
103
104 9
            if (!empty($config['required'])) {
105 7
                $resolver->setRequired([$key]);
106
            }
107
108 9
            if (!empty($config['choices'])) {
109 3
                $resolver->setAllowedValues($key, $config['choices']);
110
            }
111
112 9
            if (!empty($config['default'])) {
113 4
                $resolver->setDefault($key, $config['default']);
114
            }
115
116
            // Si hay un schema anidado, configurar el normalizador.
117 9
            if (!empty($config['schema'])) {
118 3
                $resolver->setDefault($key, []);
119 3
                $resolver->setAllowedTypes($key, 'array');
120
121 3
                $resolver->setNormalizer(
122 3
                    $key,
123 3
                    fn (Options $options, $value) =>
124 3
                        $this->resolve($value ?? [], $config['schema'])
125 3
                );
126 9
            } elseif (!empty($config['normalizer'])) {
127 3
                $resolver->setNormalizer($key, $config['normalizer']);
128
            }
129
        }
130
131 9
        return $resolver->resolve($data);
132
    }
133
}
134