Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Configurator
  • Framework
  • LegacyObject

Traits

  • SmartObject
  • StaticClass

Exceptions

  • ArgumentOutOfRangeException
  • DeprecatedException
  • DirectoryNotFoundException
  • FileNotFoundException
  • InvalidArgumentException
  • InvalidStateException
  • IOException
  • MemberAccessException
  • NotImplementedException
  • NotSupportedException
  • OutOfRangeException
  • StaticClassException
  • UnexpectedValueException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  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: namespace Nette;
  9: 
 10: use Nette;
 11: use Nette\DI;
 12: use Tracy;
 13: 
 14: 
 15: /**
 16:  * Initial system DI container generator.
 17:  */
 18: class Configurator
 19: {
 20:     use SmartObject;
 21: 
 22:     const AUTO = true,
 23:         NONE = false;
 24: 
 25:     const COOKIE_SECRET = 'nette-debug';
 26: 
 27:     /** @var callable[]  function (Configurator $sender, DI\Compiler $compiler); Occurs after the compiler is created */
 28:     public $onCompile;
 29: 
 30:     /** @var array */
 31:     public $defaultExtensions = [
 32:         'php' => Nette\DI\Extensions\PhpExtension::class,
 33:         'constants' => Nette\DI\Extensions\ConstantsExtension::class,
 34:         'extensions' => Nette\DI\Extensions\ExtensionsExtension::class,
 35:         'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache']],
 36:         'decorator' => Nette\DI\Extensions\DecoratorExtension::class,
 37:         'cache' => [Nette\Bridges\CacheDI\CacheExtension::class, ['%tempDir%']],
 38:         'database' => [Nette\Bridges\DatabaseDI\DatabaseExtension::class, ['%debugMode%']],
 39:         'di' => [Nette\DI\Extensions\DIExtension::class, ['%debugMode%']],
 40:         'forms' => Nette\Bridges\FormsDI\FormsExtension::class,
 41:         'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']],
 42:         'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']],
 43:         'mail' => Nette\Bridges\MailDI\MailExtension::class,
 44:         'routing' => [Nette\Bridges\ApplicationDI\RoutingExtension::class, ['%debugMode%']],
 45:         'security' => [Nette\Bridges\SecurityDI\SecurityExtension::class, ['%debugMode%']],
 46:         'session' => [Nette\Bridges\HttpDI\SessionExtension::class, ['%debugMode%', '%consoleMode%']],
 47:         'tracy' => [Tracy\Bridges\Nette\TracyExtension::class, ['%debugMode%', '%consoleMode%']],
 48:         'inject' => Nette\DI\Extensions\InjectExtension::class,
 49:     ];
 50: 
 51:     /** @var string[] of classes which shouldn't be autowired */
 52:     public $autowireExcludedClasses = [
 53:         'stdClass',
 54:     ];
 55: 
 56:     /** @var array */
 57:     protected $parameters;
 58: 
 59:     /** @var array */
 60:     protected $dynamicParameters = [];
 61: 
 62:     /** @var array */
 63:     protected $services = [];
 64: 
 65:     /** @var array [file|array, section] */
 66:     protected $files = [];
 67: 
 68: 
 69:     public function __construct()
 70:     {
 71:         $this->parameters = $this->getDefaultParameters();
 72:     }
 73: 
 74: 
 75:     /**
 76:      * Set parameter %debugMode%.
 77:      * @param  bool|string|array  $value
 78:      * @return static
 79:      */
 80:     public function setDebugMode($value)
 81:     {
 82:         if (is_string($value) || is_array($value)) {
 83:             $value = static::detectDebugMode($value);
 84:         } elseif (!is_bool($value)) {
 85:             throw new Nette\InvalidArgumentException(sprintf('Value must be either a string, array, or boolean, %s given.', gettype($value)));
 86:         }
 87:         $this->parameters['debugMode'] = $value;
 88:         $this->parameters['productionMode'] = !$this->parameters['debugMode']; // compatibility
 89:         return $this;
 90:     }
 91: 
 92: 
 93:     /**
 94:      * @return bool
 95:      */
 96:     public function isDebugMode()
 97:     {
 98:         return $this->parameters['debugMode'];
 99:     }
100: 
101: 
102:     /**
103:      * Sets path to temporary directory.
104:      * @param  string  $path
105:      * @return static
106:      */
107:     public function setTempDirectory($path)
108:     {
109:         $this->parameters['tempDir'] = $path;
110:         return $this;
111:     }
112: 
113: 
114:     /**
115:      * Sets the default timezone.
116:      * @param  string  $timezone
117:      * @return static
118:      */
119:     public function setTimeZone($timezone)
120:     {
121:         date_default_timezone_set($timezone);
122:         @ini_set('date.timezone', $timezone); // @ - function may be disabled
123:         return $this;
124:     }
125: 
126: 
127:     /**
128:      * Adds new parameters. The %params% will be expanded.
129:      * @return static
130:      */
131:     public function addParameters(array $params)
132:     {
133:         $this->parameters = DI\Config\Helpers::merge($params, $this->parameters);
134:         return $this;
135:     }
136: 
137: 
138:     /**
139:      * Adds new dynamic parameters.
140:      * @return static
141:      */
142:     public function addDynamicParameters(array $params)
143:     {
144:         $this->dynamicParameters = $params + $this->dynamicParameters;
145:         return $this;
146:     }
147: 
148: 
149:     /**
150:      * Add instances of services.
151:      * @return static
152:      */
153:     public function addServices(array $services)
154:     {
155:         $this->services = $services + $this->services;
156:         return $this;
157:     }
158: 
159: 
160:     /**
161:      * @return array
162:      */
163:     protected function getDefaultParameters()
164:     {
165:         $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
166:         $last = end($trace);
167:         $debugMode = static::detectDebugMode();
168:         return [
169:             'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : null,
170:             'wwwDir' => isset($last['file']) ? dirname($last['file']) : null,
171:             'debugMode' => $debugMode,
172:             'productionMode' => !$debugMode,
173:             'consoleMode' => PHP_SAPI === 'cli',
174:         ];
175:     }
176: 
177: 
178:     /**
179:      * @param  string  $logDirectory
180:      * @param  string  $email
181:      * @return void
182:      */
183:     public function enableTracy($logDirectory = null, $email = null)
184:     {
185:         $this->enableDebugger($logDirectory, $email);
186:     }
187: 
188: 
189:     /**
190:      * Alias for enableTracy()
191:      * @param  string  $logDirectory
192:      * @param  string  $email
193:      * @return void
194:      */
195:     public function enableDebugger($logDirectory = null, $email = null)
196:     {
197:         Tracy\Debugger::$strictMode = true;
198:         Tracy\Debugger::enable(!$this->parameters['debugMode'], $logDirectory, $email);
199:         Nette\Bridges\Framework\TracyBridge::initialize();
200:     }
201: 
202: 
203:     /**
204:      * @return Nette\Loaders\RobotLoader
205:      * @throws Nette\NotSupportedException if RobotLoader is not available
206:      */
207:     public function createRobotLoader()
208:     {
209:         if (!class_exists(Nette\Loaders\RobotLoader::class)) {
210:             throw new Nette\NotSupportedException('RobotLoader not found, do you have `nette/robot-loader` package installed?');
211:         }
212: 
213:         $loader = new Nette\Loaders\RobotLoader;
214:         $loader->setTempDirectory($this->getCacheDirectory() . '/Nette.RobotLoader');
215:         $loader->setAutoRefresh($this->parameters['debugMode']);
216:         return $loader;
217:     }
218: 
219: 
220:     /**
221:      * Adds configuration file.
222:      * @param  string|array  $file
223:      * @return static
224:      */
225:     public function addConfig($file)
226:     {
227:         $section = func_num_args() > 1 ? func_get_arg(1) : null;
228:         if ($section !== null) {
229:             trigger_error('Sections in config file are deprecated.', E_USER_DEPRECATED);
230:         }
231:         $this->files[] = [$file, $section === self::AUTO ? ($this->parameters['debugMode'] ? 'development' : 'production') : $section];
232:         return $this;
233:     }
234: 
235: 
236:     /**
237:      * Returns system DI container.
238:      * @return DI\Container
239:      */
240:     public function createContainer()
241:     {
242:         $class = $this->loadContainer();
243:         $container = new $class($this->dynamicParameters);
244:         foreach ($this->services as $name => $service) {
245:             $container->addService($name, $service);
246:         }
247:         $container->initialize();
248:         if (class_exists(Nette\Environment::class)) {
249:             Nette\Environment::setContext($container); // back compatibility
250:         }
251:         return $container;
252:     }
253: 
254: 
255:     /**
256:      * Loads system DI container class and returns its name.
257:      * @return string
258:      */
259:     public function loadContainer()
260:     {
261:         $loader = new DI\ContainerLoader(
262:             $this->getCacheDirectory() . '/Nette.Configurator',
263:             $this->parameters['debugMode']
264:         );
265:         $class = $loader->load(
266:             [$this, 'generateContainer'],
267:             [$this->parameters, array_keys($this->dynamicParameters), $this->files, PHP_VERSION_ID - PHP_RELEASE_VERSION]
268:         );
269:         return $class;
270:     }
271: 
272: 
273:     /**
274:      * @return string
275:      * @internal
276:      */
277:     public function generateContainer(DI\Compiler $compiler)
278:     {
279:         $compiler->addConfig(['parameters' => $this->parameters]);
280:         $compiler->setDynamicParameterNames(array_keys($this->dynamicParameters));
281: 
282:         $loader = $this->createLoader();
283:         $fileInfo = [];
284:         foreach ($this->files as $info) {
285:             if (is_scalar($info[0])) {
286:                 $fileInfo[] = "// source: $info[0] $info[1]";
287:                 $info[0] = $loader->load($info[0], $info[1]);
288:             }
289:             $compiler->addConfig($this->fixCompatibility($info[0]));
290:         }
291:         $compiler->addDependencies($loader->getDependencies());
292: 
293:         $builder = $compiler->getContainerBuilder();
294:         $builder->addExcludedClasses($this->autowireExcludedClasses);
295: 
296:         foreach ($this->defaultExtensions as $name => $extension) {
297:             list($class, $args) = is_string($extension) ? [$extension, []] : $extension;
298:             if (class_exists($class)) {
299:                 $args = DI\Helpers::expand($args, $this->parameters, true);
300:                 $compiler->addExtension($name, (new \ReflectionClass($class))->newInstanceArgs($args));
301:             }
302:         }
303: 
304:         $this->onCompile($this, $compiler);
305: 
306:         $classes = $compiler->compile();
307:         return implode("\n", $fileInfo) . "\n\n" . $classes;
308:     }
309: 
310: 
311:     /**
312:      * @return DI\Config\Loader
313:      */
314:     protected function createLoader()
315:     {
316:         return new DI\Config\Loader;
317:     }
318: 
319: 
320:     /**
321:      * @return string
322:      */
323:     protected function getCacheDirectory()
324:     {
325:         if (empty($this->parameters['tempDir'])) {
326:             throw new Nette\InvalidStateException('Set path to temporary directory using setTempDirectory().');
327:         }
328:         $dir = $this->parameters['tempDir'] . '/cache';
329:         Nette\Utils\FileSystem::createDir($dir);
330:         return $dir;
331:     }
332: 
333: 
334:     /**
335:      * Back compatibility with < v2.3
336:      * @return array
337:      */
338:     protected function fixCompatibility($config)
339:     {
340:         if (isset($config['nette']['security']['frames'])) {
341:             $config['nette']['http']['frames'] = $config['nette']['security']['frames'];
342:             unset($config['nette']['security']['frames']);
343:         }
344:         foreach (['application', 'cache', 'database', 'di' => 'container', 'forms', 'http',
345:             'latte', 'mail' => 'mailer', 'routing', 'security', 'session', 'tracy' => 'debugger', ] as $new => $old) {
346:             if (isset($config['nette'][$old])) {
347:                 $new = is_int($new) ? $old : $new;
348:                 if (isset($config[$new])) {
349:                     throw new Nette\DeprecatedException("You can use (deprecated) section 'nette.$old' or new section '$new', but not both of them.");
350:                 } else {
351:                     trigger_error("Configuration section 'nette.$old' is deprecated, use section '$new' (without 'nette')", E_USER_DEPRECATED);
352:                 }
353:                 $config[$new] = $config['nette'][$old];
354:                 unset($config['nette'][$old]);
355:             }
356:         }
357:         if (isset($config['nette']['xhtml'])) {
358:             trigger_error("Configuration option 'nette.xhtml' is deprecated, use section 'latte.xhtml' instead.", E_USER_DEPRECATED);
359:             $config['latte']['xhtml'] = $config['nette']['xhtml'];
360:             unset($config['nette']['xhtml']);
361:         }
362: 
363:         if (empty($config['nette'])) {
364:             unset($config['nette']);
365:         }
366:         return $config;
367:     }
368: 
369: 
370:     /********************* tools ****************d*g**/
371: 
372: 
373:     /**
374:      * Detects debug mode by IP addresses or computer names whitelist detection.
375:      * @param  string|array  $list
376:      * @return bool
377:      */
378:     public static function detectDebugMode($list = null)
379:     {
380:         $addr = isset($_SERVER['REMOTE_ADDR'])
381:             ? $_SERVER['REMOTE_ADDR']
382:             : php_uname('n');
383:         $secret = isset($_COOKIE[self::COOKIE_SECRET]) && is_string($_COOKIE[self::COOKIE_SECRET])
384:             ? $_COOKIE[self::COOKIE_SECRET]
385:             : null;
386:         $list = is_string($list)
387:             ? preg_split('#[,\s]+#', $list)
388:             : (array) $list;
389:         if (!isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !isset($_SERVER['HTTP_FORWARDED'])) {
390:             $list[] = '127.0.0.1';
391:             $list[] = '::1';
392:         }
393:         return in_array($addr, $list, true) || in_array("$secret@$addr", $list, true);
394:     }
395: }
396: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0