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

nette / di / 4405606637

pending completion
4405606637

push

github

David Grudl
more self explanatory message for factory and service mismatch (closes #199) (#284)

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

2118 of 2238 relevant lines covered (94.64%)

0.95 hits per line

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

99.12
/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
        private Nette\DI\ContainerBuilder $builder;
29

30

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

36

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

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

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

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

60
                return $def;
1✔
61
        }
62

63

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

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

73

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

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

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

95
                        return $res;
1✔
96

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

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

110
                        return $def;
1✔
111

112
                } else {
113
                        throw new Nette\DI\InvalidConfigurationException('Unexpected format of service definition');
×
114
                }
115
        }
116

117

118
        public function completeDefault(Context $context)
119
        {
120
        }
121

122

123
        private function sniffType($key, array $def): string
1✔
124
        {
125
                if (is_string($key)) {
1✔
126
                        $name = preg_match('#^@[\w\\\\]+$#D', $key)
1✔
127
                                ? $this->builder->getByType(substr($key, 1), false)
1✔
128
                                : $key;
1✔
129

130
                        if ($name && $this->builder->hasDefinition($name)) {
1✔
131
                                return get_class($this->builder->getDefinition($name));
1✔
132
                        }
133
                }
134

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

138
                } elseif (isset($def['implement'])) {
1✔
139
                        return method_exists($def['implement'], 'create')
1✔
140
                                ? Definitions\FactoryDefinition::class
1✔
141
                                : Definitions\AccessorDefinition::class;
1✔
142

143
                } elseif (isset($def['imported'])) {
1✔
144
                        return Definitions\ImportedDefinition::class;
1✔
145

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

149
                } else {
150
                        return Definitions\ServiceDefinition::class;
1✔
151
                }
152
        }
153

154

155
        private function expandParameters(array $config): array
1✔
156
        {
157
                return Nette\DI\Helpers::expand($config, $this->builder->parameters);
1✔
158
        }
159

160

161
        private static function getSchema(string $type): Schema
1✔
162
        {
163
                static $cache;
1✔
164
                $cache = $cache ?: [
1✔
165
                        Definitions\ServiceDefinition::class => self::getServiceSchema(),
1✔
166
                        Definitions\AccessorDefinition::class => self::getAccessorSchema(),
1✔
167
                        Definitions\FactoryDefinition::class => self::getFactorySchema(),
1✔
168
                        Definitions\LocatorDefinition::class => self::getLocatorSchema(),
1✔
169
                        Definitions\ImportedDefinition::class => self::getImportedSchema(),
1✔
170
                ];
171
                return $cache[$type];
1✔
172
        }
173

174

175
        private static function getServiceSchema(): Schema
176
        {
177
                return Expect::structure([
1✔
178
                        'type' => Expect::type('string'),
1✔
179
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
180
                        'arguments' => Expect::array(),
1✔
181
                        'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
1✔
182
                        'inject' => Expect::bool(),
1✔
183
                        'autowired' => Expect::type('bool|string|array'),
1✔
184
                        'tags' => Expect::array(),
1✔
185
                        'reset' => Expect::array(),
1✔
186
                        'alteration' => Expect::bool(),
1✔
187
                ]);
188
        }
189

190

191
        private static function getAccessorSchema(): Schema
192
        {
193
                return Expect::structure([
1✔
194
                        'type' => Expect::string(),
1✔
195
                        'implement' => Expect::string(),
1✔
196
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
197
                        'autowired' => Expect::type('bool|string|array'),
1✔
198
                        'tags' => Expect::array(),
1✔
199
                ]);
200
        }
201

202

203
        private static function getFactorySchema(): Schema
204
        {
205
                return Expect::structure([
1✔
206
                        'type' => Expect::string(),
1✔
207
                        'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
1✔
208
                        'implement' => Expect::string(),
1✔
209
                        'arguments' => Expect::array(),
1✔
210
                        'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
1✔
211
                        'references' => Expect::array(),
1✔
212
                        'tagged' => Expect::string(),
1✔
213
                        'inject' => Expect::bool(),
1✔
214
                        'autowired' => Expect::type('bool|string|array'),
1✔
215
                        'tags' => Expect::array(),
1✔
216
                        'reset' => Expect::array(),
1✔
217
                ]);
218
        }
219

220

221
        private static function getLocatorSchema(): Schema
222
        {
223
                return Expect::structure([
1✔
224
                        'implement' => Expect::string(),
1✔
225
                        'references' => Expect::array(),
1✔
226
                        'tagged' => Expect::string(),
1✔
227
                        'autowired' => Expect::type('bool|string|array'),
1✔
228
                        'tags' => Expect::array(),
1✔
229
                ]);
230
        }
231

232

233
        private static function getImportedSchema(): Schema
234
        {
235
                return Expect::structure([
1✔
236
                        'type' => Expect::string(),
1✔
237
                        'imported' => Expect::bool(),
1✔
238
                        'autowired' => Expect::type('bool|string|array'),
1✔
239
                        'tags' => Expect::array(),
1✔
240
                ]);
241
        }
242
}
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