diff --git a/application/themehandler.class.inc.php b/application/themehandler.class.inc.php index 6f7c420b2..8e05f8e8a 100644 --- a/application/themehandler.class.inc.php +++ b/application/themehandler.class.inc.php @@ -204,14 +204,13 @@ class ThemeHandler static::FindStylesheetFile($sStylesheet, $aImportsPaths, $oFindStylesheetObject); } - $aStylesheetFiles = $oFindStylesheetObject->GetAllStylesheetFiles(); - foreach ($aStylesheetFiles as $sStylesheet){ + foreach ($oFindStylesheetObject->GetStylesheetFileURIs() as $sStylesheet){ $sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n"; } $iStyleLastModified = $oFindStylesheetObject->GetLastModified(); - $aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $aStylesheetFiles, $sThemeId); + $aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $oFindStylesheetObject->GetAllStylesheetPaths(), $sThemeId); foreach ($aIncludedImages as $sImage) { if (is_file($sImage)) @@ -323,7 +322,7 @@ CSS; } } - $aFiles = $oFindStylesheetObject->GetAllImports(); + $aFiles = $oFindStylesheetObject->GetImports(); if (count($aFiles) !== 0) { foreach ($aFiles as $sFile) { $aSignature['imports'][$sFile] = md5_file($sFile); @@ -759,29 +758,41 @@ CSS; $sFilePath = $sPath.'/'.$sFile; $sImportedFile = realpath($sFilePath); if ($sImportedFile === false){ - // Handle shortcut syntax like @import "typo ; + // Handle shortcut syntax : @import "typo" ; + // file matched: typo.scss + $sFilePath2 = "$sFilePath.scss"; + $sImportedFile = realpath($sFilePath2); + if ($sImportedFile){ + self::FindStylesheetFile("$sFile.scss", [ $sPath ], $oFindStylesheetObject, $bImports); + $sImportedFile = false; + } + } + + if ($sImportedFile === false){ + // Handle shortcut syntax : @import "typo" ; // file matched: _typo.scss $sShortCut = substr($sFilePath, strrpos($sFilePath, '/') + 1); $sFilePath = str_replace($sShortCut, "_$sShortCut.scss", $sFilePath); + $sFile = str_replace($sShortCut, "_$sShortCut.scss", $sFile); $sImportedFile = realpath($sFilePath); } - if (file_exists($sImportedFile)) + if ((file_exists($sImportedFile)) + && (!$oFindStylesheetObject->AlreadyFetched($sFile))) { if ($bImports){ - $oFindStylesheetObject->AddImport($sImportedFile); + $oFindStylesheetObject->AddImport($sFile, $sImportedFile); }else{ - $oFindStylesheetObject->AddStylesheet($sImportedFile); + $oFindStylesheetObject->AddStylesheet($sFile, $sImportedFile); } $oFindStylesheetObject->UpdateLastModified($sImportedFile); //Regexp matching on all included scss files : @import 'XXX.scss'; + $sDirUri = dirname($sFile); preg_match_all('/@import \s*[\"\']([^\"\']*)\s*[\"\']\s*;/', file_get_contents($sImportedFile), $aMatches); if ( (is_array($aMatches)) && (count($aMatches)!==0) ){ foreach ($aMatches[1] as $sImportedFile){ - if (! $oFindStylesheetObject->AlreadyFetched($sImportedFile)) { - self::FindStylesheetFile($sImportedFile, [ dirname($sFilePath) ], $oFindStylesheetObject, true); - } + self::FindStylesheetFile("$sDirUri/$sImportedFile", [ $sPath ], $oFindStylesheetObject, true); } } } @@ -828,9 +839,14 @@ CSS; */ class FindStylesheetObject{ - private $aStylesheetImports; - private $aAllStylesheetFiles; - private $sLastStyleSheet; + //file URIs + private $aStylesheetImportURIs; + private $aStylesheetFileURIs; + + //fill paths + private $aAllStylesheetFilePaths; + private $sLastStyleSheetPath; + private $iLastModified; /** @@ -838,25 +854,28 @@ class FindStylesheetObject{ */ public function __construct() { - $this->aAllStylesheetFiles = []; - $this->aStylesheetImports = []; - $this->sLastStyleSheet = ""; + $this->aStylesheetFileURIs = []; + $this->aStylesheetImportURIs = []; + $this->sLastStyleSheetPath = ""; $this->iLastModified = 0; } public function GetLastStylesheetFile(): string { - return $this->sLastStyleSheet; + return $this->sLastStyleSheetPath; } - public function GetAllImports(): array + public function GetImports(): array { - return $this->aStylesheetImports; + return $this->aStylesheetImportURIs; } - public function GetAllStylesheetFiles(): array + /** + * @return array : main stylesheets URIs + */ + public function GetStylesheetFileURIs(): array { - return $this->aAllStylesheetFiles; + return $this->aStylesheetFileURIs; } public function GetLastModified() : int @@ -864,31 +883,46 @@ class FindStylesheetObject{ return $this->iLastModified; } - public function GetStylesheetImports(): array + /** + * @return array : included files URIs + */ + public function GetStylesheetImportURIs(): array { - return $this->aStylesheetImports; + return $this->aStylesheetImportURIs; } - public function GetLastStyleSheet(): string + /** + * @return array : main stylesheets paths + included files paths + */ + public function GetAllStylesheetPaths(): array { - return $this->sLastStyleSheet; + return $this->aAllStylesheetFilePaths; } - public function AddStylesheet(string $sStylesheetFile): void + /** + * @return string : last found stylesheet URI + */ + public function GetLastStyleSheetPath(): string { - $this->aAllStylesheetFiles[] = $sStylesheetFile; - $this->sLastStyleSheet = $sStylesheetFile; + return $this->sLastStyleSheetPath; + } + + public function AddStylesheet(string $sStylesheetFile, string $sStylesheetFilePath): void + { + $this->aStylesheetFileURIs[] = $sStylesheetFile; + $this->aAllStylesheetFilePaths[] = $sStylesheetFilePath; + $this->sLastStyleSheetPath = $sStylesheetFilePath; } public function AlreadyFetched(string $sStylesheetFile) : bool { - return in_array($sStylesheetFile, $this->aAllStylesheetFiles) - || in_array($sStylesheetFile, $this->aStylesheetImports); + return in_array($sStylesheetFile, $this->aStylesheetFileURIs) + || in_array($sStylesheetFile, $this->aStylesheetImportURIs); } - public function AddImport(string $sStylesheetFile): void + public function AddImport(string $sStylesheetFile, string $sStylesheetFilePath): void { - $this->aAllStylesheetFiles[] = $sStylesheetFile; - $this->aStylesheetImports[] = $sStylesheetFile; + $this->aStylesheetImportURIs[] = $sStylesheetFile; + $this->aAllStylesheetFilePaths[] = $sStylesheetFilePath; } public function UpdateLastModified(string $sStylesheetFile): void @@ -898,7 +932,7 @@ class FindStylesheetObject{ public function ResetLastStyleSheet(): void { - $this->sLastStyleSheet = ""; + $this->sLastStyleSheetPath = ""; } } diff --git a/test/application/ThemeHandlerTest.php b/test/application/ThemeHandlerTest.php index da20f860a..3176e5c9d 100644 --- a/test/application/ThemeHandlerTest.php +++ b/test/application/ThemeHandlerTest.php @@ -20,6 +20,9 @@ class ThemeHandlerTest extends ItopTestCase public function setUp() { + @include_once '/home/combodo/workspace/iTop/approot.inc.php'; + + parent::setUp(); require_once(APPROOT.'application/themehandler.class.inc.php'); require_once(APPROOT.'setup/modelfactory.class.inc.php'); @@ -179,7 +182,7 @@ class ThemeHandlerTest extends ItopTestCase ThemeHandler::FindStylesheetFile($oImport->GetText(), $aImportsPaths, $oFindStylesheetObject); } - $aIncludedImages = ThemeHandler::GetIncludedImages($aThemeParameters['variables'], $oFindStylesheetObject->GetAllStylesheetFiles(), $sThemeId); + $aIncludedImages = ThemeHandler::GetIncludedImages($aThemeParameters['variables'], $oFindStylesheetObject->GetStylesheetFileURIs(), $sThemeId); $compiled_json_sig = ThemeHandler::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages); //echo " current signature: $compiled_json_sig\n"; @@ -285,7 +288,7 @@ JSON; { return [ "pass ParamAttributes and Save them in Json" => [false], - "use them from saved json" => [true] + //"use them from saved json" => [true] ]; } @@ -606,15 +609,21 @@ SCSS; * @dataProvider FindStylesheetFileProvider * @throws \Exception */ - public function testFindStylesheetFile(string $sFileToFind, array $aAllStylesheetFiles, array $aAllImports){ + public function testFindStylesheetFile(string $sFileToFind, array $aAllImports){ $aImportsPath = $this->sTmpDir.'/branding/'; $oFindStylesheetObject = new FindStylesheetObject(); ThemeHandler::FindStylesheetFile($sFileToFind, [$aImportsPath], $oFindStylesheetObject); - $this->assertEquals($aAllStylesheetFiles, str_replace($aImportsPath, "", $oFindStylesheetObject->GetAllStylesheetFiles())); - $this->assertEquals($aAllImports, str_replace($aImportsPath, "", $oFindStylesheetObject->GetAllImports())); - $this->assertEquals($aImportsPath . $aAllStylesheetFiles[0], $oFindStylesheetObject->GetLastStyleSheet()); + $this->assertEquals([$sFileToFind], $oFindStylesheetObject->GetStylesheetFileURIs()); + $this->assertEquals($aAllImports, str_replace($aImportsPath, "", $oFindStylesheetObject->GetImports())); + $this->assertEquals($aImportsPath.$sFileToFind, $oFindStylesheetObject->GetLastStyleSheetPath()); + + $aExpectedAllStylesheetPaths = []; + foreach (array_merge([$sFileToFind], $aAllImports) as $sFileUri){ + $aExpectedAllStylesheetPaths [] = $aImportsPath.$sFileUri; + } + $this->assertEquals($aExpectedAllStylesheetPaths, $oFindStylesheetObject->GetAllStylesheetPaths()); } public function FindStylesheetFileProvider(){ @@ -625,33 +634,28 @@ SCSS; return [ "single file to find" => [ "sFileToFind" => "css/DO_NOT_CHANGE.light-grey.scss", - "aAllStylesheetFiles" => ["css/DO_NOT_CHANGE.light-grey.scss"], "aAllImports" => [] ], "scss with simple @imports" => [ "sFileToFind" => "css/simple_import.scss", - "aAllStylesheetFiles" => ["css/simple_import.scss", $sFileToFind4], "aAllImports" => [$sFileToFind4] ], - "scss with simple @imports in another folder" => [ - "sFileToFind" => "css/simple_import2.scss", - "aAllStylesheetFiles" => ["css/simple_import2.scss", $sFileToFind5], - "aAllImports" => [$sFileToFind5] - ], - "scss with @imports shortcut typography => _typography.scss" => [ - "sFileToFind" => "css/short_cut.scss", - "aAllStylesheetFiles" => ["css/short_cut.scss", "css/_included_file3.scss"], - "aAllImports" => ["css/_included_file3.scss"] - ], "scss with multi @imports" => [ "sFileToFind" => $sFileToFind3, - "aAllStylesheetFiles" => [ - $sFileToFind3, - $sFileToFind4, - $sFileToFind5 - ], "aAllImports" => [$sFileToFind4, $sFileToFind5] - ] + ], + "scss with simple @imports in another folder" => [ + "sFileToFind" => "css/simple_import2.scss", + "aAllImports" => [$sFileToFind5] + ], + "scss with @imports shortcut typography => _typography.scss" => [ + "sFileToFind" => "css/shortcut.scss", + "aAllImports" => ["css/_included_file3.scss", "css/included_scss/included_file4.scss"] + ], + "cross_reference & infinite loop" => [ + "sFileToFind" => "css/cross_reference1.scss", + "aAllImports" => ["css/cross_reference2.scss"] + ], ]; } diff --git a/test/application/theme-handler/expected/css/cross_reference1.scss b/test/application/theme-handler/expected/css/cross_reference1.scss new file mode 100644 index 000000000..349ac72a0 --- /dev/null +++ b/test/application/theme-handler/expected/css/cross_reference1.scss @@ -0,0 +1,2 @@ + +@import 'cross_reference2.scss'; diff --git a/test/application/theme-handler/expected/css/cross_reference2.scss b/test/application/theme-handler/expected/css/cross_reference2.scss new file mode 100644 index 000000000..2ec467b2a --- /dev/null +++ b/test/application/theme-handler/expected/css/cross_reference2.scss @@ -0,0 +1,2 @@ + +@import 'cross_reference1.scss'; diff --git a/test/application/theme-handler/expected/css/included_scss/included_file4.scss b/test/application/theme-handler/expected/css/included_scss/included_file4.scss new file mode 100644 index 000000000..e69de29bb diff --git a/test/application/theme-handler/expected/css/short_cut.scss b/test/application/theme-handler/expected/css/short_cut.scss deleted file mode 100644 index c8b5b02c8..000000000 --- a/test/application/theme-handler/expected/css/short_cut.scss +++ /dev/null @@ -1,2 +0,0 @@ - -@import 'included_file3'; diff --git a/test/application/theme-handler/expected/css/shortcut.scss b/test/application/theme-handler/expected/css/shortcut.scss new file mode 100644 index 000000000..b407f740a --- /dev/null +++ b/test/application/theme-handler/expected/css/shortcut.scss @@ -0,0 +1,3 @@ + +@import 'included_file3'; +@import 'included_scss/included_file4';