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

nette / di / 5772360309

pending completion
5772360309

push

github

dg
Resolver: added new special functions constant() and getProperty()

17 of 17 new or added lines in 2 files covered. (100.0%)

2093 of 2215 relevant lines covered (94.49%)

0.94 hits per line

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

93.59
/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(
1✔
51
                                        Nette\Utils\Type::fromReflection($method),
1✔
52
                                        "return type of $interface::$method->name()",
1✔
53
                                        $this->getDescriptor(),
1✔
54
                                        allowNullable: true,
1✔
55
                                );
56
                        }
57
                }
58

59
                return parent::setType($interface);
1✔
60
        }
61

62

63
        public function getImplement(): ?string
64
        {
65
                return $this->getType();
1✔
66
        }
67

68

69
        public function setReferences(array $references): static
1✔
70
        {
71
                $this->references = [];
1✔
72
                foreach ($references as $name => $ref) {
1✔
73
                        $this->references[$name] = str_starts_with($ref, '@')
1✔
74
                                ? new Reference(substr($ref, 1))
1✔
75
                                : Reference::fromType($ref);
1✔
76
                }
77

78
                return $this;
1✔
79
        }
80

81

82
        /** @return Reference[] */
83
        public function getReferences(): array
84
        {
85
                return $this->references;
1✔
86
        }
87

88

89
        public function setTagged(?string $tagged): static
1✔
90
        {
91
                $this->tagged = $tagged;
1✔
92
                return $this;
1✔
93
        }
94

95

96
        public function getTagged(): ?string
97
        {
98
                return $this->tagged;
1✔
99
        }
100

101

102
        public function resolveType(Nette\DI\Resolver $resolver): void
1✔
103
        {
104
        }
1✔
105

106

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

121
                                $this->references[$tag] = new Reference($name);
1✔
122
                        }
123
                }
124

125
                foreach ($this->references as $name => $ref) {
1✔
126
                        $this->references[$name] = $resolver->normalizeReference($ref);
1✔
127
                }
128
        }
1✔
129

130

131
        public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
1✔
132
        {
133
                $class = (new Nette\PhpGenerator\ClassType)
1✔
134
                        ->addImplement($this->getType());
1✔
135

136
                $class->addMethod('__construct')
1✔
137
                        ->addPromotedParameter('container')
1✔
138
                                ->setPrivate()
1✔
139
                                ->setType($generator->getClassName());
1✔
140

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

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

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

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

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

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