Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

  • NetteAccessor
  • NetteExtension
  • TracyBridge
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Bridges\Framework;
  9: 
 10: use Nette,
 11:     Nette\DI\ContainerBuilder,
 12:     Nette\Utils\Validators,
 13:     Latte;
 14: 
 15: 
 16: /**
 17:  * Core Nette Framework services.
 18:  *
 19:  * @author     David Grudl
 20:  */
 21: class NetteExtension extends Nette\DI\CompilerExtension
 22: {
 23:     public $defaults = array(
 24:         'http' => array(
 25:             'proxy' => array(),
 26:             'headers' => array(
 27:                 'X-Powered-By' => 'Nette Framework',
 28:                 'Content-Type' => 'text/html; charset=utf-8',
 29:             ),
 30:         ),
 31:         'session' => array(
 32:             'debugger' => FALSE,
 33:             'autoStart' => 'smart', // true|false|smart
 34:             'expiration' => NULL,
 35:         ),
 36:         'application' => array(
 37:             'debugger' => TRUE,
 38:             'errorPresenter' => 'Nette:Error',
 39:             'catchExceptions' => '%productionMode%',
 40:             'mapping' => NULL
 41:         ),
 42:         'routing' => array(
 43:             'debugger' => TRUE,
 44:             'routes' => array(), // of [mask => action]
 45:         ),
 46:         'security' => array(
 47:             'debugger' => TRUE,
 48:             'frames' => 'SAMEORIGIN', // X-Frame-Options
 49:             'users' => array(), // of [user => password] or [user => ['password' => password, 'roles' => [role]]]
 50:             'roles' => array(), // of [role => parents]
 51:             'resources' => array(), // of [resource => parents]
 52:         ),
 53:         'mailer' => array(
 54:             'smtp' => FALSE,
 55:             'host' => NULL,
 56:             'port' => NULL,
 57:             'username' => NULL,
 58:             'password' => NULL,
 59:             'secure' => NULL,
 60:             'timeout' => NULL,
 61:         ),
 62:         'database' => array(), // BC
 63:         'forms' => array(
 64:             'messages' => array(),
 65:         ),
 66:         'latte' => array(
 67:             'xhtml' => FALSE,
 68:             'macros' => array(),
 69:         ),
 70:         'container' => array(
 71:             'debugger' => FALSE,
 72:             'accessors' => TRUE,
 73:         ),
 74:         'debugger' => array(
 75:             'email' => NULL,
 76:             'editor' => NULL,
 77:             'browser' => NULL,
 78:             'strictMode' => NULL,
 79:             'maxLen' => NULL,
 80:             'maxDepth' => NULL,
 81:             'showLocation' => NULL,
 82:             'scream' => NULL,
 83:             'bar' => array(), // of class name
 84:             'blueScreen' => array(), // of callback
 85:         ),
 86:     );
 87: 
 88: 
 89:     public function loadConfiguration()
 90:     {
 91:         $container = $this->getContainerBuilder();
 92:         $config = $this->getConfig($this->defaults);
 93: 
 94:         if (isset($config['xhtml'])) {
 95:             $config['latte']['xhtml'] = $config['xhtml'];
 96:             unset($config['xhtml']);
 97:         }
 98:         $container->addDefinition('nette')->setClass('Nette\Bridges\Framework\NetteAccessor', array('@container'));
 99: 
100:         $this->validate($config, $this->defaults, 'nette');
101: 
102:         $this->setupCache($container);
103:         $this->setupHttp($container, $config['http']);
104:         $this->setupSession($container, $config['session']);
105:         $this->setupSecurity($container, $config['security']);
106:         $this->setupApplication($container, $config['application']);
107:         $this->setupRouting($container, $config['routing']);
108:         $this->setupMailer($container, $config['mailer']);
109:         $this->setupLatte($container, $config['latte']);
110:         $this->setupContainer($container, $config['container']);
111:     }
112: 
113: 
114:     private function setupCache(ContainerBuilder $container)
115:     {
116:         $container->addDefinition($this->prefix('cacheJournal'))
117:             ->setClass('Nette\Caching\Storages\FileJournal', array($container->expand('%tempDir%')));
118: 
119:         $container->addDefinition('cacheStorage') // no namespace for back compatibility
120:             ->setClass('Nette\Caching\Storages\FileStorage', array($container->expand('%tempDir%/cache')));
121: 
122:         if (class_exists('Nette\Caching\Storages\PhpFileStorage')) {
123:             $container->addDefinition($this->prefix('templateCacheStorage'))
124:                 ->setClass('Nette\Caching\Storages\PhpFileStorage', array($container->expand('%tempDir%/cache')))
125:                 ->addSetup('::trigger_error', array('Service templateCacheStorage is deprecated.', E_USER_DEPRECATED))
126:                 ->setAutowired(FALSE);
127:         }
128: 
129:         $container->addDefinition($this->prefix('cache'))
130:             ->setClass('Nette\Caching\Cache', array(1 => $container::literal('$namespace')))
131:             ->addSetup('::trigger_error', array('Service cache is deprecated.', E_USER_DEPRECATED))
132:             ->setParameters(array('namespace' => NULL))
133:             ->setAutowired(FALSE);
134:     }
135: 
136: 
137:     private function setupHttp(ContainerBuilder $container, array $config)
138:     {
139:         $this->validate($config, $this->defaults['http'], 'nette.http');
140: 
141:         $container->addDefinition($this->prefix('httpRequestFactory'))
142:             ->setClass('Nette\Http\RequestFactory')
143:             ->addSetup('setProxy', array($config['proxy']));
144: 
145:         $container->addDefinition('httpRequest') // no namespace for back compatibility
146:             ->setClass('Nette\Http\Request')
147:             ->setFactory('@Nette\Http\RequestFactory::createHttpRequest');
148: 
149:         $container->addDefinition('httpResponse') // no namespace for back compatibility
150:             ->setClass('Nette\Http\Response');
151: 
152:         $container->addDefinition($this->prefix('httpContext'))
153:             ->setClass('Nette\Http\Context');
154:     }
155: 
156: 
157:     private function setupSession(ContainerBuilder $container, array $config)
158:     {
159:         $session = $container->addDefinition('session') // no namespace for back compatibility
160:             ->setClass('Nette\Http\Session');
161: 
162:         if (isset($config['expiration'])) {
163:             $session->addSetup('setExpiration', array($config['expiration']));
164:         }
165: 
166:         if ($container->parameters['debugMode'] && $config['debugger']) {
167:             $session->addSetup('Tracy\Debugger::getBar()->addPanel(?)', array(
168:                 new Nette\DI\Statement('Nette\Bridges\HttpTracy\SessionPanel')
169:             ));
170:         }
171: 
172:         unset($config['expiration'], $config['autoStart'], $config['debugger']);
173:         if (!empty($config)) {
174:             $session->addSetup('setOptions', array($config));
175:         }
176:     }
177: 
178: 
179:     private function setupSecurity(ContainerBuilder $container, array $config)
180:     {
181:         $this->validate($config, $this->defaults['security'], 'nette.security');
182: 
183:         $container->addDefinition($this->prefix('userStorage'))
184:             ->setClass('Nette\Http\UserStorage');
185: 
186:         $user = $container->addDefinition('user') // no namespace for back compatibility
187:             ->setClass('Nette\Security\User');
188: 
189:         if ($container->parameters['debugMode'] && $config['debugger']) {
190:             $user->addSetup('Tracy\Debugger::getBar()->addPanel(?)', array(
191:                 new Nette\DI\Statement('Nette\Bridges\SecurityTracy\UserPanel')
192:             ));
193:         }
194: 
195:         if ($config['users']) {
196:             $usersList = $usersRoles = array();
197:             foreach ($config['users'] as $username => $data) {
198:                 $usersList[$username] = is_array($data) ? $data['password'] : $data;
199:                 $usersRoles[$username] = is_array($data) && isset($data['roles']) ? $data['roles'] : NULL;
200:             }
201: 
202:             $container->addDefinition($this->prefix('authenticator'))
203:                 ->setClass('Nette\Security\SimpleAuthenticator', array($usersList, $usersRoles));
204:         }
205: 
206:         if ($config['roles'] || $config['resources']) {
207:             $authorizator = $container->addDefinition($this->prefix('authorizator'))
208:                 ->setClass('Nette\Security\Permission');
209:             foreach ($config['roles'] as $role => $parents) {
210:                 $authorizator->addSetup('addRole', array($role, $parents));
211:             }
212:             foreach ($config['resources'] as $resource => $parents) {
213:                 $authorizator->addSetup('addResource', array($resource, $parents));
214:             }
215:         }
216:     }
217: 
218: 
219:     private function setupApplication(ContainerBuilder $container, array $config)
220:     {
221:         $this->validate($config, $this->defaults['application'], 'nette.application');
222: 
223:         $application = $container->addDefinition('application') // no namespace for back compatibility
224:             ->setClass('Nette\Application\Application')
225:             ->addSetup('$catchExceptions', array($config['catchExceptions']))
226:             ->addSetup('$errorPresenter', array($config['errorPresenter']));
227: 
228:         if ($config['debugger']) {
229:             $application->addSetup('Nette\Bridges\ApplicationTracy\RoutingPanel::initializePanel');
230:         }
231: 
232:         $presenterFactory = $container->addDefinition($this->prefix('presenterFactory'))
233:             ->setClass('Nette\Application\PresenterFactory', array(
234:                 isset($container->parameters['appDir']) ? $container->parameters['appDir'] : NULL
235:             ));
236:         if ($config['mapping']) {
237:             $presenterFactory->addSetup('setMapping', array($config['mapping']));
238:         }
239:     }
240: 
241: 
242:     private function setupRouting(ContainerBuilder $container, array $config)
243:     {
244:         $this->validate($config, $this->defaults['routing'], 'nette.routing');
245: 
246:         $router = $container->addDefinition('router') // no namespace for back compatibility
247:             ->setClass('Nette\Application\Routers\RouteList');
248: 
249:         foreach ($config['routes'] as $mask => $action) {
250:             $router->addSetup('$service[] = new Nette\Application\Routers\Route(?, ?);', array($mask, $action));
251:         }
252: 
253:         if ($container->parameters['debugMode'] && $config['debugger']) {
254:             $container->getDefinition('application')->addSetup('Tracy\Debugger::getBar()->addPanel(?)', array(
255:                 new Nette\DI\Statement('Nette\Bridges\ApplicationTracy\RoutingPanel')
256:             ));
257:         }
258:     }
259: 
260: 
261:     private function setupMailer(ContainerBuilder $container, array $config)
262:     {
263:         $this->validate($config, $this->defaults['mailer'], 'nette.mailer');
264: 
265:         if (empty($config['smtp'])) {
266:             $container->addDefinition($this->prefix('mailer'))
267:                 ->setClass('Nette\Mail\SendmailMailer');
268:         } else {
269:             $container->addDefinition($this->prefix('mailer'))
270:                 ->setClass('Nette\Mail\SmtpMailer', array($config));
271:         }
272:     }
273: 
274: 
275:     private function setupLatte(ContainerBuilder $container, array $config)
276:     {
277:         $this->validate($config, $this->defaults['latte'], 'nette.latte');
278: 
279:         $latteFactory = $container->addDefinition($this->prefix('latteFactory'))
280:             ->setClass('Latte\Engine')
281:             ->addSetup('setTempDirectory', array($container->expand('%tempDir%/cache/latte')))
282:             ->addSetup('setAutoRefresh', array($container->parameters['debugMode']))
283:             ->addSetup('setContentType', array($config['xhtml'] ? Latte\Compiler::CONTENT_XHTML : Latte\Compiler::CONTENT_HTML))
284:             ->setImplement('Nette\Bridges\ApplicationLatte\ILatteFactory');
285: 
286:         $container->addDefinition($this->prefix('templateFactory'))
287:             ->setClass('Nette\Bridges\ApplicationLatte\TemplateFactory');
288: 
289:         $latte = $container->addDefinition($this->prefix('latte')) // deprecated
290:             ->setClass('Latte\Engine')
291:             ->addSetup('setTempDirectory', array($container->expand('%tempDir%/cache/latte')))
292:             ->addSetup('setAutoRefresh', array($container->parameters['debugMode']))
293:             ->addSetup('setContentType', array($config['xhtml'] ? Latte\Compiler::CONTENT_XHTML : Latte\Compiler::CONTENT_HTML))
294:             ->setAutowired(FALSE);
295: 
296:         foreach ($config['macros'] as $macro) {
297:             if (strpos($macro, '::') === FALSE && class_exists($macro)) {
298:                 $macro .= '::install';
299:             } else {
300:                 Validators::assert($macro, 'callable');
301:             }
302:             $latte->addSetup('?->onCompile[] = function($engine) { ' . $macro . '($engine->getCompiler()); }', array('@self'));
303:             $latteFactory->addSetup('?->onCompile[] = function($engine) { ' . $macro . '($engine->getCompiler()); }', array('@self'));
304:         }
305: 
306:         if (class_exists('Nette\Templating\FileTemplate')) {
307:             $container->addDefinition($this->prefix('template')) // deprecated
308:                 ->setClass('Nette\Templating\FileTemplate')
309:                 ->addSetup('registerFilter', array(new Nette\DI\Statement(array($latteFactory, 'create'))))
310:                 ->addSetup('registerHelperLoader', array('Nette\Templating\Helpers::loader'))
311:                 ->setAutowired(FALSE);
312:         }
313:     }
314: 
315: 
316:     private function setupContainer(ContainerBuilder $container, array $config)
317:     {
318:         $this->validate($config, $this->defaults['container'], 'nette.container');
319: 
320:         if ($config['accessors']) {
321:             $container->parameters['container']['accessors'] = TRUE;
322:         }
323:     }
324: 
325: 
326:     public function afterCompile(Nette\PhpGenerator\ClassType $class)
327:     {
328:         $initialize = $class->methods['initialize'];
329:         $container = $this->getContainerBuilder();
330:         $config = $this->getConfig($this->defaults);
331: 
332:         // debugger
333:         $initialize->addBody('Nette\Bridges\Framework\TracyBridge::initialize();');
334: 
335:         foreach (array('email', 'editor', 'browser', 'strictMode', 'maxLen', 'maxDepth', 'showLocation', 'scream') as $key) {
336:             if (isset($config['debugger'][$key])) {
337:                 $initialize->addBody('Tracy\Debugger::$? = ?;', array($key, $config['debugger'][$key]));
338:             }
339:         }
340: 
341:         if ($container->parameters['debugMode']) {
342:             if ($config['container']['debugger']) {
343:                 $config['debugger']['bar'][] = 'Nette\Bridges\DITracy\ContainerPanel';
344:             }
345: 
346:             foreach ((array) $config['debugger']['bar'] as $item) {
347:                 $initialize->addBody($container->formatPhp(
348:                     'Tracy\Debugger::getBar()->addPanel(?);',
349:                     Nette\DI\Compiler::filterArguments(array(is_string($item) ? new Nette\DI\Statement($item) : $item))
350:                 ));
351:             }
352:         }
353: 
354:         foreach ((array) $config['debugger']['blueScreen'] as $item) {
355:             $initialize->addBody($container->formatPhp(
356:                     'Tracy\Debugger::getBlueScreen()->addPanel(?);',
357:                 Nette\DI\Compiler::filterArguments(array($item))
358:             ));
359:         }
360: 
361:         if (!empty($container->parameters['tempDir'])) {
362:             $initialize->addBody('Nette\Caching\Storages\FileStorage::$useDirectories = ?;', array($this->checkTempDir($container->expand('%tempDir%/cache'))));
363:         }
364: 
365:         foreach ((array) $config['forms']['messages'] as $name => $text) {
366:             $initialize->addBody('Nette\Forms\Rules::$defaultMessages[Nette\Forms\Form::?] = ?;', array($name, $text));
367:         }
368: 
369:         if ($config['session']['autoStart'] === 'smart') {
370:             $initialize->addBody('$this->getByType("Nette\Http\Session")->exists() && $this->getByType("Nette\Http\Session")->start();');
371:         } elseif ($config['session']['autoStart']) {
372:             $initialize->addBody('$this->getByType("Nette\Http\Session")->start();');
373:         }
374: 
375:         if ($config['latte']['xhtml']) {
376:             $initialize->addBody('Nette\Utils\Html::$xhtml = ?;', array(TRUE));
377:         }
378: 
379:         if (isset($config['security']['frames']) && $config['security']['frames'] !== TRUE) {
380:             $frames = $config['security']['frames'];
381:             if ($frames === FALSE) {
382:                 $frames = 'DENY';
383:             } elseif (preg_match('#^https?:#', $frames)) {
384:                 $frames = "ALLOW-FROM $frames";
385:             }
386:             $initialize->addBody('header(?);', array("X-Frame-Options: $frames"));
387:         }
388: 
389:         foreach ($container->findByTag('run') as $name => $on) {
390:             if ($on) {
391:                 $initialize->addBody('$this->getService(?);', array($name));
392:             }
393:         }
394: 
395:         if (!empty($config['container']['accessors'])) {
396:             $definitions = $container->definitions;
397:             ksort($definitions);
398:             foreach ($definitions as $name => $def) {
399:                 if (Nette\PhpGenerator\Helpers::isIdentifier($name)) {
400:                     $type = $def->implement ?: $def->class;
401:                     $class->addDocument("@property $type \$$name");
402:                 }
403:             }
404:         }
405: 
406:         foreach ($config['http']['headers'] as $key => $value) {
407:             if ($value != NULL) { // intentionally ==
408:                 $initialize->addBody('header(?);', array("$key: $value"));
409:             }
410:         }
411: 
412:         $initialize->addBody('Nette\Utils\SafeStream::register();');
413:         $initialize->addBody('Nette\Reflection\AnnotationsParser::setCacheStorage($this->getByType("Nette\Caching\IStorage"));');
414:         $initialize->addBody('Nette\Reflection\AnnotationsParser::$autoRefresh = ?;', array($container->parameters['debugMode']));
415:     }
416: 
417: 
418:     private function checkTempDir($dir)
419:     {
420:         // checks whether directory is writable
421:         $uniq = uniqid('_', TRUE);
422:         if (!@mkdir("$dir/$uniq")) { // @ - is escalated to exception
423:             throw new Nette\InvalidStateException("Unable to write to directory '$dir'. Make this directory writable.");
424:         }
425: 
426:         // checks whether subdirectory is writable
427:         $isWritable = @file_put_contents("$dir/$uniq/_", '') !== FALSE; // @ - error is expected
428:         if ($isWritable) {
429:             unlink("$dir/$uniq/_");
430:         }
431:         rmdir("$dir/$uniq");
432:         return $isWritable;
433:     }
434: 
435: 
436:     private function validate(array $config, array $expected, $name)
437:     {
438:         if ($extra = array_diff_key($config, $expected)) {
439:             $extra = implode(", $name.", array_keys($extra));
440:             throw new Nette\InvalidStateException("Unknown option $name.$extra.");
441:         }
442:     }
443: 
444: }
445: 
Nette 2.2.2 API API documentation generated by ApiGen 2.8.0