Merge remote-tracking branch 'origin/support/3.0' into develop

This commit is contained in:
Molkobain
2022-03-07 12:54:13 +01:00
65 changed files with 457 additions and 217 deletions

View File

@@ -251,7 +251,7 @@ class UIExtKeyWidget
$aOption['picture_url'] = $oImage->GetDisplayURL($sClassAllowed, $oObj->GetKey(), $sObjectImageAttCode);
$aOption['initials'] = '';
} else {
$aOption['initials'] = utils::ToAcronym($oObj->Get('friendlyname'));
$aOption['initials'] = utils::FormatInitialsForMedallion(utils::ToAcronym($oObj->Get('friendlyname')));
}
}
array_push($aOptions, $aOption);
@@ -829,7 +829,7 @@ JS
}
if (array_key_exists('initials', $aValue)) {
$aElt['initials'] = $aValue['initials'];
$aElt['initials'] = utils::FormatInitialsForMedallion($aValue['initials']);
if (array_key_exists('picture_url', $aValue)) {
$aElt['picture_url'] = $aValue['picture_url'];
}

View File

@@ -3040,6 +3040,20 @@ HTML;
return $aMentionedObjects;
}
/**
* Note: This method is not ideal, but other solutions seemed even less ideal:
* * Add a "$sMaxLength" param. to utils::ToAcronym(): Does not work for every use cases (see corresponding ticket) as in some parts utils::ToAcronym isn't necessarly meant to be used in a medallion.
*
* @param string $sInitials
*
* @return string Truncates $sInitials so it can fit in medallions
* @since 3.0.1 N°4913
*/
public static function FormatInitialsForMedallion(string $sInitials): string
{
return mb_substr($sInitials, 0, 3);
}
/**
* @param $sUrl
* @param string $sParamName

View File

@@ -1200,7 +1200,7 @@ class Config
],
'compatibility.include_deprecated_js_files' => [
'type' => 'bool',
'description' => 'Include the deprecated JS files to ease usage of not migrated extensions',
'description' => 'Include the deprecated JS files (in iTop previous version) to ease usage of not migrated extensions',
'default' => false,
'value' => false,
'source_of_value' => '',
@@ -1216,7 +1216,7 @@ class Config
],
'compatibility.include_deprecated_css_files' => [
'type' => 'bool',
'description' => 'Include the deprecated CSS files to ease usage of not migrated extensions',
'description' => 'Include the deprecated CSS files (in iTop previous version) to ease usage of not migrated extensions',
'default' => false,
'value' => false,
'source_of_value' => '',

View File

@@ -2936,52 +2936,7 @@ abstract class DBObject implements iDisplay
}
// - TriggerOnObjectMention
// 1 - Check if any caselog updated
$aChanges = $this->m_aOrigValues;
$aUpdatedLogAttCodes = array();
foreach($aChanges as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if($oAttDef instanceof AttributeCaseLog && $value->GetModifiedEntry() !== '')
{
$aUpdatedLogAttCodes[] = $sAttCode;
}
}
// 2 - Find mentioned objects
$aMentionedObjects = array();
foreach ($aUpdatedLogAttCodes as $sAttCode) {
/** @var \ormCaseLog $oUpdatedCaseLog */
$oUpdatedCaseLog = $this->Get($sAttCode);
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
}
// 3 - Trigger for those objects
// TODO: This should be refactored and moved into the caselogs loop, otherwise, we won't be able to know which case log triggered the action.
foreach ($aMentionedObjects as $sMentionedClass => $aMentionedIds) {
foreach ($aMentionedIds as $sMentionedId) {
/** @var \DBObject $oMentionedObject */
$oMentionedObject = MetaModel::GetObject($sMentionedClass, $sMentionedId);
$aTriggerArgs = $this->ToArgs('this') + array('mentioned->object()' => $oMentionedObject);
$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectMention AS t WHERE t.target_class IN (:class_list)"), array(), $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectMention $oTrigger */
try {
// Ensure to handle only mentioned object in the trigger's scope
if ($oTrigger->IsMentionedObjectInScope($oMentionedObject) === false) {
continue;
}
$oTrigger->DoActivate($aTriggerArgs);
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
}
$this->ActivateOnMentionTriggers(true);
return $this->m_iKey;
}
@@ -3245,50 +3200,7 @@ abstract class DBObject implements iDisplay
// Activate any existing trigger
$sClass = get_class($this);
// - TriggerOnObjectMention
// 1 - Check if any caselog updated
$aUpdatedLogAttCodes = array();
foreach($aChanges as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if($oAttDef instanceof AttributeCaseLog)
{
$aUpdatedLogAttCodes[] = $sAttCode;
}
}
// 2 - Find mentioned objects
$aMentionedObjects = array();
foreach ($aUpdatedLogAttCodes as $sAttCode) {
/** @var \ormCaseLog $oUpdatedCaseLog */
$oUpdatedCaseLog = $this->Get($sAttCode);
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
}
// 3 - Trigger for those objects
// TODO: This should be refactored and moved into the caselogs loop, otherwise, we won't be able to know which case log triggered the action.
foreach ($aMentionedObjects as $sMentionedClass => $aMentionedIds) {
foreach ($aMentionedIds as $sMentionedId) {
/** @var \DBObject $oMentionedObject */
$oMentionedObject = MetaModel::GetObject($sMentionedClass, $sMentionedId);
$aTriggerArgs = $this->ToArgs('this') + array('mentioned->object()' => $oMentionedObject);
$aParams = array('class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectMention AS t WHERE t.target_class IN (:class_list)"), array(), $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectMention $oTrigger */
try {
// Ensure to handle only mentioned object in the trigger's scope
if ($oTrigger->IsMentionedObjectInScope($oMentionedObject) === false) {
continue;
}
$oTrigger->DoActivate($aTriggerArgs);
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
}
$this->ActivateOnMentionTriggers(false);
$bHasANewExternalKeyValue = false;
$aHierarchicalKeys = array();
@@ -3549,6 +3461,74 @@ abstract class DBObject implements iDisplay
return $this->Get($sAttCode);
}
/**
* Activate TriggerOnObjectMention triggers for the current object
*
* @param bool $bNewlyCreatedObject
*
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
* @since 3.0.1 N°4741
*/
private function ActivateOnMentionTriggers(bool $bNewlyCreatedObject): void
{
$sClass = get_class($this);
$aChanges = $bNewlyCreatedObject ? $this->m_aOrigValues : $this->ListChanges();
// 1 - Check if any caselog updated
$aUpdatedLogAttCodes = [];
foreach ($aChanges as $sAttCode => $value) {
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef instanceof AttributeCaseLog) {
// Skip empty log on creation
if ($bNewlyCreatedObject && $value->GetModifiedEntry() === '') {
continue;
}
$aUpdatedLogAttCodes[] = $sAttCode;
}
}
// 2 - Find mentioned objects
$aMentionedObjects = [];
foreach ($aUpdatedLogAttCodes as $sAttCode) {
/** @var \ormCaseLog $oUpdatedCaseLog */
$oUpdatedCaseLog = $this->Get($sAttCode);
$aMentionedObjects = array_merge_recursive($aMentionedObjects, utils::GetMentionedObjectsFromText($oUpdatedCaseLog->GetModifiedEntry()));
}
// 3 - Trigger for those objects
// TODO: This should be refactored and moved into the caselogs loop, otherwise, we won't be able to know which case log triggered the action.
foreach ($aMentionedObjects as $sMentionedClass => $aMentionedIds) {
foreach ($aMentionedIds as $sMentionedId) {
/** @var \DBObject $oMentionedObject */
$oMentionedObject = MetaModel::GetObject($sMentionedClass, $sMentionedId);
$aTriggerArgs = $this->ToArgs('this') + ['mentioned->object()' => $oMentionedObject];
$aParams = ['class_list' => MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL)];
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnObjectMention AS t WHERE t.target_class IN (:class_list)"), [], $aParams);
while ($oTrigger = $oSet->Fetch())
{
/** @var \TriggerOnObjectMention $oTrigger */
try {
// Ensure to handle only mentioned object in the trigger's scope
if ($oTrigger->IsMentionedObjectInScope($oMentionedObject) === false) {
continue;
}
$oTrigger->DoActivate($aTriggerArgs);
}
catch (Exception $e) {
utils::EnrichRaisedException($oTrigger, $e);
}
}
}
}
}
/**
* @internal
* Save updated fields previous values for {@see DBObject::DBUpdate()} callbacks

View File

@@ -4,4 +4,5 @@
*/
@import "collapsible-section-with-blocks";
@import "collapsible-section-within-caselog-list";
@import "collapsible-section-within-caselog-list";
@import "collapsible-section-within-alert";

View File

@@ -0,0 +1,29 @@
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/* SCSS variables */
$ibo-caselog-entry-in-collapsible-section--body--background-color: transparentize($ibo-color-grey-100,0.5) !default;
$ibo-caselog-entry-in-collapsible-section--body--padding: $ibo-spacing-300 !default;
$ibo-caselog-entry-in-collapsible-section--body--color: $ibo-color-grey-900 !default;
/* - caselog display in ormcaselog */
.ibo-alert--body {
.ibo-collapsible-section {
margin: 0;
min-width: 22em;
.ibo-collapsible-section--header .ibo-collapsible-section--title {
@extend %ibo-font-size-100;
}
.ibo-collapsible-section--body {
@extend %ibo-font-size-100;
color: $ibo-caselog-entry-in-collapsible-section--body--color;
padding: $ibo-caselog-entry-in-collapsible-section--body--padding;
background-color: $ibo-caselog-entry-in-collapsible-section--body--background-color;
}
}
}

View File

@@ -75,7 +75,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Anwendungsupgrade kann durchgeführt werden',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Anwendungsupgrade nicht möglich: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Vorsicht: App-Upgrade kann fehlerschlagen: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'Sie müssen das <a href="%1$s">Setup</a> benutzen, um Ihre Applikation zu aktualisieren.<br />Einige angepasste Dateien wurden erkannt, eine Teil-Update kann nicht ausgeführt werden.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Einige angepasste Dateien wurden erkannt</b>, eine Teil-Update kann nicht ausgeführt werden.<br/>Befolgen Sie das <a href="%2$s">Verfahren</a>, um Ihr iTop manuell zu aktualisieren. Sie müssen das <a href="%1$s">Setup</a> benutzen, um Ihre Applikation zu aktualisieren.<br />',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Bereit zum Upgrade',

View File

@@ -75,7 +75,10 @@ Dict::Add('EN US', 'English', 'English', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start',

View File

@@ -76,7 +76,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'La aplicación puede ser actualizada',
'iTopUpdate:UI:CanCoreUpdate:No' => 'La aplicación no puede ser actualizada: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Advertencia: la actualización de la aplicación puede fallar: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Listo para empezar',

View File

@@ -75,7 +75,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'L\'application peut être mise à jour',
'iTopUpdate:UI:CanCoreUpdate:No' => 'L\'application ne peut pas être mise à jour : %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Attention : la mise à jour de l\'application peut échouer : %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'Vous devez utiliser la page <a href="%1$s">d\'installation</a> pour mettre à jour l\'application.<br />Des fichiers modifiés ont été détectés, une mise à jour partielle ne peut pas être effectuée.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Des fichiers modifiés ont été détectés</b>, une mise à jour partielle ne peut pas être effectuée.<br />Suivez la <a href="%2$s"> procedure</a> pour mettre à jour manuellement votre iTop. Vous devez utiliser la page <a href="%1$s">d\'installation</a> pour mettre à jour l\'application.',
'iTopUpdate:UI:CheckInProgress' => 'Veuillez patienter pendant la vérification des fichiers',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Prêt pour l\\installation',

View File

@@ -75,7 +75,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -77,7 +77,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Updaten van toepassing is mogelijk',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Updaten van de toepassing is niet mogelijk: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Klaar om verder te gaan',

View File

@@ -75,7 +75,8 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Aplikacja może być zaktualizowana',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Nie można zaktualizować aplikacji: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Ostrzeżenie: aktualizacja aplikacji może się nie powieść: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'Aby zaktualizować aplikację, musisz skorzystać ze strony <a href="%1$s">setup</a>.<br />Wykryto niektóre zmodyfikowane pliki, częściowej aktualizacji nie można przeprowadzić.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Gotowy do startu',

View File

@@ -75,7 +75,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Aplicação pode ser atualizada',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Aplicação não pode ser atualizada: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Atenção: a atualização da aplicação pode falhar: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Pronto para começar',

View File

@@ -63,7 +63,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Приложение может быть обновлено',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Приложение не может быть обновлено: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Всё готово к началу',

View File

@@ -75,7 +75,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated~~',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s~~',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => 'You must use the <a href="%1$s">setup</a> to update the application.<br />Some modified files were detected, a partial update cannot be executed.~~',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start~~',

View File

@@ -75,7 +75,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'iTopUpdate:UI:CanCoreUpdate:Yes' => '应用无法升级',
'iTopUpdate:UI:CanCoreUpdate:No' => '应用无法升级: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => '警告: 应用升级可能失败: %1$s',
'iTopUpdate:UI:CannotUpdateUseSetup' => '您必须使用 <a href="%1$s">安装向导</a> 来升级应用.<br />已检测到部分文件被修改, 无法执行部分升级.',
'iTopUpdate:UI:CannotUpdateUseSetup' => '<b>Some modified files were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
'iTopUpdate:UI:CheckInProgress' => 'Please wait during integrity check~~',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => '准备开始',

View File

@@ -38,7 +38,9 @@ class AjaxController extends Controller
else
{
$sLink = utils::GetAbsoluteUrlAppRoot().'setup/';
$aParams['sMessage'] = Dict::Format('iTopUpdate:UI:CannotUpdateUseSetup', $sLink);
$sLinkManualUpdate = 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Ainstall%3Aupgrading_itop#manually';
$aParams['sMessage'] = Dict::Format('iTopUpdate:UI:CannotUpdateUseSetup', $sLink, $sLinkManualUpdate);
$aParams['sMessageDetails'] = $sMessage;
}
} catch (FileNotExistException $e)
{

View File

@@ -535,7 +535,7 @@ final class CoreUpdater
SetupLog::Info('itop-core-update: Archive extracted, check files integrity');
// Check files integrity
FilesIntegrity::CheckInstallationIntegrity(self::UPDATE_DIR.'web/');
FilesIntegrity::CheckInstallationIntegrity(self::UPDATE_DIR.'web/', true);
SetupLog::Info('itop-core-update: Files integrity OK');
} catch (Exception $e)

View File

@@ -15,6 +15,10 @@
{{ 'iTopUpdate:UI:CanCoreUpdate:Loading'|dict_s }}
{% UISpinner Standard {} %}
{% EndUIContentBlock %}
{%UICollapsibleSection Standard {'sId':'header-requirements-details','sTitle':'UI:Details+'|dict_s, 'IsCollapsible':true, 'IsClosable':false,'AddCSSClass':'ibo-is-hidden'} %}
{% UIContentBlock Standard {'aContainerClasses':['ibo-update-core-header-requirements'], 'sId':'can-core-update-details'} %}
{% EndUIContentBlock %}
{% EndUICollapsibleSection %}
{% EndUIAlert %}
{% UIField Standard {'sLabel':'iTopUpdate:UI:CurrentVersion'|dict_s} %}
@@ -56,7 +60,11 @@
{% EndUIContentBlock %}
{% EndUIAlert %}
{% UIFileSelect Standard {sName: 'file', sId: 'file'} %}
{% UIAlert ForInformation {'sId':'check-in-progress', 'IsHidden':false} %}
{{ 'iTopUpdate:UI:CheckInProgress'|dict_s }}
{% EndUIAlert %}
{% UIFileSelect Standard {sName: 'file', sId: 'file','AddCSSClass':'ibo-is-hidden'} %}
{% UIAlert ForWarning {'sId':'dobackup-warning', 'IsHidden':true} %}
{{ 'iTopUpdate:UI:DoBackup:Warning'|dict_s }}

View File

@@ -14,9 +14,17 @@ $.ajax({
var oRequirements = $("#header-requirements");
var oCanCoreUpdate = $("#can-core-update");
oCanCoreUpdate.html(data.sMessage);
if(data.sMessageDetails){
$("#header-requirements-details").removeClass("ibo-is-hidden");
$('#can-core-update-details').html(data.sMessageDetails);
}
oRequirements.removeClass("ibo-is-information");
if (data.bStatus) {
oRequirements.addClass("ibo-is-success");
$("#check-update").prop("disabled", false);
$("#file").prop("disabled", false);
$("#file-container").removeClass("ibo-is-hidden");
$("#check-in-progress").addClass("ibo-is-hidden");
} else {
$("#check-update").prop("disabled", true);
$("#file").prop("disabled", true);

View File

@@ -25,6 +25,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'FilesInformation:Error:MissingFile' => 'Fehlende Datei: %1$s',
'FilesInformation:Error:CorruptedFile' => 'Datei %1$s ist beschädigt',
'FilesInformation:Error:CantWriteToFile' => 'Datei %1$s kann nicht geschrieben werden',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Einige neue Module wurden erkannt</b>, eine Teil-Update kann nicht ausgeführt werden.<br/>Befolgen Sie das <a href="%2$s">Verfahren</a>, um Ihr iTop manuell zu aktualisieren. Sie müssen das <a href="%1$s">Setup</a> benutzen, um Ihre Applikation zu aktualisieren.<br />',
));

View File

@@ -26,6 +26,7 @@ Dict::Add('EN US', 'English', 'English', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.',
));

View File

@@ -26,6 +26,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
'FilesInformation:Error:MissingFile' => 'Archivo faltante: %1$s',
'FilesInformation:Error:CorruptedFile' => 'El archivo %1$s está corrupto',
'FilesInformation:Error:CantWriteToFile' => 'No se puede escribir al archivo %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
'FilesInformation:Error:MissingFile' => 'Ficher manquant : %1$s',
'FilesInformation:Error:CorruptedFile' => 'Le fichier %1$s est corrompu',
'FilesInformation:Error:CantWriteToFile' => 'Impossible de modifier le fichier %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>De nouveaux modules ont été détectés</b>, une mise à jour partielle ne peut pas être effectuée.<br />Suivez la <a href="%2$s"> procedure</a> pour mettre à jour manuellement votre iTop. Vous devez utiliser la page <a href="%1$s">d\'installation</a> pour mettre à jour l\'application.',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -27,6 +27,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'FilesInformation:Error:MissingFile' => 'Ontbrekend bestand: %1$s',
'FilesInformation:Error:CorruptedFile' => 'Corrupt bestand: %1$s',
'FilesInformation:Error:CantWriteToFile' => 'Kan niet schrijven naar bestand %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -1,31 +1,32 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*
* 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
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('PL PL', 'Polish', 'Polski', array(
// Errors
'FilesInformation:Error:MissingFile' => 'Brakujący plik: %1$s',
'FilesInformation:Error:CorruptedFile' => 'Plik %1$s jest uszkodzony',
'FilesInformation:Error:CantWriteToFile' => 'Nie można zapisać do pliku %1$s',
));
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2010-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*
* 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
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('PL PL', 'Polish', 'Polski', array(
// Errors
'FilesInformation:Error:MissingFile' => 'Brakujący plik: %1$s',
'FilesInformation:Error:CorruptedFile' => 'Plik %1$s jest uszkodzony',
'FilesInformation:Error:CantWriteToFile' => 'Nie można zapisać do pliku %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'FilesInformation:Error:MissingFile' => 'Faltando arquivo: %1$s',
'FilesInformation:Error:CorruptedFile' => 'Arquivo %1$s está corrompido',
'FilesInformation:Error:CantWriteToFile' => 'Sem permissão de escrita no arquivo %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -13,6 +13,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'FilesInformation:Error:MissingFile' => 'Файл %1$s отсутствует',
'FilesInformation:Error:CorruptedFile' => 'Файл %1$s повреждён',
'FilesInformation:Error:CantWriteToFile' => 'Невозможно выполнить запись в файл %1$s',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'FilesInformation:Error:MissingFile' => 'Missing file: %1$s~~',
'FilesInformation:Error:CorruptedFile' => 'File %1$s is corrupted~~',
'FilesInformation:Error:CantWriteToFile' => 'Can not write to file %1$s~~',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -25,6 +25,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'FilesInformation:Error:MissingFile' => '文件丢失: %1$s~~',
'FilesInformation:Error:CorruptedFile' => '文件 %1$s 已损坏',
'FilesInformation:Error:CantWriteToFile' => '文件 %1$s 无法写入',
'FilesInformation:Error:CannotUpdateNewModules' => '<b>Some new modules were detected</b>, a partial update cannot be executed.</br>Follow the <a href="%2$s"> procedure</a> in order to manually upgrade your iTop. You must use the <a href="%1$s">setup</a> to update the application.~~',
));

View File

@@ -13,6 +13,8 @@ use DOMDocument;
use DOMElement;
use DOMNode;
use DOMXPath;
use MetaModel;
use utils;
class FilesIntegrity
{
@@ -79,10 +81,12 @@ class FilesIntegrity
* Check that files present in iTop folder corresponds to the manifest
*
* @param string $sRootPath
* @param bool $bCheckNewModule
*
* @throws \Combodo\iTop\FilesInformation\Service\FileIntegrityException
* @since 3.0.1 Add $bCheckNewModule parameter
*/
public static function CheckInstallationIntegrity($sRootPath = APPROOT)
public static function CheckInstallationIntegrity($sRootPath = APPROOT, $bCheckNewModule = false)
{
$aFilesInfo = FilesIntegrity::GetInstalledFiles($sRootPath.'manifest.xml');
@@ -92,6 +96,7 @@ class FilesIntegrity
}
@clearstatcache();
$sSourceDir = MetaModel::GetConfig()->Get('source_dir');
foreach ($aFilesInfo as $aFileInfo)
{
$sFile = $sRootPath.$aFileInfo['path'];
@@ -106,6 +111,15 @@ class FilesIntegrity
throw new FileIntegrityException(Dict::Format('FilesInformation:Error:CorruptedFile', $sFile));
}
}
if($bCheckNewModule && strpos($aFileInfo['path'],$sSourceDir) === 0){
$aFilePath = explode('/',$aFileInfo['path']);
$sFolderPath = $aFilePath[0].'/'.$aFilePath[1].'/'.$aFilePath[2];
if (is_dir(APPROOT.'/'.$sFolderPath) && !is_file($sRootPath.$sFolderPath)){
$sLink = utils::GetAbsoluteUrlAppRoot().'setup/';
$sLinkManualUpdate = 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Ainstall%3Aupgrading_itop#manually';
throw new FileIntegrityException(Dict::Format('FilesInformation:Error:CannotUpdateNewModules', $sLink, $sLinkManualUpdate));
}
}
// Packed with missing files...
}
}

View File

@@ -47,6 +47,3 @@ SetupWebPage::AddModule(
),
)
);
?>

View File

@@ -368,7 +368,14 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
<li>Spravovat Vaše nejdůležitější IT aktivum - Dokumentaci.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Otevřené požadavky: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Mé požadavky',
'UI:WelcomeMenu:OpenIncidents' => 'Otevřené incidenty: %1$d',

View File

@@ -357,7 +357,14 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
<li>Manage the most important asset of your IT: Documentation.</li>
</ul>
</p>~~',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Åbne anmodninger: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Mine brugerhenvendelser',
'UI:WelcomeMenu:OpenIncidents' => 'Åbne Incidents: %1$d',

View File

@@ -357,7 +357,14 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
<li>und ein besseres Verwalten des wichtigsten Bestandteiles Ihrer IT: der Dokumentation.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> 'Willkommen bei '.ITOP_APPLICATION_SHORT,
'UI:WelcomeMenu:Text'=> '<div>Willkommen bei '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Offene Requests: %1$d',
'UI:WelcomeMenu:MyCalls' => 'An mich gestellte Benutzeranfragen',
'UI:WelcomeMenu:OpenIncidents' => 'Offene Incidents: %1$d',

View File

@@ -369,7 +369,14 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
<li>Administrar el bien más importante de su infraestructura de TI: La Documentación.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Requerimientos Abiertos: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Mis Requerimientos',
'UI:WelcomeMenu:OpenIncidents' => 'Incidentes Abiertos: %1$d',

View File

@@ -1434,7 +1434,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
'UI:About:InstallationOptions' => 'Options d\'installation',
'UI:About:ManualExtensionSource' => 'Extension',
'UI:About:Extension_Version' => 'Version: %1$s',
'UI:About:RemoteExtensionSource' => 'iTop Hub',
'UI:About:RemoteExtensionSource' => 'Data',
'UI:DisconnectedDlgMessage' => 'Vous êtes déconnecté(e). Vous devez vous identifier pour pouvoir continuer à utiliser l\'application.',
'UI:DisconnectedDlgTitle' => 'Attention !',

View File

@@ -357,7 +357,14 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
<li>hatékonyan tudja kezelni az egyik legfontosabb IT eszközt, a dokumentációt.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Összes nyitott kérés: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Saját kérések',
'UI:WelcomeMenu:OpenIncidents' => 'Nyitott incidensek: %1$d',

View File

@@ -368,7 +368,14 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
<li>Gestire la risorsa più importante della tua IT: Documentazione.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Apri le richieste: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Le mie richieste',
'UI:WelcomeMenu:OpenIncidents' => 'Apri gli incidenti: %1$d',

View File

@@ -357,7 +357,14 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
<li>ITの中でもっとも重要な財産である「文書化」の管理。</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => '要求を開く: %1$d',
'UI:WelcomeMenu:MyCalls' => '担当中の要求',
'UI:WelcomeMenu:OpenIncidents' => 'インシデントを開く: %1$d',

View File

@@ -368,7 +368,14 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
<li>Het beheren van het belangrijkste middel: documentatie.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Open aanvragen: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Mijn aanvragen',
'UI:WelcomeMenu:OpenIncidents' => 'Open incidenten: %1$d',
@@ -551,22 +558,22 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'UI:ResetPwd-Ready' => 'Het wachtwoord is veranderd',
'UI:ResetPwd-Login' => 'Klik hier om in te loggen',
'UI:Login:About' => 'ITOP_APPLICATION',
'UI:Login:About' => ITOP_APPLICATION,
'UI:Login:ChangeYourPassword' => 'Verander jouw wachtwoord',
'UI:Login:OldPasswordPrompt' => 'Oud wachtwoord',
'UI:Login:NewPasswordPrompt' => 'Nieuw wachtwoord',
'UI:Login:RetypeNewPasswordPrompt' => 'Herhaal nieuwe wachtwoord',
'UI:Login:IncorrectOldPassword' => 'Fout: het oude wachtwoord is incorrect',
'UI:LogOffMenu' => 'Log uit',
'UI:LogOff:ThankYou' => 'Bedankt voor het gebruiken van ITOP_APPLICATION',
'UI:LogOff:ThankYou' => 'Bedankt voor het gebruiken van '.ITOP_APPLICATION,
'UI:LogOff:ClickHereToLoginAgain' => 'Klik hier om in te loggen',
'UI:ChangePwdMenu' => 'Verander wachtwoord',
'UI:Login:PasswordChanged' => 'Wachtwoord met succes aangepast',
'UI:AccessRO-All' => 'ITOP_APPLICATION is alleen-lezen',
'UI:AccessRO-Users' => 'ITOP_APPLICATION is alleen-lezen voor eindgebruikers',
'UI:AccessRO-All' => ITOP_APPLICATION.' is alleen-lezen',
'UI:AccessRO-Users' => ITOP_APPLICATION.' is alleen-lezen voor eindgebruikers',
'UI:ApplicationEnvironment' => 'Omgeving van de applicatie: %1$s',
'UI:Login:RetypePwdDoesNotMatch' => 'Het nieuwe wachtwoord en de herhaling van het nieuwe wachtwoord komen niet overeen',
'UI:Button:Login' => 'Ga naar ITOP_APPLICATION',
'UI:Button:Login' => 'Ga naar '.ITOP_APPLICATION,
'UI:Login:Error:AccessRestricted' => 'Geen toegang tot '.ITOP_APPLICATION_SHORT.'. Neem contact op met een '.ITOP_APPLICATION_SHORT.'-beheerder.',
'UI:Login:Error:AccessAdmin' => 'Alleen toegankelijk voor mensen met beheerdersrechten. Neem contact op met een '.ITOP_APPLICATION_SHORT.'-beheerder',
'UI:Login:Error:WrongOrganizationName' => 'Onbekende organisatie',
@@ -835,7 +842,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'UI:Delete:PleaseDoTheManualOperations' => 'Verricht eerst de handmatige handelingen die hierboven staan voordat je dit object verwijdert',
'UI:Delect:Confirm_Object' => 'Bevestig dat je %1$s wil verwijderen.',
'UI:Delect:Confirm_Count_ObjectsOf_Class' => 'Bevestig dat je de volgende %1$d objecten van klasse %2$s wilt verwijderen.',
'UI:WelcomeToITop' => 'Welkom in ITOP_APPLICATION',
'UI:WelcomeToITop' => 'Welkom in '.ITOP_APPLICATION,
'UI:DetailsPageTitle' => ITOP_APPLICATION_SHORT.' - %1$s - %2$s details',
'UI:ErrorPageTitle' => ITOP_APPLICATION_SHORT.' - Fout',
'UI:ObjectDoesNotExist' => 'Sorry, dit object bestaat niet (of je bent niet gemachtigd het te bekijken).',

View File

@@ -369,7 +369,14 @@ Dict::Add('PL PL', 'Polish', 'Polski', array(
<li>Zarządzaj najważniejszym zasobem swojego IT: dokumentacją.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Otwarte zgłoszenia: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Moje zgłoszenia',
'UI:WelcomeMenu:OpenIncidents' => 'Otwarte incydenty: %1$d',

View File

@@ -368,7 +368,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
<li>gerenciar o ativo mais importante de sua TI: Documentação</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Solicitações abertas: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Minhas solicitações',
'UI:WelcomeMenu:OpenIncidents' => 'Incidentes abertos: %1$d',

View File

@@ -358,7 +358,14 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
<li>Manažovať najdôležitejšie aktíva Vášho IT: Dokumentáciu.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Otvoriť žiadosť: %1$d',
'UI:WelcomeMenu:MyCalls' => 'Moje žiadosti',
'UI:WelcomeMenu:OpenIncidents' => 'Otvoriť incidenty: %1$d',
@@ -1424,7 +1431,7 @@ Keď sú priradené spúštačom, každej akcii je dané číslo "príkazu", šp
'UI:About:InstallationOptions' => 'Installation options~~',
'UI:About:ManualExtensionSource' => 'Extension~~',
'UI:About:Extension_Version' => 'Version: %1$s~~',
'UI:About:RemoteExtensionSource' => 'iTop Hub~~',
'UI:About:RemoteExtensionSource' => 'Data~~',
'UI:DisconnectedDlgMessage' => 'You are disconnected. You must identify yourself to continue using the application.~~',
'UI:DisconnectedDlgTitle' => 'Warning!~~',

View File

@@ -368,7 +368,14 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
<li>İşletmenin en önemli kaynağı olan dokümantasyonu yönetmesine imkan sağlar.</li>
</ul>
</p>',
'UI:WelcomeMenu:Text'=> '~~',
'UI:WelcomeMenu:Text'=> '<div>Congratulations, you landed on '.ITOP_APPLICATION.' '.ITOP_VERSION_NAME.'!</div>
<div>This version features a brand new modern and accessible backoffice design.</div>
<div>We kept '.ITOP_APPLICATION.' core functions that you liked and modernized them to make you love them.
We hope youll enjoy this version as much as we enjoyed imagining and creating it.</div>
<div>Customize your '.ITOP_APPLICATION.' preferences for a personalized experience.</div>~~',
'UI:WelcomeMenu:AllOpenRequests' => 'Açık istekler: %1$d',
'UI:WelcomeMenu:MyCalls' => 'İsteklerim',
'UI:WelcomeMenu:OpenIncidents' => 'Açık Arızalar: %1$d',

View File

@@ -19,10 +19,11 @@
// Helpers
function ShowAboutBox(sTitle)
{
var loadingDialog = $('<div style="padding-top:40px; padding-left:40px;"><i class="fa fa-sync-alt fa-spin fa-x fa-fw"></i></div>');
loadingDialog.dialog( {title:sTitle,autoOpen: true, modal: true});
var loadingDialog = $('<div id="ibo-about-box--loader"></div>');
loadingDialog.dialog( {title:sTitle,autoOpen: true, modal: true, width: 700, height:350});
$('#ibo-about-box--loader').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'about_box'}, function(data){
$('#ibo-about-box--loader').unblock();
$('body').append(data);
}).always(function() {
loadingDialog.empty();

View File

@@ -2495,7 +2495,7 @@ EOF
);
$oSet = new DBObjectSet($oSearch, [], $aSearchParams);
$oSet->OptimizeColumnLoad(array($oSearch->GetClassAlias() => array()));
$oSet->OptimizeColumnLoad([$oSearch->GetClassAlias() => [$sObjectImageAttCode]]);
$oSet->SetLimit(MetaModel::GetConfig()->Get('max_autocomplete_results'));
// Note: We have to this manually because of a bug in DBSearch not checking the user prefs. by default.
$oSet->SetShowObsoleteData(utils::ShowObsoleteData());
@@ -2520,7 +2520,7 @@ EOF
} else {
// If no image found, fallback on initials
$aMatch['picture_style'] = '';
$aMatch['initials'] = utils::ToAcronym($oObject->Get('friendlyname'));
$aMatch['initials'] = utils::FormatInitialsForMedallion(utils::ToAcronym($oObject->Get('friendlyname')));
}
}

View File

@@ -88,7 +88,7 @@ class WebPage implements Page
*/
protected const COMPATIBILITY_MOVED_LINKED_SCRIPTS_REL_PATH = [];
/**
* @var array Script linked to the page through URIs, which were deprecated but can be added back if necessary {@see "compatibility.include_deprecated_js_files" conf. param.}
* @var array Script linked to the page through URIs, which were deprecated (in iTop previous version) but can be added back if necessary {@see "compatibility.include_deprecated_js_files" conf. param.}
* @since 3.0.0
*/
protected const COMPATIBILITY_DEPRECATED_LINKED_SCRIPTS_REL_PATH = [];
@@ -98,7 +98,7 @@ class WebPage implements Page
*/
protected const COMPATIBILITY_MOVED_LINKED_STYLESHEETS_REL_PATH = [];
/**
* @var array Stylesheets linked to the page through URIs, which were deprecated but can be added back if necessary {@see "compatibility.include_deprecated_css_files" conf. param.}
* @var array Stylesheets linked to the page through URIs, which were deprecated (in iTop previous version) but can be added back if necessary {@see "compatibility.include_deprecated_css_files" conf. param.}
* @since 3.0.0
*/
protected const COMPATIBILITY_DEPRECATED_LINKED_STYLESHEETS_REL_PATH = [];

View File

@@ -772,13 +772,53 @@ class AjaxRenderController
self::DisplayUserAboutBox($oPage);
}
/**
* Display list of licenses in "About iTop" popup
* @param \AjaxPage $oPage
*
* @throws \Exception
* @since 3.0.1
*/
private static function DisplayAboutLicenses(AjaxPage $oPage): void
{
$sCurrEnv = utils::GetCurrentEnvironment();
require_once(APPROOT.'setup/setuputils.class.inc.php');
$aLicenses = SetupUtils::GetLicenses($sCurrEnv);
$oPage->add("<div>");
$oPage->add('<fieldset>');
$oPage->add('<legend>'.Dict::S('UI:About:Licenses').'</legend>');
$oPage->add('<ul style="margin: 0; font-size: smaller; max-height: 15em; overflow: auto;">');
$index = 0;
foreach ($aLicenses as $oLicense) {
$oPage->add('<li><b>'.$oLicense->product.'</b>, &copy; '.$oLicense->author.' is licensed under the <b>'.$oLicense->license_type.' license</b>. (<a id="toggle_'.$index.'" class="CollapsibleLabel" style="cursor:pointer;">Details</a>)');
$oPage->add('<div id="license_'.$index.'" class="license_text ibo-is-html-content" style="display:none;overflow:auto;max-height:10em;font-size:small;border:1px #696969 solid;margin-bottom:1em; margin-top:0.5em;padding:0.5em;">'.$oLicense->text.'</div>');
$oPage->add_ready_script(<<<JS
$("#toggle_$index").on('click', function() {
$(this).toggleClass('open');
$("#license_$index").slideToggle("normal");
});
JS
);
$index++;
}
$oPage->add('</ul>');
$oPage->add('</fieldset>');
$oPage->add("</div>");
}
/**
* Display about iTop for all user non admin
* @param \AjaxPage $oPage
*
* @throws \Exception
*/
private static function DisplayUserAboutBox(AjaxPage $oPage): void
{
$sDialogTitle = addslashes(Dict::S('UI:About:Title'));
$oPage->add_ready_script(
<<<EOF
$('#about_box').dialog({
width: 500,
width: 700,
modal: true,
title: '$sDialogTitle',
close: function() { $(this).remove(); }
@@ -791,9 +831,16 @@ EOF
$oPage->add('<a href="http://www.combodo.com" title="www.combodo.com" target="_blank" style="background: none;"><img src="../images/logo-combodo.png?t='.utils::GetCacheBusterTimestamp().'"/></a>');
$oPage->add('<div>'.$sVersionString.'</div>');
$oPage->add("</div>");
self::DisplayAboutLicenses($oPage);
$oPage->add("</div>");
}
/**
* Display about iTop for admin user
* @param \AjaxPage $oPage
*
* @throws \Exception
*/
private static function DisplayAdminAboutBox(AjaxPage $oPage): void
{
$sDialogTitle = addslashes(Dict::S('UI:About:Title'));
@@ -824,7 +871,6 @@ EOF
$oSet = new DBObjectSet($oFilter, array('installed' => false)); // Most recent first
$oLastInstall = $oSet->Fetch();
$sLastInstallDate = $oLastInstall->Get('installed');
$sDataModelVersion = $oLastInstall->Get('version');
$aDataModelInfo = json_decode($oLastInstall->Get('comment'), true);
$sDataModelSourceDir = $aDataModelInfo['source_dir'];
@@ -841,9 +887,6 @@ EOF
}
$aAvailableModules = $oRuntimeEnv->AnalyzeInstallation(MetaModel::GetConfig(), $aSearchDirs);
require_once(APPROOT.'setup/setuputils.class.inc.php');
$aLicenses = SetupUtils::GetLicenses($sCurrEnv);
$aItopSettings = array('cron_max_execution_time', 'timezone');
$aPHPSettings = array('memory_limit', 'max_execution_time', 'upload_max_filesize', 'post_max_size');
$aMySQLSettings = array('max_allowed_packet', 'key_buffer_size', 'query_cache_size');
@@ -873,7 +916,6 @@ EOF
$oPage->add('<td><a href="http://www.combodo.com" title="www.combodo.com" target="_blank" style="background: none;"><img src="../images/logo-combodo.png?t='.utils::GetCacheBusterTimestamp().'" style="float: right;"/></a></td>');
$oPage->add('<td style="padding-left: 20px;">');
$oPage->add($sVersionString.'<br/>');
//$oPage->add(Dict::S('UI:About:DataModel').': '.$sDataModelVersion.'<br/>');
$oPage->add('MySQL: '.$sMySQLVersion.'<br/>');
$oPage->add('PHP: '.$sPHPVersion.'<br/>');
$oPage->add('</td>');
@@ -881,26 +923,7 @@ EOF
$oPage->add('</table>');
$oPage->add("</div>");
$oPage->add("<div>");
$oPage->add('<fieldset>');
$oPage->add('<legend>'.Dict::S('UI:About:Licenses').'</legend>');
$oPage->add('<ul style="margin: 0; font-size: smaller; max-height: 15em; overflow: auto;">');
$index = 0;
foreach ($aLicenses as $oLicense) {
$oPage->add('<li><b>'.$oLicense->product.'</b>, &copy; '.$oLicense->author.' is licensed under the <b>'.$oLicense->license_type.' license</b>. (<a id="toggle_'.$index.'" class="CollapsibleLabel" style="cursor:pointer;">Details</a>)');
$oPage->add('<div id="license_'.$index.'" class="license_text ibo-is-html-content" style="display:none;overflow:auto;max-height:10em;font-size:small;border:1px #696969 solid;margin-bottom:1em; margin-top:0.5em;padding:0.5em;">'.$oLicense->text.'</div>');
$oPage->add_ready_script(<<<JS
$("#toggle_$index").on('click', function() {
$(this).toggleClass('open');
$("#license_$index").slideToggle("normal");
});
JS
);
$index++;
}
$oPage->add('</ul>');
$oPage->add('</fieldset>');
$oPage->add("</div>");
self::DisplayAboutLicenses($oPage);
$oPage->add('<fieldset>');
$oPage->add('<legend>'.Dict::S('UI:About:InstallationOptions').'</legend>');
@@ -942,7 +965,6 @@ JS
$oPage->add('iTopVersion: '.ITOP_VERSION."\n");
$oPage->add('iTopBuild: '.ITOP_REVISION."\n");
$oPage->add('iTopBuildDate: '.ITOP_BUILD_DATE."\n");
$oPage->add('DataModelVersion: '.$sDataModelVersion."\n");
$oPage->add('MySQLVersion: '.$sMySQLVersion."\n");
$oPage->add('PHPVersion: '.$sPHPVersion."\n");
$oPage->add('OSVersion: '.$sOSVersion."\n");

View File

@@ -648,7 +648,7 @@ HTML
// Open medallion from profile picture or first name letter
$bEntryHasMedallionPicture = (empty($aContactPicturesCache[$iEntryUserId]) === false);
$sEntryMedallionStyle = $bEntryHasMedallionPicture ? ' background-image: url(\''.$aContactPicturesCache[$iEntryUserId].'\');' : '';
$sEntryMedallionContent = $bEntryHasMedallionPicture ? '' : UserRights::GetUserInitials($sEntryUserLogin);
$sEntryMedallionContent = $bEntryHasMedallionPicture ? '' : utils::FormatInitialsForMedallion(UserRights::GetUserInitials($sEntryUserLogin));
// - Entry tooltip
$sEntryMedallionTooltip = utils::HtmlEntities($sEntryUserLogin);
$sEntryMedallionTooltipPlacement = ($iEntryUserId === $iCurrentUserId) ? 'left' : 'right';

View File

@@ -10,7 +10,7 @@
{% if oUIBlock.GetAuthorPictureAbsUrl() is not empty %}
<img class="ibo-activity-entry--author-picture" src="{{ oUIBlock.GetAuthorPictureAbsUrl() }}" alt="{{ oUIBlock.GetAuthorInitials() }}">
{% else %}
<div class="ibo-activity-entry--author-initials">{{ oUIBlock.GetAuthorInitials() }}</div>
<div class="ibo-activity-entry--author-initials">{{ oUIBlock.GetAuthorInitials()|slice(0, 3) }}</div>
{% endif %}
{% endblock %}
</div>

View File

@@ -434,7 +434,7 @@ class UtilsTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
public function testToAcronym(string $sInput, string $sExceptedAcronym)
{
$sTestedAcronym = utils::ToAcronym($sInput);
$this->assertEquals($sTestedAcronym, $sExceptedAcronym, "Acronym for '$sInput' doesn't match. Got '$sTestedAcronym', expected '$sExceptedAcronym'.");
$this->assertEquals($sExceptedAcronym, $sTestedAcronym, "Acronym for '$sInput' doesn't match. Got '$sTestedAcronym', expected '$sExceptedAcronym'.");
}
/**
@@ -479,6 +479,10 @@ class UtilsTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
'Jada Pinkett-smith',
'JP',
],
'Several words, cyrillic alphabet' => [
'Денис Александра',
'ДА',
],
];
}
@@ -550,6 +554,40 @@ class UtilsTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
];
}
/**
* @dataProvider FormatInitialsForMedallionProvider
* @covers utils::FormatInitialsForMedallion
*
* @param string $sInput
* @param string $sExpected
*/
public function testFormatInitialsForMedallion(string $sInput, string $sExpected)
{
$sTested = utils::FormatInitialsForMedallion($sInput);
$this->assertEquals($sExpected, $sTested);
}
/**
* @since 3.0.1
*/
public function FormatInitialsForMedallionProvider()
{
return [
'All letters kept (2)' => [
'AB',
'AB',
],
'All letters kept (3)' => [
'ABC',
'ABC',
],
'Only 3 first letters kept (4)' => [
'ABCD',
'ABC',
],
];
}
/**
* @param string $sExpressionToConvert
* @param int $iExpectedConvertedValue

View File

@@ -36,30 +36,36 @@ class iTopModuleXmlInstallationChecklistTest extends ItopTestCase
public function testAllModuleAreIncludedInInstallationXml()
{
$sInstallationXmlPath = APPROOT.'datamodels/2.x/installation.xml';
if (!is_file($sInstallationXmlPath))
{
if (!is_file($sInstallationXmlPath)) {
$sInstallationXmlPath = APPROOT.'datamodels/1.x/installation.xml';
}
$this->assertTrue(is_file($sInstallationXmlPath), "$sInstallationXmlPath does not exist");
$sInstallationXmlContent = file_get_contents($sInstallationXmlPath);
preg_match_all("|<module>(.*)</module>|", $sInstallationXmlContent, $aMatches);
$aDeclaredModules = [] ;
if (!empty($aMatches))
{
foreach ($aMatches[1] as $sModule)
{
if (!array_key_exists($sModule, $aDeclaredModules))
{
$aDeclaredModules = [];
if (!empty($aMatches)) {
foreach ($aMatches[1] as $sModule) {
if (!array_key_exists($sModule, $aDeclaredModules)) {
$aDeclaredModules[$sModule] = $sModule;
}
}
}
$this->assertArraySubset($this->GetFilteredModulesFromDatamodels(APPROOT.'/datamodels'), $aDeclaredModules, false, "$sInstallationXmlPath does not refer to all provided modules. Refered modules:\n " . var_export($aDeclaredModules, true));
$this->assertArraySubset(
$this->GetFilteredModulesFromDatamodels(APPROOT.'/datamodels'),
$aDeclaredModules,
false,
"{$sInstallationXmlPath} does not list all modules in /datamodels ! List of modules in installation.xml:\n ".var_export($aDeclaredModules, true)
);
$aModulesFromDatamodels = $this->GetAllModules(APPROOT.'/datamodels');
$this->assertArraySubset($aDeclaredModules, $aModulesFromDatamodels, false, "Not all modules are contained in $sInstallationXmlPath. Refered modules:\n " . var_export($aModulesFromDatamodels, true));
$this->assertArraySubset(
$aDeclaredModules,
$aModulesFromDatamodels,
false,
"Not all modules are contained in {$sInstallationXmlPath}. List of modules in /datamodels:\n ".var_export($aModulesFromDatamodels, true)
);
}
public function GetFilteredModulesFromDatamodels($sFolder)