• 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

97.03
/src/DI/PhpGenerator.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;
11

12
use Nette;
13
use Nette\DI\Definitions\Reference;
14
use Nette\DI\Definitions\Statement;
15
use Nette\PhpGenerator as Php;
16
use Nette\Utils\Strings;
17

18

19
/**
20
 * Container PHP code generator.
21
 */
22
class PhpGenerator
23
{
24
        use Nette\SmartObject;
25

26
        /** @var ContainerBuilder */
27
        private $builder;
28

29
        /** @var string */
30
        private $className;
31

32

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

38

39
        /**
40
         * Generates PHP classes. First class is the container.
41
         */
42
        public function generate(string $className): Php\ClassType
1✔
43
        {
44
                $this->className = $className;
1✔
45
                $class = new Php\ClassType($this->className);
1✔
46
                $class->setExtends(Container::class);
1✔
47
                $class->addMethod('__construct')
1✔
48
                        ->addBody('parent::__construct($params);')
1✔
49
                        ->addParameter('params', [])
1✔
50
                                ->setType('array');
1✔
51

52
                foreach ($this->builder->exportMeta() as $key => $value) {
1✔
53
                        $class->addProperty($key)
1✔
54
                                ->setProtected()
1✔
55
                                ->setValue($value);
1✔
56
                }
57

58
                $definitions = $this->builder->getDefinitions();
1✔
59
                ksort($definitions);
1✔
60

61
                foreach ($definitions as $def) {
1✔
62
                        $class->addMember($this->generateMethod($def));
1✔
63
                }
64

65
                $class->getMethod(Container::getMethodName(ContainerBuilder::ThisContainer))
1✔
66
                        ->setReturnType($className)
1✔
67
                        ->setBody('return $this;');
1✔
68

69
                $class->addMethod('initialize')
1✔
70
                        ->setReturnType('void');
1✔
71

72
                return $class;
1✔
73
        }
74

75

76
        public function toString(Php\ClassType $class): string
1✔
77
        {
78
                return '/** @noinspection PhpParamsInspection,PhpMethodMayBeStaticInspection */
79

80
declare(strict_types=1);
81

82
' . $class->__toString();
1✔
83
        }
84

85

86
        public function addInitialization(Php\ClassType $class, CompilerExtension $extension): void
1✔
87
        {
88
                $closure = $extension->getInitialization();
1✔
89
                if ($closure->getBody()) {
1✔
90
                        $class->getMethod('initialize')
1✔
91
                                ->addBody('// ' . $extension->prefix(''))
1✔
92
                                ->addBody("($closure)();");
1✔
93
                }
94
        }
1✔
95

96

97
        public function generateMethod(Definitions\Definition $def): Php\Method
1✔
98
        {
99
                $name = $def->getName();
1✔
100
                try {
101
                        $method = new Php\Method(Container::getMethodName($name));
1✔
102
                        $method->setPublic();
1✔
103
                        $method->setReturnType($def->getType());
1✔
104
                        $def->generateMethod($method, $this);
1✔
105
                        return $method;
1✔
106

107
                } catch (\Throwable $e) {
×
108
                        throw new ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e);
×
109
                }
110
        }
111

112

113
        /**
114
         * Formats PHP code for class instantiating, function calling or property setting in PHP.
115
         */
116
        public function formatStatement(Statement $statement): string
1✔
117
        {
118
                $entity = $statement->getEntity();
1✔
119
                $arguments = $statement->arguments;
1✔
120

121
                switch (true) {
122
                        case is_string($entity) && Strings::contains($entity, '?'): // PHP literal
1✔
123
                                return $this->formatPhp($entity, $arguments);
1✔
124

125
                        case is_string($entity): // create class
1✔
126
                                return $arguments
1✔
127
                                        ? $this->formatPhp("new $entity(...?:)", [$arguments])
1✔
128
                                        : $this->formatPhp("new $entity", []);
1✔
129

130
                        case is_array($entity):
1✔
131
                                switch (true) {
132
                                        case $entity[1][0] === '$': // property getter, setter or appender
1✔
133
                                                $name = substr($entity[1], 1);
1✔
134
                                                if ($append = (substr($name, -2) === '[]')) {
1✔
135
                                                        $name = substr($name, 0, -2);
1✔
136
                                                }
137

138
                                                $prop = $entity[0] instanceof Reference
1✔
139
                                                        ? $this->formatPhp('?->?', [$entity[0], $name])
1✔
140
                                                        : $this->formatPhp('?::$?', [$entity[0], $name]);
1✔
141
                                                return $arguments
1✔
142
                                                        ? $this->formatPhp(($append ? '?[]' : '?') . ' = ?', [new Php\Literal($prop), $arguments[0]])
1✔
143
                                                        : $prop;
1✔
144

145
                                        case $entity[0] instanceof Statement:
1✔
146
                                                $inner = $this->formatPhp('?', [$entity[0]]);
1✔
147
                                                if (substr($inner, 0, 4) === 'new ') {
1✔
148
                                                        $inner = "($inner)";
1✔
149
                                                }
150

151
                                                return $this->formatPhp('?->?(...?:)', [new Php\Literal($inner), $entity[1], $arguments]);
1✔
152

153
                                        case $entity[0] instanceof Reference:
1✔
154
                                                return $this->formatPhp('?->?(...?:)', [$entity[0], $entity[1], $arguments]);
1✔
155

156
                                        case $entity[0] === '': // function call
1✔
157
                                                return $this->formatPhp('?(...?:)', [new Php\Literal($entity[1]), $arguments]);
1✔
158

159
                                        case is_string($entity[0]): // static method call
1✔
160
                                                return $this->formatPhp('?::?(...?:)', [new Php\Literal($entity[0]), $entity[1], $arguments]);
1✔
161
                                }
162
                }
163

164
                throw new Nette\InvalidStateException;
×
165
        }
166

167

168
        /**
169
         * Formats PHP statement.
170
         * @internal
171
         */
172
        public function formatPhp(string $statement, array $args): string
1✔
173
        {
174
                return (new Php\Dumper)->format($statement, ...$this->convertArguments($args));
1✔
175
        }
176

177

178
        public function convertArguments(array $args): array
1✔
179
        {
180
                array_walk_recursive($args, function (&$val): void {
1✔
181
                        if ($val instanceof Statement) {
1✔
182
                                $val = new Php\Literal($this->formatStatement($val));
1✔
183

184
                        } elseif ($val instanceof Reference) {
1✔
185
                                $name = $val->getValue();
1✔
186
                                if ($val->isSelf()) {
1✔
187
                                        $val = new Php\Literal('$service');
1✔
188
                                } elseif ($name === ContainerBuilder::ThisContainer) {
1✔
189
                                        $val = new Php\Literal('$this');
1✔
190
                                } else {
191
                                        $val = ContainerBuilder::literal('$this->getService(?)', [$name]);
1✔
192
                                }
193
                        }
194
                });
1✔
195
                return $args;
1✔
196
        }
197

198

199
        /**
200
         * Converts parameters from Definition to PhpGenerator.
201
         * @return Php\Parameter[]
202
         */
203
        public function convertParameters(array $parameters): array
1✔
204
        {
205
                $res = [];
1✔
206
                foreach ($parameters as $k => $v) {
1✔
207
                        $tmp = explode(' ', is_int($k) ? $v : $k);
1✔
208
                        $param = $res[] = new Php\Parameter(end($tmp));
1✔
209
                        if (!is_int($k)) {
1✔
210
                                $param->setDefaultValue($v);
1✔
211
                        }
212

213
                        if (isset($tmp[1])) {
1✔
214
                                $param->setType($tmp[0]);
1✔
215
                        }
216
                }
217

218
                return $res;
1✔
219
        }
220

221

222
        public function getClassName(): ?string
223
        {
224
                return $this->className;
1✔
225
        }
226
}
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