Passed
Push — master ( bda1ff...5d4ebc )
by Marwan
01:23
created

Globals::initialize()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 2
b 0
f 0
nc 4
nop 0
dl 0
loc 11
rs 10
1
<?php
2
3
/**
4
 * @author Marwan Al-Soltany <[email protected]>
5
 * @copyright Marwan Al-Soltany 2021
6
 * For the full copyright and license information, please view
7
 * the LICENSE file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace MAKS\Velox\Backend;
13
14
use MAKS\Velox\Helper\Misc;
15
16
/**
17
 * A class that serves as an abstraction/wrapper to work with superglobals.
18
 *
19
 * @method static mixed getGet(string $key)
20
 * @method static mixed getPost(string $key)
21
 * @method static mixed getFiles(string $key)
22
 * @method static mixed getCookie(string $key)
23
 * @method static mixed getSession(string $key)
24
 * @method static mixed getRequest(string $key)
25
 * @method static mixed getServer(string $key)
26
 * @method static mixed getEnv(string $key)
27
 * @method static static setGet(string $key, $value)
28
 * @method static static setPost(string $key, $value)
29
 * @method static static setFiles(string $key, $value)
30
 * @method static static setCookie(string $key, $value)
31
 * @method static static setSession(string $key, $value)
32
 * @method static static setRequest(string $key, $value)
33
 * @method static static setServer(string $key, $value)
34
 * @method static static setEnv(string $key, $value)
35
 *
36
 * @since 1.0.0
37
 */
38
class Globals
39
{
40
    public const GLOBALS = [
41
        '_GET'     => '_GET',
42
        '_POST'    => '_POST',
43
        '_FILES'   => '_FILES',
44
        '_COOKIE'  => '_COOKIE',
45
        '_SESSION' => '_SESSION',
46
        '_REQUEST' => '_REQUEST',
47
        '_SERVER'  => '_SERVER',
48
        '_ENV'     => '_ENV',
49
    ];
50
51
52
    private static array $_GET;
53
    private static array $_POST;
54
    private static array $_FILES;
55
    private static array $_COOKIE;
56
    private static array $_SESSION;
57
    private static array $_REQUEST;
58
    private static array $_SERVER;
59
    private static array $_ENV;
60
61
62
    /**
63
     * Initializes class internal state from superglobals.
64
     *
65
     * @return void
66
     */
67
    public static function initialize(): void
68
    {
69
        static $isInitialized = false;
70
71
        if (!$isInitialized) {
72
            foreach (self::GLOBALS as $global) {
73
                global $$global;
74
                self::$$global = isset($$global) ? self::$$global = &$$global : [];
75
            }
76
77
            $isInitialized = true;
78
        }
79
    }
80
81
    /**
82
     * Gets a value from the specified superglobal.
83
     *
84
     * @param string $name The superglobal name to get the value from. Can be written in any case with or without the leading underscore.
85
     * @param string $key The array element to get from the superglobal. Dot-notation can be used with nested arrays.
86
     *
87
     * @return mixed
88
     *
89
     * @throws \Exception If the passed name is not a superglobal.
90
     */
91
    public static function get(string $name, string $key = null)
92
    {
93
        static::initialize();
94
95
        $name = static::getValidNameOrFail($name);
96
97
        if ($key !== null) {
98
            return Misc::getArrayValueByKey(static::$$name, $key, null);
99
        }
100
101
        return static::$$name;
102
    }
103
104
    /**
105
     * Sets a value in the specified superglobal.
106
     *
107
     * @param string $name The superglobal name to set the value in. Can be written in any case with or without the leading underscore.
108
     * @param string $key The array element to set in the superglobal. Dot-notation can be used with nested arrays.
109
     * @param mixed $value The value to set.
110
     *
111
     * @return static
112
     *
113
     * @throws \Exception If the passed name is not a superglobal.
114
     */
115
    public static function set(string $name, string $key, $value)
116
    {
117
        static::initialize();
118
119
        $name = static::getValidNameOrFail($name);
120
121
        Misc::setArrayValueByKey(static::$$name, $key, $value);
122
123
        return new static();
124
    }
125
126
    /**
127
     * Returns a valid superglobal name from the passed name.
128
     *
129
     * @param string $name
130
     *
131
     * @return string
132
     *
133
     * @throws \Exception
134
     */
135
    private static function getValidNameOrFail(string $name): string
136
    {
137
        $variable = '_' . trim(strtoupper($name), '_');
138
139
        if (!in_array($variable, self::GLOBALS)) {
140
            $available = implode(', ', self::GLOBALS);
141
142
            throw new \Exception("There is no PHP superglobal with the name '{$name}'. Available superglobals are: [{$available}]");
143
        }
144
145
        return $variable;
146
    }
147
148
149
    /**
150
     * Class constructor.
151
     */
152
    final public function __construct()
153
    {
154
        // the constructor is final to allow to the use of
155
        // "return new static()" without caring about class dependencies.
156
157
        $this->initialize();
158
    }
159
160
    /**
161
     * Aliases getters and setter for class members.
162
     */
163
    public static function __callStatic(string $name, array $arguments)
164
    {
165
        if (preg_match('/^([gs]et)([_]{0,1}[a-z0-9]+)$/i', $name, $matches)) {
166
            return forward_static_call_array(
167
                [static::class, $matches[1]],
168
                [static::getValidNameOrFail($matches[2]), ...$arguments]
169
            );
170
        }
171
172
        throw new \Exception(sprintf('Call to undefined method %s::%s', static::class, $name));
173
    }
174
175
    /**
176
     * Allows static methods handled by self::__callStatic() to be accessible via object operator `->`.
177
     */
178
    public function __call(string $method, array $arguments)
179
    {
180
        return static::__callStatic($method, $arguments);
181
    }
182
}
183