Caller::call()   B
last analyzed

Complexity

Conditions 11
Paths 16

Size

Total Lines 43
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 24
c 1
b 0
f 0
nc 16
nop 1
dl 0
loc 43
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace MiladRahimi\PhpRouter\Dispatching;
4
5
use Closure;
6
use Laminas\Diactoros\ServerRequest;
7
use MiladRahimi\PhpContainer\Container;
8
use MiladRahimi\PhpContainer\Exceptions\ContainerException;
9
use MiladRahimi\PhpRouter\Exceptions\InvalidCallableException;
10
use Psr\Http\Message\ServerRequestInterface;
11
12
/**
13
 * It calls (runs) middleware and controllers
14
 */
15
class Caller
16
{
17
    private Container $container;
18
19
    public function __construct(Container $container)
20
    {
21
        $this->container = $container;
22
    }
23
24
    /**
25
     * Call a callable stack
26
     *
27
     * @param string[] $callables
28
     * @param ServerRequestInterface $request
29
     * @param int $index
30
     * @return mixed
31
     * @throws ContainerException
32
     * @throws InvalidCallableException
33
     */
34
    public function stack(array $callables, ServerRequestInterface $request, int $index = 0)
35
    {
36
        $this->container->singleton(ServerRequest::class, $request);
37
        $this->container->singleton(ServerRequestInterface::class, $request);
38
39
        if (isset($callables[$index + 1])) {
40
            $this->container->closure('$next', function (ServerRequestInterface $request) use ($callables, $index) {
41
                return $this->stack($callables, $request, $index + 1);
42
            });
43
        } else {
44
            $this->container->delete('$next');
45
        }
46
47
        return $this->call($callables[$index]);
48
    }
49
50
    /**
51
     * Run a callable
52
     *
53
     * @param Closure|callable|string $callable
54
     * @return mixed
55
     * @throws InvalidCallableException
56
     * @throws ContainerException
57
     */
58
    public function call($callable)
59
    {
60
        if (is_array($callable)) {
61
            if (count($callable) != 2) {
62
                throw new InvalidCallableException('Invalid callable: ' . implode(',', $callable));
63
            }
64
65
            [$class, $method] = $callable;
66
67
            if (!class_exists($class)) {
68
                throw new InvalidCallableException("Class `$class` not found.");
69
            }
70
71
            $object = $this->container->instantiate($class);
72
73
            if (!method_exists($object, $method)) {
74
                throw new InvalidCallableException("Method `$class::$method` is not declared.");
75
            }
76
77
            $callable = [$object, $method];
78
        } else {
79
            if (is_string($callable)) {
80
                if (class_exists($callable)) {
81
                    $callable = new $callable();
82
                } else {
83
                    throw new InvalidCallableException("Class `$callable` not found.");
84
                }
85
            }
86
87
            if (is_object($callable) && !$callable instanceof Closure) {
88
                if (method_exists($callable, 'handle')) {
89
                    $callable = [$callable, 'handle'];
90
                } else {
91
                    throw new InvalidCallableException("Method `handle` is not declared.");
92
                }
93
            }
94
        }
95
96
        if (!is_callable($callable)) {
97
            throw new InvalidCallableException('Invalid callable.');
98
        }
99
100
        return $this->container->call($callable);
101
    }
102
}
103