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' => 'smart',
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' => 'SAMEORIGIN',
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: public function loadConfiguration()
78: {
79: $container = $this->getContainerBuilder();
80: $config = $this->getConfig($this->defaults);
81:
82:
83:
84: $container->addDefinition($this->prefix('cacheJournal'))
85: ->setClass('NFileJournal', array('%tempDir%'));
86:
87: $container->addDefinition('cacheStorage')
88: ->setClass('NFileStorage', array('%tempDir%/cache'));
89:
90: $container->addDefinition($this->prefix('templateCacheStorage'))
91: ->setClass('NPhpFileStorage', array('%tempDir%/cache'))
92: ->setAutowired(FALSE);
93:
94: $container->addDefinition($this->prefix('cache'))
95: ->setClass('NCache', array(1 => '%namespace%'))
96: ->setParameters(array('namespace' => NULL));
97:
98:
99:
100: $container->addDefinition($this->prefix('httpRequestFactory'))
101: ->setClass('NHttpRequestFactory')
102: ->addSetup('setEncoding', array('UTF-8'))
103: ->setInternal(TRUE);
104:
105: $container->addDefinition('httpRequest')
106: ->setClass('NHttpRequest')
107: ->setFactory('@\NHttpRequestFactory::createHttpRequest');
108:
109: $container->addDefinition('httpResponse')
110: ->setClass('NHttpResponse');
111:
112: $container->addDefinition($this->prefix('httpContext'))
113: ->setClass('NHttpContext');
114:
115:
116:
117: $session = $container->addDefinition('session')
118: ->setClass('NSession');
119:
120: if (isset($config['session']['expiration'])) {
121: $session->addSetup('setExpiration', array($config['session']['expiration']));
122: }
123: if (isset($config['session']['iAmUsingBadHost'])) {
124: $session->addSetup('NFramework::$iAmUsingBadHost = ?;', array((bool) $config['session']['iAmUsingBadHost']));
125: }
126: unset($config['session']['expiration'], $config['session']['autoStart'], $config['session']['iAmUsingBadHost']);
127: if (!empty($config['session'])) {
128: $session->addSetup('setOptions', array($config['session']));
129: }
130:
131:
132:
133: $container->addDefinition($this->prefix('userStorage'))
134: ->setClass('NUserStorage');
135:
136: $user = $container->addDefinition('user')
137: ->setClass('NUser');
138:
139: if (!$container->parameters['productionMode'] && $config['security']['debugger']) {
140: $user->addSetup('NDebugger::$bar->addPanel(?)', array(
141: new NDIStatement('NUserPanel')
142: ));
143: }
144:
145: if ($config['security']['users']) {
146: $container->addDefinition($this->prefix('authenticator'))
147: ->setClass('NSimpleAuthenticator', array($config['security']['users']));
148: }
149:
150: if ($config['security']['roles'] || $config['security']['resources']) {
151: $authorizator = $container->addDefinition($this->prefix('authorizator'))
152: ->setClass('NPermission');
153: foreach ($config['security']['roles'] as $role => $parents) {
154: $authorizator->addSetup('addRole', array($role, $parents));
155: }
156: foreach ($config['security']['resources'] as $resource => $parents) {
157: $authorizator->addSetup('addResource', array($resource, $parents));
158: }
159: }
160:
161:
162:
163: $application = $container->addDefinition('application')
164: ->setClass('NApplication')
165: ->addSetup('$catchExceptions', $config['application']['catchExceptions'])
166: ->addSetup('$errorPresenter', $config['application']['errorPresenter']);
167:
168: if ($config['application']['debugger']) {
169: $application->addSetup('NRoutingDebugger::initializePanel');
170: }
171:
172: $container->addDefinition($this->prefix('presenterFactory'))
173: ->setClass('NPresenterFactory', array(
174: isset($container->parameters['appDir']) ? $container->parameters['appDir'] : NULL
175: ));
176:
177:
178:
179: $router = $container->addDefinition('router')
180: ->setClass('NRouteList');
181:
182: foreach ($config['routing']['routes'] as $mask => $action) {
183: $router->addSetup('$service[] = new NRoute(?, ?);', array($mask, $action));
184: }
185:
186: if (!$container->parameters['productionMode'] && $config['routing']['debugger']) {
187: $application->addSetup('NDebugger::$bar->addPanel(?)', array(
188: new NDIStatement('NRoutingDebugger')
189: ));
190: }
191:
192:
193:
194: if (empty($config['mailer']['smtp'])) {
195: $container->addDefinition($this->prefix('mailer'))
196: ->setClass('NSendmailMailer');
197: } else {
198: $container->addDefinition($this->prefix('mailer'))
199: ->setClass('NSmtpMailer', array($config['mailer']));
200: }
201:
202: $container->addDefinition($this->prefix('mail'))
203: ->setClass('NMail')
204: ->addSetup('setMailer')
205: ->setShared(FALSE);
206:
207:
208:
209: $container->addDefinition($this->prefix('basicForm'))
210: ->setClass('NForm')
211: ->setShared(FALSE);
212:
213:
214:
215: $latte = $container->addDefinition($this->prefix('latte'))
216: ->setClass('NLatteFilter')
217: ->setShared(FALSE);
218:
219: if (empty($config['xhtml'])) {
220: $latte->addSetup('$service->getCompiler()->defaultContentType = ?', NLatteCompiler::CONTENT_HTML);
221: }
222:
223: $container->addDefinition($this->prefix('template'))
224: ->setClass('NFileTemplate')
225: ->addSetup('registerFilter', array($latte))
226: ->addSetup('registerHelperLoader', array('NTemplateHelpers::loader'))
227: ->setShared(FALSE);
228:
229:
230:
231: $container->addDefinition($this->prefix('database'))
232: ->setClass('NDINestedAccessor', array('@container', $this->prefix('database')));
233:
234: if (isset($config['database']['dsn'])) {
235: $config['database'] = array('default' => $config['database']);
236: }
237:
238: $autowired = TRUE;
239: foreach ((array) $config['database'] as $name => $info) {
240: if (!is_array($info)) {
241: continue;
242: }
243: $info += $this->databaseDefaults + array('autowired' => $autowired);
244: $autowired = FALSE;
245:
246: foreach ((array) $info['options'] as $key => $value) {
247: if (preg_match('#^PDO::\w+\z#', $key)) {
248: unset($info['options'][$key]);
249: $info['options'][constant($key)] = $value;
250: }
251: }
252:
253: $connection = $container->addDefinition($this->prefix("database.$name"))
254: ->setClass('NConnection', array($info['dsn'], $info['user'], $info['password'], $info['options']))
255: ->setAutowired($info['autowired'])
256: ->addSetup('setCacheStorage')
257: ->addSetup('NDebugger::$blueScreen->addPanel(?)', array(
258: 'NDatabasePanel::renderException'
259: ));
260:
261: if ($info['reflection']) {
262: $connection->addSetup('setDatabaseReflection', is_string($info['reflection'])
263: ? array(new NDIStatement(preg_match('#^[a-z]+\z#', $info['reflection']) ? 'Nette\Database\Reflection\\' . ucfirst($info['reflection']) . 'Reflection' : $info['reflection']))
264: : NConfigCompiler::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('NDatabasePanel')
271: ->setAutowired(FALSE)
272: ->addSetup('$explain', !empty($info['explain']))
273: ->addSetup('$name', $name)
274: ->addSetup('NDebugger::$bar->addPanel(?)', array('@self'));
275:
276: $connection->addSetup('$service->onQuery[] = ?', array(array($panel, 'logQuery')));
277: }
278: }
279: }
280:
281:
282: public function afterCompile(NPhpClassType $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('NDebugger::$? = ?;', array($key, $config['debugger'][$key]));
292: }
293: }
294:
295: if (!$container->parameters['productionMode']) {
296: if ($config['container']['debugger']) {
297: $config['debugger']['bar'][] = 'NContainerPanel';
298: }
299:
300: foreach ((array) $config['debugger']['bar'] as $item) {
301: $initialize->addBody($container->formatPhp(
302: 'NDebugger::$bar->addPanel(?);',
303: NConfigCompiler::filterArguments(array(is_string($item) ? new NDIStatement($item) : $item))
304: ));
305: }
306:
307: foreach ((array) $config['debugger']['blueScreen'] as $item) {
308: $initialize->addBody($container->formatPhp(
309: 'NDebugger::$blueScreen->addPanel(?);',
310: NConfigCompiler::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('NRules::$defaultMessages[NForm::?] = ?;', array($name, $text));
321: }
322:
323: if ($config['session']['autoStart'] === 'smart') {
324: $initialize->addBody('$this->getService("session")->exists() && $this->getService("session")->start();');
325: } elseif ($config['session']['autoStart']) {
326: $initialize->addBody('$this->getService("session")->start();');
327: }
328:
329: if (empty($config['xhtml'])) {
330: $initialize->addBody('NHtml::$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: private function checkTempDir($dir)
352: {
353:
354: $uniq = uniqid('_', TRUE);
355: if (!@mkdir("$dir/$uniq", 0777)) {
356: throw new InvalidStateException("Unable to write to directory '$dir'. Make this directory writable.");
357: }
358:
359:
360: $useDirs = @file_put_contents("$dir/$uniq/_", '') !== FALSE;
361: @unlink("$dir/$uniq/_");
362: @rmdir("$dir/$uniq");
363:
364: return 'NFileStorage::$useDirectories = ' . ($useDirs ? 'TRUE' : 'FALSE') . ";\n";
365: }
366:
367: }
368: