Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
9.72% covered (danger)
9.72%
7 / 72
13.89% covered (danger)
13.89%
5 / 36
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialStore
9.72% covered (danger)
9.72%
7 / 72
13.89% covered (danger)
13.89%
5 / 36
1534.94
0.00% covered (danger)
0.00%
0 / 1
 getServer
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 tryGetServer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 containsServerName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getServerNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCookie
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 tryGetCookie
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 containsCookieName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCookieNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSession
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 tryGetSession
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 containsSessionName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSessionNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 containsGetName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGet
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 tryGetGet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGetNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 containsPostName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPost
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 tryGetPost
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPostNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 containsFileName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFile
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 tryGetFile
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getFileNames
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRequestContent
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRequestJson
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getServerName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isHttps
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isLocalhost
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 getPort
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getHost
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getServerUrlCore
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
72
 getServerUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRequestUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRequestMethod
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getRequestHeader
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\Core\Store;
6
7use PeServer\Core\Binary;
8use PeServer\Core\Collection\Arr;
9use PeServer\Core\Http\HttpHeader;
10use PeServer\Core\Http\HttpMethod;
11use PeServer\Core\IO\File;
12use PeServer\Core\Mvc\UploadedFile;
13use PeServer\Core\Text;
14use PeServer\Core\Web\Url;
15use PeServer\Core\Web\UrlPath;
16use PeServer\Core\Web\UrlQuery;
17
18/**
19 * $_SERVER, $_COOKIE, $_SESSION 読み込みアクセス。
20 *
21 * @SuppressWarnings(PHPMD.Superglobals)
22 */
23class SpecialStore
24{
25    #region function
26
27    /**
28     * `$_SERVER` から値取得。
29     *
30     * @template TValue
31     * @param string $name インデックス名。
32     * @param mixed $fallbackValue 取得時失敗時の値。
33     * @phpstan-param TValue $fallbackValue
34     * @return mixed
35     * @phpstan-return TValue
36     */
37    public function getServer(string $name, mixed $fallbackValue = Text::EMPTY): mixed
38    {
39        $result = $_SERVER[$name] ?? $fallbackValue;
40        return $result;
41    }
42
43    public function tryGetServer(string $name, mixed &$result): bool
44    {
45        return Arr::tryGet($_SERVER, $name, $result);
46    }
47
48    /**
49     * `$_SERVER` に名前が存在するか。
50     *
51     * @param string $name
52     * @return boolean
53     */
54    public function containsServerName(string $name): bool
55    {
56        return isset($_SERVER[$name]);
57    }
58
59    /**
60     * `$_SERVER` の名前一覧取得。
61     *
62     * @return string[]
63     */
64    public function getServerNames(): array
65    {
66        return Arr::getKeys($_SERVER);
67    }
68
69    /**
70     * `$_COOKIE` から値取得。
71     *
72     * @param string $name
73     * @param string $fallbackValue
74     * @return string
75     */
76    public function getCookie(string $name, string $fallbackValue = Text::EMPTY): string
77    {
78        $result = $_COOKIE[$name] ?? $fallbackValue;
79        return $result;
80    }
81
82    public function tryGetCookie(string $name, ?string &$result): bool
83    {
84        return Arr::tryGet($_COOKIE, $name, $result);
85    }
86
87    /**
88     * `$_COOKIE` に名前が存在するか。
89     *
90     * @param string $name
91     * @return boolean
92     */
93    public function containsCookieName(string $name): bool
94    {
95        return isset($_COOKIE[$name]);
96    }
97
98    /**
99     * `$_COOKIE` の名前一覧取得。
100     *
101     * @return string[]
102     */
103    public function getCookieNames(): array
104    {
105        return Arr::getKeys($_COOKIE);
106    }
107
108    /**
109     * `$_SESSION` から値取得。
110     *
111     * @param string $name
112     * @param string $fallbackValue
113     * @return string
114     */
115    public function getSession(string $name, string $fallbackValue = Text::EMPTY): string
116    {
117        $result = $_SESSION[$name] ?? $fallbackValue;
118        return $result;
119    }
120
121    public function tryGetSession(string $name, ?string &$result): bool
122    {
123        return Arr::tryGet($_SESSION, $name, $result);
124    }
125
126    /**
127     * `$_SESSION` に名前が存在するか。
128     *
129     * @param string $name
130     * @return boolean
131     */
132    public function containsSessionName(string $name): bool
133    {
134        return isset($_SESSION[$name]);
135    }
136
137    /**
138     * `$_SESSION` の名前一覧取得。
139     *
140     * @return string[]
141     */
142    public function getSessionNames(): array
143    {
144        return Arr::getKeys($_SESSION);
145    }
146
147    public function containsGetName(string $name): bool
148    {
149        return isset($_GET[$name]);
150    }
151
152    public function getGet(string $name, string $fallbackValue = Text::EMPTY): string
153    {
154        $result = $_GET[$name] ?? $fallbackValue;
155        return $result;
156    }
157
158    public function tryGetGet(string $name, ?string &$result): bool
159    {
160        return Arr::tryGet($_GET, $name, $result);
161    }
162
163    /**
164     * $_GET の名前一覧取得。
165     *
166     * @return string[]
167     */
168    public function getGetNames(): array
169    {
170        return Arr::getKeys($_GET);
171    }
172
173    public function containsPostName(string $name): bool
174    {
175        return isset($_POST[$name]);
176    }
177
178    public function getPost(string $name, string $fallbackValue = Text::EMPTY): string
179    {
180        $result = $_POST[$name] ?? $fallbackValue;
181        return $result;
182    }
183
184    public function tryGetPost(string $name, ?string &$result): bool
185    {
186        return Arr::tryGet($_POST, $name, $result);
187    }
188
189    /**
190     * `$_POST` の名前一覧取得。
191     *
192     * @return string[]
193     */
194    public function getPostNames(): array
195    {
196        return Arr::getKeys($_POST);
197    }
198
199    public function containsFileName(string $name): bool
200    {
201        return isset($_FILES[$name]);
202    }
203
204    public function getFile(string $name): UploadedFile
205    {
206        if (!isset($_FILES[$name])) {
207            return UploadedFile::invalid($name);
208        }
209
210        $file = $_FILES[$name];
211        return UploadedFile::create($file);
212    }
213
214    public function tryGetFile(string $name, ?UploadedFile &$result): bool
215    {
216        if (Arr::tryGet($_FILES, $name, $file)) {
217            $result = UploadedFile::create($file);
218            return true;
219        }
220
221        return false;
222    }
223
224    /**
225     * `$_FILES` の名前一覧取得。
226     *
227     * @return string[]
228     */
229    public function getFileNames(): array
230    {
231        return Arr::getKeys($_FILES);
232    }
233
234    /**
235     * 要求本文の生データを取得。
236     *
237     * @return Binary
238     */
239    public function getRequestContent(): Binary
240    {
241        return File::readContent('php://input');
242    }
243
244    /**
245     * 要求本文から JSON を取得。
246     *
247     * @return array<mixed>
248     */
249    public function getRequestJson(): array
250    {
251        return File::readJsonFile('php://input');
252    }
253
254    public function getServerName(): string
255    {
256        return $this->getServer('SERVER_NAME');
257    }
258
259    public function isHttps(): bool
260    {
261        return $this->getServer('HTTPS') === 'on'; //@phpstan-ignore-line [TIME]
262    }
263
264    public function isLocalhost(): bool
265    {
266        return Arr::in(
267            [
268                'localhost',
269                '127.0.0.1',
270            ],
271            $this->getServerName()
272        );
273    }
274
275    public function getPort(): int
276    {
277        $raw = $this->getServer('SERVER_PORT', null);
278        // if (Text::isNullOrEmpty($raw)) {
279        //     return null;
280        // }
281
282        return (int)$raw;
283    }
284
285    public function getHost(): string
286    {
287        return $this->getServer('HTTP_HOST', TEXT::EMPTY);
288    }
289
290    private function getServerUrlCore(bool $withPathInfo): Url
291    {
292        $isHttps = $this->isHttps();
293
294        $port = $this->getPort();
295        if ($isHttps) {
296            if ($port === 443) {
297                $port = '';
298            }
299        } else {
300            if ($port === 80) {
301                $port = '';
302            }
303        }
304        if ($port !== '') {
305            $port = ":$port";
306        }
307
308        $query = $this->getServer('QUERY_STRING', Text::EMPTY);
309        if (Text::isNullOrEmpty($query)) { //@phpstan-ignore-line [TIME]
310            $query = null;
311        }
312
313        $url = $isHttps ? 'https://' : 'http://';
314        $url .= $this->getHost();
315        $url .= $port;
316        if ($withPathInfo) {
317            $url .= $this->getServer('REQUEST_URI', Text::EMPTY);
318        }
319
320        return Url::parse($url);
321    }
322
323    public function getServerUrl(): Url
324    {
325        return $this->getServerUrlCore(false);
326    }
327
328    /**
329     * URLを取得。
330     *
331     * リバースプロキシだったり認証だったりの細かい制御は行っていない。
332     *
333     * @return Url
334     */
335    public function getRequestUrl(): Url
336    {
337        return $this->getServerUrlCore(true);
338    }
339
340    public function getRequestMethod(): HttpMethod
341    {
342        $raw = $this->getServer('REQUEST_METHOD', Text::EMPTY);
343
344        return HttpMethod::from(Text::toUpper(Text::trim($raw)));
345    }
346
347    /**
348     * リクエストヘッダの取得。
349     *
350     * 直接使用するのではなく、ここで受け取ったヘッダを使いまわすイメージ。
351     *
352     * @return HttpHeader
353     */
354    public function getRequestHeader(): HttpHeader
355    {
356        return HttpHeader::getRequestHeader();
357    }
358
359
360    #endregion
361}