Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • ApplicationExtension
  • LatteExtension
  • PresenterFactoryCallback
  • RoutingExtension
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Bridges\ApplicationDI;
  9: 
 10: use Composer\Autoload\ClassLoader;
 11: use Nette;
 12: use Nette\Application\UI;
 13: use Tracy;
 14: 
 15: 
 16: /**
 17:  * Application extension for Nette DI.
 18:  */
 19: class ApplicationExtension extends Nette\DI\CompilerExtension
 20: {
 21:     public $defaults = [
 22:         'debugger' => null,
 23:         'errorPresenter' => 'Nette:Error',
 24:         'catchExceptions' => null,
 25:         'mapping' => null,
 26:         'scanDirs' => [],
 27:         'scanComposer' => null,
 28:         'scanFilter' => 'Presenter',
 29:         'silentLinks' => false,
 30:     ];
 31: 
 32:     /** @var bool */
 33:     private $debugMode;
 34: 
 35:     /** @var int */
 36:     private $invalidLinkMode;
 37: 
 38:     /** @var string */
 39:     private $tempFile;
 40: 
 41: 
 42:     public function __construct($debugMode = false, array $scanDirs = null, $tempDir = null)
 43:     {
 44:         $this->defaults['debugger'] = interface_exists(Tracy\IBarPanel::class);
 45:         $this->defaults['scanDirs'] = (array) $scanDirs;
 46:         $this->defaults['scanComposer'] = class_exists(ClassLoader::class);
 47:         $this->defaults['catchExceptions'] = !$debugMode;
 48:         $this->debugMode = $debugMode;
 49:         $this->tempFile = $tempDir ? $tempDir . '/' . urlencode(__CLASS__) : null;
 50:     }
 51: 
 52: 
 53:     public function loadConfiguration()
 54:     {
 55:         $config = $this->validateConfig($this->defaults);
 56:         $builder = $this->getContainerBuilder();
 57:         $builder->addExcludedClasses([UI\Presenter::class]);
 58: 
 59:         $this->invalidLinkMode = $this->debugMode
 60:             ? UI\Presenter::INVALID_LINK_TEXTUAL | ($config['silentLinks'] ? 0 : UI\Presenter::INVALID_LINK_WARNING)
 61:             : UI\Presenter::INVALID_LINK_WARNING;
 62: 
 63:         $application = $builder->addDefinition($this->prefix('application'))
 64:             ->setFactory(Nette\Application\Application::class)
 65:             ->addSetup('$catchExceptions', [$config['catchExceptions']])
 66:             ->addSetup('$errorPresenter', [$config['errorPresenter']]);
 67: 
 68:         if ($config['debugger']) {
 69:             $application->addSetup('Nette\Bridges\ApplicationTracy\RoutingPanel::initializePanel');
 70:         }
 71: 
 72:         $touch = $this->debugMode && $config['scanDirs'] ? $this->tempFile : null;
 73:         $presenterFactory = $builder->addDefinition($this->prefix('presenterFactory'))
 74:             ->setClass(Nette\Application\IPresenterFactory::class)
 75:             ->setFactory(Nette\Application\PresenterFactory::class, [new Nette\DI\Statement(
 76:                 Nette\Bridges\ApplicationDI\PresenterFactoryCallback::class, [1 => $this->invalidLinkMode, $touch]
 77:             )]);
 78: 
 79:         if ($config['mapping']) {
 80:             $presenterFactory->addSetup('setMapping', [$config['mapping']]);
 81:         }
 82: 
 83:         $builder->addDefinition($this->prefix('linkGenerator'))
 84:             ->setFactory(Nette\Application\LinkGenerator::class, [
 85:                 1 => new Nette\DI\Statement('@Nette\Http\IRequest::getUrl'),
 86:             ]);
 87: 
 88:         if ($this->name === 'application') {
 89:             $builder->addAlias('application', $this->prefix('application'));
 90:             $builder->addAlias('nette.presenterFactory', $this->prefix('presenterFactory'));
 91:         }
 92:     }
 93: 
 94: 
 95:     public function beforeCompile()
 96:     {
 97:         $builder = $this->getContainerBuilder();
 98:         $all = [];
 99: 
100:         foreach ($builder->findByType(Nette\Application\IPresenter::class) as $def) {
101:             $all[$def->getClass()] = $def;
102:         }
103: 
104:         $counter = 0;
105:         foreach ($this->findPresenters() as $class) {
106:             if (empty($all[$class])) {
107:                 $all[$class] = $builder->addDefinition($this->prefix(++$counter))->setClass($class);
108:             }
109:         }
110: 
111:         foreach ($all as $def) {
112:             $def->addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT)
113:                 ->addTag('nette.presenter', $def->getClass());
114: 
115:             if (is_subclass_of($def->getClass(), UI\Presenter::class)) {
116:                 $def->addSetup('$invalidLinkMode', [$this->invalidLinkMode]);
117:             }
118:         }
119:     }
120: 
121: 
122:     /** @return string[] */
123:     private function findPresenters()
124:     {
125:         $config = $this->getConfig();
126:         $classes = [];
127: 
128:         if ($config['scanDirs']) {
129:             if (!class_exists(Nette\Loaders\RobotLoader::class)) {
130:                 throw new Nette\NotSupportedException("RobotLoader is required to find presenters, install package `nette/robot-loader` or disable option {$this->prefix('scanDirs')}: false");
131:             }
132:             $robot = new Nette\Loaders\RobotLoader;
133:             $robot->addDirectory($config['scanDirs']);
134:             $robot->acceptFiles = ['*' . $config['scanFilter'] . '*.php'];
135:             $robot->rebuild();
136:             $classes = array_keys($robot->getIndexedClasses());
137:             $this->getContainerBuilder()->addDependency($this->tempFile);
138:         }
139: 
140:         if ($config['scanComposer']) {
141:             $rc = new \ReflectionClass(ClassLoader::class);
142:             $classFile = dirname($rc->getFileName()) . '/autoload_classmap.php';
143:             if (is_file($classFile)) {
144:                 $this->getContainerBuilder()->addDependency($classFile);
145:                 $classes = array_merge($classes, array_keys(call_user_func(function ($path) {
146:                     return require $path;
147:                 }, $classFile)));
148:             }
149:         }
150: 
151:         $presenters = [];
152:         foreach (array_unique($classes) as $class) {
153:             if (
154:                 strpos($class, $config['scanFilter']) !== false
155:                 && class_exists($class)
156:                 && ($rc = new \ReflectionClass($class))
157:                 && $rc->implementsInterface(Nette\Application\IPresenter::class)
158:                 && !$rc->isAbstract()
159:             ) {
160:                 $presenters[] = $rc->getName();
161:             }
162:         }
163:         return $presenters;
164:     }
165: }
166: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0