1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20: 21: 22: 23:
24: class NConfigurator extends NObject
25: {
26:
27: const AUTO = NULL,
28: NONE = FALSE;
29:
30:
31: const DEVELOPMENT = 'development',
32: PRODUCTION = 'production';
33:
34:
35: public $onCompile;
36:
37:
38: protected $parameters;
39:
40:
41: protected $files = array();
42:
43:
44:
45: public function __construct()
46: {
47: $this->parameters = $this->getDefaultParameters();
48: }
49:
50:
51:
52: 53: 54: 55: 56:
57: public function setDebugMode($value = TRUE)
58: {
59: $this->parameters['debugMode'] = is_bool($value) ? $value : self::detectDebugMode($value);
60: $this->parameters['productionMode'] = !$this->parameters['debugMode'];
61: return $this;
62: }
63:
64:
65:
66: 67: 68:
69: public function isDebugMode()
70: {
71: return !$this->parameters['productionMode'];
72: }
73:
74:
75:
76: 77: 78: 79:
80: public function setTempDirectory($path)
81: {
82: $this->parameters['tempDir'] = $path;
83: if (($cacheDir = $this->getCacheDirectory()) && !is_dir($cacheDir)) {
84: mkdir($cacheDir, 0777);
85: }
86: return $this;
87: }
88:
89:
90:
91: 92: 93: 94:
95: public function addParameters(array $params)
96: {
97: $this->parameters = NConfigHelpers::merge($params, $this->parameters);
98: return $this;
99: }
100:
101:
102:
103: 104: 105:
106: protected function getDefaultParameters()
107: {
108: $trace = PHP_VERSION_ID < 50205 ? debug_backtrace() :PHP_VERSION_ID < 50205 ? debug_backtrace() : debug_backtrace(FALSE);
109: $debugMode = self::detectDebugMode();
110: return array(
111: 'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : NULL,
112: 'wwwDir' => isset($_SERVER['SCRIPT_FILENAME']) ? dirname($_SERVER['SCRIPT_FILENAME']) : NULL,
113: 'debugMode' => $debugMode,
114: 'productionMode' => !$debugMode,
115: 'environment' => $debugMode ? 'development' : 'production',
116: 'consoleMode' => PHP_SAPI === 'cli',
117: 'container' => array(
118: 'class' => 'SystemContainer',
119: 'parent' => 'NDIContainer',
120: )
121: );
122: }
123:
124:
125:
126: 127: 128: 129: 130:
131: public function enableDebugger($logDirectory = NULL, $email = NULL)
132: {
133: NDebugger::$strictMode = TRUE;
134: NDebugger::enable($this->parameters['productionMode'], $logDirectory, $email);
135: }
136:
137:
138:
139: 140: 141:
142: public function createRobotLoader()
143: {
144: if (!($cacheDir = $this->getCacheDirectory())) {
145: throw new InvalidStateException("Set path to temporary directory using setTempDirectory().");
146: }
147: $loader = new NRobotLoader;
148: $loader->setCacheStorage(new NFileStorage($cacheDir));
149: $loader->autoRebuild = !$this->parameters['productionMode'];
150: return $loader;
151: }
152:
153:
154:
155: 156: 157: 158:
159: public function addConfig($file, $section = NULL)
160: {
161: $this->files[] = array($file, $section === NULL ? $this->parameters['environment'] : $section);
162: return $this;
163: }
164:
165:
166:
167:
168: public function loadConfig($file, $section = NULL)
169: {
170: trigger_error(__METHOD__ . '() is deprecated; use addConfig(file, [section])->createContainer() instead.', E_USER_WARNING);
171: return $this->addConfig($file, $section)->createContainer();
172: }
173:
174:
175:
176: 177: 178: 179:
180: public function createContainer()
181: {
182: if ($cacheDir = $this->getCacheDirectory()) {
183: $cache = new NCache(new NPhpFileStorage($cacheDir), 'Nette.Configurator');
184: $cacheKey = array($this->parameters, $this->files);
185: $cached = $cache->load($cacheKey);
186: if (!$cached) {
187: $code = $this->buildContainer($dependencies);
188: $cache->save($cacheKey, $code, array(
189: NCache::FILES => $dependencies,
190: ));
191: $cached = $cache->load($cacheKey);
192: }
193: NLimitedScope::load($cached['file'], TRUE);
194:
195: } elseif ($this->files) {
196: throw new InvalidStateException("Set path to temporary directory using setTempDirectory().");
197:
198: } else {
199: NLimitedScope::evaluate($this->buildContainer());
200: }
201:
202: $container = new $this->parameters['container']['class'];
203: $container->initialize();
204: NEnvironment::setContext($container);
205: return $container;
206: }
207:
208:
209:
210: 211: 212: 213:
214: protected function buildContainer(& $dependencies = NULL)
215: {
216: $loader = $this->createLoader();
217: $config = array();
218: $code = "<?php\n";
219: foreach ($this->files as $tmp) {
220: list($file, $section) = $tmp;
221: $config = NConfigHelpers::merge($loader->load($file, $section), $config);
222: $code .= "// source: $file $section\n";
223: }
224: $code .= "\n";
225:
226: $this->checkCompatibility($config);
227:
228: if (!isset($config['parameters'])) {
229: $config['parameters'] = array();
230: }
231: $config['parameters'] = NConfigHelpers::merge($config['parameters'], $this->parameters);
232:
233: $compiler = $this->createCompiler();
234: $this->onCompile($this, $compiler);
235:
236: $code .= $compiler->compile(
237: $config,
238: $this->parameters['container']['class'],
239: $config['parameters']['container']['parent']
240: );
241: $dependencies = array_merge($loader->getDependencies(), $this->isDebugMode() ? $compiler->getContainerBuilder()->getDependencies() : array());
242: return $code;
243: }
244:
245:
246:
247: protected function checkCompatibility(array $config)
248: {
249: foreach (array('service' => 'services', 'variable' => 'parameters', 'variables' => 'parameters', 'mode' => 'parameters', 'const' => 'constants') as $old => $new) {
250: if (isset($config[$old])) {
251: throw new DeprecatedException("Section '$old' in configuration file is deprecated; use '$new' instead.");
252: }
253: }
254: if (isset($config['services'])) {
255: foreach ($config['services'] as $key => $def) {
256: foreach (array('option' => 'arguments', 'methods' => 'setup') as $old => $new) {
257: if (is_array($def) && isset($def[$old])) {
258: throw new DeprecatedException("Section '$old' in service definition is deprecated; refactor it into '$new'.");
259: }
260: }
261: }
262: }
263: }
264:
265:
266:
267: 268: 269:
270: protected function createCompiler()
271: {
272: $compiler = new NConfigCompiler;
273: $compiler->addExtension('php', new NPhpExtension)
274: ->addExtension('constants', new NConstantsExtension)
275: ->addExtension('nette', new NNetteExtension);
276: return $compiler;
277: }
278:
279:
280:
281: 282: 283:
284: protected function createLoader()
285: {
286: return new NConfigLoader;
287: }
288:
289:
290:
291: protected function getCacheDirectory()
292: {
293: return empty($this->parameters['tempDir']) ? NULL : $this->parameters['tempDir'] . '/cache';
294: }
295:
296:
297:
298:
299:
300:
301:
302: 303: 304: 305: 306:
307: public static function detectDebugMode($list = NULL)
308: {
309: $list = is_string($list) ? preg_split('#[,\s]+#', $list) : (array) $list;
310: if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
311: $list[] = '127.0.0.1';
312: $list[] = '::1';
313: }
314: return in_array(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : php_uname('n'), $list, TRUE);
315: }
316:
317:
318:
319:
320: public function setProductionMode($value = TRUE)
321: {
322: return $this->setDebugMode(is_bool($value) ? !$value : $value);
323: }
324:
325:
326:
327:
328: public function isProductionMode()
329: {
330: return !$this->isDebugMode();
331: }
332:
333:
334:
335:
336: public static function detectProductionMode($list = NULL)
337: {
338: return !self::detectDebugMode($list);
339: }
340:
341: }
342: