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

nette / bootstrap / 6280609768

23 Sep 2023 01:00AM UTC coverage: 90.58%. Remained the same
6280609768

push

github

dg
composer: updated dependencies

125 of 138 relevant lines covered (90.58%)

0.91 hits per line

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

90.76
/src/Bootstrap/Configurator.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\Bootstrap;
11

12
use Composer\Autoload\ClassLoader;
13
use Latte;
14
use Nette;
15
use Nette\DI;
16
use Tracy;
17

18

19
/**
20
 * Initial system DI container generator.
21
 */
22
class Configurator
23
{
24
        public const CookieSecret = 'nette-debug';
25

26
        /** @deprecated  use Configurator::CookieSecret */
27
        public const COOKIE_SECRET = self::CookieSecret;
28

29

30
        /** @var callable[]  function (Configurator $sender, DI\Compiler $compiler); Occurs after the compiler is created */
31
        public array $onCompile = [];
32

33
        public array $defaultExtensions = [
34
                'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache/nette.application']],
35
                'cache' => [Nette\Bridges\CacheDI\CacheExtension::class, ['%tempDir%']],
36
                'constants' => Extensions\ConstantsExtension::class,
37
                'database' => [Nette\Bridges\DatabaseDI\DatabaseExtension::class, ['%debugMode%']],
38
                'decorator' => Nette\DI\Extensions\DecoratorExtension::class,
39
                'di' => [Nette\DI\Extensions\DIExtension::class, ['%debugMode%']],
40
                'extensions' => Nette\DI\Extensions\ExtensionsExtension::class,
41
                'forms' => Nette\Bridges\FormsDI\FormsExtension::class,
42
                'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']],
43
                'inject' => Nette\DI\Extensions\InjectExtension::class,
44
                'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']],
45
                'mail' => Nette\Bridges\MailDI\MailExtension::class,
46
                'php' => Extensions\PhpExtension::class,
47
                'routing' => [Nette\Bridges\ApplicationDI\RoutingExtension::class, ['%debugMode%']],
48
                'search' => [Nette\DI\Extensions\SearchExtension::class, ['%tempDir%/cache/nette.search']],
49
                'security' => [Nette\Bridges\SecurityDI\SecurityExtension::class, ['%debugMode%']],
50
                'session' => [Nette\Bridges\HttpDI\SessionExtension::class, ['%debugMode%', '%consoleMode%']],
51
                'tracy' => [Tracy\Bridges\Nette\TracyExtension::class, ['%debugMode%', '%consoleMode%']],
52
        ];
53

54
        /** @var string[] of classes which shouldn't be autowired */
55
        public array $autowireExcludedClasses = [
56
                \ArrayAccess::class,
57
                \Countable::class,
58
                \IteratorAggregate::class,
59
                \stdClass::class,
60
                \Traversable::class,
61
        ];
62

63
        protected array $staticParameters;
64
        protected array $dynamicParameters = [];
65
        protected array $services = [];
66

67
        /** @var array<string|array> */
68
        protected array $configs = [];
69

70

71
        public function __construct()
72
        {
73
                $this->staticParameters = $this->getDefaultParameters();
1✔
74
        }
1✔
75

76

77
        /**
78
         * Set parameter %debugMode%.
79
         */
80
        public function setDebugMode(bool|string|array $value): static
1✔
81
        {
82
                if (is_string($value) || is_array($value)) {
1✔
83
                        $value = static::detectDebugMode($value);
1✔
84
                }
85

86
                $this->staticParameters['debugMode'] = $value;
1✔
87
                $this->staticParameters['productionMode'] = !$this->staticParameters['debugMode']; // compatibility
1✔
88
                return $this;
1✔
89
        }
90

91

92
        public function isDebugMode(): bool
93
        {
94
                return $this->staticParameters['debugMode'];
1✔
95
        }
96

97

98
        /**
99
         * Sets path to temporary directory.
100
         */
101
        public function setTempDirectory(string $path): static
1✔
102
        {
103
                $this->staticParameters['tempDir'] = $path;
1✔
104
                return $this;
1✔
105
        }
106

107

108
        /**
109
         * Sets the default timezone.
110
         */
111
        public function setTimeZone(string $timezone): static
1✔
112
        {
113
                date_default_timezone_set($timezone);
1✔
114
                @ini_set('date.timezone', $timezone); // @ - function may be disabled
1✔
115
                return $this;
1✔
116
        }
117

118

119
        /** @deprecated use addStaticParameters() */
120
        public function addParameters(array $params): static
1✔
121
        {
122
                return $this->addStaticParameters($params);
1✔
123
        }
124

125

126
        /**
127
         * Adds new static parameters.
128
         */
129
        public function addStaticParameters(array $params): static
1✔
130
        {
131
                $this->staticParameters = DI\Config\Helpers::merge($params, $this->staticParameters);
1✔
132
                return $this;
1✔
133
        }
134

135

136
        /**
137
         * Adds new dynamic parameters.
138
         */
139
        public function addDynamicParameters(array $params): static
1✔
140
        {
141
                $this->dynamicParameters = $params + $this->dynamicParameters;
1✔
142
                return $this;
1✔
143
        }
144

145

146
        /**
147
         * Add instances of services.
148
         */
149
        public function addServices(array $services): static
1✔
150
        {
151
                $this->services = $services + $this->services;
1✔
152
                return $this;
1✔
153
        }
154

155

156
        protected function getDefaultParameters(): array
157
        {
158
                $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
1✔
159
                $last = end($trace);
1✔
160
                $debugMode = static::detectDebugMode();
1✔
161
                $loaderRc = class_exists(ClassLoader::class)
1✔
162
                        ? new \ReflectionClass(ClassLoader::class)
1✔
163
                        : null;
×
164
                return [
165
                        'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : null,
1✔
166
                        'wwwDir' => isset($last['file']) ? dirname($last['file']) : null,
1✔
167
                        'vendorDir' => $loaderRc ? dirname($loaderRc->getFileName(), 2) : null,
1✔
168
                        'debugMode' => $debugMode,
1✔
169
                        'productionMode' => !$debugMode,
1✔
170
                        'consoleMode' => PHP_SAPI === 'cli',
1✔
171
                ];
172
        }
173

174

175
        public function enableTracy(?string $logDirectory = null, ?string $email = null): void
176
        {
177
                if (!class_exists(Tracy\Debugger::class)) {
×
178
                        throw new Nette\NotSupportedException('Tracy not found, do you have `tracy/tracy` package installed?');
×
179
                }
180

181
                Tracy\Debugger::$strictMode = true;
×
182
                Tracy\Debugger::enable(!$this->staticParameters['debugMode'], $logDirectory, $email);
×
183
                Tracy\Bridges\Nette\Bridge::initialize();
×
184
                if (class_exists(Latte\Bridges\Tracy\BlueScreenPanel::class)) {
×
185
                        Latte\Bridges\Tracy\BlueScreenPanel::initialize();
×
186
                }
187
        }
188

189

190
        /** @deprecated use enableTracy() */
191
        public function enableDebugger(?string $logDirectory = null, ?string $email = null): void
192
        {
193
                $this->enableTracy($logDirectory, $email);
×
194
        }
195

196

197
        /**
198
         * @throws Nette\NotSupportedException if RobotLoader is not available
199
         */
200
        public function createRobotLoader(): Nette\Loaders\RobotLoader
201
        {
202
                if (!class_exists(Nette\Loaders\RobotLoader::class)) {
1✔
203
                        throw new Nette\NotSupportedException('RobotLoader not found, do you have `nette/robot-loader` package installed?');
×
204
                }
205

206
                $loader = new Nette\Loaders\RobotLoader;
1✔
207
                $loader->setTempDirectory($this->getCacheDirectory() . '/nette.robotLoader');
1✔
208
                $loader->setAutoRefresh($this->staticParameters['debugMode']);
1✔
209

210
                if (isset($this->defaultExtensions['application'])) {
1✔
211
                        $this->defaultExtensions['application'][1][1] = null;
1✔
212
                        $this->defaultExtensions['application'][1][3] = $loader;
1✔
213
                }
214

215
                return $loader;
1✔
216
        }
217

218

219
        /**
220
         * Adds configuration file.
221
         */
222
        public function addConfig(string|array $config): static
1✔
223
        {
224
                $this->configs[] = $config;
1✔
225
                return $this;
1✔
226
        }
227

228

229
        /**
230
         * Returns system DI container.
231
         */
232
        public function createContainer(bool $initialize = true): DI\Container
1✔
233
        {
234
                $class = $this->loadContainer();
1✔
235
                $container = new $class($this->dynamicParameters);
1✔
236
                foreach ($this->services as $name => $service) {
1✔
237
                        $container->addService($name, $service);
1✔
238
                }
239

240
                if ($initialize) {
1✔
241
                        $container->initialize();
1✔
242
                }
243

244
                return $container;
1✔
245
        }
246

247

248
        /**
249
         * Loads system DI container class and returns its name.
250
         */
251
        public function loadContainer(): string
252
        {
253
                $loader = new DI\ContainerLoader(
1✔
254
                        $this->getCacheDirectory() . '/nette.configurator',
1✔
255
                        $this->staticParameters['debugMode'],
1✔
256
                );
257
                return $loader->load(
1✔
258
                        [$this, 'generateContainer'],
1✔
259
                        $this->generateContainerKey(),
1✔
260
                );
261
        }
262

263

264
        /**
265
         * @internal
266
         */
267
        public function generateContainer(DI\Compiler $compiler): void
1✔
268
        {
269
                $loader = $this->createLoader();
1✔
270
                $loader->setParameters($this->staticParameters);
1✔
271

272
                foreach ($this->configs as $config) {
1✔
273
                        if (is_string($config)) {
1✔
274
                                $compiler->loadConfig($config, $loader);
1✔
275
                        } else {
276
                                $compiler->addConfig($config);
×
277
                        }
278
                }
279

280
                $compiler->addConfig(['parameters' => DI\Helpers::escape($this->staticParameters)]);
1✔
281
                $compiler->setDynamicParameterNames(array_keys($this->dynamicParameters));
1✔
282

283
                $builder = $compiler->getContainerBuilder();
1✔
284
                $builder->addExcludedClasses($this->autowireExcludedClasses);
1✔
285

286
                foreach ($this->defaultExtensions as $name => $extension) {
1✔
287
                        [$class, $args] = is_string($extension)
1✔
288
                                ? [$extension, []]
1✔
289
                                : $extension;
1✔
290
                        if (class_exists($class)) {
1✔
291
                                $args = DI\Helpers::expand($args, $this->staticParameters);
1✔
292
                                $compiler->addExtension($name, (new \ReflectionClass($class))->newInstanceArgs($args));
1✔
293
                        }
294
                }
295

296
                Nette\Utils\Arrays::invoke($this->onCompile, $this, $compiler);
1✔
297
        }
1✔
298

299

300
        protected function createLoader(): DI\Config\Loader
301
        {
302
                return new DI\Config\Loader;
1✔
303
        }
304

305

306
        protected function generateContainerKey(): array
307
        {
308
                return [
309
                        $this->staticParameters,
1✔
310
                        array_keys($this->dynamicParameters),
1✔
311
                        $this->configs,
1✔
312
                        PHP_VERSION_ID - PHP_RELEASE_VERSION, // minor PHP version
1✔
313
                        class_exists(ClassLoader::class) // composer update
1✔
314
                                ? filemtime((new \ReflectionClass(ClassLoader::class))->getFilename())
1✔
315
                                : null,
316
                ];
317
        }
318

319

320
        protected function getCacheDirectory(): string
321
        {
322
                if (empty($this->staticParameters['tempDir'])) {
1✔
323
                        throw new Nette\InvalidStateException('Set path to temporary directory using setTempDirectory().');
1✔
324
                }
325

326
                $dir = $this->staticParameters['tempDir'] . '/cache';
1✔
327
                Nette\Utils\FileSystem::createDir($dir);
1✔
328
                return $dir;
1✔
329
        }
330

331

332
        /********************* tools ****************d*g**/
333

334

335
        /**
336
         * Detects debug mode by IP addresses or computer names whitelist detection.
337
         */
338
        public static function detectDebugMode(string|array $list = null): bool
1✔
339
        {
340
                $addr = $_SERVER['REMOTE_ADDR'] ?? php_uname('n');
1✔
341
                $secret = is_string($_COOKIE[self::CookieSecret] ?? null)
1✔
342
                        ? $_COOKIE[self::CookieSecret]
1✔
343
                        : null;
1✔
344
                $list = is_string($list)
1✔
345
                        ? preg_split('#[,\s]+#', $list)
1✔
346
                        : (array) $list;
1✔
347
                if (!isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !isset($_SERVER['HTTP_FORWARDED'])) {
1✔
348
                        $list[] = '127.0.0.1';
1✔
349
                        $list[] = '::1';
1✔
350
                        $list[] = '[::1]'; // workaround for PHP < 7.3.4
1✔
351
                }
352

353
                return in_array($addr, $list, true) || in_array("$secret@$addr", $list, true);
1✔
354
        }
355
}
356

357

358
class_exists(Nette\Configurator::class);
1✔
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