Test Failed
Push — master ( 73c405...d57cd2 )
by Konstantins
03:14
created

ObjectInflector   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 15.79%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 1
dl 0
loc 71
ccs 3
cts 19
cp 0.1579
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A addInflection() 0 4 1
B applyInflections() 0 33 5
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Container;
4
5
use Venta\Contracts\Container\ArgumentResolver as ArgumentResolverContract;
6
use Venta\Contracts\Container\ObjectInflector as ObjectInflectorContract;
7
8
/**
9
 * Class ObjectInflector.
10
 *
11
 * @package Venta\Container
12
 */
13
final class ObjectInflector implements ObjectInflectorContract
14
{
15
16
    /**
17
     * @var ArgumentResolverContract
18
     */
19
    private $argumentResolver;
20
21
    /**
22
     * A list of methods with arguments which will be invoked on the subject object.
23
     *
24
     * @var string[][]
25
     */
26
    private $inflections = [];
27
28
    /**
29
     * ObjectInflector constructor.
30
     *
31
     * @param ArgumentResolverContract $argumentResolver
32
     */
33 2
    public function __construct(ArgumentResolverContract $argumentResolver)
34
    {
35 2
        $this->argumentResolver = $argumentResolver;
36 2
    }
37
38
    /**
39
     * @inheritDoc
40
     */
41
    public function addInflection(string $id, string $method, array $arguments = [])
42
    {
43
        $this->inflections[$id][$method] = $arguments;
44
    }
45
46
    /**
47
     * @inheritDoc
48
     */
49
    public function applyInflections($object)
50
    {
51
        foreach ($this->inflections as $type => $methods) {
52
            if (!$object instanceof $type) {
53
                continue;
54
            }
55
56
            foreach ($methods as $method => $inflection) {
57
                // $inflection may be array of arguments to pass to the method
58
                // OR prepared closure to call with the provided object context.
59
                if (!is_callable($inflection)) {
60
61
                    // Reflect and resolve method arguments.
62
                    $callback = $this->argumentResolver->resolveArguments(
63
                        $this->argumentResolver->reflectCallable([$type, $method])
64
                    );
65
66
                    // Replace method arguments with provided ones (if any).
67
                    $arguments = $callback($inflection);
68
69
                    // Wrap calling method with closure to avoid reflecting / resolving each time inflection applied.
70
                    $this->inflections[$type][$method] = $inflection = function () use ($method, $arguments) {
71
                        $this->$method(...$arguments);
72
                    };
73
                }
74
75
                // We have callable inflection ready, so we simply swap the context to provided object and call it.
76
                $inflection->call($object);
77
            }
78
        }
79
80
        return $object;
81
    }
82
83
}