Test Failed
Pull Request — master (#37)
by Divine Niiquaye
03:24
created

Definition::should()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 45
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 28
c 1
b 0
f 0
dl 0
loc 45
ccs 28
cts 28
cp 1
rs 8.4444
cc 8
nc 8
nop 2
crap 8
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of DivineNii opensource projects.
7
 *
8
 * PHP version 7.4 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2021 DivineNii (https://divinenii.com/)
12
 * @license   https://opensource.org/licenses/BSD-3-Clause License
13
 *
14
 * For the full copyright and license information, please view the LICENSE
15
 * file that was distributed with this source code.
16
 */
17
18
namespace Rade\DI;
19
20
use PhpParser\Node\Expr\{Assign, Variable};
21
use PhpParser\Node\Stmt\Return_;
22
use Rade\DI\Exceptions\ServiceCreationException;
23
use Rade\DI\Definitions\{DefinitionAwareInterface, DefinitionInterface, DepreciableDefinitionInterface, ShareableDefinitionInterface, TypedDefinitionInterface};
24
use Rade\DI\Definitions\Traits as Defined;
25
use Rade\DI\Exceptions\ContainerResolutionException;
26
27
/**
28
 * Represents definition of standard service.
29
 *
30
 * @author Divine Niiquaye Ibok <[email protected]>
31
 */
32
class Definition implements DefinitionInterface, TypedDefinitionInterface, ShareableDefinitionInterface, DefinitionAwareInterface, DepreciableDefinitionInterface
33
{
34
    use Defined\DeprecationTrait;
35
    use Defined\ParameterTrait;
36
    use Defined\BindingTrait;
0 ignored issues
show
Bug introduced by
The trait Rade\DI\Definitions\Traits\BindingTrait requires the property $var which is not provided by Rade\DI\Definition.
Loading history...
37
    use Defined\VisibilityTrait;
38
    use Defined\AutowireTrait;
39
    use Defined\DefinitionAwareTrait;
40
41
    /** @var mixed The service entity */
42
    private $entity;
43
44
    /**
45
     * Definition constructor.
46
     *
47
     * @param mixed                   $entity
48
     * @param array<int|string,mixed> $arguments
49
     */
50
    public function __construct($entity, array $arguments = [])
51
    {
52
        $this->replace($entity, true);
53
        $this->arguments = $arguments;
54
    }
55
56
    /**
57
     * {@inheritdoc}
58
     */
59
    public function getEntity()
60
    {
61
        return $this->entity;
62
    }
63
64
    /**
65
     * Replace existing entity to a new entity.
66
     *
67
     * @param mixed $entity
68
     *
69
     * @return $this
70
     */
71
    public function replace($entity, bool $if)
72
    {
73
        if ($entity instanceof DefinitionInterface) {
74
            throw new ServiceCreationException(\sprintf('A definition entity must not be an instance of "%s".', DefinitionInterface::class));
75
        }
76
77
        if ($if /* Replace if matches a rule */) {
78
            $this->entity = $entity;
79
80
            if ($this->autowired) {
81
                $this->autowire(Resolver::autowireService($entity, false, isset($this->innerId) ? $this->container : null));
82
            }
83
        }
84
85
        return $this;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function build(string $id, Resolver $resolver)
92
    {
93
        $builder = $resolver->getBuilder();
94
        $resolved = $this->entity;
95
96
        if ($this->abstract) {
97
            throw new ContainerResolutionException(\sprintf('Resolving an abstract definition %s is not allowed.', $id));
98
        }
99
100
        if (!empty($this->deprecation)) {
101
            $deprecation = $this->triggerDeprecation($id, $builder);
102 117
        }
103
104 117
        if (null === $builder) {
105 117
            if (\is_callable($resolved)) {
106 117
                $resolved = $resolver->resolveCallable($resolved, $this->arguments);
107
            } elseif (!\is_object($resolved)) {
108
                $resolved = $resolver->resolve($resolved, $this->arguments);
109
            }
110
111
            if ($this->hasBindings) {
112
                foreach ($this->parameters as $property => $propertyValue) {
113
                    $resolved->{$property} = $resolver->resolve($propertyValue);
114
                }
115
116 49
                foreach ($this->calls as [$method, $methodValue]) {
117
                    $resolver->resolve([$resolved, $method], $methodValue ?? []);
118 49
                }
119 38
120
                foreach ($this->extras as [$extend, $code]) {
121
                    $resolver->resolve($code, $extend ? [$resolved] : []);
122 22
                }
123
            }
124
125
            return $resolved;
126
        }
127
128 21
        $this->triggerReturnType($defNode = $builder->method($resolver->createMethod($id))->makeProtected());
129
130 21
        if (isset($deprecation)) {
131
            $defNode->addStmt($deprecation);
132
        }
133
134
        if ($this->isLazy()) {
135
            $createdDef = $builder->methodCall($builder->propertyFetch($builder->var('this'), 'resolver'), 'resolver', [$resolved, $resolver->resolveArguments($this->arguments)]);
136
        } else {
137
            $createdDef = $resolver->resolve($resolved, $this->arguments);
138
139 91
            if ($createdDef instanceof Injector\Injectable) {
140
                $createdDef = $createdDef->build($defNode, $builder->var('service'), $builder);
141 91
            }
142 91
        }
143
144 91
        if ($this->hasBinding()) {
145 49
            if (!$createdDef instanceof Assign) {
146
                $defNode->addStmt($createdDef = new Assign(new Variable('service'), $createdDef));
147 91
            }
148
149
            $this->resolveBinding($defNode, $createdDef, $resolver, $builder);
150
        }
151
152
        if ($this->isShared()) {
153
            $createdDef = $this->triggerSharedBuild($id, $createdDef instanceof Assign ? $createdDef->var : $createdDef, $builder);
154
        }
155
156 57
        return $defNode->addStmt(new Return_($createdDef));
157
    }
158
}
159