N°3777 - favicon: change easily favicon

This commit is contained in:
Anne-Cath
2024-02-26 18:51:38 +01:00
parent e7b87128b1
commit 27022ed93a
10 changed files with 156 additions and 76 deletions

View File

@@ -110,6 +110,17 @@ class LoginWebPage extends NiceWebPage
return Branding::GetLoginFavIconAbsoluteUrl();
}
/**
* Return the absolute URL for the favicon
*
* @return string
* @throws \Exception
*/
protected function GetFaviconAbsoluteUrl()
{
return Branding::GetLoginFavIconAbsoluteUrl();
}
public static function SetLoginFailedMessage($sMessage)
{
self::$m_sLoginFailedMessage = $sMessage;

View File

@@ -185,7 +185,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'temporary_object.garbage_interval' => [
'temporary_object.garbage_interval' => [
'type' => 'integer',
'description' => 'Seconds between garbage collections',
'default' => 60,
@@ -193,7 +193,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'app_env_label' => [
'app_env_label' => [
'type' => 'string',
'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")',
'default' => '',
@@ -201,7 +201,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'app_root_url' => [
'app_root_url' => [
'type' => 'string',
'description' => 'Root URL used for navigating within the application, or from an email to the application (you can put $SERVER_NAME$ as a placeholder for the server\'s name)',
'default' => '',
@@ -209,7 +209,15 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'app_icon_url' => [
'branding_environment' => [
'type' => 'string',
'description' => 'type of branding. usefull for put different logo depending environment',
'default' => null,
'value' => null,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'app_icon_url' => [
'type' => 'string',
'description' => 'Hyperlink to redirect the user when clicking on the application icon (in the main window, or login/logoff pages)',
'default' => 'http://www.combodo.com/itop',
@@ -217,50 +225,50 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'db_host' => [
'db_host' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'db_user' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'db_user' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'db_pwd' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'db_pwd' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'db_name' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'db_name' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'db_subname' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'db_subname' => [
'type' => 'string',
'default' => null,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => true,
],
'db_tls.enabled' => [
'type' => 'bool',
'description' => 'If true then the connection to the DB will be encrypted',
'default' => false,
'value' => false,
'source_of_value' => '',
'db_tls.enabled' => [
'type' => 'bool',
'description' => 'If true then the connection to the DB will be encrypted',
'default' => false,
'value' => false,
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'db_tls.ca' => [
'db_tls.ca' => [
'type' => 'string',
'description' => 'Path to certificate authority file for SSL',
'default' => null,
@@ -268,7 +276,7 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'db_core_transactions_enabled' => [
'db_core_transactions_enabled' => [
'type' => 'bool',
'description' => 'If true, CRUD transactions in iTop core will be enabled',
'default' => true,
@@ -1888,6 +1896,7 @@ class Config
*/
public function Get($sPropCode)
{
return $this->m_aSettings[$sPropCode]['value'];
}

View File

@@ -72,6 +72,7 @@ class Basic extends AbstractConfiguration
*/
private function GetInitialPortalConf()
{
$aPortalConf = array(
'properties' => array(
'id' => $_ENV['PORTAL_ID'],
@@ -81,15 +82,15 @@ class Basic extends AbstractConfiguration
'favicon' => Branding::GetPortalFavIconAbsoluteUrl(),
'themes' => array(
'bootstrap' => 'itop-portal-base/portal/public/css/bootstrap-theme-combodo.scss',
'portal' => 'itop-portal-base/portal/public/css/portal.scss',
'others' => array(),
'portal' => 'itop-portal-base/portal/public/css/portal.scss',
'others' => array(),
),
'templates' => array(
'templates' => array(
'layout' => 'itop-portal-base/portal/templates/layout.html.twig',
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
'home' => 'itop-portal-base/portal/templates/home/layout.html.twig',
),
'urlmaker_class' => null,
'triggers_query' => null,
'urlmaker_class' => null,
'triggers_query' => null,
'attachments' => array(
'allow_delete' => true,
),

View File

@@ -25,7 +25,7 @@
{% block pPageExtraMetas %}
{% endblock %}
<title>{% block pPageTitle %}{% if sPageTitle is defined and sPageTitle is not null %}{{ sPageTitle }} - {{ constant('ITOP_APPLICATION_SHORT') }}{% else %}{{ 'Page:DefaultTitle'|dict_format(constant('ITOP_APPLICATION_SHORT')) }}{% endif %}{% endblock %}</title>
<link rel="shortcut icon" href="{{ app['combodo.portal.instance.conf'].properties.favicon|add_itop_version }}"/>
<link rel="shortcut icon" href="{{ app['combodo.portal.instance.conf'].properties.favicon|add_itop_version }}"/>
{% block pPageStylesheets %}
{# First bootstrap core, lib themes, then bootstrap theme, portal adjustements #}
@@ -251,7 +251,7 @@
</nav>
{% endblock %}
{# Sidebar navigation menu for normal screens #}
{# Sidebar navigation menu for normal screens #}
{% block pNavigationSideMenuWrapper %}
<nav class="navbar-default hidden-xs col-sm-3 col-md-2" id="sidebar" role="navigation">
<div class="user_card bg-primary">

View File

@@ -2000,7 +2000,7 @@
<enable_action>UR_ACTION_MODIFY</enable_action>
</menu>
</menus>
<branding>
<brandings>
<themes>
<theme id="fullmoon" _delta="define">
<variables>
@@ -2035,7 +2035,7 @@
<stylesheets>
</stylesheets>
</themes_common>
</branding>
</brandings>
<user_rights>
<groups>
</groups>

View File

@@ -729,7 +729,7 @@ PHP;
// Compile the branding
//
/** @var \MFElement $oBrandingNode */
$oBrandingNode = $this->oFactory->GetNodes('branding')->item(0);
$oBrandingNode = $this->oFactory->GetNodes('brandings')->item(0);
$this->CompileBranding($oBrandingNode, $sTempTargetDir, $sFinalTargetDir);
if (array_key_exists('_core_', $this->aSnippets))
@@ -3330,27 +3330,27 @@ EOF;
/**
* @param \MFElement $oBrandingNode
* @param string $sTempTargetDir
* @param string $sFinalTargetDir
* @param string $sEnvironment
* @param string $sNodeName
* @param string $sTargetFile
*
* @throws \Exception
*/
protected function CompileLogo($oBrandingNode, $sTempTargetDir, $sFinalTargetDir, $sNodeName, $sTargetFile)
protected function CompileLogo($oBrandingNode, $sTempTargetDir, $sEnvironment, $sNodeName, $sTargetFile)
{
$sIcon = trim($oBrandingNode->GetChildText($sNodeName) ?? '');
if (strlen($sIcon) > 0) {
$sSourceFile = $sTempTargetDir.'/'.$sIcon;
$aIconName=explode(".", $sIcon);
$sIconExtension=$aIconName[count($aIconName)-1];
$sTargetFile = '/branding/'.$sTargetFile.'.'.$sIconExtension;
$aIconName = explode(".", $sIcon);
$sIconExtension = $aIconName[count($aIconName) - 1];
$sTargetFile = '/branding/'.$sEnvironment.'/'.$sTargetFile.'.'.$sIconExtension;
if (!file_exists($sSourceFile))
{
if (!file_exists($sSourceFile)) {
throw new Exception("Branding $sNodeName: could not find the file $sIcon ($sSourceFile)");
}
copy($sSourceFile, $sTempTargetDir.$sTargetFile);
return $sTargetFile;
}
return null;
@@ -3639,22 +3639,22 @@ EOF;
}
/**
* @param \MFElement $oBrandingNode
* @param \MFElement $oBrandingsNode
* @param string $sTempTargetDir
* @param string $sFinalTargetDir
*
* @throws \DOMFormatException
* @throws \Exception
*/
protected function CompileBranding($oBrandingNode, $sTempTargetDir, $sFinalTargetDir)
protected function CompileBranding($oBrandingsNode, $sTempTargetDir, $sFinalTargetDir)
{
// Enable relative paths
SetupUtils::builddir($sTempTargetDir.'/branding');
if ($oBrandingNode)
{
// Transform file refs into files in the images folder
$this->CompileFiles($oBrandingNode, $sTempTargetDir.'/branding', $sFinalTargetDir.'/branding', 'branding');
if ($oBrandingsNode) {
$aDataBranding = [];
foreach ($oBrandingsNode->childNodes as $oBrandingNode) {
// Transform file refs into files in the images folder
$this->CompileFiles($oBrandingNode, $sTempTargetDir.'/branding', $sFinalTargetDir.'/branding', 'branding');
$aLogosToCompile = [
['sNodeName' => 'login_logo', 'sTargetFile' => 'login-logo', 'sType' => Branding::ENUM_LOGO_TYPE_LOGIN_LOGO],
@@ -3665,12 +3665,16 @@ EOF;
['sNodeName' => 'main_favicon', 'sTargetFile' => 'main_favicon', 'sType' => Branding::ENUM_LOGO_TYPE_MAIN_FAVICON],
['sNodeName' => 'portal_favicon', 'sTargetFile' => 'portal_favicon', 'sType' => Branding::ENUM_LOGO_TYPE_PORTAL_FAVICON],
];
foreach ($aLogosToCompile as $aLogo) {
$sLogo = $this->CompileLogo($oBrandingNode, $sTempTargetDir, $sFinalTargetDir, $aLogo['sNodeName'], $aLogo['sTargetFile']);
if ($sLogo != null) {
$aDataBranding[$aLogo['sType']] = $sLogo;
$sEnvironment = $oBrandingNode->getAttribute('id');
SetupUtils::builddir($sTempTargetDir.'/branding/'.$sEnvironment);
foreach ($aLogosToCompile as $aLogo) {
$sLogo = $this->CompileLogo($oBrandingNode, $sTempTargetDir, $sEnvironment, $aLogo['sNodeName'], $aLogo['sTargetFile']);
if ($sLogo != null) {
$aDataBranding[$oBrandingNode->getAttribute('id')][$aLogo['sType']] = $sLogo;
}
}
}
if ($sTempTargetDir == null) {
$sWorkingPath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
} else {
@@ -3680,13 +3684,12 @@ EOF;
file_put_contents($sWorkingPath.'/branding/logos.json', json_encode($aDataBranding));
// Cleanup the images directory (eventually made by CompileFiles)
if (file_exists($sTempTargetDir.'/branding/images'))
{
if (file_exists($sTempTargetDir.'/branding/images')) {
SetupUtils::rrmdir($sTempTargetDir.'/branding/images');
}
// Compile themes
$this->CompileThemes($oBrandingNode, $sTempTargetDir);
$this->CompileThemes($oBrandingsNode, $sTempTargetDir);
}
}

View File

@@ -920,12 +920,12 @@ class iTopDesignFormat
$oNode->setAttribute('id', 'ibo-page-banner--background-color');
}
$oNodeList = $oXPath->query( '/itop_design/branding/themes/theme[@id="test-red"]/variables/variable[@id="backoffice-environment-banner-text-color"]');
$oNodeList = $oXPath->query('/itop_design/branding/themes/theme[@id="test-red"]/variables/variable[@id="backoffice-environment-banner-text-color"]');
foreach ($oNodeList as $oNode) {
$oNode->setAttribute('id', 'ibo-page-banner--text-color');
}
$oNodeList = $oXPath->query( '/itop_design/branding/themes/theme[@id="test-red"]/variables/variable[@id="backoffice-environment-banner-text-content"]');
$oNodeList = $oXPath->query('/itop_design/branding/themes/theme[@id="test-red"]/variables/variable[@id="backoffice-environment-banner-text-content"]');
foreach ($oNodeList as $oNode) {
$oNode->setAttribute('id', 'ibo-page-banner--text-content');
}
@@ -1067,7 +1067,6 @@ class iTopDesignFormat
*/
protected function From30To31($oFactory)
{
}
/**
* Downgrade the format from version 3.1 to 3.0
@@ -1097,21 +1096,44 @@ class iTopDesignFormat
$this->RemoveNodeFromXPath("/itop_design/classes//class/fields/field/sort_type");
// - Remove rank in values
$this->RemoveNodeFromXPath("/itop_design/classes//class/fields/field/values/value/rank");
}
/**
* Upgrade the format from version 3.1 to 3.2
*
* @param \ModelFactory $oFactory
*
* @return void (Errors are logged)
*/
protected function From31To32($oFactory)
{
// Nothing for now...
$oXPath = new DOMXPath($this->oDocument);
// N°3363 - Add favicon in branding
$oNodeDesign = $oXPath->query("/itop_design")->item(0);
$oNodeBranding = $oXPath->query("/itop_design/branding")->item(0);
if ($oNodeBranding) {
$oNodeBrandings = $oNodeDesign->ownerDocument->createElement("brandings");
$oNodeDesign->appendChild($oNodeBrandings);
$oNodeBrandingTheme = $oXPath->query("/itop_design/branding/themes")->item(0);
if ($oNodeBrandingTheme) {
$oNodeBrandings->appendChild($oNodeBrandingTheme);
}
$oNodeBrandingThemeCommon = $oXPath->query("/itop_design/branding/themes_common")->item(0);
if ($oNodeBrandingThemeCommon) {
$oNodeBrandings->appendChild($oNodeBrandingThemeCommon);
}
$oNodeBranding->setAttribute('id', 'default');
$oNodeBrandings->appendChild($oNodeBranding);
}
}
/**
* Downgrade the format from version 3.2 to 3.1
*
* @param \ModelFactory $oFactory
*
* @return void (Errors are logged)
*/
protected function From32To31($oFactory)

View File

@@ -93,15 +93,28 @@ class Branding
*/
protected static function GetLogoPath(string $sType, string $sAppPath, ?string $sModulePath = null): string
{
$sDefaultLogoPath = static::$aLogoPaths[$sType]['default'];
$sWorkingPath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
$aThemeParameters = json_decode(@file_get_contents($sWorkingPath.'branding/logos.json'), true);
if (isset($aThemeParameters[$sType])) {
$sCustomLogoPath = $aThemeParameters[$sType];
//environment type from config.php
$sEnvType = MetaModel::GetConfig()->Get('branding_environment');
if (utils::IsNullOrEmptyString($sEnvType)) {
$sEnvType = 'default';
}
if (isset($aThemeParameters[$sEnvType]) && isset($aThemeParameters[$sEnvType][$sType])) {
$sCustomLogoPath = $aThemeParameters[$sEnvType][$sType];
if (file_exists($sWorkingPath.$sCustomLogoPath)) {
return ($sModulePath ?? $sAppPath).$sCustomLogoPath;
}
}
//if not found => take the default logo
$sEnvType = 'default';
if (isset($aThemeParameters[$sEnvType]) && isset($aThemeParameters[$sEnvType][$sType])) {
$sCustomLogoPath = $aThemeParameters[$sEnvType][$sType];
if (file_exists($sWorkingPath.$sCustomLogoPath)) {
return ($sModulePath ?? $sAppPath).$sCustomLogoPath;
}
}
$sDefaultLogoPath = static::$aLogoPaths[$sType]['default'];
return $sAppPath.$sDefaultLogoPath;
}
@@ -201,7 +214,12 @@ class Branding
*/
public static function GetPortalFavIconAbsoluteUrl(): string
{
return static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_PORTAL_FAVICON);
$sIcon = static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_PORTAL_FAVICON);
if (utils::IsNullOrEmptyString($sIcon)) {
return static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_MAIN_FAVICON);
}
return $sIcon;
}
/**
@@ -213,6 +231,11 @@ class Branding
*/
public static function GetLoginFavIconAbsoluteUrl(): string
{
return static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_LOGIN_FAVICON);
$sIcon = static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_LOGIN_FAVICON);
if (utils::IsNullOrEmptyString($sIcon)) {
return static::GetLogoAbsoluteUrl(static::ENUM_LOGO_TYPE_MAIN_FAVICON);
}
return $sIcon;
}
}

View File

@@ -60,6 +60,17 @@ class UnauthenticatedWebPage extends NiceWebPage
/** @since 3.2.0 */
protected string $sPortalPublicFolderAbsUrl;
/**
* Return the absolute URL for the favicon
*
* @return string
* @throws \Exception
*/
protected function GetFaviconAbsoluteUrl()
{
return Branding::GetLoginFavIconAbsoluteUrl();
}
/**
* @inheritDoc
* @throws \Exception

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
<branding>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
<brandings>
<themes>
<theme id="fullmoon" _delta="define">
<variables>
@@ -20,5 +20,5 @@
<precompiled_stylesheet>itop-structure/precompiled-themes/test-red/main.css</precompiled_stylesheet>
</theme>
</themes>
</branding>
</brandings>
</itop_design>