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