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