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