• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nette / di / 6350956765

29 Sep 2023 11:27AM UTC coverage: 93.789% (-0.4%) from 94.168%
6350956765

push

github

dg
Option 'class' is allowed again

Partially reverts commit 046f89cc3.

1 of 1 new or added line in 1 file covered. (100.0%)

2250 of 2399 relevant lines covered (93.79%)

0.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.23
/src/DI/Extensions/DefinitionSchema.php
1
<?php
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Nette\DI\Extensions;
11

12
use Nette;
13
use Nette\DI\Config\Helpers;
14
use Nette\DI\Definitions;
15
use Nette\DI\Definitions\Statement;
16
use Nette\Schema\Context;
17
use Nette\Schema\Expect;
18
use Nette\Schema\Schema;
19

20

21
/**
22
 * Service configuration schema.
23
 */
24
class DefinitionSchema implements Schema
25
{
26
        use Nette\SmartObject;
27

28
        /** @var Nette\DI\ContainerBuilder */
29
        private $builder;
30

31

32
        public function __construct(Nette\DI\ContainerBuilder $builder)
1✔
33
        {
34
                $this->builder = $builder;
1✔
35
        }
1✔
36

37

38
        public function complete($def, Context $context)
1✔
39
        {
40
                if ($def === [false]) {
1✔
41
                        return (object) $def;
1✔
42
                }
43

44
                if (Helpers::takeParent($def)) {
1✔
45
                        $def['reset']['all'] = true;
1✔
46
                }
47

48
                foreach (['arguments', 'setup', 'tags'] as $k) {
1✔
49
                        if (isset($def[$k]) && Helpers::takeParent($def[$k])) {
1✔
50
                                $def['reset'][$k] = true;
1✔
51
                        }
52
                }
53

54
                $def = $this->expandParameters($def);
1✔
55
                $type = $this->sniffType(end($context->path), $def);
1✔
56
                $def = $this->getSchema($type)->complete($def, $context);
1✔
57
                if ($def) {
1✔
58
                        $def->defType = $type;
1✔
59
                }
60

61
                return $def;
1✔
62
        }
63

64

65
        public function merge($def, $base)
66
        {
67
                if (!empty($def['alteration'])) {
1✔
68
                        unset($def['alteration']);
1✔
69
                }
70

71
                return Nette\Schema\Helpers::merge($def, $base);
1✔
72
        }
73

74

75
        /**
76
         * Normalizes configuration of service definitions.
77
         */
78
        public function normalize($def, Context $context)
1✔
79
        {
80
                if ($def === null || $def === false) {
1✔
81
                        return (array) $def;
1✔
82

83
                } elseif (is_string($def) && interface_exists($def)) {
1✔
84
                        return ['implement' => $def];
1✔
85

86
                } elseif ($def instanceof Statement && is_string($def->getEntity()) && interface_exists($def->getEntity())) {
1✔
87
                        $res = ['implement' => $def->getEntity()];
1✔
88
                        if (array_keys($def->arguments) === ['tagged']) {
1✔
89
                                $res += $def->arguments;
1✔
90
                        } elseif (array_keys($def->arguments) === [0]) {
1✔
91
                                $res['create'] = $def->arguments[0];
1✔
92
                        } elseif ($def->arguments) {
1✔
93
                                $res['references'] = $def->arguments;
1✔
94
                        }
95

96
                        return $res;
1✔
97

98
                } elseif (!is_array($def) || isset($def[0], $def[1])) {
1✔
99
                        return ['create' => $def];
1✔
100

101
                } elseif (is_array($def)) {
1✔
102
                        // back compatibility
103
                        if (isset($def['factory']) && !isset($def['create'])) {
1✔
104
                                $def['create'] = $def['factory'];
1✔
105
                                unset($def['factory']);
1✔
106
                        }
107

108
                        if (
109
                                isset($def['class'])
1✔
110
                                && !isset($def['type'])
1✔
111
                                && !isset($def['dynamic'])
1✔
112
                                && !isset($def['imported'])
1✔
113
                        ) {
114
                                $def[isset($def['create']) ? 'type' : 'create'] = $def['class'];
1✔
115
                                unset($def['class']);
1✔
116
                        }
117

118
                        foreach (['class' => 'type', 'dynamic' => 'imported'] as $alias => $original) {
1✔
119
                                if (array_key_exists($alias, $def)) {
1✔
120
                                        if (array_key_exists($original, $def)) {
1✔
121
                                                throw new Nette\DI\InvalidConfigurationException(sprintf(
1✔
122
                                                        "Options '%s' and '%s' are aliases, use only '%s'.",
1✔
123
                                                        $alias,
124
                                                        $original,
125
                                                        $original
126
                                                ));
127
                                        }
128

129
                                        trigger_error(sprintf("Service '%s': option '$alias' should be changed to '$original'.", end($context->path)), E_USER_DEPRECATED);
1✔
130
                                        $def[$original] = $def[$alias];
1✔
131
                                        unset($def[$alias]);
1✔
132
                                }
133
                        }
134

135
                        return $def;
1✔
136

137
                } else {
138
                        throw new Nette\DI\InvalidConfigurationException('Unexpected format of service definition');
×
139
                }
140
        }
141

142

143
        public function completeDefault(Context $context)
144
        {
145
        }
146

147

148
        private function sniffType($key, array $def): string
1✔
149
        {
150
                if (is_string($key)) {
1✔
151
                        $name = preg_match('#^@[\w\\\\]+$#D', $key)
1✔
152
                                ? $this->builder->getByType(substr($key, 1), false)
1✔
153
                                : $key;
1✔
154

155
                        if ($name && $this->builder->hasDefinition($name)) {
1✔
156
                                return get_class($this->builder->getDefinition($name));
1✔
157
                        }
158
                }
159

160
                if (isset($def['implement'], $def['references']) || isset($def['implement'], $def['tagged'])) {
1✔
161
                        return Definitions\LocatorDefinition::class;
1✔
162

163
                } elseif (isset($def['implement'])) {
1✔
164
                        return method_exists($def['implement'], 'create')
1✔
165
                                ? Definitions\FactoryDefinition::class
1✔
166
                                : Definitions\AccessorDefinition::class;
1✔
167

168
                } elseif (isset($def['imported'])) {
1✔
169
                        return Definitions\ImportedDefinition::class;
1✔
170

171
                } elseif (!$def) {
1✔
172
                        throw new Nette\DI\InvalidConfigurationException("Service '$key': Empty definition.");
1✔
173

174
                } else {
175
                        return Definitions\ServiceDefinition::class;
1✔
176
                }
177
        }
178

179

180
        private function expandParameters(array $config): array
1✔
181
        {
182
                $params = $this->builder->parameters;
1✔
183
                if (isset($config['parameters'])) {
1✔
184
                        foreach ((array) $config['parameters'] as $k => $v) {
1✔
185
                                $v = explode(' ', is_int($k) ? $v : $k);
1✔
186
                                $params[end($v)] = $this->builder::literal('$' . end($v));
1✔
187
                        }
188
                }
189

190
                return Nette\DI\Helpers::expand($config, $params);
1✔
191
        }
192

193

194
        private static function getSchema(string $type): Schema
1✔
195
        {
196
                static $cache;
1✔
197
                $cache = $cache ?: [
1✔
198
                        Definitions\ServiceDefinition::class => self::getServiceSchema(),
1✔
199
                        Definitions\AccessorDefinition::class => self::getAccessorSchema(),
1✔
200
                        Definitions\FactoryDefinition::class => self::getFactorySchema(),
1✔
201
                        Definitions\LocatorDefinition::class => self::getLocatorSchema(),
1✔
202
                        Definitions\ImportedDefinition::class => self::getImportedSchema(),
1✔
203
                ];
204
                return $cache[$type];
1✔
205
        }
206

207

208
        private static function getServiceSchema(): Schema
209
        {
210
                return Expect::structure([
1✔
211
                        'type' => Expect::type('string'),
1✔
212
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
213
                        'arguments' => Expect::array(),
1✔
214
                        'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
1✔
215
                        'inject' => Expect::bool(),
1✔
216
                        'autowired' => Expect::type('bool|string|array'),
1✔
217
                        'tags' => Expect::array(),
1✔
218
                        'reset' => Expect::array(),
1✔
219
                        'alteration' => Expect::bool(),
1✔
220
                ]);
221
        }
222

223

224
        private static function getAccessorSchema(): Schema
225
        {
226
                return Expect::structure([
1✔
227
                        'type' => Expect::string(),
1✔
228
                        'implement' => Expect::string(),
1✔
229
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
230
                        'autowired' => Expect::type('bool|string|array'),
1✔
231
                        'tags' => Expect::array(),
1✔
232
                ]);
233
        }
234

235

236
        private static function getFactorySchema(): Schema
237
        {
238
                return Expect::structure([
1✔
239
                        'type' => Expect::string(),
1✔
240
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
241
                        'implement' => Expect::string(),
1✔
242
                        'arguments' => Expect::array(),
1✔
243
                        'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
1✔
244
                        'parameters' => Expect::array(),
1✔
245
                        'references' => Expect::array(),
1✔
246
                        'tagged' => Expect::string(),
1✔
247
                        'inject' => Expect::bool(),
1✔
248
                        'autowired' => Expect::type('bool|string|array'),
1✔
249
                        'tags' => Expect::array(),
1✔
250
                        'reset' => Expect::array(),
1✔
251
                ]);
252
        }
253

254

255
        private static function getLocatorSchema(): Schema
256
        {
257
                return Expect::structure([
1✔
258
                        'implement' => Expect::string(),
1✔
259
                        'references' => Expect::array(),
1✔
260
                        'tagged' => Expect::string(),
1✔
261
                        'autowired' => Expect::type('bool|string|array'),
1✔
262
                        'tags' => Expect::array(),
1✔
263
                ]);
264
        }
265

266

267
        private static function getImportedSchema(): Schema
268
        {
269
                return Expect::structure([
1✔
270
                        'type' => Expect::string(),
1✔
271
                        'imported' => Expect::bool(),
1✔
272
                        'autowired' => Expect::type('bool|string|array'),
1✔
273
                        'tags' => Expect::array(),
1✔
274
                ]);
275
        }
276
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc