FactoryDefinition::factoryInstance()   A
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 9
nc 5
nop 1
dl 0
loc 19
rs 9.2222
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Habemus\Definition\Build;
5
6
use Habemus\Definition\Definition;
7
use Habemus\Definition\Identifiable\IdentifiableTrait;
8
use Habemus\Definition\MethodCall\CallableMethod;
9
use Habemus\Definition\MethodCall\CallableMethodTrait;
10
use Habemus\Definition\Sharing\Shareable;
11
use Habemus\Definition\Sharing\ShareableTrait;
12
use Habemus\Definition\Tag\Taggable;
13
use Habemus\Definition\Tag\TaggableTrait;
14
use Habemus\Exception\DefinitionException;
15
use Psr\Container\ContainerInterface;
16
17
class FactoryDefinition implements Definition, Shareable, CallableMethod, Taggable
18
{
19
    use IdentifiableTrait;
20
    use ShareableTrait;
21
    use CallableMethodTrait;
22
    use TaggableTrait;
23
24
    /** @var string|object|ReferenceDefinition */
25
    protected $objectOrClass;
26
27
    /** @var string|object|null */
28
    protected $factory;
29
30
    /**
31
     * @var string
32
     */
33
    protected $methodName;
34
35
    /**
36
     * @var array
37
     */
38
    protected $methodParams;
39
40
    /**
41
     * @var bool
42
     */
43
    protected $staticCall;
44
45
    public function __construct(
46
        $objectOrClass,
47
        string $methodName = "__invoke",
48
        array $methodParams = [],
49
        bool $static = false
50
    ) {
51
        $this->objectOrClass = $objectOrClass;
52
        $this->methodName = $methodName;
53
        $this->methodParams = $methodParams;
54
        $this->factory = null;
55
        $this->staticCall = $static;
56
        $this->setShared(false);
57
    }
58
59
    public function methodParams(array $params): self
60
    {
61
        $this->methodParams = $params;
62
        return $this;
63
    }
64
65
    public function staticCall(bool $static): self
66
    {
67
        $this->staticCall = $static;
68
        return $this;
69
    }
70
71
    public function getObjectOrClass()
72
    {
73
        return $this->objectOrClass;
74
    }
75
76
    public function isStaticCall(): bool
77
    {
78
        return $this->staticCall;
79
    }
80
81
    public function getMethodName(): string
82
    {
83
        return $this->methodName;
84
    }
85
86
    public function getMethodParams(): array
87
    {
88
        return $this->methodParams;
89
    }
90
91
    public function getConcrete(ContainerInterface $container)
92
    {
93
        $this->factory = $this->factoryInstance($container);
94
95
        if (!method_exists($this->factory, $this->methodName)) {
96
            throw DefinitionException::invalidMethodCall($this, $this->factory, $this->methodName);
97
        }
98
99
        return call_user_func_array([$this->factory, $this->methodName], $this->resolveParams($container));
100
    }
101
102
    protected function factoryInstance(ContainerInterface $container)
103
    {
104
        if ($this->factory !== null) {
105
            return $this->factory;
106
        }
107
108
        if ($this->objectOrClass instanceof ReferenceDefinition) {
109
            return $this->factory = $container->get($this->objectOrClass->id());
110
        }
111
112
        if ($this->staticCall) {
113
            return $this->factory = $this->objectOrClass;
114
        }
115
116
        if (!is_object($this->objectOrClass) && is_string($this->objectOrClass)) {
117
            return $this->factory = $container->get($this->objectOrClass);
118
        }
119
120
        return $this->factory = $this->objectOrClass;
121
    }
122
123
    protected function resolveParams(ContainerInterface $container): array
124
    {
125
        return (new ArrayDefinition($this->methodParams))->getConcrete($container);
126
    }
127
}
128