diff --git a/library/Icinga/Web/JavaScript.php b/library/Icinga/Web/JavaScript.php index 1865136c76..3bdc1fead9 100644 --- a/library/Icinga/Web/JavaScript.php +++ b/library/Icinga/Web/JavaScript.php @@ -243,14 +243,26 @@ public static function optimizeDefine($js, $filePath, $basePath, $packageName) continue; } - if (preg_match('~^((?:\.\.?/)+)*(.*)~', $dependencyName, $natch)) { + $fileExtension = '.js'; + $dirname = dirname($filePath); + if (preg_match('~^((?:\.\.?/)+)*.*?(\.\w+)?$~', $dependencyName, $natch)) { + if (! empty($natch[1])) { + $dependencyName = substr($dependencyName, strlen($natch[1])); + $dirname = realpath(join(DIRECTORY_SEPARATOR, [$dirname, $natch[1]])); + } + + if (! empty($natch[2])) { + $dependencyName = substr($dependencyName, 0, -strlen($natch[2])); + $fileExtension = $natch[2]; + } + } + + $dependencyPath = join(DIRECTORY_SEPARATOR, [$dirname, $dependencyName . $fileExtension]); + if (file_exists($dependencyPath)) { $dependencyName = join(DIRECTORY_SEPARATOR, array_filter([ $packageName, - ltrim(substr( - realpath(join(DIRECTORY_SEPARATOR, [dirname($filePath), $natch[1]])), - strlen(realpath($basePath)) - ), DIRECTORY_SEPARATOR), - $natch[2] + trim(substr($dirname, strlen(realpath($basePath))), DIRECTORY_SEPARATOR . ' '), + $dependencyName ])); } } diff --git a/test/config/JavaScriptTest/someOther.js b/test/config/JavaScriptTest/someOther.js new file mode 100644 index 0000000000..6f0f80c71f --- /dev/null +++ b/test/config/JavaScriptTest/someOther.js @@ -0,0 +1,4 @@ +/* No requirements */ +define(function () { + +}); diff --git a/test/config/JavaScriptTest/someThing.js b/test/config/JavaScriptTest/someThing.js new file mode 100644 index 0000000000..09bbec4bf7 --- /dev/null +++ b/test/config/JavaScriptTest/someThing.js @@ -0,0 +1,4 @@ +/* Relative path, No extension */ +define(["someThing/Else"], function (Else) { + +}); diff --git a/test/config/JavaScriptTest/someThing/Else.js b/test/config/JavaScriptTest/someThing/Else.js new file mode 100644 index 0000000000..91707d723a --- /dev/null +++ b/test/config/JavaScriptTest/someThing/Else.js @@ -0,0 +1,4 @@ +/* Relative path outside the current directory, With extension */ +define(["../someOther.js"], function (someOther) { + +}); diff --git a/test/php/library/Icinga/Web/JavaScriptTest.php b/test/php/library/Icinga/Web/JavaScriptTest.php new file mode 100644 index 0000000000..64e12804b0 --- /dev/null +++ b/test/php/library/Icinga/Web/JavaScriptTest.php @@ -0,0 +1,102 @@ +fileRoot = Icinga::app()->getBaseDir('test/config/JavaScriptTest'); + } + + public function testLocalDefineOptimizations() + { + $expected = <<<'JS' +/* Relative path, No extension */ +define("JavaScriptTest/someThing", ["JavaScriptTest/someThing/Else"], function (Else) { + +}); + +JS; + $someThing = $this->getFile('someThing.js'); + $this->assertSame($expected, $this->optimizeFile($someThing)); + + $expected = <<<'JS' +/* Relative path outside the current directory, With extension */ +define("JavaScriptTest/someThing/Else", ["JavaScriptTest/someOther"], function (someOther) { + +}); + +JS; + $someThingElse = $this->getFile('someThing/Else.js'); + $this->assertSame($expected, $this->optimizeFile($someThingElse)); + } + + public function testNoRequirementsOptimization() + { + $expected = <<<'JS' +define("JavaScriptTest/noRequirements", [], function () { + +}); + +JS; + $source = <<<'JS' +define(function () { + +}); + +JS; + $this->assertSame($expected, JavaScript::optimizeDefine( + $source, + 'JavaScriptTest/noRequirements', + 'JavaScriptTest', + 'JavaScriptTest' + )); + } + + public function testGlobalRequirementsOptimization() + { + $expected = <<<'JS' +define("JavaScriptTest/globalRequirements", ["SomeOtherTest/Anything"], function (Anything) { + +}); + +JS; + $source = <<<'JS' +define(["SomeOtherTest/Anything"], function (Anything) { + +}); + +JS; + $this->assertSame($expected, JavaScript::optimizeDefine( + $source, + 'JavaScriptTest/globalRequirements', + 'JavaScriptTest', + 'JavaScriptTest' + )); + } + + protected function optimizeFile(SplFileObject $file): string + { + return JavaScript::optimizeDefine( + $file->fread($file->getSize()), + $file->getRealPath(), + $this->fileRoot, + 'JavaScriptTest' + ); + } + + protected function getFile(string $file): SplFileObject + { + return new SplFileObject(join(DIRECTORY_SEPARATOR, [$this->fileRoot, $file])); + } +}