1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette;
9:
10: use Nette,
11: Nette\DI,
12: Tracy;
13:
14:
15: 16: 17: 18: 19: 20: 21: 22:
23: class Configurator extends Object
24: {
25: const AUTO = TRUE;
26:
27:
28: const DEVELOPMENT = 'development',
29: PRODUCTION = 'production',
30: NONE = FALSE;
31:
32: const COOKIE_SECRET = 'nette-debug';
33:
34:
35: public $onCompile;
36:
37:
38: public $defaultExtensions = array(
39: 'php' => 'Nette\DI\Extensions\PhpExtension',
40: 'constants' => 'Nette\DI\Extensions\ConstantsExtension',
41: 'nette' => 'Nette\Bridges\Framework\NetteExtension',
42: 'database' => 'Nette\Bridges\DatabaseDI\DatabaseExtension',
43: 'extensions' => 'Nette\DI\Extensions\ExtensionsExtension',
44: );
45:
46:
47: protected $parameters;
48:
49:
50: protected $files = array();
51:
52:
53: public function __construct()
54: {
55: $this->parameters = $this->getDefaultParameters();
56: Nette\Bridges\Framework\TracyBridge::initialize();
57: }
58:
59:
60: 61: 62: 63: 64:
65: public function setDebugMode($value)
66: {
67: $this->parameters['debugMode'] = is_string($value) || is_array($value) ? static::detectDebugMode($value) : (bool) $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: Tracy\Debugger::$strictMode = TRUE;
136: Tracy\Debugger::enable(!$this->parameters['debugMode'], $logDirectory, $email);
137: }
138:
139:
140: 141: 142: 143:
144: public function createRobotLoader()
145: {
146: if (!class_exists('Nette\Loaders\RobotLoader')) {
147: throw new Nette\NotSupportedException('RobotLoader not found, do you have `nette/robot-loader` package installed?');
148: }
149:
150: $loader = new Nette\Loaders\RobotLoader;
151: $loader->setCacheStorage(new Nette\Caching\Storages\FileStorage($this->getCacheDirectory()));
152: $loader->autoRebuild = $this->parameters['debugMode'];
153: return $loader;
154: }
155:
156:
157: 158: 159: 160:
161: public function addConfig($file, $section = NULL)
162: {
163: if ($section === NULL && is_string($file) && $this->parameters['debugMode']) {
164: try {
165: $loader = new DI\Config\Loader;
166: $loader->load($file, $this->parameters['environment']);
167: trigger_error("Config file '$file' has sections, call addConfig() with second parameter Configurator::AUTO.", E_USER_WARNING);
168: $section = $this->parameters['environment'];
169: } catch (\Exception $e) {}
170: }
171: $this->files[] = array($file, $section === self::AUTO ? $this->parameters['environment'] : $section);
172: return $this;
173: }
174:
175:
176: 177: 178: 179:
180: public function createContainer()
181: {
182: $container = $this->createContainerFactory()->create();
183: $container->initialize();
184: if (class_exists('Nette\Environment')) {
185: Nette\Environment::setContext($container);
186: }
187: return $container;
188: }
189:
190:
191: 192: 193:
194: protected function createContainerFactory()
195: {
196: $factory = new DI\ContainerFactory(NULL);
197: $factory->autoRebuild = $this->parameters['debugMode'] ? TRUE : 'compat';
198: $factory->class = $this->parameters['container']['class'];
199: $factory->config = array('parameters' => $this->parameters);
200: $factory->configFiles = $this->files;
201: $factory->tempDirectory = $this->getCacheDirectory() . '/Nette.Configurator';
202: if (!is_dir($factory->tempDirectory)) {
203: @mkdir($factory->tempDirectory);
204: }
205:
206: $me = $this;
207: $factory->onCompile[] = function(DI\ContainerFactory $factory, DI\Compiler $compiler, $config) use ($me) {
208: foreach ($me->defaultExtensions as $name => $class) {
209: if (class_exists($class)) {
210: $compiler->addExtension($name, new $class);
211: }
212: }
213: $factory->parentClass = $config['parameters']['container']['parent'];
214: $me->onCompile($me, $compiler);
215: };
216: return $factory;
217: }
218:
219:
220: protected function getCacheDirectory()
221: {
222: if (empty($this->parameters['tempDir'])) {
223: throw new Nette\InvalidStateException('Set path to temporary directory using setTempDirectory().');
224: }
225: $dir = $this->parameters['tempDir'] . '/cache';
226: if (!is_dir($dir)) {
227: @mkdir($dir);
228: }
229: return $dir;
230: }
231:
232:
233:
234:
235:
236: 237: 238: 239: 240:
241: public static function detectDebugMode($list = NULL)
242: {
243: $addr = isset($_SERVER['REMOTE_ADDR'])
244: ? $_SERVER['REMOTE_ADDR']
245: : php_uname('n');
246: $secret = isset($_COOKIE[self::COOKIE_SECRET]) && is_string($_COOKIE[self::COOKIE_SECRET])
247: ? $_COOKIE[self::COOKIE_SECRET]
248: : NULL;
249: $list = is_string($list)
250: ? preg_split('#[,\s]+#', $list)
251: : (array) $list;
252: if (!isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
253: $list[] = '127.0.0.1';
254: $list[] = '::1';
255: }
256: return in_array($addr, $list, TRUE) || in_array("$secret@$addr", $list, TRUE);
257: }
258:
259: }
260: