Completed
Push — master ( 6db6da...5370d9 )
by Angel
03:42
created

Composite::parseRequest()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8977
c 0
b 0
f 0
cc 6
nc 7
nop 2
1
<?php
2
3
namespace roaresearch\yii2\roa\urlRules;
4
5
use Yii;
6
use yii\{
7
    base\InvalidConfigException,
8
    web\NotFoundHttpException,
9
    web\UrlManager,
10
    web\UrlNormalizer
11
};
12
13
/**
14
 * Url rule that can call children rule when applicable.
15
 *
16
 * @author Angel (Faryshta) Guevara <[email protected]>
17
 */
18
abstract class Composite extends \yii\web\CompositeUrlRule
19
{
20
    /**
21
     * @var bool whether this rule must throw an `NotFoundHttpException` when
22
     * parse request fails.
23
     */
24
    public $strict = true;
25
26
    /**
27
     * @var UrlNormalizer|null
28
     */
29
    public $normalizer = null;
30
31
    /**
32
     * @var string message used to create the `NotFoundHttpException` when
33
     * `$strict` equals `true` and no children rules could parse the request.
34
     */
35
    public $notFoundMessage = 'Unknown route.';
36
37
    /**
38
     * @inheritdoc
39
     */
40
    public function init()
41
    {
42
        if (is_array($this->normalizer)) {
43
            $this->normalizer = Yii::createObject(array_merge(
44
                ['class' => UrlNormalizer::class],
45
                $this->normalizer
46
            ));
47
        }
48
        if (!empty($this->normalizer)
49
            && !$this->normalizer instanceof UrlNormalizer
50
        ) {
51
            throw new InvalidConfigException(
52
                'Invalid config for `normalizer`.'
53
            );
54
        }
55
    }
56
57
    /**
58
     * Determines if this rule must parse the request using the children rules
59
     * or return `false` inmediately.
60
     *
61
     * @param string $route
62
     * @return bool
63
     */
64
    abstract protected function isApplicable(string $route): bool;
65
66
    /**
67
     * Ensures that `$rules` property is set
68
     */
69
    private function ensureRules()
70
    {
71
        if (empty($this->rules)) {
72
            $this->rules = $this->createRules();
73
        }
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function parseRequest($manager, $request)
80
    {
81
        // only parse rules applicable rules
82
        if (!$this->isApplicable($request->pathInfo)) {
83
            return false;
84
        }
85
        $normalized = false;
86
        if ($this->hasNormalizer($manager)) {
0 ignored issues
show
Documentation introduced by
$manager is of type object<yii\web\UrlManager>, but the function expects a object<web\UrlManager>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
87
            $request->pathInfo = $this->getNormalizer($manager)
88
                ->normalizePathInfo(
89
                    $request->pathInfo,
90
                    '',
91
                    $normalized
92
                );
93
        }
94
        $this->ensureRules();
95
        $result = parent::parseRequest($manager, $request);
96
        if ($result === false && $this->strict === true) {
97
            throw $this->createNotFoundException();
98
        }
99
100
        return $normalized
101
            ? $this->getNormalizer($manager)->normalizeRoute($result)
0 ignored issues
show
Bug introduced by
It seems like $result defined by parent::parseRequest($manager, $request) on line 95 can also be of type boolean; however, yii\web\UrlNormalizer::normalizeRoute() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
102
            : $result;
103
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108
    public function createUrl($manager, $route, $params)
109
    {
110
        // only parse rules applicable rules
111
        if (!$this->isApplicable($route)) {
112
            return false;
113
        }
114
        $this->ensureRules();
115
116
        return parent::createUrl($manager, $route, $params);
117
    }
118
119
    /**
120
     * @param UrlManager $manager the URL manager
121
     * @return bool
122
     */
123
    protected function hasNormalizer($manager): bool
124
    {
125
        return null !== $this->getNormalizer($manager);
126
    }
127
128
    /**
129
     * @param UrlManager $manager the URL manager
0 ignored issues
show
Documentation introduced by
Should the type for parameter $manager not be \yii\web\UrlManager?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
130
     * @return ?UrlNormalizer
0 ignored issues
show
Documentation introduced by
The doc-type ?UrlNormalizer could not be parsed: Unknown type name "?UrlNormalizer" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
131
     */
132
    protected function getNormalizer(UrlManager $manager): ?UrlNormalizer
133
    {
134
        if ($this->normalizer === null
135
            && $manager->normalizer instanceof UrlNormalizer
136
        ) {
137
            return $manager->normalizer;
138
        }
139
140
        return $this->normalizer;
141
    }
142
143
    /**
144
     * @return NotFoundHttpException
0 ignored issues
show
Documentation introduced by
Should the return type not be \yii\web\NotFoundHttpException?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
145
     */
146
    protected function createNotFoundException(): NotFoundHttpException
147
    {
148
        return new NotFoundHttpException($this->notFoundMessage);
149
    }
150
}
151