Issues (28)

src/Builder.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Biurad opensource projects.
7
 *
8
 * PHP version 7.2 and above required
9
 *
10
 * @author    Divine Niiquaye Ibok <[email protected]>
11
 * @copyright 2019 Biurad Group (https://biurad.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 Biurad\DependencyInjection;
19
20
use ArrayAccess;
21
use Biurad\DependencyInjection\Definitions\InterfaceDefinition;
22
use Biurad\DependencyInjection\Exceptions\ParameterNotFoundException;
23
use Nette\DI\ContainerBuilder as NetteContainerBuilder;
24
use Nette\DI\Definitions;
25
use Nette\DI\Definitions\Definition;
26
use Nette\InvalidArgumentException;
27
28
/**
29
 * Container builder.
30
 *
31
 * @author Divine Niiquaye Ibok <[email protected]>
32
 */
33
class Builder extends NetteContainerBuilder
34
{
35
    public function __construct()
36
    {
37
        parent::__construct();
38
39
        $this->removeDefinition(self::THIS_CONTAINER);
40
        $this->addImportedDefinition(self::THIS_CONTAINER)->setType(Container::class);
41
    }
42
43
    /**
44
     * Adds the service definitions.
45
     *
46
     * @param Definition[] $definitions An array of service definitions
47
     */
48
    public function addDefinitions(array $definitions): void
49
    {
50
        foreach ($definitions as $id => $definition) {
51
            $this->addDefinition($id, $definition);
52
        }
53
    }
54
55
    /**
56
     * Registers a service definition.
57
     *
58
     * This methods allows for simple registration of service definition
59
     * with a fluid interface.
60
     *
61
     * @param array<mixed>|Definition|Definitions\Reference|Definitions\Statement|string $class
62
     *
63
     * @return Definitions\ServiceDefinition A Definition instance
64
     */
65
    public function register(string $id, $class = null, ?Definition $definition = null): Definition
66
    {
67
        return $this->addDefinition($id, $definition)->setFactory($class);
0 ignored issues
show
Are you sure the usage of $this->addDefinition($id...on)->setFactory($class) targeting Nette\DI\Definitions\Definition::__call() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug Best Practice introduced by
The expression return $this->addDefinit...on)->setFactory($class) returns the type null which is incompatible with the type-hinted return Nette\DI\Definitions\Definition.
Loading history...
68
    }
69
70
    /**
71
     * Registers an autowired service definition.
72
     *
73
     * This method implements a shortcut for using addDefinition() with
74
     * an autowired definition.
75
     *
76
     * @return Definitions\ServiceDefinition The created definition
77
     */
78
    public function autowire(string $id, string $class = null)
79
    {
80
        return $this->register($id, $class)->setAutowired(true);
81
    }
82
83
    public function addInterfaceDefinition(string $name): InterfaceDefinition
84
    {
85
        return $this->addDefinition($name, new InterfaceDefinition());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->addDefinit...\InterfaceDefinition()) returns the type Nette\DI\Definitions\Definition which includes types incompatible with the type-hinted return Biurad\DependencyInjecti...ons\InterfaceDefinition.
Loading history...
86
    }
87
88
    /**
89
     * Computes a reasonably unique hash of a value.
90
     *
91
     * @param mixed $value A serializable value
92
     *
93
     * @return string
94
     */
95
    public static function hash($value)
96
    {
97
        $hash = \substr(\base64_encode(\hash('sha256', \serialize($value), true)), 0, 7);
98
99
        return \str_replace(['/', '+'], ['.', '_'], $hash);
100
    }
101
102
    /**
103
     * Adds the service aliases.
104
     */
105
    public function addAliases(array $aliases): void
106
    {
107
        foreach ($aliases as $alias => $id) {
108
            $this->addAlias($alias, $id);
109
        }
110
    }
111
112
    /**
113
     * Gets a parameter.
114
     *
115
     * @param string $name The parameter name
116
     *
117
     * @throws ParameterNotFoundException if the parameter is not defined
118
     *
119
     * @return mixed The parameter value
120
     */
121
    public function getParameter(string $name)
122
    {
123
        if (!\array_key_exists($name, $this->parameters)) {
124
            $alternatives = [];
125
126
            foreach ($this->parameters as $key => $parameterValue) {
127
                $lev = \levenshtein($name, $key);
128
129
                if ($lev <= \strlen($name) / 3 || false !== \strpos($key, $name)) {
130
                    $alternatives[] = $key;
131
                }
132
            }
133
134
            $nonNestedAlternative = null;
0 ignored issues
show
The assignment to $nonNestedAlternative is dead and can be removed.
Loading history...
135
136
            if (!\count($alternatives) && false !== \strpos($name, '.')) {
137
                $namePartsLength = \explode('.', $name);
138
                $key             = \array_shift($namePartsLength);
139
140
                while (\count($namePartsLength)) {
141
                    if ($this->hasParameter($key)) {
142
                        if (!\is_array($this->getParameter($key))) {
143
                            $nonNestedAlternative = $key;
144
145
                            throw new ParameterNotFoundException(
146
                                $name,
147
                                null,
148
                                $alternatives,
149
                                $nonNestedAlternative
150
                            );
151
                        }
152
153
                        return self::arrayGet($this->parameters, $name);
154
                    }
155
                }
156
            }
157
        }
158
159
        return $this->parameters[$name] ?? null;
160
    }
161
162
    /**
163
     * Checks if a parameter exists.
164
     *
165
     * @internal should not be used to check parameters existence
166
     *
167
     * @param string $name The parameter name
168
     *
169
     * @return bool The presence of parameter in container
170
     */
171
    public function hasParameter(string $name)
172
    {
173
        return \array_key_exists($name, $this->parameters);
174
    }
175
176
    /**
177
     * Adds parameters to the service container parameters.
178
     *
179
     * @param string $name  The parameter name
180
     * @param mixed  $value The parameter value
181
     */
182
    public function setParameter(string $name, $value): void
183
    {
184
        if (\strpos($name, '.') !== false) {
185
            $parameters = &$this->parameters;
186
            $keys       = \explode('.', $name);
187
188
            while (\count($keys) > 1) {
189
                $key = \array_shift($keys);
190
191
                if (!isset($parameters[$key]) || !\is_array($parameters[$key])) {
192
                    $parameters[$key] = [];
193
                }
194
195
                $parameters = &$parameters[$key];
196
            }
197
198
            $parameters[\array_shift($keys)] = $value;
199
        } else {
200
            $this->parameters[$name] = $value;
201
        }
202
    }
203
204
    /**
205
     * Removes a parameter.
206
     *
207
     * @param string $name The parameter name
208
     */
209
    public function removeParameter(string $name): void
210
    {
211
        if ($this->hasParameter($name)) {
212
            unset($this->parameters[$name]);
213
        } elseif (\strpos($name, '.') !== false) {
214
            $parts = \explode('.', $name);
215
            $array = &$this->parameters;
216
217
            while (\count($parts) > 1) {
218
                $part = \array_shift($parts);
219
220
                if (isset($array[$part]) && \is_array($array[$part])) {
221
                    $array = &$array[$part];
222
                }
223
            }
224
225
            unset($array[\array_shift($parts)]);
226
        }
227
    }
228
229
    /**
230
     * @internal
231
     *
232
     * Gets a dot-notated key from an array/object, with a default value if it does
233
     * not exist
234
     *
235
     * @param array|object $array   The search array
236
     * @param mixed        $key     The dot-notated key or array of keys
237
     * @param string       $default The default value
238
     *
239
     * @throws InvalidArgumentException
240
     *
241
     * @return mixed
242
     */
243
    public static function arrayGet($array, $key, $default = null)
244
    {
245
        if (!\is_array($array) && !$array instanceof ArrayAccess) {
246
            throw new InvalidArgumentException('First parameter must be an array or ArrayAccess object.');
247
        }
248
249
        if (null === $key) {
250
            return $array;
251
        }
252
253
        if (\is_array($key)) {
254
            $return = [];
255
256
            foreach ($key as $k) {
257
                $return[$k] = self::arrayGet($array, $k, $default);
258
            }
259
260
            return $return;
261
        }
262
263
        if (\is_object($key)) {
264
            $key = (string) $key;
265
        }
266
267
        if (isset($array[$key])) {
268
            return $array[$key];
269
        }
270
271
        foreach (\explode('.', $key) as $field) {
272
            if (\is_object($array) && isset($array->{$field})) {
273
                $array = $array->{$field};
274
            } elseif (\is_array($array) && isset($array[$field])) {
275
                $array = $array[$field];
276
            } else {
277
                return $default;
278
            }
279
        }
280
281
        return $array;
282
    }
283
}
284