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 setProductionMode($on = TRUE)
56: {
57: $this->parameters['productionMode'] = (bool) $on;
58: return $this;
59: }
60:
61:
62:
63: 64: 65:
66: public function isProductionMode()
67: {
68: return $this->parameters['productionMode'];
69: }
70:
71:
72:
73: 74: 75: 76:
77: public function setTempDirectory($path)
78: {
79: $this->parameters['tempDir'] = $path;
80: if (($cacheDir = $this->getCacheDirectory()) && !is_dir($cacheDir)) {
81: mkdir($cacheDir, 0777);
82: }
83: return $this;
84: }
85:
86:
87:
88: 89: 90: 91:
92: public function addParameters(array $params)
93: {
94: $this->parameters = NConfigHelpers::merge($params, $this->parameters);
95: return $this;
96: }
97:
98:
99:
100: 101: 102:
103: protected function getDefaultParameters()
104: {
105: $trace = debug_backtrace(FALSE);
106: return array(
107: 'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : NULL,
108: 'wwwDir' => isset($_SERVER['SCRIPT_FILENAME']) ? dirname($_SERVER['SCRIPT_FILENAME']) : NULL,
109: 'productionMode' => self::detectProductionMode(),
110: 'consoleMode' => PHP_SAPI === 'cli',
111: 'container' => array(
112: 'class' => 'SystemContainer',
113: 'parent' => 'NDIContainer',
114: )
115: );
116: }
117:
118:
119:
120: 121: 122:
123: public function createRobotLoader()
124: {
125: if (!($cacheDir = $this->getCacheDirectory())) {
126: throw new InvalidStateException("Set path to temporary directory using setTempDirectory().");
127: }
128: $loader = new NRobotLoader;
129: $loader->setCacheStorage(new NFileStorage($cacheDir));
130: $loader->autoRebuild = !$this->parameters['productionMode'];
131: return $loader;
132: }
133:
134:
135:
136: 137: 138: 139:
140: public function addConfig($file, $section = self::AUTO)
141: {
142: if ($section === self::AUTO) {
143: $section = $this->parameters['productionMode'] ? self::PRODUCTION : self::DEVELOPMENT;
144: }
145: $this->files[] = array($file, $section);
146: return $this;
147: }
148:
149:
150:
151:
152: public function loadConfig($file, $section = NULL)
153: {
154: trigger_error(__METHOD__ . '() is deprecated; use addConfig(file, [section])->createContainer() instead.', E_USER_WARNING);
155: return $this->addConfig($file, $section)->createContainer();
156: }
157:
158:
159:
160: 161: 162: 163:
164: public function createContainer()
165: {
166: if ($cacheDir = $this->getCacheDirectory()) {
167: $cache = new NCache(new NPhpFileStorage($cacheDir), 'Nette.Configurator');
168: $cacheKey = array($this->parameters, $this->files);
169: $cached = $cache->load($cacheKey);
170: if (!$cached) {
171: $code = $this->buildContainer($dependencies);
172: $cache->save($cacheKey, $code, array(
173: NCache::FILES => $this->parameters['productionMode'] ? NULL : $dependencies,
174: ));
175: $cached = $cache->load($cacheKey);
176: }
177: NLimitedScope::load($cached['file'], TRUE);
178:
179: } elseif ($this->files) {
180: throw new InvalidStateException("Set path to temporary directory using setTempDirectory().");
181:
182: } else {
183: NLimitedScope::evaluate($this->buildContainer());
184: }
185:
186: $container = new $this->parameters['container']['class'];
187: $container->initialize();
188: NEnvironment::setContext($container);
189: return $container;
190: }
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 = NConfigHelpers::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'] = NConfigHelpers::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(), $compiler->getContainerBuilder()->getDependencies());
226: return $code;
227: }
228:
229:
230:
231: protected function checkCompatibility(array $config)
232: {
233: foreach (array('service' => 'services', 'variable' => 'parameters', 'variables' => 'parameters', 'mode' => 'parameters', 'const' => 'constants') as $old => $new) {
234: if (isset($config[$old])) {
235: throw new DeprecatedException("Section '$old' in configuration file is deprecated; use '$new' instead.");
236: }
237: }
238: if (isset($config['services'])) {
239: foreach ($config['services'] as $key => $def) {
240: foreach (array('option' => 'arguments', 'methods' => 'setup') as $old => $new) {
241: if (is_array($def) && isset($def[$old])) {
242: throw new DeprecatedException("Section '$old' in service definition is deprecated; refactor it into '$new'.");
243: }
244: }
245: }
246: }
247: }
248:
249:
250:
251: 252: 253:
254: protected function createCompiler()
255: {
256: $compiler = new NConfigCompiler;
257: $compiler->addExtension('php', new NPhpExtension)
258: ->addExtension('constants', new NConstantsExtension)
259: ->addExtension('nette', new NNetteExtension);
260: return $compiler;
261: }
262:
263:
264:
265: 266: 267:
268: protected function createLoader()
269: {
270: return new NConfigLoader;
271: }
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:
290: public static function detectProductionMode()
291: {
292: return !isset($_SERVER['REMOTE_ADDR']) || !in_array($_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1'), TRUE);
293: }
294:
295: }
296: