Completed
Push — master ( 7dde0e...590fc1 )
by Jitendra
02:46 queued 01:13
created

Loader::resolveRefs()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 7
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 12
rs 9.6111
1
<?php
2
3
/*
4
 * This file is part of the PHP-ENV package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\Env;
13
14
/**
15
 * DotEnv loader for PHP.
16
 *
17
 * @author   Jitendra Adhikari <[email protected]>
18
 * @license  MIT
19
 *
20
 * @link     https://github.com/adhocore/env
21
 */
22
class Loader
23
{
24
    /**
25
     * Put the parsed key value pair into $_ENV superglobal.
26
     */
27
    const ENV    = 1;
28
29
    /**
30
     * Put the parsed key value pair into putenv().
31
     */
32
    const PUTENV = 2;
33
34
    /**
35
     * Put the parsed key value pair into $_SERVER superglobal.
36
     */
37
    const SERVER = 4;
38
39
    /**
40
     * Put the parsed key value pair into all of the sources.
41
     */
42
    const ALL    = 7;
43
44
    /**
45
     * Loads .env file and puts the key value pair in one or all of putenv()/$_ENV/$_SERVER.
46
     *
47
     * @param string $file     The full path of .env file.
48
     * @param bool   $override Whether to override already available env key.
49
     * @param int    $mode     Where to load the env vars. Defaults to putenv(). Use pipe for multiple.
50
     *                         Example: Loader::SERVER | Loader::ENV | Loader::PUTENV
51
     *
52
     * @throws \InvalidArgumentException If the file does not exist or cant be read.
53
     * @throws \RuntimeException         If the file content cant be parsed.
54
     */
55
    public function load($file, $override = false, $mode = self::PUTENV)
56
    {
57
        if (!\is_file($file)) {
58
            throw new \InvalidArgumentException('The .env file does not exist or is not readable');
59
        }
60
61
        // Get file contents, fix the comments and parse as ini.
62
        $content = \preg_replace('/^\s*#/m', ';', \file_get_contents($file));
63
        $parsed  = \parse_ini_string($content, false, INI_SCANNER_RAW);
64
65
        if ($parsed === false) {
66
            throw new \RuntimeException('The .env file cannot be parsed due to malformed values');
67
        }
68
69
        $this->setEnv($parsed, (bool) $override, (int) $mode);
70
    }
71
72
    /**
73
     * Set the env values from given vars.
74
     *
75
     * @param array $vars
76
     * @param bool  $override
77
     * @param int   $mode
78
     */
79
    protected function setEnv(array $vars, $override, $mode = self::PUTENV)
80
    {
81
        $default = \microtime(1);
82
83
        foreach ($vars as $key => $value) {
84
            // Skip if we already have value and cant override.
85
            if (!$override && $default !== Retriever::getEnv($key, $default)) {
86
                continue;
87
            }
88
89
            $this->set($key, $value, $mode);
90
        }
91
92
        $this->resolveRefs($vars, $mode);
93
    }
94
95
    protected function set($key, $value, $mode)
96
    {
97
        $this->toEnv($key, $value, $mode);
98
        $this->toServer($key, $value, $mode);
99
        $this->toPutenv($key, $value, $mode);
100
    }
101
102
    protected function resolveRefs($vars, $mode)
103
    {
104
        foreach ($vars as $key => $value) {
105
            if (!$value || \strpos($value, '${') === false) {
106
                continue;
107
            }
108
109
            $value = \preg_replace_callback('~\$\{(\w+)\}~', function ($m) {
110
                return (null === $ref = Retriever::getEnv($m[1], null)) ? $m[0] : $ref;
111
            }, $value);
112
113
            $this->set($key, $value, $mode);
114
        }
115
    }
116
117
    private function toEnv($key, $value, $mode)
118
    {
119
        if ($mode & self::ENV) {
120
            $_ENV[$key] = $value;
121
        }
122
    }
123
124
    private function toServer($key, $value, $mode)
125
    {
126
        if ($mode & self::SERVER) {
127
            $_SERVER[$key] = $value;
128
        }
129
    }
130
131
    private function toPutenv($key, $value, $mode)
132
    {
133
        if ($mode & self::PUTENV) {
134
            \putenv("$key=$value");
135
        }
136
    }
137
}
138