Completed
Push — master ( c89067...3b0f09 )
by Hong
04:25
created

ContainerTrait::matchClass()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Di
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Di\Util;
13
14
use Phoole\Config\ConfigAwareTrait;
15
use Phoole\Di\Exception\LogicException;
16
use Phoole\Di\Exception\UnresolvedClassException;
17
18
/**
19
 * ContainerTrait
20
 *
21
 * @package Phoole\Di
22
 */
23
trait ContainerTrait
24
{
25
    use ResolveTrait;
26
    use FactoryTrait;
27
    use ConfigAwareTrait;
28
29
    /**
30
     * service objects stored by its service id
31
     *
32
     * @var object[]
33
     */
34
    protected $objects = [];
35
36
    /**
37
     * DI definition prefix in $config
38
     *
39
     * @var string
40
     */
41
    protected $prefix = 'di.';
42
43
    /**
44
     * Get the instance by id, create it if not yet
45
     *
46
     * @param  string $id
47
     * @return object
48
     * @throws UnresolvedClassException
49
     * @throws LogicException
50
     */
51
    protected function getInstance(string $id): object
52
    {
53
        // found in cache
54
        if (isset($this->objects[$id])) {
55
            return $this->objects[$id];
56
        }
57
58
        // initiate object
59
        $object = $this->newInstance($this->getServiceDefinition($id));
60
61
        // if '@' at the end, return without store in cache
62
        if ('@' === substr($id, -1)) {
63
            return $object;
64
        }
65
66
        // store in cache
67
        $this->objects[$id] = $object;
68
69
        // store in classmap
70
        if (FALSE === strpos($id, '@')) {
71
            $this->storeClass($object);
72
        }
73
74
        return $object;
75
    }
76
77
    /**
78
     * create a new instance by its definition
79
     *
80
     * @param  array $definition
81
     * @return object
82
     * @throws UnresolvedClassException
83
     * @throws LogicException
84
     */
85
    protected function newInstance(array $definition): object
86
    {
87
        $this->executeMethods($definition, 'before');
88
        $obj = $this->fabricate($definition);
89
        $this->executeMethods($obj, 'after');
90
91
        return $obj;
92
    }
93
94
    /**
95
     * get the raw service id with the scope '@XXX' cut-off
96
     *
97
     * @param  string $id
98
     * @return string
99
     */
100
    protected function getRawId(string $id): string
101
    {
102
        $prefix = $this->prefix . 'service.';
103
        return $prefix . explode('@', $id, 2)[0];
104
    }
105
106
    /**
107
     * execute 'di.before' or 'di.after' methods for newly created object
108
     *
109
     * @param  object|array $object  newly created object or object definition
110
     * @param  string       $stage   'before' | 'after'
111
     * @return void
112
     * @throws LogicException
113
     */
114
    protected function executeMethods($object, string $stage): void
115
    {
116
        $node = $this->prefix . $stage;
117
        if ($this->getConfig()->has($node)) {
118
            foreach ($this->getConfig()->get($node) as $line) {
119
                list($runner, $arguments) = $this->fixMethod((array) $line, $object);
0 ignored issues
show
Bug introduced by
It seems like $object can also be of type array; however, Phoole\Di\Util\FactoryTrait::fixMethod() does only seem to accept object|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
120
                $this->executeCallable($runner, $arguments);
121
            }
122
        }
123
    }
124
125
    /**
126
     * Find a service in the definitions
127
     *
128
     * @param  string $id
129
     * @return bool
130
     */
131
    protected function hasDefinition(string $id): bool
132
    {
133
        return $this->getConfig()->has($this->getRawId($id));
134
    }
135
136
    /**
137
     * @param  string $id
138
     * @return array
139
     */
140
    protected function getServiceDefinition(string $id): array
141
    {
142
        $def = $this->getConfig()->get($this->getRawId($id));
143
        return $this->fixDefinition($def);
0 ignored issues
show
Documentation introduced by
$def is of type *, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
144
    }
145
}