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

nette / di / 6739042234

02 Nov 2023 10:31PM UTC coverage: 93.846% (+41.8%) from 52.037%
6739042234

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%)

2257 of 2405 relevant lines covered (93.85%)

0.94 hits per line

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

91.03
/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 $references = [];
22

23
        /** @var string|null */
24
        private $tagged;
25

26

27
        /** @return static */
28
        public function setImplement(string $interface)
1✔
29
        {
30
                if (!interface_exists($interface)) {
1✔
31
                        throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface '%s' not found.", $this->getName(), $interface));
1✔
32
                }
33

34
                $methods = (new \ReflectionClass($interface))->getMethods();
1✔
35
                if (!$methods) {
1✔
36
                        throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface %s must have at least one method.", $this->getName(), $interface));
1✔
37
                }
38

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

52
                        if ($method->getNumberOfParameters() === 0) {
1✔
53
                                try {
54
                                        Nette\DI\Helpers::ensureClassType(Nette\Utils\Type::fromReflection($method), "return type of $interface::$method->name()", true);
1✔
55
                                } catch (Nette\DI\ServiceCreationException $e) {
×
56
                                        trigger_error($e->getMessage(), E_USER_DEPRECATED);
×
57
                                }
58
                        }
59
                }
60

61
                return parent::setType($interface);
1✔
62
        }
63

64

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

70

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

81
                return $this;
1✔
82
        }
83

84

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

91

92
        /** @return static */
93
        public function setTagged(?string $tagged)
1✔
94
        {
95
                $this->tagged = $tagged;
1✔
96
                return $this;
1✔
97
        }
98

99

100
        public function getTagged(): ?string
101
        {
102
                return $this->tagged;
1✔
103
        }
104

105

106
        public function resolveType(Nette\DI\Resolver $resolver): void
1✔
107
        {
108
        }
1✔
109

110

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

125
                                $this->references[$tag] = new Reference($name);
1✔
126
                        }
127
                }
128

129
                foreach ($this->references as $name => $ref) {
1✔
130
                        $this->references[$name] = $resolver->normalizeReference($ref);
1✔
131
                }
132
        }
1✔
133

134

135
        public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
1✔
136
        {
137
                $class = (new Nette\PhpGenerator\ClassType)
1✔
138
                        ->addImplement($this->getType());
1✔
139

140
                $class->addProperty('container')
1✔
141
                        ->setPrivate();
1✔
142

143
                $class->addMethod('__construct')
1✔
144
                        ->addBody('$this->container = $container;')
1✔
145
                        ->addParameter('container')
1✔
146
                        ->setType($generator->getClassName());
1✔
147

148
                foreach ((new \ReflectionClass($this->getType()))->getMethods() as $rm) {
1✔
149
                        preg_match('#^(get|create)(.*)#', $rm->name, $m);
1✔
150
                        $name = lcfirst($m[2]);
1✔
151
                        $nullable = $rm->getReturnType()->allowsNull();
1✔
152

153
                        $methodInner = $class->addMethod($rm->name)
1✔
154
                                ->setReturnType((string) Nette\Utils\Type::fromReflection($rm));
1✔
155

156
                        if (!$name) {
1✔
157
                                $class->addProperty('mapping', array_map(function ($item) { return $item->getValue(); }, $this->references))
1✔
158
                                        ->setPrivate();
1✔
159

160
                                $methodInner->setBody('if (!isset($this->mapping[$name])) {
1✔
161
        ' . ($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service \'$name\' is not defined.");') . '
1✔
162
}
163
return $this->container->' . $m[1] . 'Service($this->mapping[$name]);')
1✔
164
                                        ->addParameter('name');
1✔
165

166
                        } elseif (isset($this->references[$name])) {
1✔
167
                                $ref = $this->references[$name]->getValue();
1✔
168
                                if ($m[1] === 'get') {
1✔
169
                                        $methodInner->setBody('return $this->container->getService(?);', [$ref]);
1✔
170
                                } else {
171
                                        $methodInner->setBody('return $this->container->?();', [Nette\DI\Container::getMethodName($ref)]);
1✔
172
                                }
173
                        } else {
174
                                $methodInner->setBody($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service is not defined.");');
1✔
175
                        }
176
                }
177

178
                $method->setBody('return new class ($this) ' . $class . ';');
1✔
179
        }
1✔
180
}
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