Environment::setEnv()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 3
nc 2
nop 3
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Env
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Env;
13
14
use Phoole\Base\Reference\ReferenceTrait;
15
use Phoole\Base\Reference\ReferenceInterface;
16
17
/**
18
 * Load environment key/value pairs from certain path.
19
 *
20
 * @package Phoole\Env
21
 */
22
class Environment implements ReferenceInterface
23
{
24
    use ReferenceTrait;
25
26
    /**
27
     * Load environment variables from a .env file
28
     *
29
     * @param  string $path       full path of the .env file
30
     * @param  bool   $overwrite  overwrite existing values
31
     * @return object $this          able to chain
32
     * @throws \RuntimeException     if $path not readable
33
     */
34
    public function load(string $path, bool $overwrite = FALSE): object
35
    {
36
        return $this->parse($this->loadPath($path), $overwrite);
37
    }
38
39
    /**
40
     * Parse an array to set environment variables
41
     *
42
     * @param  array $arr        full path of the .env file
43
     * @param  bool  $overwrite  overwrite existing env values
44
     * @return object $this         able to chain
45
     */
46
    public function parse(array $arr, bool $overwrite = FALSE): object
47
    {
48
        foreach ($arr as $key => $val) {
49
            $this->setEnv($key, $this->deReferenceString($val), $overwrite);
50
        }
51
        return $this;
52
    }
53
54
    /**
55
     * load content of a file into array
56
     *
57
     * @param  string $path  full path of the .env file
58
     * @return array
59
     * @throws \RuntimeException   if $path not readable
60
     */
61
    protected function loadPath(string $path): array
62
    {
63
        try {
64
            if ($str = \file_get_contents($path)) {
65
                return $this->parseString($str);
66
            }
67
            return [];
68
        } catch (\Throwable $e) {
69
            throw new \RuntimeException($e->getMessage());
70
        }
71
    }
72
73
    /**
74
     * Parse 'ENV = value' into pairs
75
     *
76
     * @param  string $str  string to parse
77
     * @return array
78
     */
79
    protected function parseString(string $str): array
80
    {
81
        $regex =
82
            '~^\s*+
83
            (?:
84
                (?:([^#\s=]++) \s*+ = \s*+
85
                    (?|
86
                        (([^"\'#\s][^#\n]*?)) |
87
                        (["\'])((?:\\\2|.)*?)\2
88
                    )?
89
                ) |
90
                (?: (\.|source) \s++ ([^#\n]*) )
91
            )\s*?(?:[#].*)?
92
        $~mx';
93
        $pairs = [];
94
        if (\preg_match_all($regex, $str, $matched, \PREG_SET_ORDER)) {
95
            foreach ($matched as $m) {
96
                if (isset($m[3])) {
97
                    $pairs[$m[1]] = $m[3];
98
                } else {
99
                    $pairs[$m[1]] = '';
100
                }
101
            }
102
        }
103
        return $pairs;
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     */
109
    protected function getReference(string $name)
110
    {
111
        $default = '';
112
        if (FALSE !== strpos($name, ':-')) {
113
            list($name, $default) = explode(':-', $name, 2);
114
        } elseif (FALSE !== strpos($name, ':=')) {
115
            list($name, $default) = explode(':=', $name, 2);
116
            $this->setEnv($name, $default, FALSE);
117
        }
118
        return getenv($name) === FALSE ? $default : getenv($name);
119
    }
120
121
    /**
122
     * @param  string $key  key to set
123
     * @param  string $val  value to set
124
     * @param  bool   $overwrite
125
     * @return void
126
     */
127
    protected function setEnv(string $key, string $val, bool $overwrite): void
128
    {
129
        if ($overwrite || FALSE === getenv($key)) {
130
            putenv("$key=$val");
131
        }
132
    }
133
}