DataContainer::resolve()   B
last analyzed

Complexity

Conditions 10
Paths 99

Size

Total Lines 63
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 10.0023

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 31
c 1
b 0
f 0
nc 99
nop 3
dl 0
loc 63
ccs 34
cts 35
cp 0.9714
crap 10.0023
rs 7.6666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 ArrayAccess;
28
use ArrayObject;
29
use Derafu\Lib\Core\Support\Store\Abstract\AbstractStore;
30
use Derafu\Lib\Core\Support\Store\Contract\DataContainerInterface;
31
use Symfony\Component\OptionsResolver\Options;
32
use Symfony\Component\OptionsResolver\OptionsResolver;
33
34
/**
35
 * Clase para contenedor de datos estructurados con schema.
36
 */
37
class DataContainer extends AbstractStore implements DataContainerInterface
38
{
39
    /**
40
     * Configuración del schema de datos.
41
     *
42
     * @var array
43
     */
44
    protected array $schema = [];
45
46
    /**
47
     * Constructor del contenedor.
48
     *
49
     * @param array|ArrayAccess|ArrayObject $data Datos iniciales.
50
     * @param array $schema Schema inicial.
51
     * @param bool $allowUndefinedKeys Permitir o no índices no definidos.
52
     */
53 69
    public function __construct(
54
        array|ArrayAccess|ArrayObject $data = [],
55
        array $schema = [],
56
        bool $allowUndefinedKeys = false
57
    ) {
58 69
        $this->setSchema($schema);
59 69
        if (!is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
60 2
            $data = $this->createFrom($data)->toArray();
61
        }
62 69
        $data = $this->resolve($data, $this->schema, $allowUndefinedKeys);
63 66
        $this->data = $this->createFrom($data);
64
    }
65
66
    /**
67
     * {@inheritDoc}
68
     */
69 69
    public function setSchema(array $schema): static
70
    {
71 69
        $this->schema = $schema;
72
73 69
        return $this;
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79 1
    public function getSchema(): array
80
    {
81 1
        return $this->schema;
82
    }
83
84
    /**
85
     * {@inheritDoc}
86
     */
87 38
    public function validate(bool $allowUndefinedKeys = false): void
88
    {
89 38
        $this->resolve($this->toArray(), $this->schema, $allowUndefinedKeys);
90
    }
91
92
    /**
93
     * Valida datos usando un esquema específico.
94
     *
95
     * @param array $data Datos a validar.
96
     * @param array $schema Esquema a usar.
97
     * @param bool $allowUndefinedKeys Permitir o no índices no definidos.
98
     * @return array Datos validados y normalizados.
99
     */
100 69
    private function resolve(
101
        array $data,
102
        array $schema,
103
        bool $allowUndefinedKeys = false
104
    ): array {
105
        // Si no hay esquema los datos son válidos como vienen.
106 69
        if (empty($schema)) {
107 13
            return $data;
108
        }
109
110
        // Determinar si se permitirán opciones no definidas en el esquema.
111 64
        $allowUndefinedKeys = $schema['__allowUndefinedKeys']
112 64
            ?? $allowUndefinedKeys
113 64
        ;
114 64
        unset($schema['__allowUndefinedKeys']);
115
116
        // Crear resolver y configurar.
117 64
        $resolver = new OptionsResolver();
118 64
        foreach ($schema as $key => $config) {
119
            // Configurar el nivel actual.
120 64
            if (!empty($config['types'])) {
121 64
                $resolver->setDefined([$key]);
122 64
                $resolver->setAllowedTypes($key, $config['types']);
123
            }
124
125 64
            if (!empty($config['required'])) {
126 7
                $resolver->setRequired([$key]);
127
            }
128
129 64
            if (!empty($config['choices'])) {
130 3
                $resolver->setAllowedValues($key, $config['choices']);
131
            }
132
133 64
            if (array_key_exists('default', $config)) {
134 59
                $resolver->setDefault($key, $config['default']);
135
            }
136
137
            // Si hay un schema anidado, configurar el normalizador.
138 64
            if (!empty($config['schema'])) {
139 20
                $resolver->setDefault($key, []);
140 20
                $resolver->setAllowedTypes($key, 'array');
141
142 20
                $resolver->setNormalizer(
143 20
                    $key,
144 20
                    fn (Options $options, $value) =>
145 20
                        $this->resolve(
146 20
                            $value ?? [],
147 20
                            $config['schema'],
148 20
                            $allowUndefinedKeys
149 20
                        )
150 20
                );
151 64
            } elseif (!empty($config['normalizer'])) {
152 3
                $resolver->setNormalizer($key, $config['normalizer']);
153
            }
154
        }
155
156
        // Permitir opciones adicionales no definidas.
157 64
        if ($allowUndefinedKeys) {
158
            $resolver->setDefined(array_keys($data));
159
        }
160
161
        // Resolver las opciones.
162 64
        return $resolver->resolve($data);
163
    }
164
}
165