• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
You are now the owner of this repo.

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

93.42
/src/DI/Definitions/LocatorDefinition.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\Definitions;
11

12
use Nette;
13

14

15
/**
16
 * Multi accessor/factory definition.
17
 */
18
final class LocatorDefinition extends Definition
19
{
20
        /** @var Reference[] */
21
        private array $references = [];
22
        private ?string $tagged = null;
23

24

25
        public function setImplement(string $interface): static
1✔
26
        {
27
                if (!interface_exists($interface)) {
1✔
28
                        throw new Nette\InvalidArgumentException(sprintf("[%s]\nInterface '%s' not found.", $this->getDescriptor(), $interface));
1✔
29
                }
30

31
                $methods = (new \ReflectionClass($interface))->getMethods();
1✔
32
                if (!$methods) {
1✔
33
                        throw new Nette\InvalidArgumentException(sprintf("[%s]\nInterface %s must have at least one method.", $this->getDescriptor(), $interface));
1✔
34
                }
35

36
                foreach ($methods as $method) {
1✔
37
                        if ($method->isStatic() || !(
1✔
38
                                (preg_match('#^(get|create)$#', $method->name) && $method->getNumberOfParameters() === 1)
1✔
39
                                || (preg_match('#^(get|create)[A-Z]#', $method->name) && $method->getNumberOfParameters() === 0)
1✔
40
                        )) {
41
                                throw new Nette\InvalidArgumentException(sprintf(
1✔
42
                                        "[%s]\nMethod %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.",
1✔
43
                                        $this->getDescriptor(),
1✔
44
                                        $interface,
45
                                        $method->name,
1✔
46
                                ));
47
                        }
48

49
                        if ($method->getNumberOfParameters() === 0) {
1✔
50
                                Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", $this->getDescriptor(), true);
1✔
51
                        }
52
                }
53

54
                return parent::setType($interface);
1✔
55
        }
56

57

58
        public function getImplement(): ?string
59
        {
60
                return $this->getType();
1✔
61
        }
62

63

64
        public function setReferences(array $references): static
1✔
65
        {
66
                $this->references = [];
1✔
67
                foreach ($references as $name => $ref) {
1✔
68
                        $this->references[$name] = str_starts_with($ref, '@')
1✔
69
                                ? new Reference(substr($ref, 1))
1✔
70
                                : Reference::fromType($ref);
1✔
71
                }
72

73
                return $this;
1✔
74
        }
75

76

77
        /** @return Reference[] */
78
        public function getReferences(): array
79
        {
80
                return $this->references;
1✔
81
        }
82

83

84
        public function setTagged(?string $tagged): static
1✔
85
        {
86
                $this->tagged = $tagged;
1✔
87
                return $this;
1✔
88
        }
89

90

91
        public function getTagged(): ?string
92
        {
93
                return $this->tagged;
1✔
94
        }
95

96

97
        public function resolveType(Nette\DI\Resolver $resolver): void
1✔
98
        {
99
        }
1✔
100

101

102
        public function complete(Nette\DI\Resolver $resolver): void
1✔
103
        {
104
                if ($this->tagged !== null) {
1✔
105
                        $this->references = [];
1✔
106
                        foreach ($resolver->getContainerBuilder()->findByTag($this->tagged) as $name => $tag) {
1✔
107
                                if (isset($this->references[$tag])) {
1✔
108
                                        trigger_error(sprintf(
×
109
                                                "[%s]\nDuplicated tag '%s' with value '%s'.",
×
110
                                                $this->getDescriptor(),
×
111
                                                $this->tagged,
×
112
                                                $tag,
113
                                        ), E_USER_NOTICE);
×
114
                                }
115

116
                                $this->references[$tag] = new Reference($name);
1✔
117
                        }
118
                }
119

120
                foreach ($this->references as $name => $ref) {
1✔
121
                        $this->references[$name] = $resolver->normalizeReference($ref);
1✔
122
                }
123
        }
1✔
124

125

126
        public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
1✔
127
        {
128
                $class = (new Nette\PhpGenerator\ClassType)
1✔
129
                        ->addImplement($this->getType());
1✔
130

131
                $class->addProperty('container')
1✔
132
                        ->setPrivate();
1✔
133

134
                $class->addMethod('__construct')
1✔
135
                        ->addBody('$this->container = $container;')
1✔
136
                        ->addParameter('container')
1✔
137
                        ->setType($generator->getClassName());
1✔
138

139
                foreach ((new \ReflectionClass($this->getType()))->getMethods() as $rm) {
1✔
140
                        preg_match('#^(get|create)(.*)#', $rm->name, $m);
1✔
141
                        $name = lcfirst($m[2]);
1✔
142
                        $nullable = $rm->getReturnType()->allowsNull();
1✔
143

144
                        $methodInner = $class->addMethod($rm->name)
1✔
145
                                ->setReturnType((string) Nette\Utils\Type::fromReflection($rm));
1✔
146

147
                        if (!$name) {
1✔
148
                                $class->addProperty('mapping', array_map(fn($item) => $item->getValue(), $this->references))
1✔
149
                                        ->setPrivate();
1✔
150

151
                                $methodInner->setBody('if (!isset($this->mapping[$name])) {
1✔
152
        ' . ($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service \'$name\' is not defined.");') . '
1✔
153
}
154
return $this->container->' . $m[1] . 'Service($this->mapping[$name]);')
1✔
155
                                        ->addParameter('name');
1✔
156

157
                        } elseif (isset($this->references[$name])) {
1✔
158
                                $ref = $this->references[$name]->getValue();
1✔
159
                                if ($m[1] === 'get') {
1✔
160
                                        $methodInner->setBody('return $this->container->getService(?);', [$ref]);
1✔
161
                                } else {
162
                                        $methodInner->setBody('return $this->container->?();', [Nette\DI\Container::getMethodName($ref)]);
1✔
163
                                }
164
                        } else {
165
                                $methodInner->setBody($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service is not defined.");');
1✔
166
                        }
167
                }
168

169
                $method->setBody('return new class ($this) ' . $class . ';');
1✔
170
        }
1✔
171
}
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