Completed
Push — master ( 22a756...a8d83f )
by John
02:03
created

src/OperationMatcher.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php declare(strict_types = 1);
2
/*
3
 * This file is part of the KleijnWeb\PhpApi\Descriptions package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
namespace KleijnWeb\PhpApi\Middleware;
9
10
use Interop\Http\ServerMiddleware\DelegateInterface;
11
use KleijnWeb\PhpApi\Descriptions\Description\Description;
12
use KleijnWeb\PhpApi\Descriptions\Description\Parameter;
13
use KleijnWeb\PhpApi\Descriptions\Description\Repository;
14
use KleijnWeb\PhpApi\Descriptions\Description\Schema\ScalarSchema;
15
use KleijnWeb\PhpApi\Descriptions\Description\Schema\Schema;
16
use KleijnWeb\PhpApi\Middleware\Util\Meta;
17
use KleijnWeb\PhpApi\Middleware\Util\PhpApiMiddleware;
18
use Middlewares\Utils\Factory;
19
use Psr\Http\Message\ResponseInterface;
20
use Psr\Http\Message\ServerRequestInterface;
21
22
class OperationMatcher extends PhpApiMiddleware
23
{
24
    /**
25
     * @var Repository
26
     */
27
    private $repository;
28
29
    /**
30
     * @param Repository $repository
31
     */
32
    public function __construct(Repository $repository)
33
    {
34
        $this->repository = $repository;
35
    }
36
37
    /**
38
     * Process a server request and return a response.
39
     *
40
     * @param ServerRequestInterface $request
41
     * @param DelegateInterface      $delegate
42
     *
43
     * @return ResponseInterface
44
     */
45
    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
46
    {
47
        $uriPath = $request->getUri()->getPath();
48
49
        /** @var Description $description */
50
        foreach ($this->repository as $description) {
51
52
            $basePath = $description->getBasePath() ? "{$description->getBasePath()}/" : "";
53
54
            foreach ($description->getPaths() as $path) {
55
                $pathPattern = "$basePath{$path->getPath()}";
56
57
                $parameterNames = [];
58
                foreach ($path->getOperations() as $operation) {
59
                    foreach ($operation->getParameters() as $parameter) {
60
                        if ($parameter->getIn() === Parameter::IN_PATH
61
                            && ($schema = $parameter->getSchema()) instanceof ScalarSchema
62
                        ) {
63
                            $parameterName    = $parameter->getName();
64
                            $parameterNames[] = $parameterName;
65
                            $parameterPattern = "(?P<$parameterName>.*)(?=(/|$))";
66
                            $typePattern = null;
67
                            switch ($type = $schema->getType()) {
0 ignored issues
show
$type is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
68
                                case Schema::TYPE_INT:
69
                                    $typePattern = '\d+';
70
                                    break;
71
                                case Schema::TYPE_NUMBER:
72
                                    $typePattern = '\d+(\.\d+)?';
73
                                    break;
74
                                case Schema::TYPE_NULL:
75
                                    $typePattern = 'null';
76
                                    break;
77
                                case Schema::TYPE_STRING:
78
                                    /** @var $schema ScalarSchema $routeString */
79
                                    if ($pattern = $schema->getPattern()) {
80
                                        $typePattern = $pattern;
81
                                    } elseif ($enum = $schema->getEnum()) {
82
                                        $typePattern = '('.implode('|', $enum).')';
83
                                    }
84
                                    break;
85
                                default:
86
                                    $typePattern = null;
87
                            }
88
                            if ($typePattern) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $typePattern of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
89
                                $parameterPattern = str_replace(
90
                                    "<$parameterName>.*",
91
                                    "<$parameterName>$typePattern",
92
                                    $parameterPattern
93
                                );
94
                            }
95
                            $pathPattern = str_replace('{'.$parameterName.'}', $parameterPattern, $pathPattern);
96
                        }
97
                    }
98
99
                    if (preg_match("#^$pathPattern$#", $uriPath, $matches) > 0) {
100
                        if (strtolower($request->getMethod()) !== $operation->getMethod()) {
101
                            return Factory::createResponse(405);
102
                        }
103
104
                        $request = Meta::requestWith($request, $description, $operation, $path);
105
106
                        foreach ($parameterNames as $parameterName) {
107
                            $request = $request->withAttribute($parameterName, $matches[$parameterName]);
108
                        }
109
110
                        return $delegate->process($request);
111
                    }
112
                }
113
114
            }
115
        }
116
117
        return Factory::createResponse(404);
118
    }
119
}