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