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