From 1e66220077e67c8b9544a01a9dba7d5b24b39fd2 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Wed, 3 Dec 2014 14:18:16 +0000 Subject: [PATCH] #1020 Restrict dashboard/shortcut refresh interval -retrofit from trunk SVN:2.0.3[3449] --- application/dashboard.class.inc.php | 13 +++-- application/displayblock.class.inc.php | 2 +- application/forms.class.inc.php | 68 ++++++++++++++++++++++ application/shortcut.class.inc.php | 6 +- core/config.class.inc.php | 8 +++ dictionaries/dictionary.itop.ui.php | 4 +- dictionaries/es_cr.dictionary.itop.ui.php | 4 +- dictionaries/fr.dictionary.itop.ui.php | 4 +- dictionaries/pt_br.dictionary.itop.ui.php | 4 +- dictionaries/ru.dictionary.itop.ui.php | 4 +- js/property_field.js | 71 +++++++++++++++++++++++ pages/ajax.render.php | 2 +- 12 files changed, 169 insertions(+), 21 deletions(-) diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index be4262668..7783aef6a 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -91,7 +91,7 @@ abstract class Dashboard } if ($oAutoReloadInterval = $oAutoReloadNode->getElementsByTagName('interval')->item(0)) { - $this->iAutoReloadSec = max(5, (int)$oAutoReloadInterval->textContent); + $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$oAutoReloadInterval->textContent); } } @@ -235,7 +235,7 @@ abstract class Dashboard $this->sLayoutClass = $aParams['layout_class']; $this->sTitle = $aParams['title']; $this->bAutoReload = $aParams['auto_reload'] == 'true'; - $this->iAutoReloadSec = max(5, (int) $aParams['auto_reload_sec']); + $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']); foreach($aParams['cells'] as $aCell) { @@ -300,7 +300,7 @@ abstract class Dashboard public function SetAutoReloadInterval($iAutoReloadSec) { - $this->iAutoReloadSec = max(5, (int)$iAutoReloadSec); + $this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$iAutoReloadSec); } public function AddDashlet($oDashlet) @@ -357,16 +357,17 @@ abstract class Dashboard $oField = new DesignerBooleanField('auto_reload', Dict::S('UI:DashboardEdit:AutoReload'), $this->bAutoReload); $oForm->AddField($oField); - $oField = new DesignerTextField('auto_reload_sec', Dict::S('UI:DashboardEdit:AutoReloadSec'), $this->iAutoReloadSec); - $oField->SetValidationPattern('^$|^0*([5-9]|[1-9][0-9]+)$'); // Can be empty, or a number > 4 + $oField = new DesignerIntegerField('auto_reload_sec', Dict::S('UI:DashboardEdit:AutoReloadSec'), $this->iAutoReloadSec); + $oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit $oForm->AddField($oField); + $this->SetFormParams($oForm); $oForm->RenderAsPropertySheet($oPage, false, '.itop-dashboard'); $oPage->add(''); - $sRateTitle = addslashes(Dict::S('UI:DashboardEdit:AutoReloadSec+')); + $sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval'))); $oPage->add_ready_script( << 0)) { $bAutoReload = true; - $iReloadInterval = max(5, $aExtraParams['auto_reload'])*1000; + $iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload'])*1000; } else { diff --git a/application/forms.class.inc.php b/application/forms.class.inc.php index f15b19f06..27127820c 100644 --- a/application/forms.class.inc.php +++ b/application/forms.class.inc.php @@ -814,6 +814,74 @@ EOF } } +class DesignerIntegerField extends DesignerFormField +{ + protected $iMin; // Lower boundary, inclusive + protected $iMax; // Higher boundary, inclusive + + public function __construct($sCode, $sLabel = '', $defaultValue = '') + { + parent::__construct($sCode, $sLabel, $defaultValue); + $this->iMin = 0; // Positive integer is the default + $this->iMax = null; + } + + public function SetBoundaries($iMin = null, $iMax = null) + { + $this->iMin = $iMin; + $this->iMax = $iMax; + } + + public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog') + { + $sId = $this->oForm->GetFieldId($this->sCode); + + $sName = $this->oForm->GetFieldName($this->sCode); + if ($this->IsReadOnly()) + { + $sHtmlValue = "".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."defaultValue, ENT_QUOTES, 'UTF-8')."\"/>"; + } + else + { + $sMin = json_encode($this->iMin); + $sMax = json_encode($this->iMax); + $sMandatory = $this->bMandatory ? 'true' : 'false'; + $oP->add_ready_script( +<<aCSSClasses) > 0) + { + $sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"'; + } + $sHtmlValue = "defaultValue, ENT_QUOTES, 'UTF-8')."\">"; + } + return array('label' => $this->sLabel, 'value' => $sHtmlValue); + } + + public function ReadParam(&$aValues) + { + parent::ReadParam($aValues); + + if (!is_null($this->iMin) && ($aValues[$this->sCode] < $this->iMin)) + { + // Reject the value... + $aValues[$this->sCode] = $this->defaultValue; + } + if (!is_null($this->iMax) && ($aValues[$this->sCode] > $this->iMax)) + { + // Reject the value... + $aValues[$this->sCode] = $this->defaultValue; + } + } +} + class DesignerComboField extends DesignerFormField { protected $aAllowedValues; diff --git a/application/shortcut.class.inc.php b/application/shortcut.class.inc.php index abca8f5d3..e80d32467 100644 --- a/application/shortcut.class.inc.php +++ b/application/shortcut.class.inc.php @@ -254,8 +254,8 @@ class ShortcutOQL extends Shortcut $oField = new DesignerBooleanField('auto_reload', Dict::S('Class:ShortcutOQL/Attribute:auto_reload'), false); $oForm->AddField($oField); - $oField = new DesignerTextField('auto_reload_sec', Dict::S('Class:ShortcutOQL/Attribute:auto_reload_sec'), MetaModel::GetConfig()->GetStandardReloadInterval()); - $oField->SetValidationPattern('^$|^0*([5-9]|[1-9][0-9]+)$'); // Can be empty, or a number > 4 + $oField = new DesignerIntegerField('auto_reload_sec', Dict::S('Class:ShortcutOQL/Attribute:auto_reload_sec'), MetaModel::GetConfig()->GetStandardReloadInterval()); + $oField->SetBoundaries(MetaModel::GetConfig()->Get('min_reload_interval'), null); // no upper limit $oField->SetMandatory(false); $oForm->AddField($oField); @@ -284,7 +284,7 @@ class ShortcutOQL extends Shortcut $oAppContext = new ApplicationContext(); $sContext = $oAppContext->GetForLink(); - $sRateTitle = addslashes(Dict::S('Class:ShortcutOQL/Attribute:auto_reload_sec+')); + $sRateTitle = addslashes(Dict::Format('Class:ShortcutOQL/Attribute:auto_reload_sec/tip', MetaModel::GetConfig()->Get('min_reload_interval'))); $oPage->add_ready_script( << '', 'show_in_conf_sample' => false, ), + 'min_reload_interval' => array( + 'type' => 'integer', + 'description' => 'Minimum refresh interval (seconds) for dashboards, shortcuts, etc. Even if the interval is set programmatically, it is forced to that minimum', + 'default' => 5, // In iTop 2.0.3, this was the hardcoded value + 'value' => '', + 'source_of_value' => '', + 'show_in_conf_sample' => false, + ), ); public function IsProperty($sPropCode) diff --git a/dictionaries/dictionary.itop.ui.php b/dictionaries/dictionary.itop.ui.php index f61763546..2920dff31 100644 --- a/dictionaries/dictionary.itop.ui.php +++ b/dictionaries/dictionary.itop.ui.php @@ -1093,7 +1093,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:DashboardEdit:DashboardTitle' => 'Title', 'UI:DashboardEdit:AutoReload' => 'Automatic refresh', 'UI:DashboardEdit:AutoReloadSec' => 'Automatic refresh interval (seconds)', - 'UI:DashboardEdit:AutoReloadSec+' => 'The minimum allowed is 5 seconds', + 'UI:DashboardEdit:AutoReloadSec+' => 'The minimum allowed is %1$d seconds', 'UI:DashboardEdit:Layout' => 'Layout', 'UI:DashboardEdit:Properties' => 'Dashboard Properties', @@ -1193,7 +1193,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Disabled', 'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Custom rate', 'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Automatic refresh interval (seconds)', - 'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'The minimum allowed is 5 seconds', + 'Class:ShortcutOQL/Attribute:auto_reload_sec/tip' => 'The minimum allowed is %1$d seconds', 'UI:FillAllMandatoryFields' => 'Please fill all mandatory fields.', diff --git a/dictionaries/es_cr.dictionary.itop.ui.php b/dictionaries/es_cr.dictionary.itop.ui.php index 46e5368d1..f62005d29 100644 --- a/dictionaries/es_cr.dictionary.itop.ui.php +++ b/dictionaries/es_cr.dictionary.itop.ui.php @@ -1085,7 +1085,7 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden", 'UI:DashboardEdit:DashboardTitle' => 'Título', 'UI:DashboardEdit:AutoReload' => 'Actualización Automática', 'UI:DashboardEdit:AutoReloadSec' => 'Interválo de Actualización Automática (segundos)', - 'UI:DashboardEdit:AutoReloadSec+' => 'El interválo mínimo es de 5 segundos', + 'UI:DashboardEdit:AutoReloadSec+' => 'El interválo mínimo es de %1$d segundos', 'UI:DashboardEdit:Layout' => 'Distribución', 'UI:DashboardEdit:Properties' => 'Propiedades', 'UI:DashboardEdit:Dashlets' => 'Dashlets disponibles', @@ -1184,7 +1184,7 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden", 'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Deshabilitado', 'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Frecuencia configurable', 'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Interválo de Actualización Automática (segundos)', - 'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'El interválo mínimo es de 5 segundos', + 'Class:ShortcutOQL/Attribute:auto_reload_sec/tip' => 'El interválo mínimo es de %1$d segundos', 'UI:FillAllMandatoryFields' => 'Por favor llenar los campos obligatorios.', 'UI:CSVImportConfirmTitle' => 'Por favor confirme la operación', 'UI:CSVImportConfirmMessage' => '¿Está seguro?', diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 9fd8aebaf..62654acd6 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/dictionaries/fr.dictionary.itop.ui.php @@ -934,7 +934,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'UI:DashboardEdit:DashboardTitle' => 'Titre', 'UI:DashboardEdit:AutoReload' => 'Réactualisation automatique', 'UI:DashboardEdit:AutoReloadSec' => 'Réactualisation toutes les (secondes)', - 'UI:DashboardEdit:AutoReloadSec+' => 'Le minimum permis est de 5 secondes', + 'UI:DashboardEdit:AutoReloadSec+' => 'Le minimum permis est de %1$d secondes', 'UI:DashboardEdit:Layout' => 'Mise en page', 'UI:DashboardEdit:Properties' => 'Propriétés du tableau de bord', 'UI:DashboardEdit:Dashlets' => 'Indicateurs', @@ -1033,7 +1033,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé 'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Désactivée', 'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Personnalisée', 'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Réactualisation toutes les (secondes)', - 'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'Le minimum permis est de 5 secondes', + 'Class:ShortcutOQL/Attribute:auto_reload_sec/tip' => 'Le minimum permis est de %1$d secondes', 'UI:FillAllMandatoryFields' => 'Veuillez remplir tous les champs obligatoires.', diff --git a/dictionaries/pt_br.dictionary.itop.ui.php b/dictionaries/pt_br.dictionary.itop.ui.php index e094d7c18..5bf3528e6 100644 --- a/dictionaries/pt_br.dictionary.itop.ui.php +++ b/dictionaries/pt_br.dictionary.itop.ui.php @@ -1084,7 +1084,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'UI:DashboardEdit:DashboardTitle' => 'Título', 'UI:DashboardEdit:AutoReload' => 'Atualizar automaticamente', 'UI:DashboardEdit:AutoReloadSec' => 'Intervalo atualização automática (segundos)', - 'UI:DashboardEdit:AutoReloadSec+' => 'O mínimo permitido é 5 segundos', + 'UI:DashboardEdit:AutoReloadSec+' => 'O mínimo permitido é %1$d segundos', 'UI:DashboardEdit:Layout' => 'Layout', 'UI:DashboardEdit:Properties' => 'Propriedades', @@ -1184,7 +1184,7 @@ When associated with a trigger, each action is given an "order" number, specifyi 'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Desabilitado', 'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Avaliar', 'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Intervalo atualização automática (segundos)', - 'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'O mínimo permitido é 5 sgundos', + 'Class:ShortcutOQL/Attribute:auto_reload_sec/tip' => 'O mínimo permitido é %1$d sgundos', 'UI:FillAllMandatoryFields' => 'Por favor, preencha todos os campos obrigatórios.', 'UI:CSVImportConfirmTitle' => 'Por favor, confirme a operação', diff --git a/dictionaries/ru.dictionary.itop.ui.php b/dictionaries/ru.dictionary.itop.ui.php index e42c4e368..8e4f3c369 100644 --- a/dictionaries/ru.dictionary.itop.ui.php +++ b/dictionaries/ru.dictionary.itop.ui.php @@ -1077,7 +1077,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array( 'UI:DashboardEdit:DashboardTitle' => 'Заголовок', 'UI:DashboardEdit:AutoReload' => 'Обновлять автоматически', 'UI:DashboardEdit:AutoReloadSec' => 'Интервал обновления (секунды)', - 'UI:DashboardEdit:AutoReloadSec+' => 'Минимальный интервал 5 секунд', + 'UI:DashboardEdit:AutoReloadSec+' => 'Минимальный интервал %1$d секунд', 'UI:DashboardEdit:Layout' => 'Макет', 'UI:DashboardEdit:Properties' => 'Свойства дашборда', @@ -1177,7 +1177,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', array( 'Class:ShortcutOQL/Attribute:auto_reload/Value:none' => 'Disabled', 'Class:ShortcutOQL/Attribute:auto_reload/Value:custom' => 'Custom rate', 'Class:ShortcutOQL/Attribute:auto_reload_sec' => 'Automatic refresh interval (seconds)', - 'Class:ShortcutOQL/Attribute:auto_reload_sec+' => 'The minimum allowed is 5 seconds', + 'Class:ShortcutOQL/Attribute:auto_reload_sec/tip' => 'The minimum allowed is %1$d seconds', 'UI:FillAllMandatoryFields' => 'Пожалуйста, заполните все обязательные поля.', diff --git a/js/property_field.js b/js/property_field.js index 1a6e33e0b..7ffe413e4 100644 --- a/js/property_field.js +++ b/js/property_field.js @@ -272,6 +272,77 @@ function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbidden } } +function ValidateInteger(sFieldId, bMandatory, sFormId, iMin, iMax, sExplainFormat) +{ + var currentVal = $('#'+sFieldId).val(); + var bValid = true; + var sMessage = null; + + if (bMandatory && (currentVal == '')) + { + bValid = false; + } + + re = new RegExp('^$|^-?[0-9]+$'); + bValid = re.test(currentVal); + + if (bValid && (currentVal != '')) + { + // It is a valid number, let's check the boundaries + var iValue = parseInt(currentVal, 10); + + if ((iMin != null) && (iValue < iMin)) + { + bValid = false; + } + + if ((iMax != null) && (iValue > iMax)) + { + bValid = false; + } + + if (!bValid && (sExplainFormat != undefined)) + { + sMessage = sExplainFormat; + } + } + + if (oFormValidation[sFormId] == undefined) oFormValidation[sFormId] = []; + if (!bValid) + { + $('#v_'+sFieldId).addClass('ui-state-error'); + iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]); + if (iFieldIdPos == -1) + { + oFormValidation[sFormId].push(sFieldId); + } + if (sMessage) + { + $('#'+sFieldId).attr('title', sMessage).tooltip(); + if ($('#'+sFieldId).is(":focus")) + { + $('#'+sFieldId).tooltip('open'); + } + } + } + else + { + $('#v_'+sFieldId).removeClass('ui-state-error'); + if ($('#'+sFieldId).data('uiTooltip')) + { + $('#'+sFieldId).tooltip('close'); + } + $('#'+sFieldId).removeAttr('title'); + // Remove the element from the array + iFieldIdPos = jQuery.inArray(sFieldId, oFormValidation[sFormId]); + if (iFieldIdPos > -1) + { + oFormValidation[sFormId].splice(iFieldIdPos, 1); + } + } +} + + function ValidateForm(sFormId, bValidateAll) { oFormValidation[sFormId] = []; diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 3bb593c4d..6f93f5281 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -1020,7 +1020,7 @@ EOF $iAutoReload = (int)$aValues['auto_reload_sec']; if (($aValues['auto_reload']) && ($iAutoReload > 0)) { - $oShortcut->Set("auto_reload_sec", max(5, $iAutoReload)); + $oShortcut->Set("auto_reload_sec", max(MetaModel::GetConfig()->Get('min_reload_interval'), $iAutoReload)); $oShortcut->Set("auto_reload", 'custom'); } $iId = $oShortcut->DBInsertNoReload();