Skip to content

Commit

Permalink
DI extensions: are using configuration Schema
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Mar 26, 2019
1 parent d8141c0 commit 0f0c24c
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 61 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"mockery/mockery": "^1.0"
},
"conflict": {
"nette/di": "<2.4",
"nette/di": "<3.0",
"nette/forms": "<3.0",
"nette/latte": "<3.0"
},
Expand Down
68 changes: 37 additions & 31 deletions src/Bridges/ApplicationDI/ApplicationExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
use Composer\Autoload\ClassLoader;
use Nette;
use Nette\Application\UI;
use Nette\DI\Config\Expect;
use Nette\DI\Definitions;
use Tracy;


Expand All @@ -20,20 +22,12 @@
*/
final class ApplicationExtension extends Nette\DI\CompilerExtension
{
private $defaults = [
'debugger' => null,
'errorPresenter' => 'Nette:Error',
'catchExceptions' => null,
'mapping' => null,
'scanDirs' => [],
'scanComposer' => null,
'scanFilter' => 'Presenter',
'silentLinks' => false,
];

/** @var bool */
private $debugMode;

/** @var array */
private $scanDirs;

/** @var int */
private $invalidLinkMode;

Expand All @@ -43,48 +37,60 @@ final class ApplicationExtension extends Nette\DI\CompilerExtension

public function __construct(bool $debugMode = false, array $scanDirs = null, string $tempDir = null)
{
$this->defaults['debugger'] = interface_exists(Tracy\IBarPanel::class);
$this->defaults['scanDirs'] = (array) $scanDirs;
$this->defaults['scanComposer'] = class_exists(ClassLoader::class);
$this->defaults['catchExceptions'] = !$debugMode;
$this->debugMode = $debugMode;
$this->scanDirs = (array) $scanDirs;
$this->tempDir = $tempDir;
}


public function getConfigSchema(): Nette\DI\Config\Schema
{
return Expect::structure([
'debugger' => Expect::bool(interface_exists(Tracy\IBarPanel::class)),
'errorPresenter' => Expect::string('Nette:Error')->dynamic(),
'catchExceptions' => Expect::bool(!$this->debugMode)->dynamic(),
'mapping' => Expect::arrayOf('string')->dynamic(),
'scanDirs' => Expect::enum(Expect::arrayOf('string')->default($this->scanDirs), false),
'scanComposer' => Expect::bool(class_exists(ClassLoader::class)),
'scanFilter' => Expect::string('Presenter'),
'silentLinks' => Expect::bool(),
]);
}


public function loadConfiguration()
{
$config = $this->validateConfig($this->defaults);
$config = $this->config;
$builder = $this->getContainerBuilder();
$builder->addExcludedClasses([UI\Presenter::class]);

$this->invalidLinkMode = $this->debugMode
? UI\Presenter::INVALID_LINK_TEXTUAL | ($config['silentLinks'] ? 0 : UI\Presenter::INVALID_LINK_WARNING)
? UI\Presenter::INVALID_LINK_TEXTUAL | ($config->silentLinks ? 0 : UI\Presenter::INVALID_LINK_WARNING)
: UI\Presenter::INVALID_LINK_WARNING;

$application = $builder->addDefinition($this->prefix('application'))
->setFactory(Nette\Application\Application::class)
->addSetup('$catchExceptions', [$config['catchExceptions']])
->addSetup('$errorPresenter', [$config['errorPresenter']]);
->addSetup('$catchExceptions', [$config->catchExceptions])
->addSetup('$errorPresenter', [$config->errorPresenter]);

if ($config['debugger']) {
if ($config->debugger) {
$application->addSetup([Nette\Bridges\ApplicationTracy\RoutingPanel::class, 'initializePanel']);
}

$touch = $this->debugMode && $config['scanDirs'] && $this->tempDir ? $this->tempDir . '/touch' : null;
$touch = $this->debugMode && $config->scanDirs && $this->tempDir ? $this->tempDir . '/touch' : null;
$presenterFactory = $builder->addDefinition($this->prefix('presenterFactory'))
->setType(Nette\Application\IPresenterFactory::class)
->setFactory(Nette\Application\PresenterFactory::class, [new Nette\DI\Definitions\Statement(
->setFactory(Nette\Application\PresenterFactory::class, [new Definitions\Statement(
Nette\Bridges\ApplicationDI\PresenterFactoryCallback::class, [1 => $this->invalidLinkMode, $touch]
)]);

if ($config['mapping']) {
$presenterFactory->addSetup('setMapping', [$config['mapping']]);
if ($config->mapping) {
$presenterFactory->addSetup('setMapping', [$config->mapping]);
}

$builder->addDefinition($this->prefix('linkGenerator'))
->setFactory(Nette\Application\LinkGenerator::class, [
1 => new Nette\DI\Definitions\Statement('@Nette\Http\IRequest::getUrl'),
1 => new Definitions\Statement('@Nette\Http\IRequest::getUrl'),
]);

if ($this->name === 'application') {
Expand Down Expand Up @@ -115,7 +121,7 @@ public function beforeCompile()
$def->addTag(Nette\DI\Extensions\InjectExtension::TAG_INJECT)
->setAutowired(false);

if (is_subclass_of($def->getType(), UI\Presenter::class)) {
if (is_subclass_of($def->getType(), UI\Presenter::class) && $def instanceof Definitions\ServiceDefinition) {
$def->addSetup('$invalidLinkMode', [$this->invalidLinkMode]);
}
}
Expand All @@ -127,13 +133,13 @@ private function findPresenters(): array
$config = $this->getConfig();
$classes = [];

if ($config['scanDirs']) {
if ($config->scanDirs) {
if (!class_exists(Nette\Loaders\RobotLoader::class)) {
throw new Nette\NotSupportedException("RobotLoader is required to find presenters, install package `nette/robot-loader` or disable option {$this->prefix('scanDirs')}: false");
}
$robot = new Nette\Loaders\RobotLoader;
$robot->addDirectory(...$config['scanDirs']);
$robot->acceptFiles = ['*' . $config['scanFilter'] . '*.php'];
$robot->addDirectory(...$config->scanDirs);
$robot->acceptFiles = ['*' . $config->scanFilter . '*.php'];
if ($this->tempDir) {
$robot->setTempDirectory($this->tempDir);
$robot->refresh();
Expand All @@ -144,7 +150,7 @@ private function findPresenters(): array
$this->getContainerBuilder()->addDependency($this->tempDir . '/touch');
}

if ($config['scanComposer']) {
if ($config->scanComposer) {
$rc = new \ReflectionClass(ClassLoader::class);
$classFile = dirname($rc->getFileName()) . '/autoload_classmap.php';
if (is_file($classFile)) {
Expand All @@ -158,7 +164,7 @@ private function findPresenters(): array
$presenters = [];
foreach (array_unique($classes) as $class) {
if (
strpos($class, $config['scanFilter']) !== false
strpos($class, $config->scanFilter) !== false
&& class_exists($class)
&& ($rc = new \ReflectionClass($class))
&& $rc->implementsInterface(Nette\Application\IPresenter::class)
Expand Down
30 changes: 17 additions & 13 deletions src/Bridges/ApplicationDI/LatteExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@
*/
final class LatteExtension extends Nette\DI\CompilerExtension
{
public $defaults = [
'xhtml' => false,
'macros' => [],
'templateClass' => null,
'strictTypes' => false,
];

/** @var bool */
private $debugMode;

Expand All @@ -36,6 +29,17 @@ public function __construct(string $tempDir, bool $debugMode = false)
{
$this->tempDir = $tempDir;
$this->debugMode = $debugMode;

$this->config = new class {
/** @var bool */
public $xhtml = false;
/** @var string[] */
public $macros = [];
/** @var ?string */
public $templateClass;
/** @var bool */
public $strictTypes = false;
};
}


Expand All @@ -45,7 +49,7 @@ public function loadConfiguration()
return;
}

$config = $this->validateConfig($this->defaults);
$config = $this->config;
$builder = $this->getContainerBuilder();

$latteFactory = $builder->addFactoryDefinition($this->prefix('latteFactory'))
Expand All @@ -54,19 +58,19 @@ public function loadConfiguration()
->setFactory(Latte\Engine::class)
->addSetup('setTempDirectory', [$this->tempDir])
->addSetup('setAutoRefresh', [$this->debugMode])
->addSetup('setContentType', [$config['xhtml'] ? Latte\Compiler::CONTENT_XHTML : Latte\Compiler::CONTENT_HTML])
->addSetup('Nette\Utils\Html::$xhtml = ?', [(bool) $config['xhtml']]);
->addSetup('setContentType', [$config->xhtml ? Latte\Compiler::CONTENT_XHTML : Latte\Compiler::CONTENT_HTML])
->addSetup('Nette\Utils\Html::$xhtml = ?', [$config->xhtml]);

if ($config['strictTypes']) {
if ($config->strictTypes) {
$latteFactory->addSetup('setStrictTypes', [true]);
}

$builder->addDefinition($this->prefix('templateFactory'))
->setType(Nette\Application\UI\ITemplateFactory::class)
->setFactory(Nette\Bridges\ApplicationLatte\TemplateFactory::class)
->setArguments(['templateClass' => $config['templateClass']]);
->setArguments(['templateClass' => $config->templateClass]);

foreach ($config['macros'] as $macro) {
foreach ($config->macros as $macro) {
$this->addMacro($macro);
}

Expand Down
40 changes: 24 additions & 16 deletions src/Bridges/ApplicationDI/RoutingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Nette\Bridges\ApplicationDI;

use Nette;
use Nette\DI\Definitions;
use Tracy;


Expand All @@ -18,36 +19,38 @@
*/
final class RoutingExtension extends Nette\DI\CompilerExtension
{
public $defaults = [
'debugger' => null,
'routes' => [], // of [mask => action]
'routeClass' => null,
'cache' => false,
];

/** @var bool */
private $debugMode;


public function __construct(bool $debugMode = false)
{
$this->defaults['debugger'] = interface_exists(Tracy\IBarPanel::class);
$this->debugMode = $debugMode;

$this->config = new class {
/** @var bool */
public $debugger;
/** @var string[] */
public $routes = [];
/** @var ?string */
public $routeClass = Nette\Application\Routers\Route::class;
/** @var bool */
public $cache = false;
};
$this->config->debugger = interface_exists(Tracy\IBarPanel::class);
}


public function loadConfiguration()
{
$config = $this->validateConfig($this->defaults);
$builder = $this->getContainerBuilder();

$router = $builder->addDefinition($this->prefix('router'))
->setType(Nette\Application\IRouter::class)
->setFactory(Nette\Application\Routers\RouteList::class);

$routeClass = $config['routeClass'] ?: Nette\Application\Routers\Route::class;
foreach ($config['routes'] as $mask => $action) {
$router->addSetup('$service[] = new ' . $routeClass . '(?, ?)', [$mask, $action]);
foreach ($this->config->routes as $mask => $action) {
$router->addSetup('$service[] = new ' . $this->config->routeClass . '(?, ?)', [$mask, $action]);
}

if ($this->name === 'routing') {
Expand All @@ -60,17 +63,22 @@ public function beforeCompile()
{
$builder = $this->getContainerBuilder();

if ($this->debugMode && $this->config['debugger'] && $application = $builder->getByType(Nette\Application\Application::class)) {
$builder->getDefinition($application)->addSetup('@Tracy\Bar::addPanel', [
new Nette\DI\Definitions\Statement(Nette\Bridges\ApplicationTracy\RoutingPanel::class),
if (
$this->debugMode &&
$this->config->debugger &&
($name = $builder->getByType(Nette\Application\Application::class)) &&
($application = $builder->getDefinition($name)) instanceof Definitions\ServiceDefinition
) {
$application->addSetup('@Tracy\Bar::addPanel', [
new Definitions\Statement(Nette\Bridges\ApplicationTracy\RoutingPanel::class),
]);
}
}


public function afterCompile(Nette\PhpGenerator\ClassType $class)
{
if (!empty($this->config['cache'])) {
if ($this->config->cache) {
$method = $class->getMethod(Nette\DI\Container::getMethodName($this->prefix('router')));
try {
$router = eval($method->getBody());
Expand Down

0 comments on commit 0f0c24c

Please sign in to comment.