Passed
Pull Request — master (#223)
by Arman
03:12
created

Environment::hasKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 2
b 0
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.6
13
 */
14
15
namespace Quantum\Environment;
16
17
use Quantum\Environment\Exceptions\EnvException;
18
use Quantum\Di\Exceptions\DiException;
19
use Quantum\Exceptions\BaseException;
20
use Quantum\Loader\Loader;
21
use Quantum\Loader\Setup;
22
use ReflectionException;
23
use Quantum\App\App;
24
use Dotenv\Dotenv;
25
use Quantum\Di\Di;
26
27
/**
28
 * Class Environment
29
 * @package Quantum\Environment
30
 * @uses Dotenv
31
 */
32
class Environment
33
{
34
35
    /**
36
     * Environment file
37
     * @var string
38
     */
39
    private $envFile = '.env';
40
41
    /**
42
     * @var bool
43
     */
44
    private $isMutable = false;
45
46
    /**
47
     * Loaded env content
48
     * @var array
49
     */
50
    private $envContent = [];
51
52
    private static $appEnv = 'production';
53
54
    /**
55
     * Instance of Environment
56
     * @var Environment
57
     */
58
    private static $instance = null;
59
60
    /**
61
     * GetInstance
62
     * @return Environment
63
     */
64
    public static function getInstance(): Environment
65
    {
66
        if (self::$instance === null) {
67
            self::$instance = new self();
68
        }
69
70
        return self::$instance;
71
    }
72
73
    /**
74
     * @param bool $isMutable
75
     * @return Environment
76
     */
77
    public function setMutable(bool $isMutable): Environment
78
    {
79
        $this->isMutable = $isMutable;
80
        return $this;
81
    }
82
83
    /**
84
     * Loads environment variables from file
85
     * @param Setup $setup
86
     * @return void
87
     * @throws BaseException
88
     * @throws EnvException
89
     * @throws DiException
90
     * @throws ReflectionException
91
     */
92
    public function load(Setup $setup)
93
    {
94
        if (!empty($this->envContent)) {
95
            return;
96
        }
97
98
        $envConfig = Di::get(Loader::class)->setup($setup)->load();
99
100
        $appEnv = $envConfig['app_env'] ?? 'production';
101
        $this->envFile = ".env" . ($appEnv !== 'production' ? ".$appEnv" : '');
102
103
        if (!file_exists(App::getBaseDir() . DS . $this->envFile)) {
104
            throw EnvException::fileNotFound($this->envFile);
105
        }
106
107
        $dotenv = $this->isMutable
108
            ? Dotenv::createMutable(App::getBaseDir(), $this->envFile)
109
            : Dotenv::createImmutable(App::getBaseDir(), $this->envFile);
110
111
        $this->envContent = $dotenv->load();
112
113
        self::$appEnv = $appEnv;
114
    }
115
116
    /**
117
     * Gets the app current environment
118
     * @return string
119
     */
120
    public function getAppEnv(): string
121
    {
122
        return self::$appEnv;
123
    }
124
125
    /**
126
     * Gets the environment variable value
127
     * @param string $key
128
     * @param null|mixed $default
129
     * @return mixed
130
     * @throws EnvException
131
     */
132
    public function getValue(string $key, $default = null)
133
    {
134
        if (empty($this->envContent)) {
135
            throw EnvException::environmentNotLoaded();
136
        }
137
138
        $val = getenv($key);
139
140
        return $val !== false ? $val : $default;
141
    }
142
143
    /**
144
     * Checks if there is a such key
145
     * @param string $key
146
     * @return bool
147
     */
148
    public function hasKey(string $key): bool
149
    {
150
        return $this->findKeyRow($key) !== null;
151
    }
152
153
    /**
154
     * Gets the row of .env file by given key
155
     * @param string $key
156
     * @return string|null
157
     */
158
    public function getRow(string $key): ?string
159
    {
160
        return $this->findKeyRow($key);
161
    }
162
163
    /**
164
     * Creates or updates the row in .env
165
     * @param string $key
166
     * @param string|null $value
167
     * @throws EnvException
168
     */
169
    public function updateRow(string $key, ?string $value)
170
    {
171
        if (!$this->isMutable) {
172
            throw EnvException::environmentImmutable();
173
        }
174
175
        if (empty($this->envContent)) {
176
            throw EnvException::environmentNotLoaded();
177
        }
178
179
        $row = $this->getRow($key);
180
181
        $envFilePath = App::getBaseDir() . DS . $this->envFile;
182
183
        if ($row) {
184
            $envFileContent = file_get_contents($envFilePath);
185
            $envFileContent = preg_replace('/^' . preg_quote($row, '/') . '/m', $key . "=" . $value, $envFileContent);
186
            file_put_contents($envFilePath, $envFileContent);
187
        } else {
188
            file_put_contents($envFilePath, PHP_EOL . $key . "=" . $value . PHP_EOL, FILE_APPEND);
189
        }
190
191
        $this->envContent = Dotenv::createMutable(App::getBaseDir(), $this->envFile)->load();
192
    }
193
194
    /**
195
     * @param string $key
196
     * @return string|null
197
     */
198
    private function findKeyRow(string $key): ?string
199
    {
200
        foreach ($this->envContent as $index => $row) {
201
            if (preg_match('/^' . $key . '/', $index)) {
202
                return $key . '=' . preg_quote($row, '/');
203
            }
204
        }
205
206
        return null;
207
    }
208
}