From 307713d326ad0f8a7b5e94d8e882e83c57e1d611 Mon Sep 17 00:00:00 2001 From: odain Date: Thu, 4 Jun 2020 08:55:28 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B02996=20-=20Remove=20iTop=20version=20fro?= =?UTF-8?q?m=20css-variable.scss=20=09Include=20images=20in=20precompilati?= =?UTF-8?q?on=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .make/release/update-versions.php | 1 - .make/release/update.classes.inc.php | 20 - application/themehandler.class.inc.php | 330 ++++++++++- application/utils.inc.php | 8 +- css/css-variables.scss | 3 - .../precompiled-themes/light-grey/main.css | 2 +- .../precompiled-themes/test-red/main.css | 2 +- lib/composer/autoload_classmap.php | 18 +- lib/composer/autoload_static.php | 18 +- test/application/ThemeHandlerTest.php | 543 +++++++++++++----- .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 418 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 312 bytes .../images/ui-icons_1c94c4_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 6922 bytes .../images/ui-icons_E87C1E_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_F26522_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6299 bytes .../testimages/images/ac-background.gif | Bin 0 -> 61 bytes .../testimages/images/actions_right.png | Bin 0 -> 240 bytes .../copied/testimages/images/bg.gif | Bin 0 -> 64 bytes .../images/breadcrumb-separator.png | Bin 0 -> 324 bytes .../copied/testimages/images/calendar.png | Bin 0 -> 676 bytes .../copied/testimages/images/delete.png | Bin 0 -> 842 bytes .../copied/testimages/images/desc.gif | Bin 0 -> 54 bytes .../copied/testimages/images/error.png | Bin 0 -> 543 bytes .../testimages/images/eye-closed-555.png | Bin 0 -> 274 bytes .../testimages/images/eye-closed-fff.png | Bin 0 -> 237 bytes .../copied/testimages/images/eye-open-555.png | Bin 0 -> 355 bytes .../copied/testimages/images/eye-open-fff.png | Bin 0 -> 327 bytes .../copied/testimages/images/full-screen.png | Bin 0 -> 1011 bytes .../copied/testimages/images/green-header.gif | Bin 0 -> 124 bytes .../copied/testimages/images/green-square.gif | Bin 0 -> 56 bytes .../copied/testimages/images/indicator.gif | Bin 0 -> 1553 bytes .../copied/testimages/images/info-mini.png | Bin 0 -> 850 bytes .../copied/testimages/images/minus.gif | Bin 0 -> 139 bytes .../copied/testimages/images/ok.png | Bin 0 -> 643 bytes .../testimages/images/orange-header.gif | Bin 0 -> 122 bytes .../copied/testimages/images/plus.gif | Bin 0 -> 142 bytes .../copied/testimages/images/red-header.gif | Bin 0 -> 122 bytes .../copied/testimages/images/truncated.png | Bin 0 -> 1429 bytes .../testimages/images/tv-collapsable-last.gif | Bin 0 -> 85 bytes .../testimages/images/tv-collapsable.gif | Bin 0 -> 781 bytes .../testimages/images/tv-expandable-last.gif | Bin 0 -> 89 bytes .../testimages/images/tv-expandable.gif | Bin 0 -> 787 bytes .../copied/testimages/images/tv-item-last.gif | Bin 0 -> 65 bytes .../copied/testimages/images/tv-item.gif | Bin 0 -> 750 bytes .../expected/css/css-variables.scss | 3 - .../ui-bg_diagonals-thick_18_b81900_40x40.png | Bin 0 -> 418 bytes .../ui-bg_diagonals-thick_20_666666_40x40.png | Bin 0 -> 312 bytes .../images/ui-icons_1c94c4_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 6922 bytes .../images/ui-icons_E87C1E_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_F26522_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ffd27a_256x240.png | Bin 0 -> 4549 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6299 bytes .../testimages/images/ac-background.gif | Bin 0 -> 61 bytes .../testimages/images/actions_right.png | Bin 0 -> 240 bytes .../expected/testimages/images/bg.gif | Bin 0 -> 64 bytes .../images/breadcrumb-separator.png | Bin 0 -> 324 bytes .../expected/testimages/images/calendar.png | Bin 0 -> 676 bytes .../expected/testimages/images/delete.png | Bin 0 -> 842 bytes .../expected/testimages/images/desc.gif | Bin 0 -> 54 bytes .../expected/testimages/images/error.png | Bin 0 -> 543 bytes .../testimages/images/eye-closed-555.png | Bin 0 -> 274 bytes .../testimages/images/eye-closed-fff.png | Bin 0 -> 237 bytes .../testimages/images/eye-open-555.png | Bin 0 -> 355 bytes .../testimages/images/eye-open-fff.png | Bin 0 -> 327 bytes .../testimages/images/full-screen.png | Bin 0 -> 1011 bytes .../testimages/images/green-header.gif | Bin 0 -> 120 bytes .../testimages/images/green-square.gif | Bin 0 -> 56 bytes .../expected/testimages/images/indicator.gif | Bin 0 -> 1553 bytes .../expected/testimages/images/info-mini.png | Bin 0 -> 850 bytes .../expected/testimages/images/minus.gif | Bin 0 -> 139 bytes .../expected/testimages/images/ok.png | Bin 0 -> 643 bytes .../testimages/images/orange-header.gif | Bin 0 -> 122 bytes .../expected/testimages/images/plus.gif | Bin 0 -> 142 bytes .../expected/testimages/images/red-header.gif | Bin 0 -> 122 bytes .../expected/testimages/images/truncated.png | Bin 0 -> 1429 bytes .../testimages/images/tv-collapsable-last.gif | Bin 0 -> 85 bytes .../testimages/images/tv-collapsable.gif | Bin 0 -> 781 bytes .../testimages/images/tv-expandable-last.gif | Bin 0 -> 89 bytes .../testimages/images/tv-expandable.gif | Bin 0 -> 787 bytes .../testimages/images/tv-item-last.gif | Bin 0 -> 65 bytes .../expected/testimages/images/tv-item.gif | Bin 0 -> 750 bytes .../expected/themes/basque-red/main.css | 2 +- .../themes/basque-red/main_imagemodified.css | 6 + .../themes/basque-red/main_importmodified.css | 2 +- .../themes/basque-red/main_stylesheet.css | 2 +- .../basque-red/main_testcompilethemes.css | 6 + .../themes/basque-red/main_varchanged.css | 2 +- .../getimages/expected-getimages.json | 42 ++ .../getimages/test-getimages.scss | 9 + 93 files changed, 819 insertions(+), 200 deletions(-) create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_1c94c4_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100644 test/application/theme-handler/copied/testimages/images/ac-background.gif create mode 100644 test/application/theme-handler/copied/testimages/images/actions_right.png create mode 100644 test/application/theme-handler/copied/testimages/images/bg.gif create mode 100644 test/application/theme-handler/copied/testimages/images/breadcrumb-separator.png create mode 100644 test/application/theme-handler/copied/testimages/images/calendar.png create mode 100644 test/application/theme-handler/copied/testimages/images/delete.png create mode 100644 test/application/theme-handler/copied/testimages/images/desc.gif create mode 100644 test/application/theme-handler/copied/testimages/images/error.png create mode 100644 test/application/theme-handler/copied/testimages/images/eye-closed-555.png create mode 100644 test/application/theme-handler/copied/testimages/images/eye-closed-fff.png create mode 100644 test/application/theme-handler/copied/testimages/images/eye-open-555.png create mode 100644 test/application/theme-handler/copied/testimages/images/eye-open-fff.png create mode 100644 test/application/theme-handler/copied/testimages/images/full-screen.png create mode 100644 test/application/theme-handler/copied/testimages/images/green-header.gif create mode 100644 test/application/theme-handler/copied/testimages/images/green-square.gif create mode 100644 test/application/theme-handler/copied/testimages/images/indicator.gif create mode 100644 test/application/theme-handler/copied/testimages/images/info-mini.png create mode 100644 test/application/theme-handler/copied/testimages/images/minus.gif create mode 100644 test/application/theme-handler/copied/testimages/images/ok.png create mode 100644 test/application/theme-handler/copied/testimages/images/orange-header.gif create mode 100644 test/application/theme-handler/copied/testimages/images/plus.gif create mode 100644 test/application/theme-handler/copied/testimages/images/red-header.gif create mode 100644 test/application/theme-handler/copied/testimages/images/truncated.png create mode 100644 test/application/theme-handler/copied/testimages/images/tv-collapsable-last.gif create mode 100644 test/application/theme-handler/copied/testimages/images/tv-collapsable.gif create mode 100644 test/application/theme-handler/copied/testimages/images/tv-expandable-last.gif create mode 100644 test/application/theme-handler/copied/testimages/images/tv-expandable.gif create mode 100644 test/application/theme-handler/copied/testimages/images/tv-item-last.gif create mode 100644 test/application/theme-handler/copied/testimages/images/tv-item.gif create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_1c94c4_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffd27a_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png create mode 100644 test/application/theme-handler/expected/testimages/images/ac-background.gif create mode 100644 test/application/theme-handler/expected/testimages/images/actions_right.png create mode 100644 test/application/theme-handler/expected/testimages/images/bg.gif create mode 100644 test/application/theme-handler/expected/testimages/images/breadcrumb-separator.png create mode 100644 test/application/theme-handler/expected/testimages/images/calendar.png create mode 100644 test/application/theme-handler/expected/testimages/images/delete.png create mode 100644 test/application/theme-handler/expected/testimages/images/desc.gif create mode 100644 test/application/theme-handler/expected/testimages/images/error.png create mode 100644 test/application/theme-handler/expected/testimages/images/eye-closed-555.png create mode 100644 test/application/theme-handler/expected/testimages/images/eye-closed-fff.png create mode 100644 test/application/theme-handler/expected/testimages/images/eye-open-555.png create mode 100644 test/application/theme-handler/expected/testimages/images/eye-open-fff.png create mode 100644 test/application/theme-handler/expected/testimages/images/full-screen.png create mode 100644 test/application/theme-handler/expected/testimages/images/green-header.gif create mode 100644 test/application/theme-handler/expected/testimages/images/green-square.gif create mode 100644 test/application/theme-handler/expected/testimages/images/indicator.gif create mode 100644 test/application/theme-handler/expected/testimages/images/info-mini.png create mode 100644 test/application/theme-handler/expected/testimages/images/minus.gif create mode 100644 test/application/theme-handler/expected/testimages/images/ok.png create mode 100644 test/application/theme-handler/expected/testimages/images/orange-header.gif create mode 100644 test/application/theme-handler/expected/testimages/images/plus.gif create mode 100644 test/application/theme-handler/expected/testimages/images/red-header.gif create mode 100644 test/application/theme-handler/expected/testimages/images/truncated.png create mode 100644 test/application/theme-handler/expected/testimages/images/tv-collapsable-last.gif create mode 100644 test/application/theme-handler/expected/testimages/images/tv-collapsable.gif create mode 100644 test/application/theme-handler/expected/testimages/images/tv-expandable-last.gif create mode 100644 test/application/theme-handler/expected/testimages/images/tv-expandable.gif create mode 100644 test/application/theme-handler/expected/testimages/images/tv-item-last.gif create mode 100644 test/application/theme-handler/expected/testimages/images/tv-item.gif create mode 100644 test/application/theme-handler/expected/themes/basque-red/main_imagemodified.css create mode 100644 test/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css create mode 100644 test/application/theme-handler/getimages/expected-getimages.json create mode 100644 test/application/theme-handler/getimages/test-getimages.scss diff --git a/.make/release/update-versions.php b/.make/release/update-versions.php index 0f1dcd24e..488131d4b 100644 --- a/.make/release/update-versions.php +++ b/.make/release/update-versions.php @@ -25,7 +25,6 @@ require_once (__DIR__.DIRECTORY_SEPARATOR.'update.classes.inc.php'); /** @var \FileVersionUpdater[] $aFilesUpdaters */ $aFilesUpdaters = array( new iTopVersionFileUpdater(), - new CssVariablesFileUpdater(), new DatamodelsModulesFiles(), ); diff --git a/.make/release/update.classes.inc.php b/.make/release/update.classes.inc.php index 6e20ee0d7..d344455c0 100644 --- a/.make/release/update.classes.inc.php +++ b/.make/release/update.classes.inc.php @@ -89,26 +89,6 @@ class iTopVersionFileUpdater extends AbstractSingleFileVersionUpdater } } -class CssVariablesFileUpdater extends AbstractSingleFileVersionUpdater -{ - public function __construct() - { - parent::__construct('css/css-variables.scss'); - } - - /** - * @inheritDoc - */ - public function UpdateFileContent($sVersionLabel, $sFileContent, $sFileFullPath) - { - return preg_replace( - '/(\$version: "v)[^"]*(";)/', - '${1}'.$sVersionLabel.'${2}', - $sFileContent - ); - } -} - abstract class AbstractGlobFileVersionUpdater extends FileVersionUpdater { protected $sGlobPattern; diff --git a/application/themehandler.class.inc.php b/application/themehandler.class.inc.php index 99931a724..ab636a5a9 100644 --- a/application/themehandler.class.inc.php +++ b/application/themehandler.class.inc.php @@ -25,6 +25,8 @@ */ class ThemeHandler { + const IMAGE_EXTENSIONS = array('png', 'gif', 'jpg', 'jpeg'); + private static $oCompileCSSService; /** * Return default theme name and parameters @@ -173,12 +175,15 @@ class ThemeHandler $iStyleLastModified = 0; clearstatcache(); // Loading files to import and stylesheet to compile, also getting most recent modification time on overall files + + $aStylesheetFiles = array(); foreach ($aThemeParameters['imports'] as $sImport) { $sTmpThemeScssContent .= '@import "'.$sImport.'";'."\n"; $sFile = static::FindStylesheetFile($sImport, $aImportsPaths); $iImportLastModified = @filemtime($sFile); + $aStylesheetFiles[] = $sFile; $iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified; } foreach ($aThemeParameters['stylesheets'] as $sStylesheet) @@ -187,9 +192,24 @@ class ThemeHandler $sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths); $iStylesheetLastModified = @filemtime($sFile); + $aStylesheetFiles[] = $sFile; $iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified; } + $aIncludedImages=static::GetIncludedImages($aThemeParameters['variables'], $aStylesheetFiles, $sThemeFolderPath); + foreach ($aIncludedImages as $sImage) + { + if (!is_file($sImage)) + { + IssueLog::Warning("Cannot find $sImage during SCSS $sThemeId precompilation"); + } + else + { + $iStylesheetLastModified = @filemtime($sImage); + $iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified; + } + } + // Checking if our compiled css is outdated $iFilemetime = @filemtime($sThemeCssPath); $bFileExists = file_exists($sThemeCssPath); @@ -208,7 +228,7 @@ class ThemeHandler if (!$bFileExists || $bVarSignatureChanged || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified))) { // Dates don't match. Second chance: check if the already compiled stylesheet exists and is consistent based on its signature - $sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths); + $sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages); if ($bFileExists && !$bSetup) { @@ -232,11 +252,11 @@ $sActualSignature */ CSS; - if (!self::$oCompileCSSService) + if (!static::$oCompileCSSService) { - self::$oCompileCSSService = new CompileCSSService(); + static::$oCompileCSSService = new CompileCSSService(); } - $sTmpThemeCssContent = self::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, + $sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, $aThemeParameters['variables']); file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent); } @@ -251,16 +271,18 @@ CSS; * * @param string[] $aThemeParameters * @param string[] $aImportsPaths + * @param string[] $aIncludedImages * * @return string * @throws \Exception */ - public static function ComputeSignature($aThemeParameters, $aImportsPaths) + public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages) { $aSignature = array( 'variables' => md5(json_encode($aThemeParameters['variables'])), 'stylesheets' => array(), 'imports' => array(), + 'images' => array(), ); foreach ($aThemeParameters['imports'] as $key => $sImport) @@ -273,9 +295,303 @@ CSS; $sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths); $aSignature['stylesheets'][$key] = md5_file($sFile); } + foreach ($aIncludedImages as $sImage) + { + if (is_file($sImage)) + { + $aSignature['images'][$sImage] = md5_file($sImage); + } + } + return json_encode($aSignature); } + /** + * Search for images referenced in stylesheet files + * @param array $aThemeParametersVariables + * @param array $aStylesheetFiles + * @param string $sThemeFolderPath : used as relative paths to find css images + * + * @return array + * @since 2.8.0 + */ + public static function GetIncludedImages($aThemeParametersVariables, $aStylesheetFiles, $sThemeFolderPath) + { + $aCompleteUrls = array(); + $aToCompleteUrls = array(); + $aMissingVariables = array(); + $aFoundVariables = array('version'=>''); + $aMap = array( + 'aCompleteUrls' => $aCompleteUrls, + 'aToCompleteUrls' => $aToCompleteUrls, + 'aMissingVariables' => $aMissingVariables, + 'aFoundVariables' => $aFoundVariables, + ); + + foreach ($aStylesheetFiles as $sStylesheetFile) + { + $aRes = static::GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile); + /** @var array $aVal */ + foreach($aMap as $key => $aVal) + { + if (array_key_exists($key, $aMap)) + { + $aMap[$key] = array_merge($aVal, $aRes[$key]); + } + } + } + + $aMap = static::ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFiles); + $aImages = array(); + foreach ($aMap ['aCompleteUrls'] as $sUrl) + { + $sImg = $sUrl; + if (preg_match("/(.*)\?/", $sUrl, $aMatches)) + { + $sImg=$aMatches[1]; + } + + if (static::HasImageExtension($sImg) + && ! array_key_exists($sImg, $aImages)) + { + if (!is_file($sImg)) + { + $sImg=$sThemeFolderPath.DIRECTORY_SEPARATOR.$sImg; + } + $aImages[$sImg]=$sImg; + } + } + + return array_values($aImages); + } + + /** + * Complete url using provided variables. Example with $var=1: XX + $var => XX1 + * @param $aMap + * @param $aThemeParametersVariables + * @param $aStylesheetFile + * + * @return mixed + */ + public static function ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFile) + { + $sContent=""; + foreach ($aStylesheetFile as $sStylesheetFile) + { + if (is_file($sStylesheetFile)) + { + $sContent .= '\n' . file_get_contents($sStylesheetFile); + } + } + + $aMissingVariables=$aMap['aMissingVariables']; + $aFoundVariables=$aMap['aFoundVariables']; + $aToCompleteUrls=$aMap['aToCompleteUrls']; + $aCompleteUrls=$aMap['aCompleteUrls']; + list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, true); + list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls); + $aMap['aMissingVariables']=$aMissingVariables; + $aMap['aFoundVariables']=$aFoundVariables; + $aMap['aToCompleteUrls']=$aToCompleteUrls; + $aMap['aCompleteUrls']=$aCompleteUrls; + return $aMap; + } + + /** + * Find missing variable values from SCSS content based on their name. + * + * @param $aThemeParametersVariables + * @param $aMissingVariables + * @param $aFoundVariables + * @param $sContent : scss content + * @param bool $bForceEmptyValueWhenNotFound + * + * @return array + */ + public static function FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, $bForceEmptyValueWhenNotFound=false) + { + $aNewMissingVars = array(); + if (!empty($aMissingVariables)) + { + foreach ($aMissingVariables as $var) + { + if (array_key_exists($var, $aThemeParametersVariables)) + { + $aFoundVariables[$var] = $aThemeParametersVariables[$var]; + } + else + { + if (preg_match_all("/\\\$$var\s*:\s*[\"']{0,1}(.*)[\"']{0,1};/", $sContent, $aValues)) + { + $sValue = $aValues[1][0]; + if (preg_match_all("/([^!]+)!/", $sValue, $aSubValues)) + { + $sValue = trim($aSubValues[1][0], ' "\''); + } + + if (strpos($sValue, '$') === false) + { + $aFoundVariables[$var] = $sValue; + } + else{ + $aNewMissingVars[] = $var; + } + } + else + { + if ($bForceEmptyValueWhenNotFound) + { + $aFoundVariables[$var] = ''; + } + else + { + $aNewMissingVars[] = $var; + } + } + } + } + } + + return array($aNewMissingVars, $aFoundVariables); + } + + /** + * @param $aFoundVariables + * @param array $aToCompleteUrls + * @param array $aCompleteUrls + * + * @return array + */ + public static function ResolveUrls($aFoundVariables, array $aToCompleteUrls, array $aCompleteUrls) + { + if (!empty($aFoundVariables)) + { + foreach ($aToCompleteUrls as $sUrlTemplate) + { + unset($aToCompleteUrls[$sUrlTemplate]); + $sResolvedUrl = static::ResolveUrl($sUrlTemplate, $aFoundVariables); + if ($sResolvedUrl == false) + { + $aToCompleteUrls[$sUrlTemplate] = $sUrlTemplate; + } + else + { + $aCompleteUrls[$sUrlTemplate] = $sResolvedUrl; + } + } + } + + return array($aToCompleteUrls, $aCompleteUrls); + } + + /** + * Find all referenced URLs from a SCSS file. + * @param $aThemeParametersVariables + * @param $sStylesheetFile + * + * @return array + */ + public static function GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile) + { + $aCompleteUrls = array(); + $aToCompleteUrls = array(); + $aMissingVariables = array(); + $aFoundVariables = array(); + + if (is_file($sStylesheetFile)) + { + $sContent = file_get_contents($sStylesheetFile); + if (preg_match_all("/url\s*\((.*)\)/", $sContent, $aMatches)) + { + foreach ($aMatches[1] as $path) + { + if (!array_key_exists($path, $aCompleteUrls) + && !array_key_exists($path, $aToCompleteUrls)) + { + if (preg_match_all("/\\$([\w-_]+)/", $path, $aCurrentVars)) + { + /** @var string $aCurrentVars */ + foreach ($aCurrentVars[1] as $var) + { + if (!array_key_exists($var, $aMissingVariables)) + { + $aMissingVariables[$var] = $var; + } + } + $aToCompleteUrls[$path] = $path; + } + else + { + $aCompleteUrls[$path] = trim($path, "\"'"); + } + } + } + } + if (!empty($aMissingVariables)) + { + list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent); + list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls); + } + } + + return array( + 'aCompleteUrls' => $aCompleteUrls, + 'aToCompleteUrls' => $aToCompleteUrls, + 'aMissingVariables' => $aMissingVariables, + 'aFoundVariables' => $aFoundVariables, + ); + } + + /** + * Calculate url based on its template + variables. + * @param $sUrlTemplate + * @param $aFoundVariables + * + * @return bool|string + */ + public static function ResolveUrl($sUrlTemplate, $aFoundVariables) + { + $aPattern=array(); + $aReplacement=array(); + foreach ($aFoundVariables as $aFoundVariable => $aFoundVariableValue) + { + //XX + $key + YY + $aPattern[]="/['\"]\s*\+\s*\\\$" . $aFoundVariable . "[\s\+]+\s*['\"]/"; + $aReplacement[]=$aFoundVariableValue; + //$key + YY + $aPattern[]="/\\\$" . $aFoundVariable. "[\s\+]+\s*['\"]/"; + $aReplacement[]=$aFoundVariableValue; + //XX + $key + $aPattern[]="/['\"]\s*[\+\s]+\\\$" . $aFoundVariable . "$/"; + $aReplacement[]=$aFoundVariableValue; + } + $sResolvedUrl=preg_replace($aPattern, $aReplacement, $sUrlTemplate); + if (strpos($sResolvedUrl, "+")!==false) + { + return false; + } + return trim($sResolvedUrl, "\"'"); + } + + /** + * indicate whether a string ends with image suffix. + * @param $path + * + * @return bool + */ + private static function HasImageExtension($path) + { + foreach (static::IMAGE_EXTENSIONS as $sExt) + { + if (endsWith($path, $sExt)) + { + return true; + } + } + return false; + } + + /** * Extract the signature for a generated CSS file. The signature MUST be alone one line immediately * followed (on the next line) by the === SIGNATURE END === pattern @@ -322,7 +638,7 @@ CSS; * @throws Exception * @return string */ - private static function FindStylesheetFile($sFile, $aImportsPaths) + public static function FindStylesheetFile($sFile, $aImportsPaths) { foreach($aImportsPaths as $sPath) { @@ -337,7 +653,7 @@ CSS; public static function mockCompileCSSService($oCompileCSSServiceMock) { - self::$oCompileCSSService = $oCompileCSSServiceMock; + static::$oCompileCSSService = $oCompileCSSServiceMock; } } diff --git a/application/utils.inc.php b/application/utils.inc.php index 529dbe21b..2f7d7edec 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -1858,17 +1858,13 @@ class utils } /** + * @deprecated * @param string $sModuleName * @return string|NULL compiled version of a given module, as it was seen by the compiler */ public static function GetCompiledModuleVersion($sModuleName) { - $aModulesInfo = GetModulesInfo(); - if (array_key_exists($sModuleName, $aModulesInfo)) - { - return $aModulesInfo[$sModuleName]['version']; - } - return null; + return static::GetCacheBusterTimestamp(); } /** diff --git a/css/css-variables.scss b/css/css-variables.scss index 1df379aca..f3eefbd7b 100644 --- a/css/css-variables.scss +++ b/css/css-variables.scss @@ -15,9 +15,6 @@ * * You should have received a copy of the GNU Affero General Public License */ - -// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0 -$version: "v2.7.1"; $approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css // Base colors diff --git a/datamodels/2.x/itop-config-mgmt/precompiled-themes/light-grey/main.css b/datamodels/2.x/itop-config-mgmt/precompiled-themes/light-grey/main.css index eb2e38767..9fbd0b990 100644 --- a/datamodels/2.x/itop-config-mgmt/precompiled-themes/light-grey/main.css +++ b/datamodels/2.x/itop-config-mgmt/precompiled-themes/light-grey/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]} +{"variables":"d751713988987e9331980363e24189ce","stylesheets":{"css-variables":"1d4b4ae2a6fba3db101f8dd1cecab082","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"0dd837aeddc3f407c980e0b20f06dd4c"},"imports":[],"images":[]} === SIGNATURE END === */ /*! diff --git a/datamodels/2.x/itop-config-mgmt/precompiled-themes/test-red/main.css b/datamodels/2.x/itop-config-mgmt/precompiled-themes/test-red/main.css index 534707f1b..cd8efbcaa 100644 --- a/datamodels/2.x/itop-config-mgmt/precompiled-themes/test-red/main.css +++ b/datamodels/2.x/itop-config-mgmt/precompiled-themes/test-red/main.css @@ -1,6 +1,6 @@ /* === SIGNATURE BEGIN === -{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[]} +{"variables":"8cfe86f2c55d8eff36d57eb4e83d89f1","stylesheets":{"css-variables":"1d4b4ae2a6fba3db101f8dd1cecab082","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"0dd837aeddc3f407c980e0b20f06dd4c","environment-banner":"3de3ffb8232b9a649e912b570a64bf5d"},"imports":[],"images":[]} === SIGNATURE END === */ /*! diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 8f8e6b200..0690a8add 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -268,6 +268,7 @@ return array( 'HistoryBlock' => $baseDir . '/application/displayblock.class.inc.php', 'Html2Text\\Html2Text' => $baseDir . '/application/Html2Text.php', 'Html2Text\\Html2TextException' => $baseDir . '/application/Html2TextException.php', + 'ILogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', 'ITopArchiveTar' => $baseDir . '/core/tar-itop.class.inc.php', 'InlineImage' => $baseDir . '/core/inlineimage.class.inc.php', 'InlineImageGC' => $baseDir . '/core/inlineimage.class.inc.php', @@ -286,7 +287,6 @@ return array( 'ListOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', 'LogAPI' => $baseDir . '/core/log.class.inc.php', 'LogFileNameBuilderFactory' => $baseDir . '/core/log.class.inc.php', - 'LogFileRotationProcess' => $baseDir . '/core/log.class.inc.php', 'LoginBlockExtension' => $baseDir . '/application/logintwig.class.inc.php', 'LoginTwigContext' => $baseDir . '/application/logintwig.class.inc.php', 'LoginTwigRenderer' => $baseDir . '/application/logintwig.class.inc.php', @@ -304,7 +304,6 @@ return array( 'ModuleDesign' => $baseDir . '/core/moduledesign.class.inc.php', 'ModuleHandlerAPI' => $baseDir . '/core/modulehandler.class.inc.php', 'ModuleHandlerApiInterface' => $baseDir . '/core/modulehandler.class.inc.php', - 'MonthlyRotatingLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', 'MyHelpers' => $baseDir . '/core/MyHelpers.class.inc.php', 'MySQLException' => $baseDir . '/core/cmdbsource.class.inc.php', 'MySQLHasGoneAwayException' => $baseDir . '/core/cmdbsource.class.inc.php', @@ -606,6 +605,9 @@ return array( 'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/psr/log/Psr/Log/Test/TestLogger.php', 'Psr\\SimpleCache\\CacheException' => $vendorDir . '/psr/simple-cache/src/CacheException.php', 'Psr\\SimpleCache\\CacheInterface' => $vendorDir . '/psr/simple-cache/src/CacheInterface.php', 'Psr\\SimpleCache\\InvalidArgumentException' => $vendorDir . '/psr/simple-cache/src/InvalidArgumentException.php', @@ -844,6 +846,9 @@ return array( 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateNameParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => $vendorDir . '/symfony/framework-bundle/Templating/TemplateReference.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => $vendorDir . '/symfony/framework-bundle/Templating/TimedPhpEngine.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => $vendorDir . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => $vendorDir . '/symfony/framework-bundle/Test/KernelTestCase.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => $vendorDir . '/symfony/framework-bundle/Test/WebTestCase.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => $vendorDir . '/symfony/framework-bundle/Translation/PhpExtractor.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => $vendorDir . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => $vendorDir . '/symfony/framework-bundle/Translation/TranslationLoader.php', @@ -1656,6 +1661,7 @@ return array( 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => $vendorDir . '/symfony/var-dumper/Dumper/DataDumperInterface.php', 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => $vendorDir . '/symfony/var-dumper/Dumper/HtmlDumper.php', 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => $vendorDir . '/symfony/var-dumper/Exception/ThrowingCasterException.php', + 'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => $vendorDir . '/symfony/var-dumper/Test/VarDumperTestTrait.php', 'Symfony\\Component\\VarDumper\\VarDumper' => $vendorDir . '/symfony/var-dumper/VarDumper.php', 'Symfony\\Component\\Yaml\\Command\\LintCommand' => $vendorDir . '/symfony/yaml/Command/LintCommand.php', 'Symfony\\Component\\Yaml\\Dumper' => $vendorDir . '/symfony/yaml/Dumper.php', @@ -1859,6 +1865,8 @@ return array( 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => $vendorDir . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => $vendorDir . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => $vendorDir . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -2056,6 +2064,11 @@ return array( 'Twig_Test' => $vendorDir . '/twig/twig/lib/Twig/Test.php', 'Twig_TestCallableInterface' => $vendorDir . '/twig/twig/lib/Twig/TestCallableInterface.php', 'Twig_TestInterface' => $vendorDir . '/twig/twig/lib/Twig/TestInterface.php', + 'Twig_Test_Function' => $vendorDir . '/twig/twig/lib/Twig/Test/Function.php', + 'Twig_Test_IntegrationTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', + 'Twig_Test_Method' => $vendorDir . '/twig/twig/lib/Twig/Test/Method.php', + 'Twig_Test_Node' => $vendorDir . '/twig/twig/lib/Twig/Test/Node.php', + 'Twig_Test_NodeTestCase' => $vendorDir . '/twig/twig/lib/Twig/Test/NodeTestCase.php', 'Twig_Token' => $vendorDir . '/twig/twig/lib/Twig/Token.php', 'Twig_TokenParser' => $vendorDir . '/twig/twig/lib/Twig/TokenParser.php', 'Twig_TokenParserBroker' => $vendorDir . '/twig/twig/lib/Twig/TokenParserBroker.php', @@ -2127,7 +2140,6 @@ return array( 'iDBObjectSetIterator' => $baseDir . '/core/dbobjectiterator.php', 'iDBObjectURLMaker' => $baseDir . '/application/applicationcontext.class.inc.php', 'iDisplay' => $baseDir . '/core/dbobject.class.php', - 'iLogFileNameBuilder' => $baseDir . '/core/log.class.inc.php', 'iLoginExtension' => $baseDir . '/application/applicationextension.inc.php', 'iLoginFSMExtension' => $baseDir . '/application/applicationextension.inc.php', 'iLoginUIExtension' => $baseDir . '/application/applicationextension.inc.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 818c364ae..6de80b7dd 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -498,6 +498,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'HistoryBlock' => __DIR__ . '/../..' . '/application/displayblock.class.inc.php', 'Html2Text\\Html2Text' => __DIR__ . '/../..' . '/application/Html2Text.php', 'Html2Text\\Html2TextException' => __DIR__ . '/../..' . '/application/Html2TextException.php', + 'ILogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'ITopArchiveTar' => __DIR__ . '/../..' . '/core/tar-itop.class.inc.php', 'InlineImage' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', 'InlineImageGC' => __DIR__ . '/../..' . '/core/inlineimage.class.inc.php', @@ -516,7 +517,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'ListOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', 'LogAPI' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'LogFileNameBuilderFactory' => __DIR__ . '/../..' . '/core/log.class.inc.php', - 'LogFileRotationProcess' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'LoginBlockExtension' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', 'LoginTwigContext' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', 'LoginTwigRenderer' => __DIR__ . '/../..' . '/application/logintwig.class.inc.php', @@ -534,7 +534,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'ModuleDesign' => __DIR__ . '/../..' . '/core/moduledesign.class.inc.php', 'ModuleHandlerAPI' => __DIR__ . '/../..' . '/core/modulehandler.class.inc.php', 'ModuleHandlerApiInterface' => __DIR__ . '/../..' . '/core/modulehandler.class.inc.php', - 'MonthlyRotatingLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'MyHelpers' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', 'MySQLException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', 'MySQLHasGoneAwayException' => __DIR__ . '/../..' . '/core/cmdbsource.class.inc.php', @@ -836,6 +835,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php', 'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php', 'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php', + 'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php', + 'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/TestLogger.php', 'Psr\\SimpleCache\\CacheException' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheException.php', 'Psr\\SimpleCache\\CacheInterface' => __DIR__ . '/..' . '/psr/simple-cache/src/CacheInterface.php', 'Psr\\SimpleCache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/simple-cache/src/InvalidArgumentException.php', @@ -1074,6 +1076,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateNameParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TemplateReference.php', 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TimedPhpEngine' => __DIR__ . '/..' . '/symfony/framework-bundle/Templating/TimedPhpEngine.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\ForwardCompatTestTrait' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/ForwardCompatTestTrait.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/KernelTestCase.php', + 'Symfony\\Bundle\\FrameworkBundle\\Test\\WebTestCase' => __DIR__ . '/..' . '/symfony/framework-bundle/Test/WebTestCase.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpExtractor' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpExtractor.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\PhpStringTokenParser' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/PhpStringTokenParser.php', 'Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader' => __DIR__ . '/..' . '/symfony/framework-bundle/Translation/TranslationLoader.php', @@ -1886,6 +1891,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Symfony\\Component\\VarDumper\\Dumper\\DataDumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/DataDumperInterface.php', 'Symfony\\Component\\VarDumper\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/symfony/var-dumper/Dumper/HtmlDumper.php', 'Symfony\\Component\\VarDumper\\Exception\\ThrowingCasterException' => __DIR__ . '/..' . '/symfony/var-dumper/Exception/ThrowingCasterException.php', + 'Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait' => __DIR__ . '/..' . '/symfony/var-dumper/Test/VarDumperTestTrait.php', 'Symfony\\Component\\VarDumper\\VarDumper' => __DIR__ . '/..' . '/symfony/var-dumper/VarDumper.php', 'Symfony\\Component\\Yaml\\Command\\LintCommand' => __DIR__ . '/..' . '/symfony/yaml/Command/LintCommand.php', 'Symfony\\Component\\Yaml\\Dumper' => __DIR__ . '/..' . '/symfony/yaml/Dumper.php', @@ -2089,6 +2095,8 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', + 'Twig\\Test\\IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/IntegrationTestCase.php', + 'Twig\\Test\\NodeTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => __DIR__ . '/..' . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -2286,6 +2294,11 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'Twig_Test' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test.php', 'Twig_TestCallableInterface' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TestCallableInterface.php', 'Twig_TestInterface' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TestInterface.php', + 'Twig_Test_Function' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Function.php', + 'Twig_Test_IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/IntegrationTestCase.php', + 'Twig_Test_Method' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Method.php', + 'Twig_Test_Node' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/Node.php', + 'Twig_Test_NodeTestCase' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Test/NodeTestCase.php', 'Twig_Token' => __DIR__ . '/..' . '/twig/twig/lib/Twig/Token.php', 'Twig_TokenParser' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TokenParser.php', 'Twig_TokenParserBroker' => __DIR__ . '/..' . '/twig/twig/lib/Twig/TokenParserBroker.php', @@ -2357,7 +2370,6 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b 'iDBObjectSetIterator' => __DIR__ . '/../..' . '/core/dbobjectiterator.php', 'iDBObjectURLMaker' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', 'iDisplay' => __DIR__ . '/../..' . '/core/dbobject.class.php', - 'iLogFileNameBuilder' => __DIR__ . '/../..' . '/core/log.class.inc.php', 'iLoginExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'iLoginFSMExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'iLoginUIExtension' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', diff --git a/test/application/ThemeHandlerTest.php b/test/application/ThemeHandlerTest.php index c72a5a98e..2ad2789ef 100644 --- a/test/application/ThemeHandlerTest.php +++ b/test/application/ThemeHandlerTest.php @@ -10,10 +10,13 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase; */ class ThemeHandlerTest extends ItopTestCase { + const PATTERN = '|\\\/var[^"]+testimages|'; + private $compileCSSServiceMock; private $cssPath; private $jsonThemeParamFile; private $tmpDir; + private $aDirsToCleanup=array(); public function setUp() { @@ -25,18 +28,38 @@ class ThemeHandlerTest extends ItopTestCase ThemeHandler::mockCompileCSSService($this->compileCSSServiceMock); $this->tmpDir=$this->tmpdir(); + $aDirsToCleanup[] = $this->tmpDir; - if (!is_dir($this->tmpDir ."/branding")) - { - @mkdir($this->tmpDir."/branding"); - } - @mkdir($this->tmpDir."/branding/themes/"); - @mkdir($this->tmpDir."/branding/themes/basque-red"); + $this->recurseMkdir($this->tmpDir."/branding/themes/basque-red"); $this->cssPath = $this->tmpDir . '/branding/themes/basque-red/main.css'; $this->jsonThemeParamFile = $this->tmpDir . '/branding/themes/basque-red/theme-parameters.json'; $this->recurse_copy(APPROOT."/test/application/theme-handler/expected/css", $this->tmpDir."/branding/css"); } + public function tearDown() + { + parent::tearDown(); + foreach ($this->aDirsToCleanup as $dir) + { + $this->rrmdir($dir); + } + } + + function rrmdir($dir) { + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != "." && $object != "..") { + if (is_dir($dir."/".$object)) + $this->rrmdir($dir."/".$object); + else + unlink($dir."/".$object); + } + } + rmdir($dir); + } + } + function tmpdir() { $tmpfile=tempnam(sys_get_temp_dir(),''); if (file_exists($tmpfile)) @@ -68,11 +91,129 @@ class ThemeHandlerTest extends ItopTestCase closedir($dir); } + /** + * Test used to be notified by CI when precompiled styles are not up to date anymore in code repository. + * @param $xmlDataCusto + * @dataProvider providePrecompiledStyleSheets + * @throws \Exception + */ + public function testValidatePrecompiledStyles($xmlDataCusto) + { + echo "=== datamodel custo: $xmlDataCusto\n"; + $oDom = new MFDocument(); + $oDom->load($xmlDataCusto); + /**DOMNodeList **/$oThemeNodes=$oDom->GetNodes("/itop_design/branding/themes/theme"); + $this->assertNotNull($oThemeNodes); + + // Parsing themes from DM + foreach($oThemeNodes as $oTheme) + { + $sPrecompiledStylesheet = $oTheme->GetChildText('precompiled_stylesheet', ''); + if (empty($sPrecompiledStylesheet)) + { + continue; + } + + $sThemeId = $oTheme->getAttribute('id'); + + echo "=== theme: $sThemeId ===\n"; + $precompiledSig= ThemeHandler::GetSignature(dirname(__FILE__)."/../../datamodels/2.x/".$sPrecompiledStylesheet); + echo " precompiled signature: $precompiledSig\n"; + $this->assertFalse(empty($precompiledSig), "Signature in precompiled theme '".$sThemeId."' is not retrievable (cf precompiledsheet $sPrecompiledStylesheet / datamodel $xmlDataCusto)"); + + $aThemeParameters = array( + 'variables' => array(), + 'imports' => array(), + 'stylesheets' => array(), + 'precompiled_stylesheet' => '', + ); + + $aThemeParameters['precompiled_stylesheet'] = $sPrecompiledStylesheet; + /** @var \DOMNodeList $oVariables */ + $oVariables = $oTheme->GetNodes('variables/variable'); + foreach($oVariables as $oVariable) + { + $sVariableId = $oVariable->getAttribute('id'); + $aThemeParameters['variables'][$sVariableId] = $oVariable->GetText(); + } + + /** @var \DOMNodeList $oImports */ + $aStylesheetFiles = array(); + $aImportsPaths = array(APPROOT.'datamodels'); + $oImports = $oTheme->GetNodes('imports/import'); + foreach($oImports as $oImport) + { + $sImportId = $oImport->getAttribute('id'); + $aThemeParameters['imports'][$sImportId] = $oImport->GetText(); + $sFile = ThemeHandler::FindStylesheetFile($oImport->GetText(), $aImportsPaths); + $aStylesheetFiles[] = $sFile; + } + + /** @var \DOMNodeList $oStylesheets */ + $oStylesheets = $oTheme->GetNodes('stylesheets/stylesheet'); + foreach($oStylesheets as $oStylesheet) + { + $sStylesheetId = $oStylesheet->getAttribute('id'); + $aThemeParameters['stylesheets'][$sStylesheetId] = $oStylesheet->GetText(); + $sFile = ThemeHandler::FindStylesheetFile($oStylesheet->GetText(), $aImportsPaths); + $aStylesheetFiles[] = $sFile; + } + $sThemeFolderPath = APPROOT.'env-production/branding/themes/'.$sThemeId.'/test'; + if (!$this->recurseMkdir($sThemeFolderPath)) + { + $this->assertTrue(false, "Cannot create directory $sThemeFolderPath"); + } + + $aIncludedImages=ThemeHandler::GetIncludedImages($aThemeParameters['variables'], $aStylesheetFiles, $sThemeFolderPath); + $compiled_json_sig = ThemeHandler::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages); + echo " current signature: $compiled_json_sig\n"; + rmdir($sThemeFolderPath); + $this->assertEquals($precompiledSig, $compiled_json_sig, "Precompiled signature does not match currently compiled one on theme '".$sThemeId."' (cf precompiledsheet $sPrecompiledStylesheet / datamodel $xmlDataCusto)"); + } + } + + function recurseMkdir($dir) + { + if (is_dir($dir)) + { + return true; + } + + $sParentDir = dirname($dir); + if (!$this->recurseMkdir($sParentDir)) + { + return false; + } + + return @mkdir($dir); + } + + public function providePrecompiledStyleSheets() + { + $datamodelfiles=glob(dirname(__FILE__)."/../../datamodels/2.x/**/datamodel*.xml"); + $test_set = array(); + + foreach ($datamodelfiles as $datamodelfile) + { + if (is_file($datamodelfile) && + $datamodelfile=="/var/www/html/iTop/test/application/../../datamodels/2.x/itop-config-mgmt/datamodel.itop-config-mgmt.xml") + { + $content=file_get_contents($datamodelfile); + if (strpos($content, "precompiled_stylesheet")!==false) + { + $test_set[$datamodelfile]=array($datamodelfile); + } + } + } + + return $test_set; + } + public function testGetSignature() { $sig = ThemeHandler::GetSignature(APPROOT.'test/application/theme-handler/expected/themes/basque-red/main.css'); $expect_sig=<<assertEquals($expect_sig,$sig); @@ -166,168 +307,274 @@ JSON; ); } - - /** - * @param $ThemeParametersJson - * @param $CompileCSSFromSASSCount - * @param int $missingFile - * @param int $filesTouchedRecently - * @param int $fileMd5sumModified - * @param null $fileToTest - * - * @param null $expected_maincss_path - * - * @throws \CoreException - * @dataProvider CompileThemesProvider - */ - public function testCompileThemes($ThemeParametersJson, $CompileCSSFromSASSCount, $missingFile=0, $filesTouchedRecently=0, $fileMd5sumModified=0, $fileToTest=null, $expected_maincss_path=null, $bSetup=true) - { - $fileToTest=$this->tmpDir.'/'.$fileToTest; - $cssPath = $this->tmpDir . '/branding/themes/basque-red/main.css'; - copy(APPROOT . 'test/application/theme-handler/expected/themes/basque-red/main.css', $cssPath); - - if ($missingFile==1) - { - unlink($fileToTest); - } - - if ($filesTouchedRecently==1) - { - sleep(1); - touch($fileToTest); - } - - if ($fileMd5sumModified==1) - { - sleep(1); - file_put_contents($fileToTest, "###\n".file_get_contents($fileToTest)); - } - - $this->compileCSSServiceMock->expects($this->exactly($CompileCSSFromSASSCount)) - ->method("CompileCSSFromSASS") - ->willReturn("====CSSCOMPILEDCONTENT===="); - - ThemeHandler::CompileTheme('basque-red', $bSetup, json_decode($ThemeParametersJson, true), array($this->tmpDir.'/branding/themes/'), $this->tmpDir); - - if ($CompileCSSFromSASSCount==1) - { - $this->assertEquals(file_get_contents(APPROOT . $expected_maincss_path), file_get_contents($cssPath)); - } - } - /** * @return array */ public function CompileThemesProvider() { - $modifiedVariableThemeParameterJson='{"variables":{"brand-primary1":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"imports":{"css-variables":"..\/css\/css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}'; - $initialThemeParamJson='{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"imports":{"css-variables":"..\/css\/css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}'; - $import_file_path = '/branding/css/css-variables.scss'; - $importmodified_maincss="test/application/theme-handler/expected/themes/basque-red/main_importmodified.css"; - $varchanged_maincss="test/application/theme-handler/expected/themes/basque-red/main_varchanged.css"; - $stylesheet_maincss="test/application/theme-handler/expected/themes/basque-red/main_stylesheet.css"; - $stylesheet_file_path = '/branding/css/light-grey.scss'; + $sModifiedVariableThemeParameterJson='{"variables":{"brand-primary1":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"imports":{"css-variables":"..\/css\/css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}'; + $sInitialThemeParamJson='{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"imports":{"css-variables":"..\/css\/css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}'; + $sImportFilePath = '/branding/css/css-variables.scss'; + $sVarChangedMainCssPath="test/application/theme-handler/expected/themes/basque-red/main_varchanged.css"; + $sStylesheetMainCssPath="test/application/theme-handler/expected/themes/basque-red/main_stylesheet.css"; + $sImageMainCssPath="test/application/theme-handler/expected/themes/basque-red/main_imagemodified.css"; + $sImportModifiedMainCssPath="test/application/theme-handler/expected/themes/basque-red/main_importmodified.css"; + $sStylesheetFilePath = '/branding/css/light-grey.scss'; + $sImageFilePath = 'test/application/theme-handler/copied/testimages/images/green-header.gif'; return array( - "setup context: variables list modified without any file touched" => array($modifiedVariableThemeParameterJson, 1,0,0,0,$import_file_path, $varchanged_maincss), - "setup context: variables list modified with files touched" => array($modifiedVariableThemeParameterJson, 1,0,1,0,$import_file_path, $varchanged_maincss, false), - "itop page/theme loading; variables list modified sans touch de fichier" => array($modifiedVariableThemeParameterJson, 0,0,0,0,$import_file_path, $varchanged_maincss, false), + "setup context: variables list modified without any file touched" => array($sModifiedVariableThemeParameterJson, 1,false,false,false,$sImportFilePath, $sVarChangedMainCssPath), + "setup context: variables list modified with files touched" => array($sModifiedVariableThemeParameterJson, 1,false,true,false,$sImportFilePath, $sVarChangedMainCssPath, false), + "itop page/theme loading; variables list modified without any file touched" => array($sModifiedVariableThemeParameterJson, 0,false,false,false,$sImportFilePath, $sVarChangedMainCssPath, false), //imports - "import file missing" => array($initialThemeParamJson, 0, 1, 0, 0, $import_file_path), - "import file touched" => array($initialThemeParamJson, 0, 0, 1, 0, $import_file_path), - "import file modified" => array($initialThemeParamJson, 1, 0, 0, 1, $import_file_path, $importmodified_maincss), + "import file missing" => array($sInitialThemeParamJson, 0, true, false, false, $sImportFilePath), + "import file touched" => array($sInitialThemeParamJson, 0, false, true, false, $sImportFilePath), + "import file modified" => array($sInitialThemeParamJson, 1, false, false, true, $sImportFilePath, $sImportModifiedMainCssPath), //stylesheets - "stylesheets file missing" => array($initialThemeParamJson, 0, 1, 0, 0, $stylesheet_file_path), - "stylesheets file touched" => array($initialThemeParamJson, 0, 0, 1, 0, $stylesheet_file_path), - "stylesheets file modified" => array($initialThemeParamJson, 1, 0, 0, 1, $stylesheet_file_path, $stylesheet_maincss) + "stylesheets file missing" => array($sInitialThemeParamJson, 0, true, false, false, $sStylesheetFilePath), + "stylesheets file touched" => array($sInitialThemeParamJson, 0, false, true, false, $sStylesheetFilePath), + "stylesheets file modified" => array($sInitialThemeParamJson, 1, false, false, true, $sStylesheetFilePath, $sStylesheetMainCssPath), + //images + "image file missing" => array($sInitialThemeParamJson, 0, true, false, false, $sImageFilePath), + "image file touched" => array($sInitialThemeParamJson, 0, false, true, false, $sImageFilePath), + "image file modified" => array($sInitialThemeParamJson, 1, false, false, true, $sImageFilePath, $sImageMainCssPath), ); } + /** - * @param $xmlDataCusto - * @dataProvider providePrecompiledStyleSheets - * @throws \Exception + * @param $ThemeParametersJson + * @param int $iCompileCSSFromSASSCount + * @param boolean $bMissingFile + * @param boolean $bFilesTouchedRecently + * @param boolean $bFileMd5sumModified + * @param null $sFileToTest + * @param null $sExpectedMainCssPath + * @param bool $bSetup + * + * @throws \CoreException + * @dataProvider CompileThemesProvider */ - public function testValidatePrecompiledStyles($xmlDataCusto) + public function testCompileThemes($ThemeParametersJson, $iCompileCSSFromSASSCount, $bMissingFile=false, $bFilesTouchedRecently=false, $bFileMd5sumModified=false, $sFileToTest=null, $sExpectedMainCssPath=null, $bSetup=true) { - echo "=== datamodel custo: $xmlDataCusto\n"; - $oDom = new MFDocument(); - $oDom->load($xmlDataCusto); - /**DOMNodeList **/$oThemeNodes=$oDom->GetNodes("/itop_design/branding/themes/theme"); - $this->assertNotNull($oThemeNodes); - - // Parsing themes from DM - foreach($oThemeNodes as $oTheme) + $sAfterReplacementCssVariableMd5sum=''; + if (is_file($this->tmpDir.'/'.$sFileToTest)) { - $sPrecompiledStylesheet = $oTheme->GetChildText('precompiled_stylesheet', ''); - if (empty($sPrecompiledStylesheet)) - { - continue; - } - - $sThemeId = $oTheme->getAttribute('id'); - - echo "=== theme: $sThemeId ===\n"; - $precompiledSig= ThemeHandler::GetSignature(dirname(__FILE__)."/../../datamodels/2.x/".$sPrecompiledStylesheet); - echo " precompiled signature: $precompiledSig\n"; - $this->assertFalse(empty($precompiledSig), "Signature in precompiled theme '".$sThemeId."' is not retrievable (cf precompiledsheet $sPrecompiledStylesheet / datamodel $xmlDataCusto)"); - - $aThemeParameters = array( - 'variables' => array(), - 'imports' => array(), - 'stylesheets' => array(), - 'precompiled_stylesheet' => '', - ); - - $aThemeParameters['precompiled_stylesheet'] = $sPrecompiledStylesheet; - /** @var \DOMNodeList $oVariables */ - $oVariables = $oTheme->GetNodes('variables/variable'); - foreach($oVariables as $oVariable) - { - $sVariableId = $oVariable->getAttribute('id'); - $aThemeParameters['variables'][$sVariableId] = $oVariable->GetText(); - } - - /** @var \DOMNodeList $oImports */ - $oImports = $oTheme->GetNodes('imports/import'); - foreach($oImports as $oImport) - { - $sImportId = $oImport->getAttribute('id'); - $aThemeParameters['imports'][$sImportId] = $oImport->GetText(); - } - - /** @var \DOMNodeList $oStylesheets */ - $oStylesheets = $oTheme->GetNodes('stylesheets/stylesheet'); - foreach($oStylesheets as $oStylesheet) - { - $sStylesheetId = $oStylesheet->getAttribute('id'); - $aThemeParameters['stylesheets'][$sStylesheetId] = $oStylesheet->GetText(); - } - $compiled_json_sig = ThemeHandler::ComputeSignature($aThemeParameters, array(APPROOT.'datamodels')); - echo " current signature: $compiled_json_sig\n"; - $this->assertEquals($precompiledSig, $compiled_json_sig, "Precompiled signature does not match currently compiled one on theme '".$sThemeId."' (cf precompiledsheet $sPrecompiledStylesheet / datamodel $xmlDataCusto)"); + $sFileToTest=$this->tmpDir.'/'.$sFileToTest; + } + else + { + $sFileToTest=APPROOT.'/'.$sFileToTest; } - } + //copy images in test dir + $sAbsoluteImagePath = APPROOT .'test/application/theme-handler/copied/testimages/'; + $this->recurseMkdir($sAbsoluteImagePath); + $aDirsToCleanup[] = $sAbsoluteImagePath; + $this->recurse_copy(APPROOT .'test/application/theme-handler/expected/testimages/', $sAbsoluteImagePath); - public function providePrecompiledStyleSheets() - { - $datamodelfiles=glob(dirname(__FILE__)."/../../datamodels/2.x/**/datamodel*.xml"); - $test_set = array(); - - foreach ($datamodelfiles as $datamodelfile) + //change approot-relative in css-variable to use absolute path + $sCssVarPath = $this->tmpDir."/branding/css/css-variables.scss"; + $sBeforeReplacementCssVariableMd5sum = md5_file($sCssVarPath); + echo 'BEFORE :' . $sBeforeReplacementCssVariableMd5sum .' ' . $sCssVarPath . ' '; + $sCssVariableContent = file_get_contents($sCssVarPath); + $sLine = '$approot-relative: "'.$sAbsoluteImagePath.'" !default;'; + $sCssVariableContent=preg_replace("/\\\$approot-relative: \"(.*)\"/", $sLine, $sCssVariableContent); + file_put_contents($sCssVarPath, $sCssVariableContent); + if ($bMissingFile) { - if (is_file($datamodelfile) && - $datamodelfile=="/var/www/html/iTop/test/application/../../datamodels/2.x/itop-config-mgmt/datamodel.itop-config-mgmt.xml") - { - $content=file_get_contents($datamodelfile); - if (strpos($content, "precompiled_stylesheet")!==false) - { - $test_set[$datamodelfile]=array($datamodelfile); - } - } + $sAfterReplacementCssVariableMd5sum = $sBeforeReplacementCssVariableMd5sum; + unlink($sFileToTest); } - return $test_set; + if (is_file($sCssVarPath)) + { + $sAfterReplacementCssVariableMd5sum = md5_file($sCssVarPath); + } + + //change cssvar md5sum + image absolute paths + $sMainCssContent = file_get_contents(APPROOT."test/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css"); + $sMainCssContent = preg_replace('/MD5SUM/', $sAfterReplacementCssVariableMd5sum, $sMainCssContent); + $sReplacement = rtrim($sAbsoluteImagePath, '/'); + $sReplacement=preg_replace('|\/|', '\/', $sReplacement); + $sMainCssContent = preg_replace(static::PATTERN, $sReplacement, $sMainCssContent); + $cssPath = $this->tmpDir . '/branding/themes/basque-red/main.css'; + echo 'PUT md5sum: '.$sAfterReplacementCssVariableMd5sum.' in '.$cssPath.' '; + file_put_contents($cssPath, $sMainCssContent); + + //should be after main.css modification to make sure precompilation check will be performed + if ($bFilesTouchedRecently) + { + sleep(1); + touch($sFileToTest); + } + + //same: it should be after main.css modification + if ($bFileMd5sumModified) + { + $sMd5sum = md5_file($sFileToTest); + echo ' BEFORE touch: ' . $sMd5sum .' ' . $sFileToTest; + sleep(1); + file_put_contents($sFileToTest, "###\n".file_get_contents($sFileToTest)); + + $sMd5sum = md5_file($sFileToTest); + echo ' AFTER touch: ' . $sMd5sum .' ' . $sFileToTest; + } + + if (is_file($sCssVarPath)) + { + $sAfterReplacementCssVariableMd5sum = md5_file($sCssVarPath); + } + + $this->compileCSSServiceMock->expects($this->exactly($iCompileCSSFromSASSCount)) + ->method("CompileCSSFromSASS") + ->willReturn("====CSSCOMPILEDCONTENT===="); + + $aThemeParameters = json_decode($ThemeParametersJson, true); + ThemeHandler::CompileTheme('basque-red', $bSetup, $aThemeParameters, array($this->tmpDir.'/branding/themes/'), $this->tmpDir); + + if ($iCompileCSSFromSASSCount==1) + { + $sExpectedMainCssFile = APPROOT.$sExpectedMainCssPath; + if (!is_file($sExpectedMainCssFile)) + { + $this->assertTrue(false, "Cannot find expected main css file $sExpectedMainCssFile"); + } + + $aPatterns = array(static::PATTERN, '/'.$sBeforeReplacementCssVariableMd5sum.'/'); + $aPatterns[] = "/8100523d2e76a70266f3e7110e2fe5fb/"; + $aReplacements = array($sReplacement, $sAfterReplacementCssVariableMd5sum); + $aReplacements[] = md5(json_encode($aThemeParameters['variables'])); + var_dump($aReplacements); + $this->DoInnerJsonValidation($sExpectedMainCssFile, $cssPath, $aPatterns, $aReplacements); + } } + public function DoInnerJsonValidation($sExpectedCssFile, $sActualCssFile, $aPatterns, $aReplacements) + { + $sActualContent = file_get_contents($sActualCssFile); + + //replace absolute path to fix it in any envt + $sExpectedContent = preg_replace($aPatterns, $aReplacements, file_get_contents($sExpectedCssFile)); + + //echo($sExpectedContent); + if ($sExpectedContent != $sActualContent) + { + //try to have inner json diff failure + /** @var array $aExpectedJson */ + //replace absolute path to fix it in any envt + $sExpectedJson = preg_replace($aPatterns, $aReplacements, ThemeHandler::GetSignature($sExpectedCssFile)); + $aExpectedJson = json_decode($sExpectedJson, true); + /** @var array $aActualJson */ + $aActualJson = json_decode(ThemeHandler::GetSignature($sActualCssFile), true); + $this->assertEquals($aExpectedJson, $aActualJson, "CSS file dont match ($sExpectedCssFile / $sActualCssFile)"); + } + + $this->assertTrue(true); + } + + /** + * @param $sScssFile + * + * @dataProvider GetAllUrlFromScssProvider + */ + public function testGetAllUrlFromScss($sScssFile) + { + $aIncludedUrls = ThemeHandler::GetAllUrlFromScss(array('attr' => "123"),APPROOT.$sScssFile); + $this->assertEquals(array('approot-relative', 'version', 'version1'), array_values($aIncludedUrls['aMissingVariables'])); + $this->assertEquals(array("attr"=>"123"), + $aIncludedUrls['aFoundVariables']); + $aExpectedCompletedUrls = array( + 'css/ui-lightness/images/tutu.jpg', + "css/ui-lightness/images/tata.jpeg", + "css/ui-lightness/images/tete.jpeg?g=123" + ); + $aExpectedToCompleteUrls = array( + '\'abc/\'+ $approot-relative + "css/ui-lightness/images/toutou.png?v=" + $version', + "\$approot-relative + \"css/ui-lightness/images/toto.png?v=\" + \$version", + '$approot-relative + \'css/ui-lightness/images/titi.gif?v=\' + $version1', + '"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=" + $version', + ); + + $aIncludedUrls['aCompleteUrls']; + $this->assertEquals($aExpectedCompletedUrls, array_values($aIncludedUrls['aCompleteUrls'])); + $this->assertEquals($aExpectedToCompleteUrls, array_values($aIncludedUrls['aToCompleteUrls'])); + } + + /** + * @return array + */ + public function GetAllUrlFromScssProvider() + { + return array('test-getimages.scss' => array('test/application/theme-handler/getimages/test-getimages.scss')); + } + + public function testFindMissingVariables() + { + $sContent = <<< 'SCSS' +$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css +$approot-relative2: "../../" !default; // relative to env-***/branding/themes/***/main.css +$gray-base: #000 !default; +$gray-darker: lighten($gray-base, 13.5%) !default; // #222 +$brand-primary: $combodo-orange !default; +$brand-primary-lightest: lighten($brand-primary, 15%) !default; +$content-color: #eeeeee !default; +$default-font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif !default; +$icons-filter: hue-rotate(0deg) !default; +$toto : titi; +SCSS; + $aMissingVariables = array('gabu', 'toto', 'approot-relative', 'approot-relative2', 'gray-base', 'gray-darker', 'brand-primary', 'brand-primary-lightest', 'content-color', 'default-font-family', 'icons-filter'); + list($aMissingVariables, $aFoundVariables) = ThemeHandler::FindMissingVariables(array('gabu' => 'zomeu'), $aMissingVariables, array("a" => "b"), $sContent); + $aExpectedFoundVariables = array( + 'gabu' => 'zomeu', + 'toto' => 'titi', + 'approot-relative' => '../../../../../', + 'approot-relative2' => '../../', + 'gray-base' => '#000', + 'a' => 'b', + 'content-color' => '#eeeeee', + 'default-font-family' => 'Trebuchet MS,Tahoma,Verdana,Arial,sans-serif', + 'icons-filter' => 'hue-rotate(0deg)', + 'toto' => 'titi', + ); + $this->assertEquals($aExpectedFoundVariables, $aFoundVariables); + $this->assertEquals(array('gray-darker', 'brand-primary', 'brand-primary-lightest'), $aMissingVariables); + } + + /** + * @param $sUrlTemplate + * @param $aFoundVariables + * @param $sExpectedUrl + * + * @dataProvider ResolveUrlProvider + */ + public function testResolveUrl($sUrlTemplate, $aFoundVariables, $sExpectedUrl) + { + $this->assertEquals($sExpectedUrl, ThemeHandler::ResolveUrl($sUrlTemplate, $aFoundVariables)); + } + + public function ResolveUrlProvider() + { + return array( + 'XXX + $key1 UNresolved' => array("abc/'+ \$key1", array('key'=>'123'), false), + '$key1 + XXX UNresolved' => array("\$key1 + abs", array('key'=>'123'), false), + 'XXX + $key UNresolved' => array("abc/'+ \$unknownkey", array('key'=>'123'), false), + 'XXX + $key resolved' => array("abc/'+ \$key", array('key'=>'123'), "abc/123"), + 'XXX + $key1 resolved' => array("abc/'+ \$key1", array('key1'=>'123'), "abc/123"), + '$key + XXX resolved' => array("\$key + \"/abc", array('key'=>'123'), "123/abc"), + 'XXX + $key + YYY resolved' => array("abc/'+ \$key + '/def", array('key'=>'123'), "abc/123/def"), + ); + } + + public function testGetIncludedImages() + { + $aStylesheetFile=glob($this->tmpDir."/branding/css/*.scss"); + $aStylesheetFile[]=$this->tmpDir."/branding/css/ui-lightness/jqueryui.scss"; + $expectJsonFilePath = APPROOT.'test/application/theme-handler/expected/themes/basque-red/theme-parameters.json'; + $expectedThemeParamJson = file_get_contents($expectJsonFilePath); + $aThemeParametersVariables = json_decode($expectedThemeParamJson, true); + $aIncludedImages = ThemeHandler::GetIncludedImages($aThemeParametersVariables['variables'], $aStylesheetFile, "RELATIVEPATH"); + + $aExpectedImages = json_decode(file_get_contents(APPROOT.'test/application/theme-handler/getimages/expected-getimages.json'), true); + $this->assertEquals($aExpectedImages, $aIncludedImages); + } } \ No newline at end of file diff --git a/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png b/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..ea3abcbd5be801a33a04927354fc8d53fb742b6c GIT binary patch literal 418 zcmeAS@N?(olHy`uVBq!ia0vp^8Xzpd1SErbK34)Mwj^(Nm;YeE8S(uNP=vFJ#Am<$En9-cLebC{re^wgoll|t(`&s7)9J{YxO^N-aI z$5L3jD^ISzl+wQbw$Cm(|Mhq4jH=@2wI8o7+Gd%b|IIx5*Zn&?>lgCSXrXO^WskXw=UX3LH%8!s;k z#x%*aEGp*Jjm(QM&8zq~)!)n5QqVsS=vUPe*NBpo#FA922>S z4={E+nQaGTRC&5MhIkx*d-b$ng949h;3{8svn*F5o}?c;Kir+G=xvlfb9Ucnx!LzV zKYw1UzcGecb6t~6xWlB=3a51)dX2qx%p0t(H?ll;Xvl-Ua7M6%M)vm*~w}RD4lnZuhbmcl2i$G2U9fNc+T-xj%reP%UwdC`m~y zNwrEYN(E93Mh1qax&|h?M#dqAhE~SLR;EVU1_o9J1}EaHQ&2SI=BH$)RpQpLlj-mc Ppaup{S3j3^P6aCC*T9U%t&g&$ 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 F`VU*HUSR+L literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png b/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..e9c8e16ac5e7f61c843fbac290ce30c5de7e40b6 GIT binary patch literal 6922 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 Q^5g_ikWrPcku(qaFX2Wbe*gdg literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png b/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..07fa75b35e1a333859ca1a67e880f2e1332f863e GIT binary patch literal 4549 zcmeHK_fr!&AcDpfAG%i?7h3QXYTIVnLGDBG1R}w#K6k{005Y@(VE5p z0PxfWY|zu3&STm-2d5j%hPtMx1>E`nAOBV0b!XwqsX&(g#`-1z9+qohdc)?&nUWW8 z`5>LKyzJ7wOc#_m)zKLEc`LyyQYK=NGST=p*Dw7Y@+khsx=*;$>Vmkp#qR_vMUH_v zMwiwZARwB=*LPBNaw|NhU*2?3^$JbCcYwV8=QIfL4(6sNAcpoF`g8&HMqB!w+P^*; zpw;E30sx$G)YeopefVS57UnQs!wTs_zg^6DX8RGtUi5y%@$2u)-%FS4%j18zd(`JI zvIW?#Q>n>7+)wZ5Xp3$Rk6$U`%k(V7U?qG2Kp4i#$|?oAl(bS0RU8q}`iflteVII} z+QL}e+s39Y#=@Zsx)&7ZpO!@y1eAd`Op#wDRheDchCnxfP>;l9{R+4sKIf|_HZujt zgI%pHC2P+!GCUi%s~7j1>8rYhfc@6X=gP2-*<kKlgB346yHe z)&I+6LoiMe;AWUBvmx+vDcO;1*-L6kbFLtc12Au!L#&}Hk1Z5L<6MZPG|%W0+M|rj z&ffsqJmDMaZ*!t&C0@Z3E7bP=4LD6&6y!2LNPi%KnvN{}9_oD=4~ytir~j2sIu_zB z&x;LgQStn)0Y2GAKAH7JZafBG1=znMW!En^5HG(H_@t-xKjKW7ZcnHGAoZce8U`m( zKaK{-#`{-I!(7jPReLW|~tJ^%(u z8oa#0-8R(+R7(6zjIhLGMYn;VFL1Q+cLGONOWuxkd9v#FDF(W*7vOaujGWo2EI?SE zcewZuTJb$iv3@rrm9DzoaA-(C)yXfUH@!I_CXyHW10l{HZ+3iNOZ748C%;?S=lWDn zGv?_-3Md;9QZ|UDvkAsPunaIk$~GHlSNf2R9P+6_cN3?I_fToGsc>H1p{48lNLC15 z2Fv^`jK#OJF>e(H&4}c9T4zI^F`V=gPz-Dsm}MPoOtWP?TD)Ko%DSF&Ruou;aaV36 zg=b~yVh1x1aLt#q>1#X_q4q~$dMN9Z!0$NbSp6<`!LS9{DyXmwmHbMzKB{hwg8KV$ zHeUJWM_SH4io{wQRMStp*VK%3P+5;y;a(cVoaVyi$UxKut!nPp8VMLjh43vCv=PFw zBS6HIGj|KN%qB1BEj9^xxUF70iaCy7=!FBWvc)}2e`+xe?m*$44zk%(*)rMiR0hmS zRKjHsEUPn`t$0Mw z>6f#KUBVtHhi~Op`7_MtIH9{CDxOdH;as(7;6hxm$QmqKm;Li9?`(wDWqIMJBEGxb z{g4X<)-v-AulRh7-0Be99@e@}HI>zNMRMwNI={*HhC}S9u1qj+@ z0;!cGFr(GkbkW1elnn>k=d?tQ0fAdS$`F8S?%>R?&20xg;vn5&vow93-#qj9`StWJ zpbq{URYMo=VhrD*(>HorcuY=sOad{dEg_VLwg8qcRB_;2oXlslvqi8}Tk@Li1Z}$d zZP39~PEuNh9r~2K+jM3Ud}$W1^z2eJl);`nJKL@dA?7(EmlC1Ep;n-7H5OKHyX;_U zh#$F_7n~TQumIKv1ZirpfK*zy*tb4=9Ney>&pq23&Q{z?BAE;bb&J6jU+T}jSOXQT z2$8GQgW+92!KE8khZe@XA(W6Kq!R_#+7<56qLmlS-us_pa4~9i4+ce9{B}>rlEF+6d3^TS32n z^XnFRO%l&CGX}zJlvR;XVIJZ3-6W@2wsSb;j=aVChz}YSE(OQ$mIVH$O(|a`+=78Y zi(&;6cASDvTJ+vCdh{Z2DCRz4vSVz^DyMedti0=_qmrfh!m3E)o-B{YxfG4fn)sc5 z={}9JGp+U0Y2f$sdf97k?$Xnm5`bbIOorS-Sl~=H=uL-}}l|Obm0q1*=WU zwF!aWr=d`VU(_a_TewUOOEdfY%%1$G zzJesaO2pi+E~#g?4!L0FG+~n+4_Lc@{BWG$3^{XlQ&6P znN{nIwVfEE06B4U=So?w@9~qk@H0Go2EI#&HNLC8MZ1*q*DvzYIeQb5_)S}HUvu~{ ze=+wwZ4xa%@zu{f&!iy%z3-9YWXT!!Kjz8>{yJjhR12cWdwe8o(3kUuOvWBK%+g`i zGZha$3&@uI1Ar{#-f=5f=_7TJ=Ad%fE@&wO&(UpJq;Hx7GPI71D8&@7=|A1-dA!h1 zv(K?CnG+%s-F)!ez#8O8HBg?vhMIS0k-cL1{gUb*nuRL4WRGdUuM{rR&_F(p;X;XQ zn{xUIi62{GX;?UyISVQpFuf7>FQY%ei{xaOmGi%>RO;X9#7tRPNT43BhYS?aij>VA z@=j;<13qR6w3^!mAIsvxvix$lB`>I!t+k|F@%9?dPdVo7^VhgGJA)`Z-j8*k2r3oT0;V}5%@`t<8{bt@Hocrq4o;Av# zVp^PecVC&!yJj` z0~p9Rv1?0ypOrDZnwK{os4~iK<_k_$EpZ0KsrGdq{{}QMrE?m!N=b*|V5lcKA)=+qY#zZODV^Vwb+W@Y1| zds@2vsE6AFF@A&RG`9@GOd1s_JA1A%2PZq_e6sK;~yj0^W|-ARCL?RFhw`N)i(M8HvX4k0<99nMOiQNtGL$owhahx*yK| zD_~il$ANG&PBhN#$=?^CPgKUn-%!GDHsU~dLoAD7VS&7c6lVBEvRY(syi$eq$F}ju z`(J4>QNEGxNRTdrF6eDlP2b#H^3ot91Sp@)jtobs@L)YV&P4zkc{11x^+Si^#i+gB zFP0fI@R_J0LPu0xA60a~=jd}?PTGclz z>*c1|?lNw&Ykr}0J>OfR-5^rF)4;mIz){mp#jf;hCcnX~K|?TKLf`R<4#XstV2}c@*T0iF~F4ecgj_EVFmWgM{c~R|WOxe8L>n`^NQI zui2ePewSZmCB~d$fr)}cq6=RX*LT}4FN;PaU!9@v^5?TP|L7JRJV)M%=B$uQUexL? z_Z_8By442eX{MGyya(zBQC!tF9tGkgyJ~4eOL@}t(su1v3hhJEaDx6biF=2%AyX}M z180$i~Gf0i#?F$9J!(4J)9(Q5NBDg>pxAj>B|T zH)8U<9D=>x*v=uM9yn4IjQ=@KhxOlV=l&`a6GMN-we#n<*}?E5Dv^L=f&x^5b1+fi z)5@7*aHcbUNfg>5$o@F@kzd#B^mP2WL6GMWw>Rm(joG-C?|r2(vIP1|y_dh<7b+d^ zH8$3J%MkFua&X%AbQG;&a7F4#A#LjTc+c~2{DalLp;5A7cCbe$zAUUn_0vq+iFqf4 zVuehjE-g)ug323Dg4aRJ#}%vGEcg-X(in08RF7PoJkrvPj$Kp+q$E~WpA;Nj)y;{53U zCa7%>a-9-*{zfqIa`q3f_jLlOIeOi3f@^!&-*qx}vUhys)8(XedI+G6($_3k$3FfK DuSjEe literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png b/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2e78524236c91d8db8250fe048714d532276783e GIT binary patch literal 4549 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 xX^c;T#CixG^)-yMyFwHf|M( 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 F^dCirsK5XK literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png b/test/application/theme-handler/copied/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..4d66f596e5967a460a37526e2130a55711eeca3c GIT binary patch literal 6299 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 literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/ac-background.gif b/test/application/theme-handler/copied/testimages/images/ac-background.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f72b4f039e61927ff7823824459dcc9c82cd1d0 GIT binary patch literal 61 zcmZ?wbhEHb6kyDSr z1<%~X^wgl##FWaylc_d9MUy;T978H@y}7oLx5+`IAyJ|29;?TlL%uKO9+pjDs+x8n zX#0Ytn=iJV^7i3SoEFyqUR$p`Jnr9~7`xcjJl__6U^yZCgs+HwXY(D$cM9b{W;d%V z^n5C@i~IHU?B>{`G*81q_)))7*J&Uf1x_mFa?Z?sck86#u`<5&H o&#Jq3damq5>!S7!J0>263Imn--}}zq2fB{I)78&qol`;+0Qo~?5&!@I literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/bg.gif b/test/application/theme-handler/copied/testimages/images/bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2d7d0e3c74e53f5eb697d5abfa3fc087a695fda GIT binary patch literal 64 zcmZ?wbhEHb6lLIKXkcWJnR4X+|Nn|VSr{1@7#VaJfB+=Jz$D(&-*B4qR#HWXQPwy$!fk$L9 z0|Vb75M~tB@M-`GvX^-Jy0SlD5#m#m;MdvL2Nb&K>EaloalW-*-}_jBNb7uE9nNkg zF-Hj=$A}w#q4rIVF8ezVzA*pj%5%;9$M$(s8xtfY?x~omCq>M3z5L$X=HtER_lo_B zs>}DsUjM3X?Dg5EetWGEw}|V%#=#L951bA{%!n?%$~a& zU2ku*KCp4gUIpjtrP7y8=6YFiIen|$Z`SvC-;&K4-H8&{RCS+a{bNYn?BnD3m`M%j OIR;NxKbLh*2~7akop^Ns literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/calendar.png b/test/application/theme-handler/copied/testimages/images/calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..353be63d939399347cf10969b642b8d19c15e46d GIT binary patch literal 676 zcmV;V0$crwP)1yyhs z#DOtUU9EtrLdAeF{J!~;QrXr8oYdx^a3Bq0qfomeQUOx|TZP3u0LHoo0Vg{G9;_8W zB_a`tNL(!g*(?Cn9RXC8d(ZN^T{3!qYC~03AG}^yRn>>nQ9n8p^%JvEE)+|8p-0HWwpq@wkBGeVs#5v zBDKKxc>ZAvfZXy59v&|iwlD%B%Gb3b?TI+4wq~4buwbo?X5howffQkIoiqI@UVYr+ zbbpHR*#b+eKS{R6Nhg~TQ39VjfpL+Af$jwPA0>LTE#%g>>FkK}>3fmRBqS4YGVLu9 zY2Z;?!VsW4)y&AFCAKRTV;#mioE3}{tTX@Ig(F>iqp!Eyb^Z&KDNUK?hN?OM0000< KMNUMnLSTaD+$8}3 literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/delete.png b/test/application/theme-handler/copied/testimages/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..e9920bf47d78cdf4c3ab8f7642cbf3bd981ced21 GIT binary patch literal 842 zcmV-Q1GW5#P))_`%oDz7N*vvT4qUVYa}$i$!RF&xK8@m>Xi~}+|C=4xYM~~k8C>R{xUVr}QXmr9(By2m8 zu&*9C@Drf?AN*%Le%GFxv+Z-|?9W1>5kL@LhMuU;_d1#e*)09>_`q~;@7Q*eFtkh! z4P9yI?+>xI22Lk2ulGaX1yO)D-_p{tmM2e;o0_0lB-Gj2wl9-;g$@C?*y+`#N`6NpGTPtzu&sW=Eeq|x;m6yyFd_d$?|hCw>y^B^?SEVr3GnZd}W&7-!aX5t?TO@u22Xi7zD#W6a?phstzt`+M*ON&4}%E z;!ss+Y$Th@u`)Bmr-mBEtV~Qecv$I?*m8MW3{3Xoiy1VT; zw_D#0Cw6#7M<0yb^mvSot}gpDTmynno2|os|5#WM-rNCxrah7rf7jb-Q zag`tu6obp!L~)B0F04hs!e-fWL9np!FIZTLT3Lt|f`$77+}0w6){1Cgk(Djfu;K@q znfLacmk$ORL`dN9PR=>^<=&eap|wUkpV-OjRHUJl8gxYMiagMXAt_}gDkq~vtrP;U zc9@+hfgq>$t_wJl4*aF=-Vgb%v1t(G)S||f5x?FkocMZf?mH@HmlovI=)HLX+f=@H zJW%)wxc{)Sd1^sUjo#}~WT*kxgpDQf_ z=WBp>izV$c&8R?krb){CiP!g!m=3GV{oeqv0>Jz|F2%SjxZ@ zxGsL|j9QS_wUo`+tf^tGR7!93O%@RMewtR3tzslx+}~C$$Xl0~4703ZtvFdN=!tK= zjZKRB$-`mmjcxlz2)L}~=IZ2h?+;>uuTkEc#wShO4s#feu)1W0F+BR|pu=#aRe@P%VcQqxk5x>wm>YiBTwzrZ&rfJ9 za;RVqIas}7I$zVAjwdPg3S|yL)eK4z3+gmmb}^+KU|dmtVec0Puj5P`xkBWXPcXQx zI8txYY}L3!=GD=^0qV^$ng01v;Lb3>*dwdlyBR UFZ;m733NY$r>mdKI;Vst02p{=6951J literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/eye-closed-fff.png b/test/application/theme-handler/copied/testimages/images/eye-closed-fff.png new file mode 100644 index 0000000000000000000000000000000000000000..765064b1add0e348c751fa4d5f9eb8469e7c2645 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X`aNA7Ln>}1{rdmko>_H9XQPur)`0}W2lfKz)dS}<3hZZp z^n1aPf`9fbA_6ljL?(P;X<%WQz;aFaf(*lv_Y1Rx9g=hco;Q48Q{Zc`%4HOgXL-c$ z;rER_iCtwQdxFr(pL`zc4zRs*&XiwKC6M4yCb!E`HsBUxXIpklV$Q!7$&|h&63)sz h#!bEp85me37@kk_o#(Li2p`aC44$rjF6*2UngBHOP^l$V#+*Vot7)b#iFPn|lotE=nFmoKHIr3ncMt5&VLa^*^BXz2g{|Jhj< zJAv&E@(TuXu>uB06Rzz*MV+25jv*DdQu=T69ai9R=3QFyomcA7pa0YK8ni-Z%PYyU zGq?Tas5ROAe8%OBW%_$xIk&SO_fDJsWOnq0>cS7jcdJ$}e0PVxFNW9p`muvc^qF^9 z_%3r~`E$c;;!(3sInQlp!W-m1#;nx*CFl5SX&84Z=PJ$MLw|Nn6YN|o7kel8=*m0s fw>R%&;$b*-UBs}?{n1aLqZmA0{an^LB{Ts5_CBSe literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/eye-open-fff.png b/test/application/theme-handler/copied/testimages/images/eye-open-fff.png new file mode 100644 index 0000000000000000000000000000000000000000..b118f2b3fa0e7459552edca302eb4f4b38e1bf96 GIT binary patch literal 327 zcmV-N0l5B&P)8KqK7++)-8o4rRl%pLljt?8hfW0H~C!H6b9nDN2lsGrKLN^&?jvY3;72+Q8 z$s2UEP?15MXoU|f1VIClH%N)Sd5&rZ{|Xt#JH|@lxXtoE+(HTW=FcnSV9)~hWH2x3 zvi$leEMOE|qBk*gQiEg-mh?Xc>tl3R2acGL)-~xL|qm>m2a)002ovPDHLkV1g2He)0eS literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/full-screen.png b/test/application/theme-handler/copied/testimages/images/full-screen.png new file mode 100644 index 0000000000000000000000000000000000000000..300b153db721185842492021960af41c81dc1e48 GIT binary patch literal 1011 zcmaJ=PiWIn9L`W=RJVg5xb5=DE`m16OWV}O#o0CORy5sg%T_1ivgB0UFmMM2MP#0Q>DJDJHSqHO@O|I!`~BYU-5e_n zcSU+548wHgN7N#n574o{b07Vmc54^u)I+irQo=K&u6u|{n|K<5ysgioBGS!;OK;Ht z!|VZ8xk4)18QH)#r-v9WuwBY#n1R8-)r~nsz%-h*9EJV%`~?dvQ(-3(nxMHERJBGH zJycpOl#RtXBW1FKC&54M;&`vph_tQlW+@MkyldFE~UGqK@C+R8Wy`c$P~n?0`^FpT_e-alm zq6Omv-Q^)Cgef(Fn)ZLFZMV=qDWYA!{}lGi3ohb|$j9@ZK`(BmKMdu{84u|Mdu5Dk z%_@#nF~NQnyC73afCY3Zib_Q;{V?$M@R8NGgjJ_swXrpv*{<+JJTRnWQT z>5Z3bS9cRT$?!8;9-O}cG>0NdC6?gUL z%8^LtlZTU!&c|nb99Af5rT)t{mCEg5urg=A(g z{C|6SPb~9Xage|wB`SrZk2FOMYM!buln2sX?5Y+T78iB(Zu9cS7|LZyZ++}u$^oi1 z_j@S}bW9OzU2R+RMy&~OT>X-oZ98$jq#ogNfJ!BM-42wHGZk*6s2KD}U*IA%epmxb zm}|6BK9YoIF;*xSL!+z@<64lB7->LTW2Vi4ostCA(z&2XniwNIv}fFo-`MbG;)u4G z^p@F!)|9HhZprHd_vXjDoxs6WkK-6P0@lfxnGT>*p(QHoUV=u1FAqb@b%*W=a3{`LsH5k^AvQNL>6fPpy#oU(&MuH(*aEX4b35*} zn4n7)`I2U%=+Z=?BVZQ?vjQFW4gD@~XSOO6b{qu81`4&LFuU2(ilxW+1|ZkNMnWe79C$gs zWT?Ele|HR{JGPe)5BTW>0Ey?-Ls6S#GoV0tbt6ku7B&*0 z;i9QM$W1Rj*rRIdceL)rAOSl+sDe3LkB87<%){;ZdHp6|SNlopDXRx< zxBDF9-lTo&v`8$humFygUij@qgT=Qzhj8{ym2-{Xciwqq_Xwk%=O3B-MNAL_6e`3U zyxwmXex4`g0^1RYw~Dth3av3Dl^AAlpO3mG!nLr#&ZZ7c_wUboI+deC+&%TFjK2Lm z!Y&f1h|T_On%RCV&=4bx`!>(YezqGVhl&QpED?N6GV)HmzJ9&rh$x*i?*@o9#6QI< z5ZI_MRX;0+pY8$`j)eF#TlUyG(eE%E7S!rj;mj^M5vhUicPm zVWQ2z+imFyg}SRABmOBY_@osR!>7Ov!ioK`NB6_Rv}7Ud?35ed5Sb@?yND?kv~RCa wqs^a3Sh>&&L4)!LKI?D2&k@))k(LESaga|C278ChSzn3NWVkcuNoY&{0f?~U_5c6? literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/info-mini.png b/test/application/theme-handler/copied/testimages/images/info-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..de189bd8f1d27929df17df2780d814fe9df19c6d GIT binary patch literal 850 zcmV-Y1FigtP)8&>#E9BH zy93X2&f@tU!2`M|8Gr4h-EBSRyVgh?w`;-n);xdwT%dYw{r_(DpXuzU&z~4MK5^lN zqc1*_?>(ILOyX3tv9lN7EDSII@cq%Lc<%F0fbfC4&bbdK-?_4w+*q#a!fK#@UAeFC zZZ-Ao^}3#2sp&$op}(Hl)o0(ndK+(W>>wurtkJh7KbXAq@hi{vh#*X;G$IaXEk*`> zdVG_)wFZ@XglDFlKQq*~=8jz~PG9>5_I4%S@sn>%T%I~N+$}1Nn05*Y2Bm5nOKKKN zO*VprSVO&?vKMw38a(3O+A)Wke_sE}$ew!r&5^-=u^B`J5!53=ts`)J7iB7J*Cy1G zAQIF&P-$tRxXtPDmtMx~A61$D{8RNPMH--lfoVu$42H8dLwyeY?UdP4Ogl|T6HOGS zL{W_D$|-UKPpU*nIa6#gkTV$Qwa6M0p%fh<0foc)HXr7-*AFpE4B#Q&HOIFq5QE7t_giUbh(0JqfJ#SOiK~Q zpoM{}By%&1+?jfRf>w1_0_gJWPb>F~al3E$*y!V39LWhD%?O_8v+#XMl;Pr);5U-bo;dSrEUH4$zs(O@aG+km2hzVo cjfa{30tr4@$0SIS761SM07*qoM6N<$f?;f*O#lD@ literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/minus.gif b/test/application/theme-handler/copied/testimages/images/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..289ea73744e443726799fbc727678b95b1b590f1 GIT binary patch literal 139 zcmZ?wbhEHb p`m{J%5^i_?;oxch!`JL55F)|cn3!OgVOA>HcdU42l)4~;H2_agKXw2B literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/ok.png b/test/application/theme-handler/copied/testimages/images/ok.png new file mode 100644 index 0000000000000000000000000000000000000000..46710a0cd2620abd4bb3412ccf5e8b6e19012750 GIT binary patch literal 643 zcmV-}0(||6P)9mM0wGMsnpFjV@ z5B_sPa>bIHmZMAW0_v!Ba*6p$kGETS;_6i5OU+jS?O)@R1F>~?CR!CwU_$ZEdz5Bp zgQD3bT>SY){C<@~(8}V}HEMsyX=R2BXR1y*GGf*+>K`H~OT2J*BO8^iY5>zt?eW9M zO6z3xcUtG$r0I6*BRKtt?p#IX!P8c~o$KUR&Ox{OhD0SL8 z8=OHUhDnS`A~8oOBKvF3j^ZulDLNazpqDAh!@%4#-hFtF>pBh601iMF5y-S`lnSP` zF5ICZe2NQ=K~Y(=Oslnm25)GD(coL$;X%B^GdLTh+J%0q02x4B{LIVnJZUR)b=g8( zh;M?Qu-cDNh(#}|QK@7MIyDOu0)3Z!muLH^j$i;02nB}e3NFgFth|KvdXtJI?K12! zS)?26EH`E_;|kDm*4a4KBUk>4BL@INekWZ)Nm`X#U|*YRvSHP&V4W$K@h@XEoqE{f zc`Tg(!hhOJ+=g=f{bu)G<&Atp>F}Oc?8VyX76+IM9mdWU*B)h4nc)_oj|N9dvgA_% d#QqD8svmTf-+uGGFAe|z002ovPDHLkV1h1LEeiku literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/orange-header.gif b/test/application/theme-handler/copied/testimages/images/orange-header.gif new file mode 100644 index 0000000000000000000000000000000000000000..b491460d7c7eea1001bcc637d31e94d695d70072 GIT binary patch literal 122 zcmZ?wbhEHbA8BZ#p|=X*Sl);d1TIWShddm^*$$^^KQBK9oM~gdH=t8L4gD# GgEaunlPXXE literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/plus.gif b/test/application/theme-handler/copied/testimages/images/plus.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2ec0742e2b5e8e38e91c36102a4c25dbcae9e1e GIT binary patch literal 142 zcmZ?wbhEHb(`GP4qd)~`_lja|8HDAdFjmlWBb-UeR%86 zjq^W#{P^(U4Nx2i6o0ZXGBEHn=zw&B%wS-#{&3QB^CB F4FDB2C8huX literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/truncated.png b/test/application/theme-handler/copied/testimages/images/truncated.png new file mode 100644 index 0000000000000000000000000000000000000000..57d3e77eae6a4956ecde31a0268b844cd70b6c98 GIT binary patch literal 1429 zcmc(e`!^E`0LLeV>u}W~Q99^xN~f-rlj|fYn)P6jBDW6i*64&hN=4rGWDKKim{+!v zM_$9so6Y-~VY7^R??E2JJnsIB`#tCT{haU5-}6O796*}t`sx4xKoe|l>!cu5VO=$4 zMRsEJ|4`r{+~%PT08qldeh9Om=z76+uEEa!FM~ro17QFgsJ|D?5bWy-hdIGKp&tS| zU^f5&B?RQbW4nlmh}qd$u~_``=g*Xsl-1Q$JRVOV5D*9iolZxgP*G7)xw*MZOH1M5 z;a|Rd85$ZI92{gY7%M9)ySuw}b#){XiAtr8j*cRc$f>ER@$vEA-rmT_$c2Rk91a&9 z9W4@x&}j6=#s-haYieprO-*fYZ~y-Ndqze^Yinz4Y%B(Y+1uNjnVDH!TwGpWPE1VX z^ZCii$rBS3)6>%l2?_D>@g*fCGMOwZE32%mjLYSgmX>B_W|GO|_4W0+xw(dhhP1S_ zk&zLhP}tYk_x0;n7K??&VvCB33JMBpYHEs$i`i`UuV25Ko12+T=I76!b8>Rx;^L%I zX-`iNg+i&WuAZNt&&$gzEG#4viE_ETs;cVu@84@{Ye`8-9UUDKi6kZ_Mj#Lj4-a>B zbu~6N?(FPzc6L@&RM2R&+S=NIfdLMO)6&w?*4DPYySSPyr*L6HFOQGI?hEaMm zf~30!rdwJnb$9qi(xedfz8Y{~uSmR|?tj%Jaz`1;T|ttZqb42KsWbWNI|M5#DPm~( zFGjYR8(f$R2lDm~ZGF&ttTa*Rq%_m?-sEx=*oPTv4s)ij-!U%HOuqH8AbiPhuwI-X zzMx@u<^HXB%DuyRP;z79?V+Q8n-gD~5LCS^F+R`VZMhb2CP~183xG~NJ4=%z+SAH~ zE+5Zdbz^N*w3#JM&96Pl86|oX?)mgZ%k4?$;JW?ZCLRYZ(#o)bH8f%?TnMzr87ajX z8*nbA^wsNEVFf47J}=64X3tB%gsST4x=ultCAipnnTG6f`qxMd%?9reM-%m)PU}Y@?vopKDb}|geQ`v zvfY37EG+oYDKq^4uWU)XD%d6dj_pa+}#Sss3snu zW*0-XSM#c9*Fg=?G2cRnw+{bZSXUZdSJ&JOG-AZPj$8wyFsbEZWhw>d$(jY-kke2; zrCp!0inAdcV{h m&KuQ>!#3re=R9b^b+)pkV^-bj*+~+v*T3~X-xbWjU=0A^yc^^I literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/tv-collapsable.gif b/test/application/theme-handler/copied/testimages/images/tv-collapsable.gif new file mode 100644 index 0000000000000000000000000000000000000000..857262faecaaf363ab3d6fe1779ec6d6eb85c3f3 GIT binary patch literal 781 zcmV+o1M>VwNk%w1VGsbY1d##&0001hfPnx1{{R30A^8LW00062EC2ui01yDM1ONj6 zl#i(v>%SVDDcF0XR%^3A-Pw$vten~kQ$Df3Aka`(CO$Gso^r^Yw5H0V?n zhzPhSm>6YPq}a$PS^4Pr1Sw^iiP@yNHYv*a=~-xcg_@JQIl35Hb0`nuLOKm8KC~DS<3v0E6**q? zm=WYgJRM1XG#L`*NIfT6rgXWoPfM9EX~raUPod6jHxKRX)-%%2dP8&aESeALKBfJb z{&N}->OiRlsUEbN@TgXxSS5DV_*GAtOt_pV;K zdHL>L8W*r#zk~(%HT<_}V8w$G7iN4Ia^k0pDL0n<*m7jelcQGle3^4*(3?qjp86Se zXw#!rmv()+YHHc5VYjCJ8h7lgvw7FnecN|#;k&c`CLY}QaOK6l_GX^k`Elrut7En< z8ar$4wz&iMjvPGo>*TYS-+sP(`tR$*w;yjlK6?4;>9e=*9zXo~{OkALzyDu;0q*Bt zfdCpPAc6!Q$Y6pEF6dx{5KbuFauqfQ)^is|m*I39iud7rA?i2cfF&w;;)5wlxFUre zTKFP{Vrdv7hckLuBZxVQxFd-@n)oA%L8>?;i$%J4BaBJPNEVGt+SnwHPwF@&k5&43 zC6HMPxh0WZ8u=xXQ7SnmlV&+tCX{DNnI@HOTKOiHacVgymvwr1CzyGPxh9!?nu!*g zf2tWMn}fP}D4dDPxhS2D+W9D+k?J`qpN0B)DWGa0nkk{1D%vThpE4RMsG~YsDygSJ LnkuS<6aWA_b2fL3 literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/tv-expandable-last.gif b/test/application/theme-handler/copied/testimages/images/tv-expandable-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ede2de78e046691bafcd19d8f953d820a8a939d GIT binary patch literal 89 zcmZ?wbhEHb6krfzn8?J?(9poZ!0`Y7e;}#&lZBCifr&u}$Yub^GcajQ>0inAdcV{h q&KuQ>!-85aE8abxaj=r>ESKDpU6s1x-4bq3f1UgO@4W^CgEatFOCAgW literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/tv-expandable.gif b/test/application/theme-handler/copied/testimages/images/tv-expandable.gif new file mode 100644 index 0000000000000000000000000000000000000000..305d57fc8b14c89431818b5f21d81e39072723b5 GIT binary patch literal 787 zcmV+u1MK`qNk%w1VGsbY1d##&0001hfPnx1{{R30A^8LW00062EC2ui01yDM1ONj6 zl#i(v>%SVDDcF0XR#Je|A>GGlz1le|i8=~as(Px~3Y#jsDi#ZROFE0Y zt6NK!%i1gaYZh!fj9iR%44mw|tk!J&OdZWO&0MX0?UpUQ4c-m+jU8@2E_d#|PTsDb zepk*OpEvJbzjqJ+%A4QU&sRWV1CsGaU6>nC( zTlseN`xS6l!D9)RHGCFv+PjSNHs1TVZ{)v|16Lk=xp3ygn-h0l>^L-J(UM71HfVqJ9X~WyIc2u{X2H>*|v-0Hm(~vZ{@z319vVQI`QMwlUHAU zy?OTM+oN}%ZaqA9@!H9AH}4%i`0?z^w?F?ref;(A>%+G%A3y#3{PXwZ-|t_501n8O zVg-J7plk^ax1e+le)phy5zaTEeiip@Au)_@Rj* z#?_LFEy{SJf-BlMBa1aMcq5NF;<%%OJqr1wk3m8>B$7oEd8C9%I=Q5hO;Y$Il~F=D zrG-^$d8L(EVz?!kU2^%QhGCjHrkG`Nm?oNQZV2a@Y`!UHoNdneB8f5Tn5T;+(%2`U zfATpfkbx4qr=f)!d8nd^GP)>}jY9gUq>)NFsil=-dMTEfa=NLfoqGAHsG*WNDw(CC RdaA0as=2DGt#VcX06Vosfm8qh literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/tv-item-last.gif b/test/application/theme-handler/copied/testimages/images/tv-item-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..42a139ad59777163fb406f3692ebf5333ef379d9 GIT binary patch literal 65 zcmZ?wbhEHb6krfzXkcV$XlVHV|G(l-7DfgJMg|=QAOOiQFiG_EuVj0@Uuus3rEZ;L SYuWd=KJu9MtaBPGgEatO+7%uE literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/copied/testimages/images/tv-item.gif b/test/application/theme-handler/copied/testimages/images/tv-item.gif new file mode 100644 index 0000000000000000000000000000000000000000..281e5dce6705bbba1be16919ccad1883d9a9b7b5 GIT binary patch literal 750 zcmVi2fsz(rj1Z(I%uk_Z1$dUHLJCFC+@t*{rh7DQ$tg6bPOd)Ib9R>WJIOY zC1?7iG(~*cW?M%k^nH`*-V=i`xtK z>l-Y#TUe}i?3nDfEc#3uZ90uwt$NLx?Ya%yEz9_=8%|Cu4t!3WF5E0v&bw~>jvTK% z&s^_(54|tlPyNqYKx_lG736l%TS9Q=7LIEO5uQVI6V+8@m(N{9djA*YZN%5n-ba2T z{gniGQeaAgD-E_p_)=j^h7xB!tcjDOO^Q1$_QV)c-%pP@K@JsJlw?wqOHnpe`IKc; zms4R@m3ft>&a5}LdNsJN672wB*X9FPF}IdUNW|t3S66 z{d%URkG?T6W3jmwM*e=bnBB3h1DQ g3W{iJ#Am<$En9-cLebC{re^wgoll|t(`&s7)9J{YxO^N-aI z$5L3jD^ISzl+wQbw$Cm(|Mhq4jH=@2wI8o7+Gd%b|IIx5*Zn&?>lgCSXrXO^WskXw=UX3LH%8!s;k z#x%*aEGp*Jjm(QM&8zq~)!)n5QqVsS=vUPe*NBpo#FA922>S z4={E+nQaGTRC&5MhIkx*d-b$ng949h;3{8svn*F5o}?c;Kir+G=xvlfb9Ucnx!LzV zKYw1UzcGecb6t~6xWlB=3a51)dX2qx%p0t(H?ll;Xvl-Ua7M6%M)vm*~w}RD4lnZuhbmcl2i$G2U9fNc+T-xj%reP%UwdC`m~y zNwrEYN(E93Mh1qax&|h?M#dqAhE~SLR;EVU1_o9J1}EaHQ&2SI=BH$)RpQpLlj-mc Ppaup{S3j3^P6aCC*T9U%t&g&$ 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 F`VU*HUSR+L literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png b/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..e9c8e16ac5e7f61c843fbac290ce30c5de7e40b6 GIT binary patch literal 6922 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 Q^5g_ikWrPcku(qaFX2Wbe*gdg literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png b/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..07fa75b35e1a333859ca1a67e880f2e1332f863e GIT binary patch literal 4549 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 DuSjEe literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png b/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2e78524236c91d8db8250fe048714d532276783e GIT binary patch literal 4549 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 xX^c;T#CixG^)-yMyFwHf|M( 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 F^dCirsK5XK literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png b/test/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..4d66f596e5967a460a37526e2130a55711eeca3c GIT binary patch literal 6299 zcmZ`-cRXBOw>~q<7|})-qC`UU7QJNj-jhg_42c$f^g4PECI~`gL=S>QFF_`y005=7mYN9wfG!__ zT{7a!yZUQS_@x0q*40!4E@D##+b>&C53Pq@msacVOQX+O2>_THwbhjG`p;}xS;gJ# z@i`CtSZ{y-QArOtTHfVD`NL;Rd7=`{MDN)nwt2|-HXuK&jMyo{TQZn=LCX~!`f!2p z-b9;g)tt_S-@6vA**bN&cu-p6tdmik8Z!(L)7`yys9$oSMH3J_)`@Ac=jCNeK4r~k z^G$c|AtbzZwoHB2*Mjf;uqr8&<5G)yMmP2q{>2*xrIEP~@;-p$^yTS#;Ui)nPshQmA+_s{v&4Q?r$)HS{=tBZ296jl59gzAuo;Mu&hW1b5{vWwQv!!}V0CozRb&VsEI4q~C^vJ%#qN zJWmsYwrjOcnd>al89iJ4%CCvK;&#jF%O({saBtpQGkxl_cTgTg1o_aI$TG8-8+cGY za2j!Azxl6Vm$a-GV?*9(eREL?!$9;ZRa(OD3oV5Bv<&WiYjY2tsS_D=2|EoAqc|Gf zy`H|}UNd0zK4g_ht0~RYuP0NvX?w|wD{mOG*tQ|FyH0WJVEpf*4PjayM<**HFxyjyn%m^@Eu<^7 z{lwQbT{>ImhTz{1k3{YIkzAB!r)FrW9E55ra}5&sk3io5!`x<~gZg)%x6o6Z@07Cs{EArh`ckmUo_Nz0 zZ;1z!Ki41sX?8Tb;#suqMfaW2EujT#PNnDPfinc{=b{pOdSy5`J-$5e_wI-3Zqop8Y> zZAd2P;`tIkKZ<#@ag~!h6FBL5^PARyBgHpGR$7UC+8ggmX*1l8pq&1OV;OJ`N_uQ| z)8i2SBcphV5x1`TNon?NONR9O&V1AnnLTlq|Y@gg4}P1{HK#IV}us+<;5v$ytQ>va$oR%r5`PT6j2QFU;E?Si0f+8*oUXD>cpZt92?v168-f(pLn>{s-*aLtW6kJw+!WVSa` zx+ID`#n6_8b4prl|3Ga-Car(#^>x2Ey5>lFBPCbB_c3M3>$(8>qOO9Kn};I5-iNhA zs`cg2f9_2by%{QuuD~{y=zl*JZsMeZs_o%cmE8w#wN zj0B~yh_$1jGPfkUd=?)hu^(}1@yBcx(p7l(4s(&G7CvsQ zx0p10kS87H7j6Iqq?@yE37h*QsAhogQlk`iii9&SFTuD)K8D`c`ZHswH{WlpG1A*1Rts$N+4g?3r8 z=HQ2#Wb8$jPK9#c=?;3V9>Km@e2t8dyD6yrLyu?El!d^fHqHCuCGiLSzC|zGjFK|% zNyJBR+m$jVjnaGe3)Wx$OkP=-(wSaiAu09cFqVnHTj380C#_P~!9c^Eu!a7^X2kqQ z)ubCkZtPf^=K3!imY`!QmGI7sXxM4R^!iz&O?x7a^kR!UqO)QMl9i6<7R-_atFcMg z4>QpqEB=A*g0!I1BHp|^us^)-(>aFb8|21%$wUVQ+?YO3Wa*tyAjC^g1vI{~WTz~)KbJx7&aemf6DsjbdX zFL&q011kPI4Rwu9WRHS;pOseiX=c|N@|-5E1X4B4y<^#%qQKL>qZ_3af{n@vK_xp% zjAQSrp3_QxsrO?Updm@y0Rh_&c)aGiGm+HrgjsBpe51A9GLs;8!T`3RAbXRijjOg@ z(Uw)$b{b-1sB1%Qp+gP0uy{((n|WqpN1lap4EWQ)IgXR61C_#sG?sF5gheo!?_-V! zc8ZE4fa85bpQ|z1*dPEE#f_{VHaQRYe08ZnWmCYPdNzWPx~kJwXe9P|mYk%1x1Q@} zX`%$4A%>$%q<;rvy}!$;6i!?cW%-ESwpcSYb6+ISfLUmW>`~SQ_3rTcuXS@@oY5{f z+e9bsVJ}(rb;p`I){Y4x!2Jb1r)8&wUR(s&XWv09X*h5jWi|MV^qe)6Y?0&rr|wYJ zTYO*EtOa)79?Y-H7-e0gR9BdG9HTNMLO+5*O$GfkUkx9=EQj2>1tj91mr!l!&j&1z zeW69Y4wWC!;`q`s-4Oz?`ZH1gyr5{3z4CTT+|*BVhkQ?#puc5le=f493|s&}7s=d( zShX9fCalDRyrlY>>7>DLkU|&)@DSQ8{!D;VyZ@vW{wXxz{Z)xd^a~9{XlFlj&jSD6 zasWZ?06!s-st%{)d<82>cYF9O)Bs;&0~Kym2~L#Fe11-<6te>W!ixqxju&bcB1<16 zzEVe{E7|j6i8$TQAbN+#lCqlN3!+Lx{Qc&Aq#xw3f5iARAA<;mgb)ta&S&|;*9gWv zG=!+{m=)~6_OQ-=K`@2hwG`uR&8$pG{J>-n!`YL;B&ZT8BenKKi4arBDhwSI=cR~~ z451)Rswg^!zR5sOAry$I#%pSpskVtuu3?XZGFadCMF6kN%ui419J0QSr%Se0)uF!N zflp7K2ZLZjG=Fowf1~yT!PW?~Z1oW+I%3g0%N6n>`B`NOV~7X)p%8YjZrh#pYRX4d z)i&4OCS~3Ui#92cEI=qKK#?-nRyK^CkhevQB^z-+6Xg%(^GT&O#+<69Pm;oXpYm~N zG-_ZwrqqD9^j4N_-nF0ugcIco2 z^!7mg?29pC+4Ci=NkKqeWX&O97LOB&!!guHAH+{j-l=3?bcY^TfkP5AvJNjb0~>ODMQ6w%u#9yDNH3kIqnEgFfc9j_F}*+PEJ3nV=+m z90BIz4oXlObSKpRQVmSt>bQ4xV)>M3N2(OX(Z3L>la^t(pF=-grfoIWY$ppd9=3TU z{QLPBp|YnV0sQvnkr(!O&FTF+MRb+C|FxY{l4rO$P+rhxPZSJT%m|SC3L#?~W%{dv z`41QQ3FGu)rDpES3ziBTS50x1?viaOzYnc`biX6eIplU7zn1cJU;9pnRQXTywo>l~ zjqrsYVc}(QrD(&Su_xX__V?w@_7UG-7p=Fg<(vqT87@L;loE%`g9FYIY_>k3aOf5l z3g@TH-0;=!KG$c8xF~<2`AZx!3OYRjcM*a~4kciT2twntJ>D zgjt@kS@p95R;t zHb?`y9x!4wY>w7zDt~6nOa??KsX%WYz~nw%wbkOxSN=7&=E+M3Ka9;1$P{LHCrY3c@oR0mg7IsSZA3nQ^_y)r~{t&!)F^k2|nuGheq-VuOveG*LijN zpCoDj31oN9Y%G{ISI;_YT{9Of{&;Yx-_K_@|2~xxT!JoRg zX97BhDVmfJIG#3_!I}R0-C>@AZLwKA9Xn(f0fb%Lbu!zqrhclWI#cw$6)I@Xf$5eW zn8f_7gf(Cq&c@3^Yh2{lrpNto{KoTCe#`+!cr;dH_?6?6`h^~x*mC<^=naZ?Irfcs$v8DvPdMmBu8(!{#Ei)r2(oNsGm&8^42%4H{If|iW!cu)4S2ZMqO7y ztBG~7Xb}UfjR^Y_rE!ko^zM*uGGF7MKtYe^#*Lb4L6a+}by-fL6q=sUO}>MLoIp1o zc-ZXSlUIXEi;@{Yl^8iTJa0xcYJ$L~JvUHp$z|!8|IxG2G3CV>HZ(bTeM2HU{7|VQ zrkEHAw`zPS9r_VtG&T8~)H|9PHab?TW@sUK^1@9SinhAAQdKh#!I5N^+2ptkbl%ad_aS&JyOrHeZu5e9L**`xYV&LiwVs4SMLFrpKm=%q-+Xg%&@;`-I0uP#5s=A; zW3ju*)l+{C88(S=bffHBqwM$-hSe2OfeylaI#5|4YVw2d^1JIQCYs$k+#OtggyBc6 z^-~}mpu0XAZ^|Ln*PN)o^kB{v!*U|L{5{mmnSS%#Kcz1ixhL!UcKpXfJjqvmt2Nx8Rcuv&M*6?kZ^~!%b#dd?5*LCtA0`vHfnoBOQPy` zz}d!^Cv-S>AQ91jm-7FSCbF2r%yrjj_(5^srIaBymQ_(%jBaE*Qjjo^uZ8X!UH7eP zqm`mpO9F}Xv|%E3PRt{2+hkWqD)T^5!2xN)3zN6&kW*A_kwZi&)9RGdb%PV1%rHYy zw4ibSLnrohBq^Re=wW0oP=BICj4u38P$F!F=CZNi!auzx47TN|Ky8@N=qxwgo+h(S z+2Mhk(#;kTNGZGmcBRApJU|PMNX4eeD~(|;xpO3Tg9^r9AJO=A3f-PwObAtYaKjy* zgiQ>lUX%m3LX2{iqvZXyT@dLt?I*89N)3hU=NyjlTZLZnILg~%9hKIPAIio4Mck1$ zME{q-5vvWDJQ8Gw0sP=X{Qb8M$jJ{=C@F96q3cOmy7a_a$Ompz`(#uPx!o7RZ81zp z+@1>5%im^}IebpZJ|K!RAZd$c6akCFsrMgs)g`f)EIsO+C~e*FyLf=zt7eNfj^Bon z9bBg*^G~Alcq2|t$0~!E?e`|iX^a=}C(iVU6KI?-Eyovr`*ou<1sk)S9WY~bZbhZ`27~yhkcfcMQAHPP^;u{GJVABt6UpWxxkX?4&RxX9yYq&+g$tX_ z7xGX4io>j0cOw56Y%izLwrzJagrPpOe|mKQx5HR9ES+7ez@AaCOKQLKxiLk0Pf)6( z{dqw)r3c7*F5hVbQ7u`UnAm@U!H>n-RhJt|; zXXif*4$^y6-5<2{Z-$)WUdcQ-JLIfn@6R}2ZY+5jN}&k%r90sl2zr6%>BB%g=%n}E%LqO< z8O0nBW`)ACYO)WSUWbAF`@gJ29>c^acs%g&!lOR5+r}zwH0`taP9E zwGJ=>tiEus^JPD1sV^qxK*U)<@=HK*If8cFv<83GR#MAE50OF!zl0u>q zLSkZf#cs<<%F2m}3y6x!iHeH8eOmrM99-RPpV|lf{|?FrqfD0$EPst)>Td7tXX9xH kDBHR}w&T=xwQ;aBv9qxaK=#=wTy_Gq)eY1tRjeca3k5U7C;$Ke literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/ac-background.gif b/test/application/theme-handler/expected/testimages/images/ac-background.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f72b4f039e61927ff7823824459dcc9c82cd1d0 GIT binary patch literal 61 zcmZ?wbhEHb6kyDSr z1<%~X^wgl##FWaylc_d9MUy;T978H@y}7oLx5+`IAyJ|29;?TlL%uKO9+pjDs+x8n zX#0Ytn=iJV^7i3SoEFyqUR$p`Jnr9~7`xcjJl__6U^yZCgs+HwXY(D$cM9b{W;d%V z^n5C@i~IHU?B>{`G*81q_)))7*J&Uf1x_mFa?Z?sck86#u`<5&H o&#Jq3damq5>!S7!J0>263Imn--}}zq2fB{I)78&qol`;+0Qo~?5&!@I literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/bg.gif b/test/application/theme-handler/expected/testimages/images/bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..e2d7d0e3c74e53f5eb697d5abfa3fc087a695fda GIT binary patch literal 64 zcmZ?wbhEHb6lLIKXkcWJnR4X+|Nn|VSr{1@7#VaJfB+=Jz$D(&-*B4qR#HWXQPwy$!fk$L9 z0|Vb75M~tB@M-`GvX^-Jy0SlD5#m#m;MdvL2Nb&K>EaloalW-*-}_jBNb7uE9nNkg zF-Hj=$A}w#q4rIVF8ezVzA*pj%5%;9$M$(s8xtfY?x~omCq>M3z5L$X=HtER_lo_B zs>}DsUjM3X?Dg5EetWGEw}|V%#=#L951bA{%!n?%$~a& zU2ku*KCp4gUIpjtrP7y8=6YFiIen|$Z`SvC-;&K4-H8&{RCS+a{bNYn?BnD3m`M%j OIR;NxKbLh*2~7akop^Ns literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/calendar.png b/test/application/theme-handler/expected/testimages/images/calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..353be63d939399347cf10969b642b8d19c15e46d GIT binary patch literal 676 zcmV;V0$crwP)1yyhs z#DOtUU9EtrLdAeF{J!~;QrXr8oYdx^a3Bq0qfomeQUOx|TZP3u0LHoo0Vg{G9;_8W zB_a`tNL(!g*(?Cn9RXC8d(ZN^T{3!qYC~03AG}^yRn>>nQ9n8p^%JvEE)+|8p-0HWwpq@wkBGeVs#5v zBDKKxc>ZAvfZXy59v&|iwlD%B%Gb3b?TI+4wq~4buwbo?X5howffQkIoiqI@UVYr+ zbbpHR*#b+eKS{R6Nhg~TQ39VjfpL+Af$jwPA0>LTE#%g>>FkK}>3fmRBqS4YGVLu9 zY2Z;?!VsW4)y&AFCAKRTV;#mioE3}{tTX@Ig(F>iqp!Eyb^Z&KDNUK?hN?OM0000< KMNUMnLSTaD+$8}3 literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/delete.png b/test/application/theme-handler/expected/testimages/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..e9920bf47d78cdf4c3ab8f7642cbf3bd981ced21 GIT binary patch literal 842 zcmV-Q1GW5#P))_`%oDz7N*vvT4qUVYa}$i$!RF&xK8@m>Xi~}+|C=4xYM~~k8C>R{xUVr}QXmr9(By2m8 zu&*9C@Drf?AN*%Le%GFxv+Z-|?9W1>5kL@LhMuU;_d1#e*)09>_`q~;@7Q*eFtkh! z4P9yI?+>xI22Lk2ulGaX1yO)D-_p{tmM2e;o0_0lB-Gj2wl9-;g$@C?*y+`#N`6NpGTPtzu&sW=Eeq|x;m6yyFd_d$?|hCw>y^B^?SEVr3GnZd}W&7-!aX5t?TO@u22Xi7zD#W6a?phstzt`+M*ON&4}%E z;!ss+Y$Th@u`)Bmr-mBEtV~Qecv$I?*m8MW3{3Xoiy1VT; zw_D#0Cw6#7M<0yb^mvSot}gpDTmynno2|os|5#WM-rNCxrah7rf7jb-Q zag`tu6obp!L~)B0F04hs!e-fWL9np!FIZTLT3Lt|f`$77+}0w6){1Cgk(Djfu;K@q znfLacmk$ORL`dN9PR=>^<=&eap|wUkpV-OjRHUJl8gxYMiagMXAt_}gDkq~vtrP;U zc9@+hfgq>$t_wJl4*aF=-Vgb%v1t(G)S||f5x?FkocMZf?mH@HmlovI=)HLX+f=@H zJW%)wxc{)Sd1^sUjo#}~WT*kxgpDQf_ z=WBp>izV$c&8R?krb){CiP!g!m=3GV{oeqv0>Jz|F2%SjxZ@ zxGsL|j9QS_wUo`+tf^tGR7!93O%@RMewtR3tzslx+}~C$$Xl0~4703ZtvFdN=!tK= zjZKRB$-`mmjcxlz2)L}~=IZ2h?+;>uuTkEc#wShO4s#feu)1W0F+BR|pu=#aRe@P%VcQqxk5x>wm>YiBTwzrZ&rfJ9 za;RVqIas}7I$zVAjwdPg3S|yL)eK4z3+gmmb}^+KU|dmtVec0Puj5P`xkBWXPcXQx zI8txYY}L3!=GD=^0qV^$ng01v;Lb3>*dwdlyBR UFZ;m733NY$r>mdKI;Vst02p{=6951J literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/eye-closed-fff.png b/test/application/theme-handler/expected/testimages/images/eye-closed-fff.png new file mode 100644 index 0000000000000000000000000000000000000000..765064b1add0e348c751fa4d5f9eb8469e7c2645 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5X`aNA7Ln>}1{rdmko>_H9XQPur)`0}W2lfKz)dS}<3hZZp z^n1aPf`9fbA_6ljL?(P;X<%WQz;aFaf(*lv_Y1Rx9g=hco;Q48Q{Zc`%4HOgXL-c$ z;rER_iCtwQdxFr(pL`zc4zRs*&XiwKC6M4yCb!E`HsBUxXIpklV$Q!7$&|h&63)sz h#!bEp85me37@kk_o#(Li2p`aC44$rjF6*2UngBHOP^l$V#+*Vot7)b#iFPn|lotE=nFmoKHIr3ncMt5&VLa^*^BXz2g{|Jhj< zJAv&E@(TuXu>uB06Rzz*MV+25jv*DdQu=T69ai9R=3QFyomcA7pa0YK8ni-Z%PYyU zGq?Tas5ROAe8%OBW%_$xIk&SO_fDJsWOnq0>cS7jcdJ$}e0PVxFNW9p`muvc^qF^9 z_%3r~`E$c;;!(3sInQlp!W-m1#;nx*CFl5SX&84Z=PJ$MLw|Nn6YN|o7kel8=*m0s fw>R%&;$b*-UBs}?{n1aLqZmA0{an^LB{Ts5_CBSe literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/eye-open-fff.png b/test/application/theme-handler/expected/testimages/images/eye-open-fff.png new file mode 100644 index 0000000000000000000000000000000000000000..b118f2b3fa0e7459552edca302eb4f4b38e1bf96 GIT binary patch literal 327 zcmV-N0l5B&P)8KqK7++)-8o4rRl%pLljt?8hfW0H~C!H6b9nDN2lsGrKLN^&?jvY3;72+Q8 z$s2UEP?15MXoU|f1VIClH%N)Sd5&rZ{|Xt#JH|@lxXtoE+(HTW=FcnSV9)~hWH2x3 zvi$leEMOE|qBk*gQiEg-mh?Xc>tl3R2acGL)-~xL|qm>m2a)002ovPDHLkV1g2He)0eS literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/full-screen.png b/test/application/theme-handler/expected/testimages/images/full-screen.png new file mode 100644 index 0000000000000000000000000000000000000000..300b153db721185842492021960af41c81dc1e48 GIT binary patch literal 1011 zcmaJ=PiWIn9L`W=RJVg5xb5=DE`m16OWV}O#o0CORy5sg%T_1ivgB0UFmMM2MP#0Q>DJDJHSqHO@O|I!`~BYU-5e_n zcSU+548wHgN7N#n574o{b07Vmc54^u)I+irQo=K&u6u|{n|K<5ysgioBGS!;OK;Ht z!|VZ8xk4)18QH)#r-v9WuwBY#n1R8-)r~nsz%-h*9EJV%`~?dvQ(-3(nxMHERJBGH zJycpOl#RtXBW1FKC&54M;&`vph_tQlW+@MkyldFE~UGqK@C+R8Wy`c$P~n?0`^FpT_e-alm zq6Omv-Q^)Cgef(Fn)ZLFZMV=qDWYA!{}lGi3ohb|$j9@ZK`(BmKMdu{84u|Mdu5Dk z%_@#nF~NQnyC73afCY3Zib_Q;{V?$M@R8NGgjJ_swXrpv*{<+JJTRnWQT z>5Z3bS9cRT$?!8;9-O}cG>0NdC6?gUL z%8^LtlZTU!&c|nb99Af5rT)t{mCEg5urg=A(g z{C|6SPb~9Xage|wB`SrZk2FOMYM!buln2sX?5Y+T78iB(Zu9cS7|LZyZ++}u$^oi1 z_j@S}bW9OzU2R+RMy&~OT>X-oZ98$jq#ogNfJ!BM-42wHGZk*6s2KD}U*IA%epmxb zm}|6BK9YoIF;*xSL!+z@<64lB7->LTW2Vi4ostCA(z&2XniwNIv}fFo-`MbG;)u4G z^p@F!)|9HhZprHd_vXjDoxs6WkK-6P0@lfxnGT>*p(QHoUV=u1FAqb@b%*W=a3{`LsH5k^AvQNL>6fPpy#oU(&MuH(*aEX4b35*} zn4n7)`I2U%=+Z=?BVZQ?vjQFW4gD@~XSOO6b{qu81`4&LFuU2(ilxW+1|ZkNMnWe79C$gs zWT?Ele|HR{JGPe)5BTW>0Ey?-Ls6S#GoV0tbt6ku7B&*0 z;i9QM$W1Rj*rRIdceL)rAOSl+sDe3LkB87<%){;ZdHp6|SNlopDXRx< zxBDF9-lTo&v`8$humFygUij@qgT=Qzhj8{ym2-{Xciwqq_Xwk%=O3B-MNAL_6e`3U zyxwmXex4`g0^1RYw~Dth3av3Dl^AAlpO3mG!nLr#&ZZ7c_wUboI+deC+&%TFjK2Lm z!Y&f1h|T_On%RCV&=4bx`!>(YezqGVhl&QpED?N6GV)HmzJ9&rh$x*i?*@o9#6QI< z5ZI_MRX;0+pY8$`j)eF#TlUyG(eE%E7S!rj;mj^M5vhUicPm zVWQ2z+imFyg}SRABmOBY_@osR!>7Ov!ioK`NB6_Rv}7Ud?35ed5Sb@?yND?kv~RCa wqs^a3Sh>&&L4)!LKI?D2&k@))k(LESaga|C278ChSzn3NWVkcuNoY&{0f?~U_5c6? literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/info-mini.png b/test/application/theme-handler/expected/testimages/images/info-mini.png new file mode 100644 index 0000000000000000000000000000000000000000..de189bd8f1d27929df17df2780d814fe9df19c6d GIT binary patch literal 850 zcmV-Y1FigtP)8&>#E9BH zy93X2&f@tU!2`M|8Gr4h-EBSRyVgh?w`;-n);xdwT%dYw{r_(DpXuzU&z~4MK5^lN zqc1*_?>(ILOyX3tv9lN7EDSII@cq%Lc<%F0fbfC4&bbdK-?_4w+*q#a!fK#@UAeFC zZZ-Ao^}3#2sp&$op}(Hl)o0(ndK+(W>>wurtkJh7KbXAq@hi{vh#*X;G$IaXEk*`> zdVG_)wFZ@XglDFlKQq*~=8jz~PG9>5_I4%S@sn>%T%I~N+$}1Nn05*Y2Bm5nOKKKN zO*VprSVO&?vKMw38a(3O+A)Wke_sE}$ew!r&5^-=u^B`J5!53=ts`)J7iB7J*Cy1G zAQIF&P-$tRxXtPDmtMx~A61$D{8RNPMH--lfoVu$42H8dLwyeY?UdP4Ogl|T6HOGS zL{W_D$|-UKPpU*nIa6#gkTV$Qwa6M0p%fh<0foc)HXr7-*AFpE4B#Q&HOIFq5QE7t_giUbh(0JqfJ#SOiK~Q zpoM{}By%&1+?jfRf>w1_0_gJWPb>F~al3E$*y!V39LWhD%?O_8v+#XMl;Pr);5U-bo;dSrEUH4$zs(O@aG+km2hzVo cjfa{30tr4@$0SIS761SM07*qoM6N<$f?;f*O#lD@ literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/minus.gif b/test/application/theme-handler/expected/testimages/images/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..289ea73744e443726799fbc727678b95b1b590f1 GIT binary patch literal 139 zcmZ?wbhEHb p`m{J%5^i_?;oxch!`JL55F)|cn3!OgVOA>HcdU42l)4~;H2_agKXw2B literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/ok.png b/test/application/theme-handler/expected/testimages/images/ok.png new file mode 100644 index 0000000000000000000000000000000000000000..46710a0cd2620abd4bb3412ccf5e8b6e19012750 GIT binary patch literal 643 zcmV-}0(||6P)9mM0wGMsnpFjV@ z5B_sPa>bIHmZMAW0_v!Ba*6p$kGETS;_6i5OU+jS?O)@R1F>~?CR!CwU_$ZEdz5Bp zgQD3bT>SY){C<@~(8}V}HEMsyX=R2BXR1y*GGf*+>K`H~OT2J*BO8^iY5>zt?eW9M zO6z3xcUtG$r0I6*BRKtt?p#IX!P8c~o$KUR&Ox{OhD0SL8 z8=OHUhDnS`A~8oOBKvF3j^ZulDLNazpqDAh!@%4#-hFtF>pBh601iMF5y-S`lnSP` zF5ICZe2NQ=K~Y(=Oslnm25)GD(coL$;X%B^GdLTh+J%0q02x4B{LIVnJZUR)b=g8( zh;M?Qu-cDNh(#}|QK@7MIyDOu0)3Z!muLH^j$i;02nB}e3NFgFth|KvdXtJI?K12! zS)?26EH`E_;|kDm*4a4KBUk>4BL@INekWZ)Nm`X#U|*YRvSHP&V4W$K@h@XEoqE{f zc`Tg(!hhOJ+=g=f{bu)G<&Atp>F}Oc?8VyX76+IM9mdWU*B)h4nc)_oj|N9dvgA_% d#QqD8svmTf-+uGGFAe|z002ovPDHLkV1h1LEeiku literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/orange-header.gif b/test/application/theme-handler/expected/testimages/images/orange-header.gif new file mode 100644 index 0000000000000000000000000000000000000000..b491460d7c7eea1001bcc637d31e94d695d70072 GIT binary patch literal 122 zcmZ?wbhEHbA8BZ#p|=X*Sl);d1TIWShddm^*$$^^KQBK9oM~gdH=t8L4gD# GgEaunlPXXE literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/plus.gif b/test/application/theme-handler/expected/testimages/images/plus.gif new file mode 100644 index 0000000000000000000000000000000000000000..a2ec0742e2b5e8e38e91c36102a4c25dbcae9e1e GIT binary patch literal 142 zcmZ?wbhEHb(`GP4qd)~`_lja|8HDAdFjmlWBb-UeR%86 zjq^W#{P^(U4Nx2i6o0ZXGBEHn=zw&B%wS-#{&3QB^CB F4FDB2C8huX literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/truncated.png b/test/application/theme-handler/expected/testimages/images/truncated.png new file mode 100644 index 0000000000000000000000000000000000000000..57d3e77eae6a4956ecde31a0268b844cd70b6c98 GIT binary patch literal 1429 zcmc(e`!^E`0LLeV>u}W~Q99^xN~f-rlj|fYn)P6jBDW6i*64&hN=4rGWDKKim{+!v zM_$9so6Y-~VY7^R??E2JJnsIB`#tCT{haU5-}6O796*}t`sx4xKoe|l>!cu5VO=$4 zMRsEJ|4`r{+~%PT08qldeh9Om=z76+uEEa!FM~ro17QFgsJ|D?5bWy-hdIGKp&tS| zU^f5&B?RQbW4nlmh}qd$u~_``=g*Xsl-1Q$JRVOV5D*9iolZxgP*G7)xw*MZOH1M5 z;a|Rd85$ZI92{gY7%M9)ySuw}b#){XiAtr8j*cRc$f>ER@$vEA-rmT_$c2Rk91a&9 z9W4@x&}j6=#s-haYieprO-*fYZ~y-Ndqze^Yinz4Y%B(Y+1uNjnVDH!TwGpWPE1VX z^ZCii$rBS3)6>%l2?_D>@g*fCGMOwZE32%mjLYSgmX>B_W|GO|_4W0+xw(dhhP1S_ zk&zLhP}tYk_x0;n7K??&VvCB33JMBpYHEs$i`i`UuV25Ko12+T=I76!b8>Rx;^L%I zX-`iNg+i&WuAZNt&&$gzEG#4viE_ETs;cVu@84@{Ye`8-9UUDKi6kZ_Mj#Lj4-a>B zbu~6N?(FPzc6L@&RM2R&+S=NIfdLMO)6&w?*4DPYySSPyr*L6HFOQGI?hEaMm zf~30!rdwJnb$9qi(xedfz8Y{~uSmR|?tj%Jaz`1;T|ttZqb42KsWbWNI|M5#DPm~( zFGjYR8(f$R2lDm~ZGF&ttTa*Rq%_m?-sEx=*oPTv4s)ij-!U%HOuqH8AbiPhuwI-X zzMx@u<^HXB%DuyRP;z79?V+Q8n-gD~5LCS^F+R`VZMhb2CP~183xG~NJ4=%z+SAH~ zE+5Zdbz^N*w3#JM&96Pl86|oX?)mgZ%k4?$;JW?ZCLRYZ(#o)bH8f%?TnMzr87ajX z8*nbA^wsNEVFf47J}=64X3tB%gsST4x=ultCAipnnTG6f`qxMd%?9reM-%m)PU}Y@?vopKDb}|geQ`v zvfY37EG+oYDKq^4uWU)XD%d6dj_pa+}#Sss3snu zW*0-XSM#c9*Fg=?G2cRnw+{bZSXUZdSJ&JOG-AZPj$8wyFsbEZWhw>d$(jY-kke2; zrCp!0inAdcV{h m&KuQ>!#3re=R9b^b+)pkV^-bj*+~+v*T3~X-xbWjU=0A^yc^^I literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/tv-collapsable.gif b/test/application/theme-handler/expected/testimages/images/tv-collapsable.gif new file mode 100644 index 0000000000000000000000000000000000000000..857262faecaaf363ab3d6fe1779ec6d6eb85c3f3 GIT binary patch literal 781 zcmV+o1M>VwNk%w1VGsbY1d##&0001hfPnx1{{R30A^8LW00062EC2ui01yDM1ONj6 zl#i(v>%SVDDcF0XR%^3A-Pw$vten~kQ$Df3Aka`(CO$Gso^r^Yw5H0V?n zhzPhSm>6YPq}a$PS^4Pr1Sw^iiP@yNHYv*a=~-xcg_@JQIl35Hb0`nuLOKm8KC~DS<3v0E6**q? zm=WYgJRM1XG#L`*NIfT6rgXWoPfM9EX~raUPod6jHxKRX)-%%2dP8&aESeALKBfJb z{&N}->OiRlsUEbN@TgXxSS5DV_*GAtOt_pV;K zdHL>L8W*r#zk~(%HT<_}V8w$G7iN4Ia^k0pDL0n<*m7jelcQGle3^4*(3?qjp86Se zXw#!rmv()+YHHc5VYjCJ8h7lgvw7FnecN|#;k&c`CLY}QaOK6l_GX^k`Elrut7En< z8ar$4wz&iMjvPGo>*TYS-+sP(`tR$*w;yjlK6?4;>9e=*9zXo~{OkALzyDu;0q*Bt zfdCpPAc6!Q$Y6pEF6dx{5KbuFauqfQ)^is|m*I39iud7rA?i2cfF&w;;)5wlxFUre zTKFP{Vrdv7hckLuBZxVQxFd-@n)oA%L8>?;i$%J4BaBJPNEVGt+SnwHPwF@&k5&43 zC6HMPxh0WZ8u=xXQ7SnmlV&+tCX{DNnI@HOTKOiHacVgymvwr1CzyGPxh9!?nu!*g zf2tWMn}fP}D4dDPxhS2D+W9D+k?J`qpN0B)DWGa0nkk{1D%vThpE4RMsG~YsDygSJ LnkuS<6aWA_b2fL3 literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/tv-expandable-last.gif b/test/application/theme-handler/expected/testimages/images/tv-expandable-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ede2de78e046691bafcd19d8f953d820a8a939d GIT binary patch literal 89 zcmZ?wbhEHb6krfzn8?J?(9poZ!0`Y7e;}#&lZBCifr&u}$Yub^GcajQ>0inAdcV{h q&KuQ>!-85aE8abxaj=r>ESKDpU6s1x-4bq3f1UgO@4W^CgEatFOCAgW literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/tv-expandable.gif b/test/application/theme-handler/expected/testimages/images/tv-expandable.gif new file mode 100644 index 0000000000000000000000000000000000000000..305d57fc8b14c89431818b5f21d81e39072723b5 GIT binary patch literal 787 zcmV+u1MK`qNk%w1VGsbY1d##&0001hfPnx1{{R30A^8LW00062EC2ui01yDM1ONj6 zl#i(v>%SVDDcF0XR#Je|A>GGlz1le|i8=~as(Px~3Y#jsDi#ZROFE0Y zt6NK!%i1gaYZh!fj9iR%44mw|tk!J&OdZWO&0MX0?UpUQ4c-m+jU8@2E_d#|PTsDb zepk*OpEvJbzjqJ+%A4QU&sRWV1CsGaU6>nC( zTlseN`xS6l!D9)RHGCFv+PjSNHs1TVZ{)v|16Lk=xp3ygn-h0l>^L-J(UM71HfVqJ9X~WyIc2u{X2H>*|v-0Hm(~vZ{@z319vVQI`QMwlUHAU zy?OTM+oN}%ZaqA9@!H9AH}4%i`0?z^w?F?ref;(A>%+G%A3y#3{PXwZ-|t_501n8O zVg-J7plk^ax1e+le)phy5zaTEeiip@Au)_@Rj* z#?_LFEy{SJf-BlMBa1aMcq5NF;<%%OJqr1wk3m8>B$7oEd8C9%I=Q5hO;Y$Il~F=D zrG-^$d8L(EVz?!kU2^%QhGCjHrkG`Nm?oNQZV2a@Y`!UHoNdneB8f5Tn5T;+(%2`U zfATpfkbx4qr=f)!d8nd^GP)>}jY9gUq>)NFsil=-dMTEfa=NLfoqGAHsG*WNDw(CC RdaA0as=2DGt#VcX06Vosfm8qh literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/tv-item-last.gif b/test/application/theme-handler/expected/testimages/images/tv-item-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..42a139ad59777163fb406f3692ebf5333ef379d9 GIT binary patch literal 65 zcmZ?wbhEHb6krfzXkcV$XlVHV|G(l-7DfgJMg|=QAOOiQFiG_EuVj0@Uuus3rEZ;L SYuWd=KJu9MtaBPGgEatO+7%uE literal 0 HcmV?d00001 diff --git a/test/application/theme-handler/expected/testimages/images/tv-item.gif b/test/application/theme-handler/expected/testimages/images/tv-item.gif new file mode 100644 index 0000000000000000000000000000000000000000..281e5dce6705bbba1be16919ccad1883d9a9b7b5 GIT binary patch literal 750 zcmVi2fsz(rj1Z(I%uk_Z1$dUHLJCFC+@t*{rh7DQ$tg6bPOd)Ib9R>WJIOY zC1?7iG(~*cW?M%k^nH`*-V=i`xtK z>l-Y#TUe}i?3nDfEc#3uZ90uwt$NLx?Ya%yEz9_=8%|Cu4t!3WF5E0v&bw~>jvTK% z&s^_(54|tlPyNqYKx_lG736l%TS9Q=7LIEO5uQVI6V+8@m(N{9djA*YZN%5n-ba2T z{gniGQeaAgD-E_p_)=j^h7xB!tcjDOO^Q1$_QV)c-%pP@K@JsJlw?wqOHnpe`IKc; zms4R@m3ft>&a5}LdNsJN672wB*X9FPF}IdUNW|t3S66 z{d%URkG?T6W3jmwM*e=bnBB3h1DQ g3W{i