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