Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
31.58% covered (danger)
31.58%
6 / 19
44.44% covered (danger)
44.44%
4 / 9
CRAP
33.33% covered (danger)
33.33%
1 / 3
MiddlewareResult
18.18% covered (danger)
18.18%
2 / 11
40.00% covered (danger)
40.00%
2 / 5
25.72
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 none
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 redirect
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 error
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canNext
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 apply
n/a
0 / 0
n/a
0 / 0
0
LocalRedirectMiddlewareResultImpl
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 2
6
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 apply
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
LocalErrorMiddlewareResultImpl
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
2 / 2
2
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 apply
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace PeServer\Core\Mvc\Middleware;
6
7use PeServer\Core\Http\HttpStatus;
8use PeServer\Core\Regex;
9use PeServer\Core\Store\SpecialStore;
10use PeServer\Core\Text;
11use PeServer\Core\Throws\ArgumentException;
12use PeServer\Core\Throws\HttpStatusException;
13use PeServer\Core\Throws\InvalidOperationException;
14use PeServer\Core\Web\Url;
15
16/**
17 * ミドルウェア結果。
18 */
19abstract class MiddlewareResult
20{
21    #region define
22
23    protected const RESULT_KIND_NONE = 0;
24    protected const RESULT_KIND_STATUS = 1;
25
26    #endregion
27
28    #region variable
29
30    /** 結果なしキャッシュ。 */
31    private static ?MiddlewareResult $none = null;
32
33    #endregion
34
35
36    /**
37     * 生成。
38     *
39     * @param int $kind
40     * @phpstan-param self::RESULT_KIND_* $kind
41     */
42    protected function __construct(
43        private readonly int $kind
44    ) {
45    }
46
47    #region function
48
49    /**
50     * 結果なし。
51     *
52     * 特に何かすることのないミドルウェアはこいつを呼べば問題なし。
53     *
54     * @return MiddlewareResult
55     */
56    public static function none(): MiddlewareResult
57    {
58        return self::$none ??= new class extends MiddlewareResult
59        {
60            public function __construct()
61            {
62                parent::__construct(parent::RESULT_KIND_NONE);
63            }
64
65            public function apply(): void
66            {
67                // こいつがここまでくればバグってる
68                throw new InvalidOperationException();
69            }
70        };
71    }
72
73    /**
74     * リダイレクト処理生成。
75     *
76     * @param Url $url
77     * @param HttpStatus $status
78     * @return MiddlewareResult
79     */
80    public static function redirect(Url $url, HttpStatus $status = HttpStatus::Found): MiddlewareResult
81    {
82        if (!$status->isRedirect()) {
83            throw new ArgumentException('$status');
84        }
85
86        return new LocalRedirectMiddlewareResultImpl($status, $url);
87    }
88
89    /**
90     * エラー処理生成。
91     *
92     * @param HttpStatus $status
93     * @param string $message
94     * @return MiddlewareResult
95     */
96    public static function error(HttpStatus $status, string $message = Text::EMPTY): MiddlewareResult
97    {
98        return new LocalErrorMiddlewareResultImpl($status, $message);
99    }
100
101    /**
102     * 次のミドルウェア処理へ移れるか。
103     *
104     * @return bool 真: 処理可能。
105     */
106    final public function canNext(): bool
107    {
108        return $this->kind === self::RESULT_KIND_NONE;
109    }
110
111    /**
112     * ミドルウェア結果適用。
113     */
114    abstract public function apply(): void;
115
116    #endregion
117}
118
119//phpcs:ignore PSR1.Classes.ClassDeclaration.MultipleClasses
120class LocalRedirectMiddlewareResultImpl extends MiddlewareResult
121{
122    private HttpStatus $status;
123    private Url $url;
124
125    public function __construct(HttpStatus $status, Url $url)
126    {
127        parent::__construct(parent::RESULT_KIND_STATUS);
128
129        $this->status = $status;
130        $this->url = $url;
131    }
132
133    public function apply(): void
134    {
135        header('Location: ' . $this->url->toString(), true, $this->status->value);
136    }
137}
138
139//phpcs:ignore PSR1.Classes.ClassDeclaration.MultipleClasses
140class LocalErrorMiddlewareResultImpl extends MiddlewareResult
141{
142    private HttpStatus $status;
143    private string $message;
144
145    public function __construct(HttpStatus $status, string $message)
146    {
147        parent::__construct(parent::RESULT_KIND_STATUS);
148
149        $this->status = $status;
150        $this->message = $message;
151    }
152
153    public function apply(): void
154    {
155        throw new HttpStatusException($this->status, $this->message);
156    }
157}