1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Nette\Config\Extensions;
13:
14: use Nette,
15: Nette\DI\ContainerBuilder,
16: Nette\Utils\Validators;
17:
18:
19:
20: 21: 22: 23: 24:
25: class NetteExtension extends Nette\Config\CompilerExtension
26: {
27: public $defaults = array(
28: 'xhtml' => TRUE,
29: 'session' => array(
30: 'iAmUsingBadHost' => NULL,
31: 'autoStart' => 'smart',
32: 'expiration' => NULL,
33: ),
34: 'application' => array(
35: 'debugger' => TRUE,
36: 'errorPresenter' => NULL,
37: 'catchExceptions' => '%productionMode%',
38: ),
39: 'routing' => array(
40: 'debugger' => TRUE,
41: 'routes' => array(),
42: ),
43: 'security' => array(
44: 'debugger' => TRUE,
45: 'frames' => 'SAMEORIGIN',
46: 'users' => array(),
47: 'roles' => array(),
48: 'resources' => array(),
49: ),
50: 'mailer' => array(
51: 'smtp' => FALSE,
52: ),
53: 'database' => array(),
54: 'forms' => array(
55: 'messages' => array(),
56: ),
57: 'container' => array(
58: 'debugger' => FALSE,
59: ),
60: 'debugger' => array(
61: 'email' => NULL,
62: 'editor' => NULL,
63: 'browser' => NULL,
64: 'strictMode' => NULL,
65: 'bar' => array(),
66: 'blueScreen' => array(),
67: ),
68: );
69:
70: public $databaseDefaults = array(
71: 'dsn' => NULL,
72: 'user' => NULL,
73: 'password' => NULL,
74: 'options' => NULL,
75: 'debugger' => TRUE,
76: 'explain' => TRUE,
77: 'reflection' => 'Nette\Database\Reflection\DiscoveredReflection',
78: );
79:
80:
81:
82: public function loadConfiguration()
83: {
84: $container = $this->getContainerBuilder();
85: $config = $this->getConfig($this->defaults);
86:
87:
88:
89: $container->addDefinition($this->prefix('cacheJournal'))
90: ->setClass('Nette\Caching\Storages\FileJournal', array('%tempDir%'));
91:
92: $container->addDefinition('cacheStorage')
93: ->setClass('Nette\Caching\Storages\FileStorage', array('%tempDir%/cache'));
94:
95: $container->addDefinition($this->prefix('templateCacheStorage'))
96: ->setClass('Nette\Caching\Storages\PhpFileStorage', array('%tempDir%/cache'))
97: ->setAutowired(FALSE);
98:
99: $container->addDefinition($this->prefix('cache'))
100: ->setClass('Nette\Caching\Cache', array(1 => '%namespace%'))
101: ->setParameters(array('namespace' => NULL));
102:
103:
104:
105: $container->addDefinition($this->prefix('httpRequestFactory'))
106: ->setClass('Nette\Http\RequestFactory')
107: ->addSetup('setEncoding', array('UTF-8'))
108: ->setInternal(TRUE);
109:
110: $container->addDefinition('httpRequest')
111: ->setClass('Nette\Http\Request')
112: ->setFactory('@Nette\Http\RequestFactory::createHttpRequest');
113:
114: $container->addDefinition('httpResponse')
115: ->setClass('Nette\Http\Response');
116:
117: $container->addDefinition($this->prefix('httpContext'))
118: ->setClass('Nette\Http\Context');
119:
120:
121:
122: $session = $container->addDefinition('session')
123: ->setClass('Nette\Http\Session');
124:
125: if (isset($config['session']['expiration'])) {
126: $session->addSetup('setExpiration', array($config['session']['expiration']));
127: }
128: if (isset($config['session']['iAmUsingBadHost'])) {
129: $session->addSetup('Nette\Framework::$iAmUsingBadHost = ?;', array((bool) $config['session']['iAmUsingBadHost']));
130: }
131: unset($config['session']['expiration'], $config['session']['autoStart'], $config['session']['iAmUsingBadHost']);
132: if (!empty($config['session'])) {
133: $session->addSetup('setOptions', array($config['session']));
134: }
135:
136:
137:
138: $container->addDefinition($this->prefix('userStorage'))
139: ->setClass('Nette\Http\UserStorage');
140:
141: $user = $container->addDefinition('user')
142: ->setClass('Nette\Security\User');
143:
144: if (!$container->parameters['productionMode'] && $config['security']['debugger']) {
145: $user->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array(
146: new Nette\DI\Statement('Nette\Security\Diagnostics\UserPanel')
147: ));
148: }
149:
150: if ($config['security']['users']) {
151: $container->addDefinition($this->prefix('authenticator'))
152: ->setClass('Nette\Security\SimpleAuthenticator', array($config['security']['users']));
153: }
154:
155: if ($config['security']['roles'] || $config['security']['resources']) {
156: $authorizator = $container->addDefinition($this->prefix('authorizator'))
157: ->setClass('Nette\Security\Permission');
158: foreach ($config['security']['roles'] as $role => $parents) {
159: $authorizator->addSetup('addRole', array($role, $parents));
160: }
161: foreach ($config['security']['resources'] as $resource => $parents) {
162: $authorizator->addSetup('addResource', array($resource, $parents));
163: }
164: }
165:
166:
167:
168: $application = $container->addDefinition('application')
169: ->setClass('Nette\Application\Application')
170: ->addSetup('$catchExceptions', $config['application']['catchExceptions'])
171: ->addSetup('$errorPresenter', $config['application']['errorPresenter']);
172:
173: if ($config['application']['debugger']) {
174: $application->addSetup('Nette\Application\Diagnostics\RoutingPanel::initializePanel');
175: }
176:
177: $container->addDefinition($this->prefix('presenterFactory'))
178: ->setClass('Nette\Application\PresenterFactory', array(
179: isset($container->parameters['appDir']) ? $container->parameters['appDir'] : NULL
180: ));
181:
182:
183:
184: $router = $container->addDefinition('router')
185: ->setClass('Nette\Application\Routers\RouteList');
186:
187: foreach ($config['routing']['routes'] as $mask => $action) {
188: $router->addSetup('$service[] = new Nette\Application\Routers\Route(?, ?);', array($mask, $action));
189: }
190:
191: if (!$container->parameters['productionMode'] && $config['routing']['debugger']) {
192: $application->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array(
193: new Nette\DI\Statement('Nette\Application\Diagnostics\RoutingPanel')
194: ));
195: }
196:
197:
198:
199: if (empty($config['mailer']['smtp'])) {
200: $container->addDefinition($this->prefix('mailer'))
201: ->setClass('Nette\Mail\SendmailMailer');
202: } else {
203: Validators::assertField($config, 'mailer', 'array');
204: $container->addDefinition($this->prefix('mailer'))
205: ->setClass('Nette\Mail\SmtpMailer', array($config['mailer']));
206: }
207:
208: $container->addDefinition($this->prefix('mail'))
209: ->setClass('Nette\Mail\Message')
210: ->addSetup('setMailer')
211: ->setShared(FALSE);
212:
213:
214:
215: $container->addDefinition($this->prefix('basicForm'))
216: ->setClass('Nette\Forms\Form')
217: ->setShared(FALSE);
218:
219:
220:
221: $latte = $container->addDefinition($this->prefix('latte'))
222: ->setClass('Nette\Latte\Engine')
223: ->setShared(FALSE);
224:
225: if (empty($config['xhtml'])) {
226: $latte->addSetup('$service->getCompiler()->defaultContentType = ?', Nette\Latte\Compiler::CONTENT_HTML);
227: }
228:
229: $container->addDefinition($this->prefix('template'))
230: ->setClass('Nette\Templating\FileTemplate')
231: ->addSetup('registerFilter', array($latte))
232: ->addSetup('registerHelperLoader', array('Nette\Templating\Helpers::loader'))
233: ->setShared(FALSE);
234:
235:
236:
237: $container->addDefinition($this->prefix('database'))
238: ->setClass('Nette\DI\NestedAccessor', array('@container', $this->prefix('database')));
239:
240: $autowired = TRUE;
241: foreach ((array) $config['database'] as $name => $info) {
242: if (!is_array($info)) {
243: continue;
244: }
245: $info += $this->databaseDefaults + array('autowired' => $autowired);
246: $autowired = FALSE;
247:
248: foreach ((array) $info['options'] as $key => $value) {
249: unset($info['options'][$key]);
250: $info['options'][constant($key)] = $value;
251: }
252:
253: $connection = $container->addDefinition($this->prefix("database.$name"))
254: ->setClass('Nette\Database\Connection', array($info['dsn'], $info['user'], $info['password'], $info['options']))
255: ->setAutowired($info['autowired'])
256: ->addSetup('setCacheStorage')
257: ->addSetup('Nette\Diagnostics\Debugger::$blueScreen->addPanel(?)', array(
258: 'Nette\Database\Diagnostics\ConnectionPanel::renderException'
259: ));
260:
261: if ($info['reflection']) {
262: $connection->addSetup('setDatabaseReflection', is_string($info['reflection'])
263: ? array(new Nette\DI\Statement(preg_match('#^[a-z]+$#', $info['reflection']) ? 'Nette\Database\Reflection\\' . ucfirst($info['reflection']) . 'Reflection' : $info['reflection']))
264: : Nette\Config\Compiler::filterArguments(array($info['reflection']))
265: );
266: }
267:
268: if (!$container->parameters['productionMode'] && $info['debugger']) {
269: $panel = $container->addDefinition($this->prefix("database.{$name}ConnectionPanel"))
270: ->setClass('Nette\Database\Diagnostics\ConnectionPanel')
271: ->setAutowired(FALSE)
272: ->addSetup('$explain', !empty($info['explain']))
273: ->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array('@self'));
274:
275: $connection->addSetup('$service->onQuery[] = ?', array(array($panel, 'logQuery')));
276: }
277: }
278: }
279:
280:
281:
282: public function afterCompile(Nette\Utils\PhpGenerator\ClassType $class)
283: {
284: $initialize = $class->methods['initialize'];
285: $container = $this->getContainerBuilder();
286: $config = $this->getConfig($this->defaults);
287:
288:
289: foreach (array('email', 'editor', 'browser', 'strictMode', 'maxLen', 'maxDepth') as $key) {
290: if (isset($config['debugger'][$key])) {
291: $initialize->addBody('Nette\Diagnostics\Debugger::$? = ?;', array($key, $config['debugger'][$key]));
292: }
293: }
294:
295: if (!$container->parameters['productionMode']) {
296: if ($config['container']['debugger']) {
297: $config['debugger']['bar'][] = 'Nette\DI\Diagnostics\ContainerPanel';
298: }
299:
300: foreach ((array) $config['debugger']['bar'] as $item) {
301: $initialize->addBody($container->formatPhp(
302: 'Nette\Diagnostics\Debugger::$bar->addPanel(?);',
303: Nette\Config\Compiler::filterArguments(array(is_string($item) ? new Nette\DI\Statement($item) : $item))
304: ));
305: }
306:
307: foreach ((array) $config['debugger']['blueScreen'] as $item) {
308: $initialize->addBody($container->formatPhp(
309: 'Nette\Diagnostics\Debugger::$blueScreen->addPanel(?);',
310: Nette\Config\Compiler::filterArguments(array($item))
311: ));
312: }
313: }
314:
315: if (!empty($container->parameters['tempDir'])) {
316: $initialize->addBody($this->checkTempDir($container->expand('%tempDir%/cache')));
317: }
318:
319: foreach ((array) $config['forms']['messages'] as $name => $text) {
320: $initialize->addBody('Nette\Forms\Rules::$defaultMessages[Nette\Forms\Form::?] = ?;', array($name, $text));
321: }
322:
323: if ($config['session']['autoStart'] === 'smart') {
324: $initialize->addBody('$this->session->exists() && $this->session->start();');
325: } elseif ($config['session']['autoStart']) {
326: $initialize->addBody('$this->session->start();');
327: }
328:
329: if (empty($config['xhtml'])) {
330: $initialize->addBody('Nette\Utils\Html::$xhtml = ?;', array((bool) $config['xhtml']));
331: }
332:
333: if (isset($config['security']['frames']) && $config['security']['frames'] !== TRUE) {
334: $frames = $config['security']['frames'];
335: if ($frames === FALSE) {
336: $frames = 'DENY';
337: } elseif (preg_match('#^https?:#', $frames)) {
338: $frames = "ALLOW-FROM $frames";
339: }
340: $initialize->addBody('header(?);', array("X-Frame-Options: $frames"));
341: }
342:
343: foreach ($container->findByTag('run') as $name => $on) {
344: if ($on) {
345: $initialize->addBody('$this->getService(?);', array($name));
346: }
347: }
348: }
349:
350:
351:
352: private function checkTempDir($dir)
353: {
354:
355: $uniq = uniqid('_', TRUE);
356: if (!@mkdir("$dir/$uniq", 0777)) {
357: throw new Nette\InvalidStateException("Unable to write to directory '$dir'. Make this directory writable.");
358: }
359:
360:
361: $useDirs = @file_put_contents("$dir/$uniq/_", '') !== FALSE;
362: @unlink("$dir/$uniq/_");
363: @rmdir("$dir/$uniq");
364:
365: return 'Nette\Caching\Storages\FileStorage::$useDirectories = ' . ($useDirs ? 'TRUE' : 'FALSE') . ";\n";
366: }
367:
368: }
369: