Passed
Push — master ( ae3156...6fb22a )
by Esteban De La Fuente
03:24
created

AbstractApplication::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Foundation\Abstract;
26
27
use Derafu\Lib\Core\Foundation\Adapter\ServiceAdapter;
28
use Derafu\Lib\Core\Foundation\Configuration;
29
use Derafu\Lib\Core\Foundation\Contract\ApplicationInterface;
30
use Derafu\Lib\Core\Foundation\Contract\ConfigurationInterface;
31
use Derafu\Lib\Core\Foundation\Contract\KernelInterface;
32
use Derafu\Lib\Core\Foundation\Contract\PackageInterface;
33
use Derafu\Lib\Core\Foundation\Contract\ServiceInterface;
34
use LogicException;
35
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
36
37
/**
38
 * Clase base para la clase principal de la aplicación.
39
 */
40
abstract class AbstractApplication implements ApplicationInterface
41
{
42
    /**
43
     * Instancia del núcleo de la aplicación.
44
     *
45
     * @var KernelInterface
46
     */
47
    private KernelInterface $kernel;
48
49
    /**
50
     * Instancia de la clase para el patrón singleton.
51
     *
52
     * @var self
53
     */
54
    private static self $instance;
55
56
    /**
57
     * Constructor de la aplicación.
58
     *
59
     * Debe ser privado para respetar el patrón singleton.
60
     *
61
     * @param string|array|null $config Configuración de la aplicación.
62
     * Puede ser la clase que implementa la configuración, una ruta al archivo
63
     * de configuración o un arreglo con la configuración.
64
     */
65 16
    private function __construct(string|array|null $config)
66
    {
67 16
        $this->initialize($config);
68
    }
69
70
    /**
71
     * Inicializa la aplicación.
72
     *
73
     * @param string|array|null $config
74
     */
75 16
    protected function initialize(string|array|null $config)
76
    {
77
        // Cargar configuración.
78 16
        $configuration = $this->resolveConfiguration($config);
79
80
        // Iniciar el kernel.
81 16
        $kernelClass = $configuration->getKernelClass();
82 16
        $this->kernel = new $kernelClass();
83 16
        $this->kernel->initialize($configuration);
84
    }
85
86
    /**
87
     * Resuelve y carga la configuración de la aplicación.
88
     *
89
     * @param string|array|null $config
90
     * @return ConfigurationInterface
91
     */
92 16
    protected function resolveConfiguration(
93
        string|array|null $config
94
    ): ConfigurationInterface {
95 16
        if ($config === null) {
0 ignored issues
show
introduced by
The condition $config === null is always false.
Loading history...
96 10
            return new Configuration();
97
        }
98
99 6
        if (is_array($config)) {
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
100
            return new Configuration($config);
101
        }
102
103 6
        if (class_exists($config)) {
104
            return new $config();
105
        }
106
107 6
        return new Configuration($config);
108
    }
109
110
    /**
111
     * {@inheritdoc}
112
     */
113
    public function path(?string $path = null): string
114
    {
115
        return $this->kernel->getConfiguration()->resolvePath($path);
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function config(string $name, mixed $default = null): mixed
122
    {
123
        return $this->kernel->getConfiguration()->get($name, $default);
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function hasPackage(string $package): bool
130
    {
131
        $servicesPrefix = $this->kernel->getConfiguration()->getServicesPrefix();
132
        $service = $servicesPrefix . $package;
133
134
        return $this->kernel->getContainer()->has($service);
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140 6
    public function getPackage(string $package): PackageInterface
141
    {
142 6
        $servicesPrefix = $this->kernel->getConfiguration()->getServicesPrefix();
143 6
        $service = $servicesPrefix . $package;
144
145
        try {
146 6
            $instance = $this->kernel->getContainer()->get($service);
147
        } catch (ServiceNotFoundException $e) {
148
            $instance = null;
149
        }
150
151 6
        if (!$instance instanceof PackageInterface) {
152
            throw new LogicException(sprintf(
153
                'El paquete %s no existe en la aplicación.',
154
                $package
155
            ));
156
        }
157
158 6
        $config = $this->kernel->getConfiguration()->getPackageConfiguration(
159 6
            $package
160 6
        );
161 6
        $instance->setConfiguration($config);
162
163 6
        return $instance;
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169 1
    public function getPackages(): array
170
    {
171 1
        $packages = [];
172 1
        $ids = $this->kernel->getContainer()->findTaggedServiceIds('package');
173 1
        $servicesPrefix = $this->kernel->getConfiguration()->getServicesPrefix();
174 1
        foreach ($ids as $id => $tags) {
175 1
            $packages[str_replace($servicesPrefix, '', $id)] =
176 1
                $this->kernel->getContainer()->get($id)
177 1
            ;
178
        }
179
180 1
        return $packages;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function hasService(string $service): bool
187
    {
188
        return $this->kernel->getContainer()->has($service);
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194 8
    public function getService(string $service): ServiceInterface
195
    {
196 8
        $instance = $this->kernel->getContainer()->get($service);
197
198 4
        if ($instance instanceof ServiceInterface) {
199 2
            return $instance;
200
        }
201
202 2
        return new ServiceAdapter($instance);
0 ignored issues
show
Bug introduced by
It seems like $instance can also be of type null; however, parameter $adaptee of Derafu\Lib\Core\Foundati...eAdapter::__construct() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
        return new ServiceAdapter(/** @scrutinizer ignore-type */ $instance);
Loading history...
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208 16
    public static function getInstance(string|array|null $config = null): static
209
    {
210 16
        if (!isset(self::$instance)) {
211 16
            $class = static::class;
212 16
            self::$instance = new $class($config);
213
        }
214
215 16
        assert(self::$instance instanceof static);
216
217 16
        return self::$instance;
218
    }
219
}
220