Passed
Push — bugfix/support-windows ( 517fb4...0e99e7 )
by Chema
04:47
created

Config::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
nc 1
nop 1
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\Config;
6
7
use Gacela\Framework\Bootstrap\SetupGacelaInterface;
8
use Gacela\Framework\Event\Dispatcher\EventDispatcherInterface;
9
use Gacela\Framework\Exception\ConfigException;
10
use RuntimeException;
11
12
use function array_key_exists;
13
14
final class Config implements ConfigInterface
15
{
16
    private static ?self $instance = null;
17
18
    private static ?EventDispatcherInterface $eventDispatcher = null;
19
20
    private ?ConfigFactory $configFactory = null;
21
22
    private ?string $appRootDir = null;
23
24
    /** @var array<string,mixed> */
25
    private array $config = [];
26
27 84
    private function __construct(
28
        private SetupGacelaInterface $setup,
29
    ) {
30 84
    }
31
32 84
    public static function createWithSetup(SetupGacelaInterface $setup): self
33
    {
34 84
        self::$instance = new self($setup);
35
36 84
        return self::$instance;
37
    }
38
39 75
    public static function getInstance(): self
40
    {
41 75
        if (self::$instance === null) {
42
            throw new RuntimeException('You have to call createWithSetup() first.');
43
        }
44
45 75
        return self::$instance;
46
    }
47
48
    /**
49
     * @internal
50
     */
51 45
    public static function resetInstance(): void
52
    {
53 45
        self::$instance = null;
54 45
        self::$eventDispatcher = null;
55
    }
56
57 76
    public static function getEventDispatcher(): EventDispatcherInterface
58
    {
59 76
        if (self::$eventDispatcher === null) {
60 45
            self::$eventDispatcher = self::getInstance()
61 45
                ->getSetupGacela()
62 45
                ->getEventDispatcher();
63
        }
64
65 76
        return self::$eventDispatcher;
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::eventDispatcher could return the type null which is incompatible with the type-hinted return Gacela\Framework\Event\D...ventDispatcherInterface. Consider adding an additional type-check to rule them out.
Loading history...
66
    }
67
68
    /**
69
     * @throws ConfigException
70
     */
71 24
    public function get(string $key, mixed $default = self::DEFAULT_CONFIG_VALUE): mixed
72
    {
73 24
        if (empty($this->config)) {
74 3
            $this->init();
75
        }
76
77 24
        if ($default !== self::DEFAULT_CONFIG_VALUE && !$this->hasKey($key)) {
78 2
            return $default;
79
        }
80
81 22
        if (!$this->hasKey($key)) {
82 1
            throw ConfigException::keyNotFound($key, self::class);
83
        }
84
85 21
        return $this->config[$key];
86
    }
87
88
    /**
89
     * Force loading all config values in memory.
90
     *
91
     * @throws ConfigException
92
     */
93 84
    public function init(): void
94
    {
95 84
        $this->configFactory = null;
96 84
        $this->config = $this->loadAllConfigValues();
97 84
        $this->config = array_merge($this->config, $this->getSetupGacela()->getConfigKeyValues());
98
    }
99
100 84
    public function setAppRootDir(string $dir): self
101
    {
102 84
        $this->appRootDir = rtrim($dir, DIRECTORY_SEPARATOR);
103
104 84
        if (empty($this->appRootDir)) {
105
            $this->appRootDir = getcwd() ?: ''; // @codeCoverageIgnore
106
        }
107
108 84
        return $this;
109
    }
110
111 84
    public function getAppRootDir(): string
112
    {
113 84
        return $this->appRootDir ?? getcwd() ?: '';
114
    }
115
116 4
    public function getCacheDir(): string
117
    {
118 4
        return $this->getAppRootDir()
119 4
            . DIRECTORY_SEPARATOR
120 4
            . ltrim($this->getSetupGacela()->getFileCacheDirectory(), DIRECTORY_SEPARATOR);
121
    }
122
123
    /**
124
     * @internal
125
     */
126 84
    public function getFactory(): ConfigFactory
127
    {
128 84
        if ($this->configFactory === null) {
129 84
            $this->configFactory = new ConfigFactory(
130 84
                $this->getAppRootDir(),
131 84
                $this->getSetupGacela(),
132 84
            );
133
        }
134
135 84
        return $this->configFactory;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->configFactory could return the type null which is incompatible with the type-hinted return Gacela\Framework\Config\ConfigFactory. Consider adding an additional type-check to rule them out.
Loading history...
136
    }
137
138 84
    public function getSetupGacela(): SetupGacelaInterface
139
    {
140 84
        return $this->setup;
141
    }
142
143 47
    public function hasKey(string $key): bool
144
    {
145 47
        return array_key_exists($key, $this->config);
146
    }
147
148
    /**
149
     * @return array<string,mixed>
150
     */
151 84
    private function loadAllConfigValues(): array
152
    {
153 84
        return $this->getFactory()
154 84
            ->createConfigLoader()
155 84
            ->loadAll();
156
    }
157
}
158