Completed
Push — master ( 4abd02...ac9184 )
by Hong
57s
created

ContainerTrait::getRawId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
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\ConfigInterface;
15
use Psr\Container\ContainerInterface;
16
use Phoole\Base\Reference\ReferenceTrait;
17
use Phoole\Di\Exception\RuntimeException;
18
use Phoole\Di\Exception\NotFoundException;
19
20
/**
21
 * ContainerTrait
22
 *
23
 * @package Phoole\Di
24
 */
25
trait ContainerTrait
26
{
27
    use FactoryTrait;
28
    use ReferenceTrait;
29
    
30
    /**
31
     * for configuration lookup
32
     *
33
     * @var ConfigInterface
34
     */
35
    protected $config;
36
37
    /**
38
     * delegator for object lookup
39
     *
40
     * @var ContainerInterface
41
     */
42
    protected $delegator;
43
44
    /**
45
     * object pool
46
     *
47
     * @var array
48
     */
49
    protected $objects;
50
51
    /**
52
     * service prefix
53
     *
54
     * @var string
55
     */
56
    protected $prefix = 'di.service.';
57
58
    /**
59
     * common prefix
60
     *
61
     * @var string
62
     */
63
    protected $common = 'di.common';
64
65
    /**
66
     * init the container
67
     *
68
     * @param  ConfigInterface $config
69
     * @param  ContainerInterface $delegator
70
     * @return void
71
     */
72
    protected function initContainer(
73
        ConfigInterface $config,
74
        ContainerInterface $delegator = null
75
    ): void {
76
        $this->config = $config;
77
        $this->delegator = $delegator ?? $this;
0 ignored issues
show
Documentation Bug introduced by
It seems like $delegator ?? $this can also be of type this<Phoole\Di\Util\ContainerTrait>. However, the property $delegator is declared as type object<Psr\Container\ContainerInterface>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
78
79
        $this->setReferencePattern('${#', '}');
80
        $this->reloadAll();
81
    }
82
83
    /**
84
     * Reload all service definitions
85
     *
86
     * @return void
87
     */
88
    protected function reloadAll(): void
89
    {
90
        $this->objects = [];
91
92
        // some predefined objects
93
        $this->objects['config'] = $this->config;
94
        $this->objects['container'] = $this->delegator;
95
96
        // do the job
97
        $settings = &($this->config->getTree())->get('');
98
        $this->deReference($settings);
99
    }
100
101
    /**
102
     * Get the instance
103
     *
104
     * @param  string $id
105
     * @return object
106
     */
107
    protected function getInstance(string $id): object
108
    {
109
        // get new object
110
        if ('@' === substr($id, -1)) {
111
            return $this->newInstance($id);
112
        }
113
114
        // check the pool for shared object
115
        if (!isset($this->objects[$id])) {
116
            $this->objects[$id] = $this->newInstance($id);
117
        }
118
        return $this->objects[$id];
119
    }
120
121
    /**
122
     * creaet a new instance
123
     *
124
     * @param  string $id
125
     * @return object
126
     */
127
    protected function newInstance(string $id): object
128
    {
129
        $def = $this->config->get($this->getRawId($id));
130
        $obj = $this->fabricate($def);
131
        $this->executeCommon($obj);
132
        return $obj;
133
    }
134
135
    /**
136
     * Try find a service in the definition
137
     *
138
     * @param  string $id
139
     * @return bool
140
     */
141
    protected function hasDefinition(string $id): bool
142
    {
143
        return $this->config->has($this->getRawId($id));
144
    }
145
146
    /**
147
     * get the raw id as defined in $config
148
     *
149
     * @param  string $id
150
     * @return string
151
     */
152
    protected function getRawId(string $id): string
153
    {
154
        return $this->prefix . explode('@', $id, 2)[0];
155
    }
156
157
    /**
158
     * {@inheritDoc}
159
     */
160
    protected function getReference(string $name)
161
    {
162
        return $this->delegator->get($name);
163
    }
164
165
    /**
166
     * execute common methods for newed objects
167
     *
168
     * @param  object $object
169
     * @return void
170
     */
171
    protected function executeCommon(object $object): void
172
    {
173
        if ($this->config->has($this->common)) {
174
            $args = [ $object ];
175
            foreach ($this->config->get($this->common) as $pair) {
176
                $tester = $pair[0]; // test function
177
                $runner = $pair[1]; // callable with $object as arguments
178
                if ($tester($object, $this)) {
179
                    $this->executeCallable($runner, $args);
180
                }
181
            }
182
        }
183
    }
184
}
185