CallableTrait   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 3
dl 0
loc 100
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
C getCallable() 0 35 8
A arguments() 0 6 1
B executeCallable() 0 28 5
1
<?php
2
3
namespace Psr7Middlewares\Utils;
4
5
use RuntimeException;
6
use Psr7Middlewares\Utils;
7
use Psr\Http\Message\RequestInterface;
8
use Psr\Http\Message\ResponseInterface;
9
10
/**
11
 * Utilities used by middlewares with callables.
12
 */
13
trait CallableTrait
14
{
15
    private $arguments = [];
16
17
    /**
18
     * Extra arguments passed to the callable.
19
     *
20
     * @return self
21
     */
22
    public function arguments()
23
    {
24
        $this->arguments = func_get_args();
25
26
        return $this;
27
    }
28
29
    /**
30
     * Execute the callable.
31
     *
32
     * @param mixed             $target
33
     * @param RequestInterface  $request
34
     * @param ResponseInterface $response
35
     *
36
     * @return ResponseInterface
37
     */
38
    private function executeCallable($target, RequestInterface $request, ResponseInterface $response)
39
    {
40
        ob_start();
41
        $level = ob_get_level();
42
43
        try {
44
            $arguments = array_merge([$request, $response], $this->arguments);
45
            $target = self::getCallable($target, $arguments);
46
            $return = call_user_func_array($target, $arguments);
47
48
            if ($return instanceof ResponseInterface) {
49
                $response = $return;
50
                $return = '';
51
            }
52
53
            $return = Utils\Helpers::getOutput($level).$return;
54
            $body = $response->getBody();
55
56
            if ($return !== '' && $body->isWritable()) {
57
                $body->write($return);
58
            }
59
60
            return $response;
61
        } catch (\Exception $exception) {
62
            Utils\Helpers::getOutput($level);
63
            throw $exception;
64
        }
65
    }
66
67
    /**
68
     * Resolves the target of the route and returns a callable.
69
     *
70
     * @param mixed $target
71
     * @param array $construct_args
72
     *
73
     * @throws RuntimeException If the target is not callable
74
     *
75
     * @return callable
76
     */
77
    private static function getCallable($target, array $construct_args)
78
    {
79
        if (empty($target)) {
80
            throw new RuntimeException('No callable provided');
81
        }
82
83
        if (is_string($target)) {
84
            //is a class "classname::method"
85
            if (strpos($target, '::') === false) {
86
                $class = $target;
87
                $method = '__invoke';
88
            } else {
89
                list($class, $method) = explode('::', $target, 2);
90
            }
91
92
            if (!class_exists($class)) {
93
                throw new RuntimeException("The class {$class} does not exists");
94
            }
95
96
            $fn = new \ReflectionMethod($class, $method);
97
98
            if (!$fn->isStatic()) {
99
                $class = new \ReflectionClass($class);
100
                $instance = $class->hasMethod('__construct') ? $class->newInstanceArgs($construct_args) : $class->newInstance();
101
                $target = [$instance, $method];
102
            }
103
        }
104
105
        //if it's callable as is
106
        if (is_callable($target)) {
107
            return $target;
108
        }
109
110
        throw new RuntimeException('Invalid callable provided');
111
    }
112
}
113