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