mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°2982 - speedup themes/scss compilation during setup
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
class ThemeHandler
|
||||
{
|
||||
private static $oCompileCSSService;
|
||||
/**
|
||||
* Return default theme name and parameters
|
||||
*
|
||||
@@ -108,7 +109,7 @@ class ThemeHandler
|
||||
SetupUtils::builddir($sDefaultThemeDirPath);
|
||||
}
|
||||
|
||||
static::CompileTheme($sThemeId, $aDefaultTheme['parameters']);
|
||||
static::CompileTheme($sThemeId, false, $aDefaultTheme['parameters']);
|
||||
}
|
||||
|
||||
// Return absolute url to theme compiled css
|
||||
@@ -121,13 +122,14 @@ class ThemeHandler
|
||||
* 2) The produced CSS file exists and its signature is equal to the expected signature (imports, stylesheets, variables)
|
||||
*
|
||||
* @param string $sThemeId
|
||||
* @param bool $bSetup : indicated whether compilation is performed in setup context (true) or when loading a page/theme (false)
|
||||
* @param array|null $aThemeParameters Parameters (variables, imports, stylesheets) for the theme, if not passed, will be retrieved from compiled DM
|
||||
* @param array|null $aImportsPaths Paths where imports can be found. Must end with '/'
|
||||
* @param string|null $sWorkingPath Path of the folder used during compilation. Must end with a '/'
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public static function CompileTheme($sThemeId, $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
|
||||
public static function CompileTheme($sThemeId, $bSetup=false, $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
|
||||
{
|
||||
// Default working path
|
||||
if($sWorkingPath === null)
|
||||
@@ -150,6 +152,11 @@ class ThemeHandler
|
||||
// Save parameters if passed... (typically during DM compilation)
|
||||
if(is_array($aThemeParameters))
|
||||
{
|
||||
if (!is_dir($sThemeFolderPath))
|
||||
{
|
||||
mkdir($sWorkingPath.'/branding/');
|
||||
mkdir($sWorkingPath.'/branding/themes/');
|
||||
}
|
||||
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
|
||||
}
|
||||
// ... Otherwise, retrieve them from compiled DM (typically when switching current theme in the config. file)
|
||||
@@ -185,33 +192,52 @@ class ThemeHandler
|
||||
|
||||
// Checking if our compiled css is outdated
|
||||
$iFilemetime = @filemtime($sThemeCssPath);
|
||||
if (!file_exists($sThemeCssPath) || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified)))
|
||||
$bFileExists = file_exists($sThemeCssPath);
|
||||
$bVarSignatureChanged=false;
|
||||
if ($bFileExists && $bSetup)
|
||||
{
|
||||
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
|
||||
//check variable signature has changed which is independant from any file modification
|
||||
if (!empty($sPrecompiledSignature)){
|
||||
$sPreviousVariableSignature = static::GetVarSignature($sPrecompiledSignature);
|
||||
$sCurrentVariableSignature = md5(json_encode($aThemeParameters['variables']));
|
||||
$bVarSignatureChanged= ($sPreviousVariableSignature!==$sCurrentVariableSignature);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (file_exists($sThemeCssPath))
|
||||
|
||||
if ($bFileExists && !$bSetup)
|
||||
{
|
||||
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
|
||||
if($sActualSignature == $sPrecompiledSignature)
|
||||
{
|
||||
touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sPrecompiledSignature) && $sActualSignature == $sPrecompiledSignature)
|
||||
{
|
||||
touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time
|
||||
}
|
||||
else
|
||||
{
|
||||
// Alas, we really need to recompile
|
||||
// Add the signature to the generated CSS file so that the file can be used as a precompiled stylesheet if needed
|
||||
$sSignatureComment =
|
||||
<<<CSS
|
||||
<<<CSS
|
||||
/*
|
||||
=== SIGNATURE BEGIN ===
|
||||
$sActualSignature
|
||||
=== SIGNATURE END ===
|
||||
*/
|
||||
|
||||
CSS
|
||||
;
|
||||
$sTmpThemeCssContent = utils::CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, $aThemeParameters['variables']);
|
||||
*/
|
||||
|
||||
CSS;
|
||||
if (!self::$oCompileCSSService)
|
||||
{
|
||||
self::$oCompileCSSService = new CompileCSSService();
|
||||
}
|
||||
$sTmpThemeCssContent = self::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths,
|
||||
$aThemeParameters['variables']);
|
||||
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
|
||||
}
|
||||
}
|
||||
@@ -222,12 +248,14 @@ CSS
|
||||
* 1) one MD5 of all the variables/values (JSON encoded)
|
||||
* 2) the MD5 of each stylesheet file
|
||||
* 3) the MD5 of each import file
|
||||
*
|
||||
*
|
||||
* @param string[] $aThemeParameters
|
||||
* @param string[] $aImportsPaths
|
||||
*
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function ComputeSignature($aThemeParameters, $aImportsPaths)
|
||||
public static function ComputeSignature($aThemeParameters, $aImportsPaths)
|
||||
{
|
||||
$aSignature = array(
|
||||
'variables' => md5(json_encode($aThemeParameters['variables'])),
|
||||
@@ -251,14 +279,15 @@ CSS
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* Note the signature can be place anywhere in the CSS file (obviously inside a CSS comment !) but the
|
||||
* function will be faster if the signature is at the beginning of the file (since the file is scanned from the start)
|
||||
*
|
||||
* @param string $sFile
|
||||
*
|
||||
* @param $sFilepath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function GetSignature($sFilepath)
|
||||
public static function GetSignature($sFilepath)
|
||||
{
|
||||
$sPreviousLine = '';
|
||||
$hFile = @fopen($sFilepath, "r");
|
||||
@@ -276,6 +305,16 @@ CSS
|
||||
return $sPreviousLine;
|
||||
}
|
||||
|
||||
public static function GetVarSignature($JsonSignature)
|
||||
{
|
||||
$aJsonArray = json_decode($JsonSignature, true);
|
||||
if (array_key_exists('variables', $aJsonArray))
|
||||
{
|
||||
return $aJsonArray['variables'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the given file in the list of ImportsPaths directory
|
||||
* @param string $sFile
|
||||
@@ -295,5 +334,25 @@ CSS
|
||||
}
|
||||
return ''; // Not found, fail silently, maybe the SCSS compiler knowns better...
|
||||
}
|
||||
|
||||
public static function mockCompileCSSService($oCompileCSSServiceMock)
|
||||
{
|
||||
self::$oCompileCSSService = $oCompileCSSServiceMock;
|
||||
}
|
||||
}
|
||||
|
||||
class CompileCSSService
|
||||
{
|
||||
/**
|
||||
* CompileCSSService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function CompileCSSFromSASS($sSassContent, $aImportPaths = array(), $aVariables = array()){
|
||||
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2759,7 +2759,7 @@ EOF;
|
||||
{
|
||||
$this->Log("Precompiled file not found: '$sPrecompiledFile'");
|
||||
}
|
||||
ThemeHandler::CompileTheme($sThemeId, $aThemeParameters, $aImportsPaths, $sTempTargetDir);
|
||||
ThemeHandler::CompileTheme($sThemeId, true, $aThemeParameters, $aImportsPaths, $sTempTargetDir);
|
||||
}
|
||||
$this->Log(sprintf('Themes compilation took: %.3f ms for %d themes.', (microtime(true) - $fStart)*1000.0, count($aThemes)));
|
||||
}
|
||||
|
||||
333
test/application/ThemeHandlerTest.php
Normal file
333
test/application/ThemeHandlerTest.php
Normal file
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
* @covers utils
|
||||
*/
|
||||
class ThemeHandlerTest extends ItopTestCase
|
||||
{
|
||||
private $compileCSSServiceMock;
|
||||
private $cssPath;
|
||||
private $jsonThemeParamFile;
|
||||
private $tmpDir;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
require_once(APPROOT.'application/themehandler.class.inc.php');
|
||||
require_once(APPROOT.'setup/modelfactory.class.inc.php');
|
||||
|
||||
$this->compileCSSServiceMock = $this->createMock('CompileCSSService');
|
||||
ThemeHandler::mockCompileCSSService($this->compileCSSServiceMock);
|
||||
|
||||
$this->tmpDir=$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->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");
|
||||
}
|
||||
|
||||
function tmpdir() {
|
||||
$tmpfile=tempnam(sys_get_temp_dir(),'');
|
||||
if (file_exists($tmpfile))
|
||||
{
|
||||
unlink($tmpfile);
|
||||
}
|
||||
mkdir($tmpfile);
|
||||
if (is_dir($tmpfile))
|
||||
{
|
||||
return $tmpfile;
|
||||
}
|
||||
|
||||
return sys_get_temp_dir();
|
||||
}
|
||||
|
||||
public function recurse_copy($src,$dst) {
|
||||
$dir = opendir($src);
|
||||
@mkdir($dst);
|
||||
while(false !== ( $file = readdir($dir)) ) {
|
||||
if (( $file != '.' ) && ( $file != '..' )) {
|
||||
if ( is_dir($src . '/' . $file) ) {
|
||||
$this->recurse_copy($src . '/' . $file,$dst . '/' . $file);
|
||||
}
|
||||
else {
|
||||
copy($src . '/' . $file,$dst . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
public function testGetSignature()
|
||||
{
|
||||
$sig = ThemeHandler::GetSignature(APPROOT.'test/application/theme-handler/expected/themes/basque-red/main.css');
|
||||
$expect_sig=<<<JSON
|
||||
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]}
|
||||
JSON;
|
||||
|
||||
$this->assertEquals($expect_sig,$sig);
|
||||
}
|
||||
|
||||
public function testGetVarSignature()
|
||||
{
|
||||
$sig=<<<JSON
|
||||
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]}
|
||||
JSON;
|
||||
$var_sig = ThemeHandler::GetVarSignature($sig);
|
||||
|
||||
$this->assertEquals("37c31105548fce44fecca5cb34e455c9",$var_sig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $readFromParamAttributeFromJson
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @dataProvider CompileThemesProviderWithoutCss
|
||||
*/
|
||||
public function testCompileThemeWithoutCssFile_FocusOnParamAttribute($readFromParamAttributeFromJson=false)
|
||||
{
|
||||
$expectJsonFilePath = APPROOT.'test/application/theme-handler/expected/themes/basque-red/theme-parameters.json';
|
||||
$expectedThemeParamJson = file_get_contents($expectJsonFilePath);
|
||||
$aThemeParameters = json_decode($expectedThemeParamJson, true);
|
||||
if (is_file($this->jsonThemeParamFile))
|
||||
{
|
||||
unlink($this->jsonThemeParamFile);
|
||||
}
|
||||
if (is_file($this->cssPath))
|
||||
{
|
||||
unlink($this->cssPath);
|
||||
}
|
||||
|
||||
$this->compileCSSServiceMock->expects($this->exactly(1))
|
||||
->method("CompileCSSFromSASS")
|
||||
->willReturn("====CSSCOMPILEDCONTENT====");
|
||||
|
||||
if($readFromParamAttributeFromJson)
|
||||
{
|
||||
copy($expectJsonFilePath, $this->jsonThemeParamFile);
|
||||
ThemeHandler::CompileTheme('basque-red', true, null, array($this->tmpDir.'/branding/themes/'), $this->tmpDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThemeHandler::CompileTheme('basque-red', true, $aThemeParameters, array($this->tmpDir.'/branding/themes/'), $this->tmpDir);
|
||||
}
|
||||
$this->assertTrue(is_file($this->cssPath));
|
||||
$this->assertEquals($expectedThemeParamJson, file_get_contents($this->jsonThemeParamFile));
|
||||
$this->assertEquals(file_get_contents(APPROOT . 'test/application/theme-handler/expected/themes/basque-red/main.css'), file_get_contents($this->cssPath));
|
||||
}
|
||||
|
||||
public function CompileThemesProviderWithoutCss()
|
||||
{
|
||||
return array(
|
||||
"pass ParamAttributes and Save them in Json" => array(false),
|
||||
"use them from saved json" => array(true)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $ThemeParametersJson
|
||||
*
|
||||
* @param int $CompileCount
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @dataProvider CompileThemesProviderEmptyArray
|
||||
*/
|
||||
public function testCompileThemesEmptyArray($ThemeParametersJson, $CompileCount=0)
|
||||
{
|
||||
$cssPath = $this->tmpDir . '/branding/themes/basque-red/main.css';
|
||||
copy(APPROOT . 'test/application/theme-handler/expected/themes/basque-red/main.css', $cssPath);
|
||||
|
||||
$this->compileCSSServiceMock->expects($this->exactly($CompileCount))
|
||||
->method("CompileCSSFromSASS")
|
||||
->willReturn("====CSSCOMPILEDCONTENT====");
|
||||
|
||||
ThemeHandler::CompileTheme('basque-red', true, json_decode($ThemeParametersJson, true), array($this->tmpDir.'/branding/themes/'), $this->tmpDir);
|
||||
}
|
||||
|
||||
public function CompileThemesProviderEmptyArray()
|
||||
{
|
||||
$emptyImports = '{"variables":{"brand-primary":"#C53030","hover-background-color":"#F6F6F6","icons-filter":"grayscale(1)","search-form-container-bg-color":"#4A5568"},"imports":[],"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}';
|
||||
$emptyStyleSheets='{"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":[]}';
|
||||
$emptyVars='{"variables":[],"imports":{"css-variables":"..\/css\/css-variables.scss"},"stylesheets":{"jqueryui":"..\/css\/ui-lightness\/jqueryui.scss","main":"..\/css\/light-grey.scss"}}';
|
||||
return array(
|
||||
"empty imports" => array($emptyImports),
|
||||
"empty styles" => array($emptyStyleSheets),
|
||||
"empty vars" => array($emptyVars, 1),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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';
|
||||
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),
|
||||
//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),
|
||||
//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)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
$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)");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
126
test/application/theme-handler/expected/css/css-variables.scss
Normal file
126
test/application/theme-handler/expected/css/css-variables.scss
Normal file
@@ -0,0 +1,126 @@
|
||||
/*!
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* 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.0-1";
|
||||
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
|
||||
|
||||
// Base colors
|
||||
$gray-base: #000 !default;
|
||||
$gray-darker: lighten($gray-base, 13.5%) !default; // #222
|
||||
$gray-dark: #444 !default;
|
||||
$gray: #777 !default;
|
||||
$gray-light: #808080 !default;
|
||||
$gray-lighter: #ddd !default;
|
||||
$gray-extra-light: #F1F1F1 !default;
|
||||
|
||||
$white: #FFFFFF !default;
|
||||
|
||||
$combodo-orange: #EA7D1E !default;
|
||||
$combodo-dark-gray: #585653 !default;
|
||||
|
||||
$combodo-orange-dark: darken($combodo-orange, 13.8%) !default;
|
||||
$combodo-orange-darker: darken($combodo-orange, 18%) !default;
|
||||
$combodo-dark-gray-dark: darken($combodo-dark-gray, 13.5%) !default;
|
||||
$combodo-dark-gray-darker: darken($combodo-dark-gray, 18%) !default;
|
||||
|
||||
// Brand colors
|
||||
// - Bases
|
||||
$brand-primary: $combodo-orange !default;
|
||||
$brand-secondary: $combodo-dark-gray !default;
|
||||
// - Shades
|
||||
$brand-primary-lightest: lighten($brand-primary, 15%) !default;
|
||||
$brand-primary-lighter: lighten($brand-primary, 10%) !default;
|
||||
$brand-primary-light: lighten($brand-primary, 6%) !default;
|
||||
$brand-primary-dark: darken($brand-primary, 6%) !default;
|
||||
$brand-primary-darker: darken($brand-primary, 10%) !default;
|
||||
$brand-primary-darkest: darken($brand-primary, 15%) !default;
|
||||
$brand-secondary-lightest: lighten($brand-secondary, 15%) !default;
|
||||
$brand-secondary-lighter: lighten($brand-secondary, 10%) !default;
|
||||
$brand-secondary-light: lighten($brand-secondary, 6%) !default;
|
||||
$brand-secondary-dark: darken($brand-secondary, 6%) !default;
|
||||
$brand-secondary-darker: darken($brand-secondary, 10%) !default;
|
||||
$brand-secondary-darkest: darken($brand-secondary, 15%) !default;
|
||||
|
||||
// Vars
|
||||
$highlight-color: $brand-primary !default;
|
||||
$grey-color: #555555 !default;
|
||||
$complement-color: #1c94c4 !default;
|
||||
$complement-light: #d6e8ef !default;
|
||||
$frame-background-color: $gray-extra-light !default;
|
||||
$text-color: #000 !default;
|
||||
$box-radius: 0px !default;
|
||||
$box-shadow-regular: 0 1px 1px rgba(0, 0, 0, 0.15) !default;
|
||||
$body-background-color : $white !default;
|
||||
|
||||
$hyperlink-color: $complement-color !default;
|
||||
$hyperlink-text-decoration: none !default;
|
||||
|
||||
////////////
|
||||
// Search //
|
||||
$search-form-container-color: $white !default;
|
||||
$search-form-container-bg-color: $complement-color !default;
|
||||
//
|
||||
$search-criteria-box-color: #2D2D2D !default;
|
||||
$search-criteria-box-picto-color: $brand-primary !default;
|
||||
$search-criteria-box-bg-color: #EEEEEE !default;
|
||||
$search-criteria-box-hover-color: $white !default;
|
||||
$search-criteria-box-border-color: #CCCCCC !default;
|
||||
$search-criteria-box-border: 1px solid $search-criteria-box-border-color !default;
|
||||
$search-criteria-box-radius: 1px !default;
|
||||
$search-criteria-more-less-details-color: #3F7294 !default;
|
||||
//
|
||||
$search-add-criteria-box-color: $search-criteria-box-color !default;
|
||||
$search-add-criteria-box-bg-color: $white !default;
|
||||
$search-add-criteria-box-hover-color: $gray-extra-light !default;
|
||||
//
|
||||
$search-button-box-color: $brand-primary !default;
|
||||
$search-button-box-bg-color: $white !default;
|
||||
$search-button-box-bg-hover-color: $gray-extra-light !default;
|
||||
|
||||
/////////////
|
||||
// Buttons //
|
||||
/////////////
|
||||
// Toggle button
|
||||
$toggle-button-bg-color: #CCCCCC !default;
|
||||
$toggle-button-bg-checked-color: $brand-primary !default;
|
||||
$toggle-button-slider-bg-color: #FFFFFF !default;
|
||||
|
||||
// Console elements
|
||||
$summary-details-background: $grey-color !default;
|
||||
$main-header-background: $frame-background-color !default;
|
||||
$table-even-background: $frame-background-color !default;
|
||||
$table-hover-background: #fdf5d0 !default;
|
||||
$popup-menu-highlight-color: $highlight-color !default;
|
||||
$popup-menu-text-color: #000 !default;
|
||||
$popup-menu-background-color: #fff !default;
|
||||
$popup-menu-text-higlight-color: #fff !default;
|
||||
$breadcrumb-color: $grey-color !default;
|
||||
$breadcrumb-highlight-color: $highlight-color !default;
|
||||
|
||||
// jQuery UI widgets vars
|
||||
$primary-text-color: #333333 !default;
|
||||
$secondary-text-color: $grey-color !default;
|
||||
$error-text-color: $white !default;
|
||||
$highlight-text-color: #363636 !default;
|
||||
$hover-background-color: #fde17c !default;
|
||||
$border-highlight-color: $brand-primary-dark !default;
|
||||
$highlight-item-color: $white !default;
|
||||
$content-color: #eeeeee !default;
|
||||
$default-font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif !default;
|
||||
$icons-filter: hue-rotate(0deg) !default;
|
||||
3893
test/application/theme-handler/expected/css/light-grey.scss
Normal file
3893
test/application/theme-handler/expected/css/light-grey.scss
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
=== SIGNATURE BEGIN ===
|
||||
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]}
|
||||
=== SIGNATURE END ===
|
||||
*/
|
||||
====CSSCOMPILEDCONTENT====
|
||||
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
=== SIGNATURE BEGIN ===
|
||||
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"6b9dcbf6f6ae66d3f94ab6c19729b5ee","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]}
|
||||
=== SIGNATURE END ===
|
||||
*/
|
||||
====CSSCOMPILEDCONTENT====
|
||||
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
=== SIGNATURE BEGIN ===
|
||||
{"variables":"37c31105548fce44fecca5cb34e455c9","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"63ba7dfe2a2eba40c2596ebb2a405f0b"},"imports":[]}
|
||||
=== SIGNATURE END ===
|
||||
*/
|
||||
====CSSCOMPILEDCONTENT====
|
||||
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
=== SIGNATURE BEGIN ===
|
||||
{"variables":"8100523d2e76a70266f3e7110e2fe5fb","stylesheets":{"css-variables":"934888ebb4991d4c76555be6b6d1d5cc","jqueryui":"78cfafc3524dac98e61fc2460918d4e5","main":"52d8a7c5530ceb3a4d777364fa4e1eea"},"imports":[]}
|
||||
=== SIGNATURE END ===
|
||||
*/
|
||||
====CSSCOMPILEDCONTENT====
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}}
|
||||
Reference in New Issue
Block a user