Passed
Push — master ( 2c1367...72194f )
by Alexey
03:21
created

ObjectInflector   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

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

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 46
    public function __construct(ArgumentResolverContract $argumentResolver)
34
    {
35 46
        $this->argumentResolver = $argumentResolver;
36 46
    }
37
38
    /**
39
     * @inheritDoc
40
     */
41 4
    public function addInflection(string $id, string $method, array $arguments = [])
42
    {
43 4
        $this->inflections[$id][$method] = $arguments;
44 4
    }
45
46
    /**
47
     * @inheritDoc
48
     */
49 27
    public function applyInflections($object)
50
    {
51 27
        foreach ($this->inflections as $type => $methods) {
52 4
            if (!$object instanceof $type) {
53 3
                continue;
54
            }
55
56 4
            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 4
                if (!is_callable($inflection)) {
60
61
                    // Reflect and resolve method arguments.
62 4
                    $callback = $this->argumentResolver->resolveArguments(
63 4
                        $this->argumentResolver->reflectCallable([$type, $method])
64
                    );
65
66
                    // Replace method arguments with provided ones (if any).
67 4
                    $arguments = $callback($inflection);
68
69
                    // Wrap calling method with closure to avoid reflecting / resolving each time inflection applied.
70 3
                    $this->inflections[$type][$method] = $inflection = function () use ($method, $arguments) {
71 3
                        $this->$method(...$arguments);
72 3
                    };
73
                }
74
75
                // We have callable inflection ready, so we simply swap the context to provided object and call it.
76 3
                $inflection->call($object);
77
            }
78
        }
79
80 26
        return $object;
81
    }
82
83
}