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' => NULL,
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' => 'DENY',
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: Validators::assertField($config, 'session', 'array');
134: $session->addSetup('setOptions', array($config['session']));
135: }
136:
137:
138:
139: $container->addDefinition($this->prefix('userStorage'))
140: ->setClass('Nette\Http\UserStorage');
141:
142: $user = $container->addDefinition('user')
143: ->setClass('Nette\Security\User');
144:
145: if (!$container->parameters['productionMode'] && $config['security']['debugger']) {
146: $user->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array(
147: new Nette\DI\Statement('Nette\Security\Diagnostics\UserPanel')
148: ));
149: }
150:
151: if ($config['security']['users']) {
152: $container->addDefinition($this->prefix('authenticator'))
153: ->setClass('Nette\Security\SimpleAuthenticator', array($config['security']['users']));
154: }
155:
156: if ($config['security']['roles'] || $config['security']['resources']) {
157: $authorizator = $container->addDefinition($this->prefix('authorizator'))
158: ->setClass('Nette\Security\Permission');
159: foreach ($config['security']['roles'] as $role => $parents) {
160: $authorizator->addSetup('addRole', array($role, $parents));
161: }
162: foreach ($config['security']['resources'] as $resource => $parents) {
163: $authorizator->addSetup('addResource', array($resource, $parents));
164: }
165: }
166:
167:
168:
169: $application = $container->addDefinition('application')
170: ->setClass('Nette\Application\Application')
171: ->addSetup('$catchExceptions', $config['application']['catchExceptions'])
172: ->addSetup('$errorPresenter', $config['application']['errorPresenter']);
173:
174: if ($config['application']['debugger']) {
175: $application->addSetup('Nette\Application\Diagnostics\RoutingPanel::initializePanel');
176: }
177:
178: $container->addDefinition($this->prefix('presenterFactory'))
179: ->setClass('Nette\Application\PresenterFactory', array(
180: isset($container->parameters['appDir']) ? $container->parameters['appDir'] : NULL
181: ));
182:
183:
184:
185: $router = $container->addDefinition('router')
186: ->setClass('Nette\Application\Routers\RouteList');
187:
188: foreach ($config['routing']['routes'] as $mask => $action) {
189: $router->addSetup('$service[] = new Nette\Application\Routers\Route(?, ?);', array($mask, $action));
190: }
191:
192: if (!$container->parameters['productionMode'] && $config['routing']['debugger']) {
193: $application->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array(
194: new Nette\DI\Statement('Nette\Application\Diagnostics\RoutingPanel')
195: ));
196: }
197:
198:
199:
200: if (empty($config['mailer']['smtp'])) {
201: $container->addDefinition($this->prefix('mailer'))
202: ->setClass('Nette\Mail\SendmailMailer');
203: } else {
204: Validators::assertField($config, 'mailer', 'array');
205: $container->addDefinition($this->prefix('mailer'))
206: ->setClass('Nette\Mail\SmtpMailer', array($config['mailer']));
207: }
208:
209: $container->addDefinition($this->prefix('mail'))
210: ->setClass('Nette\Mail\Message')
211: ->addSetup('setMailer')
212: ->setShared(FALSE);
213:
214:
215:
216: $container->addDefinition($this->prefix('basicForm'))
217: ->setClass('Nette\Forms\Form')
218: ->setShared(FALSE);
219:
220:
221:
222: $latte = $container->addDefinition($this->prefix('latte'))
223: ->setClass('Nette\Latte\Engine')
224: ->setShared(FALSE);
225:
226: if (empty($config['xhtml'])) {
227: $latte->addSetup('$service->getCompiler()->defaultContentType = ?', Nette\Latte\Compiler::CONTENT_HTML);
228: }
229:
230: $container->addDefinition($this->prefix('template'))
231: ->setClass('Nette\Templating\FileTemplate')
232: ->addSetup('registerFilter', array($latte))
233: ->addSetup('registerHelperLoader', array('Nette\Templating\Helpers::loader'))
234: ->setShared(FALSE);
235:
236:
237:
238: $container->addDefinition($this->prefix('database'))
239: ->setClass('Nette\DI\NestedAccessor', array('@container', $this->prefix('database')));
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: unset($info['options'][$key]);
251: $info['options'][constant($key)] = $value;
252: }
253:
254: $connection = $container->addDefinition($this->prefix("database.$name"))
255: ->setClass('Nette\Database\Connection', array($info['dsn'], $info['user'], $info['password'], $info['options']))
256: ->setAutowired($info['autowired'])
257: ->addSetup('setCacheStorage')
258: ->addSetup('Nette\Diagnostics\Debugger::$blueScreen->addPanel(?)', array(
259: 'Nette\Database\Diagnostics\ConnectionPanel::renderException'
260: ));
261:
262: if ($info['reflection']) {
263: $connection->addSetup('setDatabaseReflection', is_string($info['reflection'])
264: ? array(new Nette\DI\Statement(preg_match('#^[a-z]+$#', $info['reflection']) ? 'Nette\Database\Reflection\\' . ucfirst($info['reflection']) . 'Reflection' : $info['reflection']))
265: : Nette\Config\Compiler::filterArguments(array($info['reflection']))
266: );
267: }
268:
269: if (!$container->parameters['productionMode'] && $info['debugger']) {
270: $panel = $container->addDefinition($this->prefix("database.{$name}ConnectionPanel"))
271: ->setClass('Nette\Database\Diagnostics\ConnectionPanel')
272: ->setAutowired(FALSE)
273: ->addSetup('$explain', !empty($info['explain']))
274: ->addSetup('Nette\Diagnostics\Debugger::$bar->addPanel(?)', array('@self'));
275:
276: $connection->addSetup('$service->onQuery[] = ?', array(array($panel, 'logQuery')));
277: }
278: }
279: }
280:
281:
282:
283: public function afterCompile(Nette\Utils\PhpGenerator\ClassType $class)
284: {
285: $initialize = $class->methods['initialize'];
286: $container = $this->getContainerBuilder();
287: $config = $this->getConfig($this->defaults);
288:
289:
290: foreach (array('email', 'editor', 'browser', 'strictMode') as $key) {
291: if (isset($config['debugger'][$key])) {
292: $initialize->addBody('Nette\Diagnostics\Debugger::$? = ?;', array($key, $config['debugger'][$key]));
293: }
294: }
295:
296: if (!$container->parameters['productionMode']) {
297: if ($config['container']['debugger']) {
298: $config['debugger']['bar'][] = 'Nette\DI\Diagnostics\ContainerPanel';
299: }
300:
301: foreach ((array) $config['debugger']['bar'] as $item) {
302: $initialize->addBody($container->formatPhp(
303: 'Nette\Diagnostics\Debugger::$bar->addPanel(?);',
304: Nette\Config\Compiler::filterArguments(array(is_string($item) ? new Nette\DI\Statement($item) : $item))
305: ));
306: }
307:
308: foreach ((array) $config['debugger']['blueScreen'] as $item) {
309: $initialize->addBody($container->formatPhp(
310: 'Nette\Diagnostics\Debugger::$blueScreen->addPanel(?);',
311: Nette\Config\Compiler::filterArguments(array($item))
312: ));
313: }
314: }
315:
316: if (!empty($container->parameters['tempDir'])) {
317: $initialize->addBody($this->checkTempDir($container->expand('%tempDir%/cache')));
318: }
319:
320: foreach ((array) $config['forms']['messages'] as $name => $text) {
321: $initialize->addBody('Nette\Forms\Rules::$defaultMessages[Nette\Forms\Form::?] = ?;', array($name, $text));
322: }
323:
324: if ($config['session']['autoStart'] === 'smart') {
325: $initialize->addBody('$this->session->exists() && $this->session->start();');
326: } elseif ($config['session']['autoStart']) {
327: $initialize->addBody('$this->session->start();');
328: }
329:
330: if (empty($config['xhtml'])) {
331: $initialize->addBody('Nette\Utils\Html::$xhtml = ?;', array((bool) $config['xhtml']));
332: }
333:
334: if (isset($config['security']['frames'])) {
335: $initialize->addBody('header(?);', array('X-Frame-Options: ' . $config['security']['frames']));
336: }
337:
338: foreach ($container->findByTag('run') as $name => $on) {
339: if ($on) {
340: $initialize->addBody('$this->getService(?);', array($name));
341: }
342: }
343: }
344:
345:
346:
347: private function checkTempDir($dir)
348: {
349:
350: $uniq = uniqid('_', TRUE);
351: if (!@mkdir("$dir/$uniq", 0777)) {
352: throw new Nette\InvalidStateException("Unable to write to directory '$dir'. Make this directory writable.");
353: }
354:
355:
356: $useDirs = @file_put_contents("$dir/$uniq/_", '') !== FALSE;
357: @unlink("$dir/$uniq/_");
358: @rmdir("$dir/$uniq");
359:
360: return 'Nette\Caching\Storages\FileStorage::$useDirectories = ' . ($useDirs ? 'TRUE' : 'FALSE') . ";\n";
361: }
362:
363: }
364: