Completed
Pull Request — master (#6)
by Angel
12:21
created

Composite::parseRequest()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6.0073

Importance

Changes 0
Metric Value
cc 6
eloc 16
nc 7
nop 2
dl 0
loc 27
ccs 16
cts 17
cp 0.9412
crap 6.0073
rs 9.1111
c 0
b 0
f 0
1
<?php
2
3
namespace roaresearch\yii2\roa\urlRules;
4
5
use Yii;
6
use yii\{
7
    base\InvalidConfigException,
8
    di\Instance,
9
    web\NotFoundHttpException,
10
    web\UrlManager,
11
    web\UrlNormalizer
12
};
13
14
/**
15
 * Url rule that can call children rule when applicable.
16
 *
17
 * @author Angel (Faryshta) Guevara <[email protected]>
18
 */
19
abstract class Composite extends \yii\web\CompositeUrlRule
20
{
21
    /**
22
     * @var bool whether this rule must throw an `NotFoundHttpException` when
23
     * parse request fails.
24
     */
25
    public bool $strict = true;
26
27
    /**
28
     * @var string message used to create the `NotFoundHttpException` when
29
     * `$strict` equals `true` and no children rules could parse the request.
30
     */
31
    public string $notFoundMessage = 'Unknown route.';
32
33
    /**
34
     * @var ?UrlNormalizer
35
     */
36
    protected ?UrlNormalizer $normalizer = null;
37
38
    /**
39
     * @inheritdoc
40 21
     */
41
    public function setNormalizer(UrlNormalizer | array $normalizer): void
42 21
    {
43
        $this->normalizer = Instance::ensure($normalizer, UrlNormalizer::class);
44
    }
45
46
    /**
47
     * @param UrlManager $manager the URL manager
48 21
     * @return ?UrlNormalizer
49 21
     */
50
    protected function getNormalizer(UrlManager $manager): ?UrlNormalizer
51
    {
52
        if (!$this->normalizer && $manager->normalizer) {
53
            $this->setNormalizer($manager->normalizer);
0 ignored issues
show
Bug introduced by
It seems like $manager->normalizer can also be of type string and true; however, parameter $normalizer of roaresearch\yii2\roa\url...posite::setNormalizer() does only seem to accept array|yii\web\UrlNormalizer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

53
            $this->setNormalizer(/** @scrutinizer ignore-type */ $manager->normalizer);
Loading history...
54
        }
55 21
56
        return $this->normalizer;
57
    }
58
59
    /**
60
     * Determines if this rule must parse the request using the children rules
61
     * or return `false` inmediately.
62
     *
63
     * @param string $route
64
     * @return bool
65
     */
66
    abstract protected function isApplicable(string $route): bool;
67
68
    /**
69 21
     * Ensures that `$rules` property is set
70
     */
71 21
    protected function ensureRules()
72 21
    {
73
        $this->rules = $this->rules ?: $this->createRules();
74 21
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79 21
    public function parseRequest($manager, $request)
80
    {
81
        // only parse rules applicable rules
82 21
        if (!$this->isApplicable($request->pathInfo)) {
83 1
            return false;
84
        }
85 21
86 21
        $normalized = false;
87 21
        if ($this->hasNormalizer($manager)) {
88 21
            $request->pathInfo = $this->getNormalizer($manager)
89 21
                ->normalizePathInfo(
90 21
                    $request->pathInfo,
91 21
                    '',
92
                    $normalized
93
                );
94 21
        }
95 21
96 21
        $this->ensureRules();
97
        $result = parent::parseRequest($manager, $request);
98
99
        if ($result === false && $this->strict === true) {
100 21
            throw $this->createNotFoundException();
101 1
        }
102 21
103
        return $normalized
104
            ? $this->getNormalizer($manager)->normalizeRoute($result)
0 ignored issues
show
Bug introduced by
It seems like $result can also be of type false; however, parameter $route of yii\web\UrlNormalizer::normalizeRoute() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
            ? $this->getNormalizer($manager)->normalizeRoute(/** @scrutinizer ignore-type */ $result)
Loading history...
105
            : $result;
106
    }
107
108 17
    /**
109
     * @inheritdoc
110
     */
111 17
    public function createUrl($manager, $route, $params)
112 16
    {
113
        // only parse rules applicable rules
114 17
        if (!$this->isApplicable($route)) {
115
            return false;
116 17
        }
117
        $this->ensureRules();
118
119
        return parent::createUrl($manager, $route, $params);
120
    }
121
122
    /**
123 21
     * @param UrlManager $manager the URL manager
124
     * @return bool
125 21
     */
126
    protected function hasNormalizer($manager): bool
127
    {
128
        return null !== $this->getNormalizer($manager);
129
    }
130
131
    /**
132 21
     * @return NotFoundHttpException
133
     */
134 21
    protected function createNotFoundException(): NotFoundHttpException
135 21
    {
136
        return new NotFoundHttpException($this->notFoundMessage);
137
    }
138
}
139