Passed
Push — master ( 29521a...b34be3 )
by Alexander
24:53 queued 23:31
created

MiddlewareFactory::createMiddleware()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 13
ccs 7
cts 7
cp 1
crap 4
rs 10
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
12
final class MiddlewareFactory implements MiddlewareFactoryInterface
13
{
14
    private ContainerInterface $container;
15
    private WrapperFactory $wrapperFactory;
16
17 4
    public function __construct(ContainerInterface $container, WrapperFactory $wrapperFactory)
18
    {
19 4
        $this->container = $container;
20 4
        $this->wrapperFactory = $wrapperFactory;
21 4
    }
22
23 4
    public function create($middlewareDefinition): MiddlewareInterface
24
    {
25 4
        return $this->createMiddleware($middlewareDefinition);
26
    }
27
28
    /**
29
     * @param callable|string|array $middlewareDefinition
30
     * @return MiddlewareInterface
31
     */
32 4
    private function createMiddleware($middlewareDefinition): MiddlewareInterface
33
    {
34 4
        $this->validateMiddleware($middlewareDefinition);
35
36 3
        if (is_string($middlewareDefinition)) {
37 1
            return $this->container->get($middlewareDefinition);
38
        }
39
40 2
        if (is_array($middlewareDefinition) && !is_object($middlewareDefinition[0])) {
41 1
            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

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