1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette;
9:
10: use Nette,
11: Nette\DI;
12:
13:
14: 15: 16: 17: 18: 19: 20: 21:
22: class Configurator extends Object
23: {
24: const AUTO = TRUE;
25:
26:
27: const DEVELOPMENT = 'development',
28: PRODUCTION = 'production',
29: NONE = FALSE;
30:
31:
32: public $onCompile;
33:
34:
35: public $defaultExtensions = array(
36: 'php' => 'Nette\DI\Extensions\PhpExtension',
37: 'constants' => 'Nette\DI\Extensions\ConstantsExtension',
38: 'nette' => 'Nette\DI\Extensions\NetteExtension',
39: 'extensions' => 'Nette\DI\Extensions\ExtensionsExtension',
40: );
41:
42:
43: protected $parameters;
44:
45:
46: protected $files = array();
47:
48:
49: public function __construct()
50: {
51: $this->parameters = $this->getDefaultParameters();
52: }
53:
54:
55: 56: 57: 58: 59:
60: public function setDebugMode($value = '')
61: {
62: $this->parameters['debugMode'] = is_string($value) || is_array($value) ? static::detectDebugMode($value) : (bool) $value;
63: $this->parameters['productionMode'] = !$this->parameters['debugMode'];
64: return $this;
65: }
66:
67:
68: 69: 70:
71: public function isDebugMode()
72: {
73: return $this->parameters['debugMode'];
74: }
75:
76:
77: 78: 79: 80:
81: public function setTempDirectory($path)
82: {
83: $this->parameters['tempDir'] = $path;
84: return $this;
85: }
86:
87:
88: 89: 90: 91:
92: public function addParameters(array $params)
93: {
94: $this->parameters = DI\Config\Helpers::merge($params, $this->parameters);
95: return $this;
96: }
97:
98:
99: 100: 101:
102: protected function getDefaultParameters()
103: {
104: $trace = debug_backtrace(PHP_VERSION_ID >= 50306 ? DEBUG_BACKTRACE_IGNORE_ARGS : FALSE);
105: $debugMode = static::detectDebugMode();
106: return array(
107: 'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : NULL,
108: 'wwwDir' => isset($_SERVER['SCRIPT_FILENAME'])
109: ? dirname(realpath($_SERVER['SCRIPT_FILENAME']))
110: : NULL,
111: 'debugMode' => $debugMode,
112: 'productionMode' => !$debugMode,
113: 'environment' => $debugMode ? 'development' : 'production',
114: 'consoleMode' => PHP_SAPI === 'cli',
115: 'container' => array(
116: 'class' => 'SystemContainer',
117: 'parent' => 'Nette\DI\Container',
118: )
119: );
120: }
121:
122:
123: 124: 125: 126: 127:
128: public function enableDebugger($logDirectory = NULL, $email = NULL)
129: {
130: Nette\Diagnostics\Debugger::$strictMode = TRUE;
131: Nette\Diagnostics\Debugger::enable(!$this->parameters['debugMode'], $logDirectory, $email);
132: }
133:
134:
135: 136: 137:
138: public function createRobotLoader()
139: {
140: $loader = new Nette\Loaders\RobotLoader;
141: $loader->setCacheStorage(new Nette\Caching\Storages\FileStorage($this->getCacheDirectory()));
142: $loader->autoRebuild = $this->parameters['debugMode'];
143: return $loader;
144: }
145:
146:
147: 148: 149: 150:
151: public function addConfig($file, $section = NULL)
152: {
153: $this->files[] = array($file, $section === self::AUTO ? $this->parameters['environment'] : $section);
154: return $this;
155: }
156:
157:
158: 159: 160: 161:
162: public function createContainer()
163: {
164: $cache = new Nette\Caching\Cache(new Nette\Caching\Storages\PhpFileStorage($this->getCacheDirectory()), 'Nette.Configurator');
165: $cacheKey = array($this->parameters, $this->files);
166: $cached = $cache->load($cacheKey);
167: if (!$cached) {
168: $code = $this->buildContainer($dependencies);
169: $cache->save($cacheKey, $code, array($cache::FILES => $dependencies));
170: $cached = $cache->load($cacheKey);
171: }
172: require_once $cached['file'];
173:
174: $container = new $this->parameters['container']['class'];
175: $container->initialize();
176: Nette\Environment::setContext($container);
177: return $container;
178: }
179:
180:
181: 182: 183: 184:
185: protected function buildContainer(& $dependencies = NULL)
186: {
187: $loader = $this->createLoader();
188: $config = array();
189: $code = "<?php\n";
190: foreach ($this->files as $tmp) {
191: list($file, $section) = $tmp;
192: $code .= "// source: $file $section\n";
193: try {
194: if ($section === NULL) {
195: $config = DI\Config\Helpers::merge($loader->load($file, $this->parameters['environment']), $config);
196: continue;
197: }
198: } catch (Nette\InvalidStateException $e) {
199: } catch (Nette\Utils\AssertionException $e) {
200: }
201:
202: $config = DI\Config\Helpers::merge($loader->load($file, $section), $config);
203: }
204: $code .= "\n";
205:
206: if (!isset($config['parameters'])) {
207: $config['parameters'] = array();
208: }
209: $config['parameters'] = DI\Config\Helpers::merge($config['parameters'], $this->parameters);
210:
211: $compiler = $this->createCompiler();
212: $this->onCompile($this, $compiler);
213:
214: $code .= $compiler->compile(
215: $config,
216: $this->parameters['container']['class'],
217: $config['parameters']['container']['parent']
218: );
219: $dependencies = array_merge($loader->getDependencies(), $this->parameters['debugMode'] ? $compiler->getContainerBuilder()->getDependencies() : array());
220: return $code;
221: }
222:
223:
224: 225: 226:
227: protected function createCompiler()
228: {
229: $compiler = new DI\Compiler;
230:
231: foreach ($this->defaultExtensions as $name => $class) {
232: $compiler->addExtension($name, new $class);
233: }
234:
235: return $compiler;
236: }
237:
238:
239: 240: 241:
242: protected function createLoader()
243: {
244: return new DI\Config\Loader;
245: }
246:
247:
248: protected function getCacheDirectory()
249: {
250: if (empty($this->parameters['tempDir'])) {
251: throw new Nette\InvalidStateException("Set path to temporary directory using setTempDirectory().");
252: }
253: $dir = $this->parameters['tempDir'] . '/cache';
254: if (!is_dir($dir)) {
255: mkdir($dir);
256: }
257: return $dir;
258: }
259:
260:
261:
262:
263:
264: 265: 266: 267: 268:
269: public static function detectDebugMode($list = NULL)
270: {
271: $list = is_string($list) ? preg_split('#[,\s]+#', $list) : (array) $list;
272: if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
273: $list[] = '127.0.0.1';
274: $list[] = '::1';
275: }
276: return in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE);
277: }
278:
279:
280:
281: public function setProductionMode($value = TRUE)
282: {
283: trigger_error(__METHOD__ . '() is deprecated; use setDebugMode(!$value) instead.', E_USER_DEPRECATED);
284: return $this->setDebugMode(is_bool($value) ? !$value : $value);
285: }
286:
287:
288:
289: public function isProductionMode()
290: {
291: trigger_error(__METHOD__ . '() is deprecated; use !isDebugMode() instead.', E_USER_DEPRECATED);
292: return !$this->isDebugMode();
293: }
294:
295:
296:
297: public static function detectProductionMode($list = NULL)
298: {
299: trigger_error(__METHOD__ . '() is deprecated; use !detectDebugMode() instead.', E_USER_DEPRECATED);
300: return !static::detectDebugMode($list);
301: }
302:
303: }
304: