Passed
Pull Request — master (#1)
by
unknown
14:51
created

MiddlewareFactory::validateMiddleware()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 5
nc 3
nop 1
dl 0
loc 11
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\RequestModel;
6
7
use InvalidArgumentException;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Server\MiddlewareInterface;
10
use Yiisoft\Router\MiddlewareFactoryInterface;
11
use Closure;
12
13
final class MiddlewareFactory implements MiddlewareFactoryInterface
14
{
15
    private ContainerInterface $container;
16
    private WrapperFactory $wrapperFactory;
17
18
    public function __construct(ContainerInterface $container, WrapperFactory $wrapperFactory)
19
    {
20
        $this->container = $container;
21
        $this->wrapperFactory = $wrapperFactory;
22
    }
23
24
    public function create($middlewareDefinition): MiddlewareInterface
25
    {
26
        return $this->createMiddleware($middlewareDefinition);
27
    }
28
29
    /**
30
     * @param callable|string|array|Closure $middlewareDefinition
31
     * @return MiddlewareInterface
32
     */
33
    private function createMiddleware($middlewareDefinition): MiddlewareInterface
34
    {
35
        $this->validateMiddleware($middlewareDefinition);
36
37
        if (is_string($middlewareDefinition)) {
38
            return $this->container->get($middlewareDefinition);
39
        }
40
41
        if (is_array($middlewareDefinition) && !is_object($middlewareDefinition[0])) {
42
            return $this->wrapperFactory->createActionWrapper(...$middlewareDefinition);
0 ignored issues
show
Bug introduced by
The call to Yiisoft\RequestModel\Wra...::createActionWrapper() has too few arguments starting with method. ( Ignorable by Annotation )

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

42
            return $this->wrapperFactory->/** @scrutinizer ignore-call */ createActionWrapper(...$middlewareDefinition);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
43
        }
44
45
        return $this->wrapperFactory->createCallableWrapper($middlewareDefinition);
46
    }
47
48
    /**
49
     * @param callable|string|array $middlewareDefinition
50
     */
51
    private function validateMiddleware($middlewareDefinition): void
52
    {
53
        if (is_string($middlewareDefinition) && is_subclass_of($middlewareDefinition, MiddlewareInterface::class)) {
54
            return;
55
        }
56
57
        if ($this->isCallable($middlewareDefinition) && (!is_array($middlewareDefinition) || !is_object($middlewareDefinition[0]))) {
58
            return;
59
        }
60
61
        throw new InvalidArgumentException('Parameter should be either PSR middleware class name or a callable.');
62
    }
63
64
    private function isCallable($definition): bool
65
    {
66
        if (is_callable($definition)) {
67
            return true;
68
        }
69
70
        return is_array($definition) && array_keys($definition) === [0, 1] && in_array($definition[1], class_exists($definition[0]) ? get_class_methods($definition[0]) : [], true);
71
    }
72
}
73