diff --git a/WebLoader/Nette/Extension.php b/WebLoader/Nette/Extension.php index 32fc7d9..d994073 100644 --- a/WebLoader/Nette/Extension.php +++ b/WebLoader/Nette/Extension.php @@ -81,8 +81,34 @@ public function loadConfiguration() $loaderFactoryTempPaths = array(); foreach (array('css', 'js') as $type) { + $defaultConfig = $config[$type . 'Defaults']; foreach ($config[$type] as $name => $wlConfig) { - $wlConfig = Helpers::merge($wlConfig, $config[$type . 'Defaults']); + if (Helpers::isInheriting($wlConfig)) { + $parent = Helpers::takeParent($wlConfig); + if (!isset($config[$type][$parent])) { + throw new CompilationException(sprintf( + 'The section %s.%s.%s inherits from %s.%s.%s, but the parent section is not defined.', + $this->name, $type, $name, + $this->name, $type, $parent + )); + } + + $parentConfig = Helpers::merge($defaultConfig, $config[$type][$parent]); + + $mergedConfig = Helpers::merge($parentConfig, $wlConfig); + foreach ($mergedConfig as $key => $val) { + if (is_array($val) && isset($wlConfig[$key])) { + // the Helpers::merge puts the added files to the beginning, but we want them at the end + $mergedConfig[$key] = array_merge($parentConfig[$key], $wlConfig[$key]); + } + } + + $wlConfig = $mergedConfig; + + } else { + $wlConfig = Helpers::merge($wlConfig, $defaultConfig); + } + $this->addWebLoader($builder, $type . ucfirst($name), $wlConfig); $loaderFactoryTempPaths[strtolower($name)] = $wlConfig['tempPath']; diff --git a/tests/Nette/ExtensionTest.php b/tests/Nette/ExtensionTest.php index 2eca0d4..6e1695f 100644 --- a/tests/Nette/ExtensionTest.php +++ b/tests/Nette/ExtensionTest.php @@ -2,6 +2,9 @@ namespace WebLoader\Test\Nette; +use Nette\DI\CompilerExtension; +use Nette\DI\Config\Loader; +use Nette\DI\Statement; use Nette\Utils\Finder; if (!class_exists('Nette\DI\CompilerExtension')) { @@ -27,6 +30,7 @@ private function prepareContainer($class, $configFiles) $configurator = new \Nette\Configurator(); $configurator->setTempDirectory($tempDir); + $configurator->addConfig(__DIR__ . '/../fixtures/nette-reset.neon'); foreach ($configFiles as $file) { $configurator->addConfig($file, FALSE); } @@ -86,4 +90,162 @@ public function testJoinFilesOffInOneService() $this->assertFalse($this->container->getService('webloader.cssJoinOffCompiler')->getJoinFiles()); } + + + public function testSectionsInheritanceCss() + { + $config = new Loader; + $builder = $this->loadConfig($webloader = new \WebLoader\Nette\Extension(), $config->load(__DIR__ . '/../fixtures/extensionInheritanceCss.neon')); + + $this->assertArrayHasKey('webloader.cssCommonFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.cssCommonCompiler', $builder->getDefinitions()); + + $cssCommonFiles = $builder->getDefinition('webloader.cssCommonFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $cssCommonFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.css')), $cssCommonFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.css')), $cssCommonFiles->setup[1]); + $this->assertEquals(new Statement('addRemoteFiles', array(array('https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'))), $cssCommonFiles->setup[2]); + + $this->assertArrayHasKey('webloader.cssFrontFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.cssFrontCompiler', $builder->getDefinitions()); + + $cssFrontFiles = $builder->getDefinition('webloader.cssFrontFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $cssFrontFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.css')), $cssFrontFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.css')), $cssFrontFiles->setup[1]); + $this->assertEquals(new Statement('addFile', array('b.txt')), $cssFrontFiles->setup[2]); + $this->assertEquals(new Statement('addRemoteFiles', array(array('https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'))), $cssFrontFiles->setup[3]); + + $this->assertArrayHasKey('webloader.cssAdminFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.cssAdminCompiler', $builder->getDefinitions()); + + $cssAdminFiles = $builder->getDefinition('webloader.cssAdminFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $cssAdminFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.css')), $cssAdminFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.css')), $cssAdminFiles->setup[1]); + $this->assertEquals(new Statement('addFile', array('a.txt')), $cssAdminFiles->setup[2]); + $this->assertEquals(new Statement('addRemoteFiles', array(array('https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css'))), $cssAdminFiles->setup[3]); + } + + + + public function testSectionsInheritanceJs() + { + $config = new Loader; + $builder = $this->loadConfig($webloader = new \WebLoader\Nette\Extension(), $config->load(__DIR__ . '/../fixtures/extensionInheritanceJs.neon')); + + $this->assertArrayHasKey('webloader.jsCommonFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.jsCommonCompiler', $builder->getDefinitions()); + + $jsCommonFiles = $builder->getDefinition('webloader.jsCommonFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $jsCommonFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.js')), $jsCommonFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.js')), $jsCommonFiles->setup[1]); + $this->assertEquals(new Statement('addRemoteFiles', array(array( + 'https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js', + 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js', + ))), $jsCommonFiles->setup[2]); + + $this->assertArrayHasKey('webloader.jsFrontFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.jsFrontCompiler', $builder->getDefinitions()); + + $jsFrontFiles = $builder->getDefinition('webloader.jsFrontFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $jsFrontFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.js')), $jsFrontFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.js')), $jsFrontFiles->setup[1]); + $this->assertEquals(new Statement('addFile', array('a.txt')), $jsFrontFiles->setup[2]); + $this->assertEquals(new Statement('addRemoteFiles', array( + array( + 'https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js', + 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js', + ) + )), $jsFrontFiles->setup[3]); + + $this->assertArrayHasKey('webloader.jsAdminFiles', $builder->getDefinitions()); + $this->assertArrayHasKey('webloader.jsAdminCompiler', $builder->getDefinitions()); + + $jsAdminFiles = $builder->getDefinition('webloader.jsAdminFiles'); + $this->assertSame(__DIR__ . '/../fixtures', $jsAdminFiles->factory->arguments[0]); + $this->assertEquals(new Statement('addFile', array(__DIR__ . '/../fixtures/dir/one.js')), $jsAdminFiles->setup[0]); + $this->assertEquals(new Statement('addFile', array('dir/two.js')), $jsAdminFiles->setup[1]); + $this->assertEquals(new Statement('addFile', array('b.txt')), $jsAdminFiles->setup[2]); + $this->assertEquals(new Statement('addRemoteFiles', array( + array( + 'https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js', + 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js', + ) + )), $jsAdminFiles->setup[3]); + } + + + + /** + * @param CompilerExtension $extension + * @param array $config + * @return \Nette\DI\ContainerBuilder + */ + protected function loadConfig(CompilerExtension $extension, array $config) + { + $compiler = new CompilerMock(); + $compiler->addExtension('webloader', $extension); + + $compiler->config = $compiler->getContainerBuilder()->expand($config); + + $extension->loadConfiguration(); + + return $compiler->getContainerBuilder(); + } + +} + + + +class CompilerMock extends \Nette\DI\Compiler +{ + + /** + * @var \Nette\DI\ContainerBuilder + */ + public $containerBuilder; + + /** + * @var array + */ + public $config = array(); + + + + public function __construct() + { + $this->containerBuilder = new \Nette\DI\ContainerBuilder(); + $this->containerBuilder->parameters = array( + 'appDir' => __DIR__ . '/../..', + 'wwwDir' => __DIR__ . '/../..', + 'tempDir' => __DIR__ . '/../temp', + 'fixturesDir' => __DIR__ . '/../fixtures', + 'debugMode' => FALSE, + 'productionMode' => TRUE, + ); + } + + + + /** + * @return array + */ + public function getConfig() + { + return $this->config; + } + + + + /** + * @return \Nette\DI\ContainerBuilder + */ + public function getContainerBuilder() + { + return $this->containerBuilder; + } + } diff --git a/tests/fixtures/extension.neon b/tests/fixtures/extension.neon index 82b431c..3a3e897 100644 --- a/tests/fixtures/extension.neon +++ b/tests/fixtures/extension.neon @@ -1,10 +1,6 @@ parameters: cssJoinFiles: false -nette: - security: - frames: yes - services: variablesFilter: WebLoader\Filter\VariablesFilter({foo: bar}) @@ -38,4 +34,4 @@ webloader: - @variablesFilter exclude: files: - - {files: ["*"], from: %fixturesDir%, exclude: [dir/*]} \ No newline at end of file + - {files: ["*"], from: %fixturesDir%, exclude: [dir/*]} diff --git a/tests/fixtures/extensionInheritanceCss.neon b/tests/fixtures/extensionInheritanceCss.neon new file mode 100644 index 0000000..a6a02be --- /dev/null +++ b/tests/fixtures/extensionInheritanceCss.neon @@ -0,0 +1,27 @@ +services: + variablesFilter: WebLoader\Filter\VariablesFilter({foo: bar}) + +webloader: + cssDefaults: + sourceDir: %fixturesDir% + tempDir: %tempDir% + + css: + common: + remoteFiles: + - https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css + + files: + - %fixturesDir%/dir/one.css + - dir/two.css + + filters: + - @variablesFilter + + front < common: + files: + - b.txt + + admin < common: + files: + - a.txt diff --git a/tests/fixtures/extensionInheritanceJs.neon b/tests/fixtures/extensionInheritanceJs.neon new file mode 100644 index 0000000..79ddd48 --- /dev/null +++ b/tests/fixtures/extensionInheritanceJs.neon @@ -0,0 +1,28 @@ +services: + variablesFilter: WebLoader\Filter\VariablesFilter({foo: bar}) + +webloader: + jsDefaults: + sourceDir: %fixturesDir% + tempDir: %tempDir% + + js: + common: + remoteFiles: + - https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js + - https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js + + files: + - %fixturesDir%/dir/one.js + - dir/two.js + + filters: + - @variablesFilter + + front < common: + files: + - a.txt + + admin < common: + files: + - b.txt diff --git a/tests/fixtures/nette-reset.neon b/tests/fixtures/nette-reset.neon new file mode 100644 index 0000000..1835cf2 --- /dev/null +++ b/tests/fixtures/nette-reset.neon @@ -0,0 +1,15 @@ +php: + date.timezone: Europe/Prague + + +nette: + security: + frames: null + + session: + autoStart: false + + +services: + cacheStorage: + class: Nette\Caching\Storages\MemoryStorage