Completed
Push — master ( 206c33...9e77c2 )
by Oscar
05:44
created

CallableTrait   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 47
c 2
b 1
f 0
lcom 1
cbo 3
dl 0
loc 82
rs 8.439

2 Methods

Rating   Name   Duplication   Size   Complexity  
B executeCallable() 0 30 6
B getCallable() 0 27 6

How to fix   Complexity   

Complex Class

Complex classes like CallableTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CallableTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Psr7Middlewares\Utils;
4
5
use RuntimeException;
6
use Psr\Http\Message\RequestInterface;
7
use Psr\Http\Message\ResponseInterface;
8
9
/**
10
 * Utilities used by middlewares with callables.
11
 */
12
trait CallableTrait
13
{
14
    use ArgumentsTrait;
15
16
    /**
17
     * Execute the callable.
18
     *
19
     * @param mixed             $target
20
     * @param RequestInterface  $request
21
     * @param ResponseInterface $response
22
     *
23
     * @return ResponseInterface
24
     */
25
    protected function executeCallable($target, RequestInterface $request, ResponseInterface $response)
26
    {
27
        try {
28
            ob_start();
29
30
            $arguments = array_merge([$request, $response], $this->arguments);
31
            $target = static::getCallable($target, $arguments);
32
            $return = call_user_func_array($target, $arguments);
33
34
            if ($return instanceof ResponseInterface) {
35
                $response = $return;
36
                $return = '';
37
            }
38
39
            $return = ob_get_contents().$return;
40
            $body = $response->getBody();
41
42
            if ($return !== '' && $body->isWritable()) {
43
                $body->write($return);
44
            }
45
46
            return $response;
47
        } catch (\Exception $exception) {
48
            throw $exception;
49
        } finally {
50
            if (ob_get_level() > 0) {
51
                ob_end_clean();
52
            }
53
        }
54
    }
55
56
    /**
57
     * Resolves the target of the route and returns a callable.
58
     *
59
     * @param mixed $target
60
     * @param array $construct_args
61
     *
62
     * @throws RuntimeException If the target is not callable
63
     *
64
     * @return callable
65
     */
66
    protected static function getCallable($target, array $construct_args)
67
    {
68
        //if it's callable as is
69
        if (is_callable($target)) {
70
            return $target;
71
        }
72
73
        if (is_string($target)) {
74
            //is a class "classname::method"
75
            if (strpos($target, '::') === false) {
76
                $class = $target;
77
                $method = '__invoke';
78
            } else {
79
                list($class, $method) = explode('::', $target, 2);
80
            }
81
82
            if (!class_exists($class)) {
83
                throw new RuntimeException("The class {$class} does not exists");
84
            }
85
86
            $class = new \ReflectionClass($class);
87
            $instance = $class->hasMethod('__construct') ? $class->newInstanceArgs($construct_args) : $class->newInstance();
88
            $target = [$instance, $method];
0 ignored issues
show
Unused Code introduced by
$target 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...
89
        }
90
91
        throw new RuntimeException('The route target is not callable');
92
    }
93
}
94