mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-14 16:04:10 +01:00
Compare commits
32 Commits
feature/25
...
support/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a7c17b80a | ||
|
|
0682f9f3b1 | ||
|
|
b2b0ab9eff | ||
|
|
000dd3726d | ||
|
|
0a8419c1d8 | ||
|
|
61fb800f23 | ||
|
|
ea7a8888e9 | ||
|
|
1e66220077 | ||
|
|
ad3178d02e | ||
|
|
028d4b52e4 | ||
|
|
6d4a78db20 | ||
|
|
457ee5de64 | ||
|
|
9bec433e94 | ||
|
|
895a5fc5b0 | ||
|
|
4c735a6dff | ||
|
|
5fd193885e | ||
|
|
9277184ba0 | ||
|
|
aa0bd6c1ea | ||
|
|
d8382a541c | ||
|
|
5e3eab90a6 | ||
|
|
2c4c6a6690 | ||
|
|
5e600c88a7 | ||
|
|
3c4057d546 | ||
|
|
9071f340a8 | ||
|
|
5cb9363cce | ||
|
|
9dd4b05866 | ||
|
|
4841738f01 | ||
|
|
8632d5597a | ||
|
|
01e4f6af79 | ||
|
|
0a2cdff528 | ||
|
|
b5166938df | ||
|
|
441b059581 |
@@ -941,12 +941,12 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
return $oDataTable->Display($oPage, $oSettings, $bDisplayMenu, $sSelectMode, $bViewLink, $aExtraParams);
|
||||
}
|
||||
|
||||
static function DisplaySetAsCSV(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array())
|
||||
static function DisplaySetAsCSV(WebPage $oPage, CMDBObjectSet $oSet, $aParams = array(), $sCharset = 'UTF-8')
|
||||
{
|
||||
$oPage->add(self::GetSetAsCSV($oSet, $aParams));
|
||||
$oPage->add(self::GetSetAsCSV($oSet, $aParams, $sCharset));
|
||||
}
|
||||
|
||||
static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array())
|
||||
static function GetSetAsCSV(DBObjectSet $oSet, $aParams = array(), $sCharset = 'UTF-8')
|
||||
{
|
||||
$sSeparator = isset($aParams['separator']) ? $aParams['separator'] : ','; // default separator is comma
|
||||
$sTextQualifier = isset($aParams['text_qualifier']) ? $aParams['text_qualifier'] : '"'; // default text qualifier is double quote
|
||||
@@ -1064,7 +1064,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
else
|
||||
{
|
||||
$value = $oObj->Get($sAttCodeEx);
|
||||
$aRow[] = $oAttDef->GetAsCSV($value, $sSeparator, $sTextQualifier, $oObj, $bLocalize);
|
||||
$sCSVValue = $oAttDef->GetAsCSV($value, $sSeparator, $sTextQualifier, $oObj, $bLocalize);
|
||||
$aRow[] = iconv('UTF-8', $sCharset.'//IGNORE//TRANSLIT', $sCSVValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1436,20 +1437,24 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
}
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode);
|
||||
if ($oAttDef->IsExternalKey())
|
||||
if ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE))
|
||||
{
|
||||
$sTargetClass = $oAttDef->GetTargetClass();
|
||||
$oKeyAttDef = $oAttDef->GetFinalAttDef();
|
||||
$sKeyAttClass = $oKeyAttDef->GetHostClass();
|
||||
$sKeyAttCode = $oKeyAttDef->GetCode();
|
||||
|
||||
$sTargetClass = $oKeyAttDef->GetTargetClass();
|
||||
$oSearch = new DBObjectSearch($sTargetClass);
|
||||
$oSearch->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true);
|
||||
$oAllowedValues = new DBObjectSet($oSearch);
|
||||
|
||||
$iFieldSize = $oAttDef->GetMaxSize();
|
||||
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
|
||||
$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label> ";
|
||||
$iFieldSize = $oKeyAttDef->GetMaxSize();
|
||||
$iMaxComboLength = $oKeyAttDef->GetMaximumComboLength();
|
||||
$sHtml .= "<label>".MetaModel::GetFilterLabel($sKeyAttClass, $sKeyAttCode).":</label> ";
|
||||
$aExtKeyParams = $aExtraParams;
|
||||
$aExtKeyParams['iFieldSize'] = $oAttDef->GetMaxSize();
|
||||
$aExtKeyParams['iMinChars'] = $oAttDef->GetMinAutoCompleteChars();
|
||||
$sHtml .= UIExtKeyWidget::DisplayFromAttCode($oPage, $sFilterCode, $sClassName, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sSearchFormId.'search_'.$sFilterCode, false, $sFilterCode, '', $aExtKeyParams, true);
|
||||
$aExtKeyParams['iFieldSize'] = $oKeyAttDef->GetMaxSize();
|
||||
$aExtKeyParams['iMinChars'] = $oKeyAttDef->GetMinAutoCompleteChars();
|
||||
$sHtml .= UIExtKeyWidget::DisplayFromAttCode($oPage, $sKeyAttCode, $sKeyAttClass, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sSearchFormId.'search_'.$sFilterCode, false, $sFilterCode, '', $aExtKeyParams, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3074,7 +3079,7 @@ EOF
|
||||
|
||||
// Attribute is read-only
|
||||
$sHTMLValue = $this->GetAsHTML($sAttCode);
|
||||
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.htmlentities($this->Get($sAttCode), ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.htmlentities($this->GetEditValue($sAttCode), ENT_QUOTES, 'UTF-8').'"/>';
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
$sComment .= $sSynchroIcon;
|
||||
}
|
||||
@@ -3251,7 +3256,11 @@ EOF
|
||||
$currValue = $aKeys[0]; // The only value is the first key
|
||||
//echo "<p>current value for $sAttCode : $currValue</p>";
|
||||
$oDummyObj->Set($sAttCode, $currValue);
|
||||
$aComments[$sAttCode] = '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$aComments[$sAttCode] = '';
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass))
|
||||
{
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" checked id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="mono_value">1</div>';
|
||||
}
|
||||
else
|
||||
@@ -3278,7 +3287,11 @@ EOF
|
||||
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
|
||||
|
||||
$oDummyObj->Set($sAttCode, null);
|
||||
$aComments[$sAttCode] = '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
$aComments[$sAttCode] = '';
|
||||
if ($sAttCode != MetaModel::GetStateAttributeCode($sClass))
|
||||
{
|
||||
$aComments[$sAttCode] .= '<input type="checkbox" id="enable_'.$iFormId.'_'.$sAttCode.'" onClick="ToogleField(this.checked, \''.$iFormId.'_'.$sAttCode.'\')"/>';
|
||||
}
|
||||
$aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_'.$sAttCode.'">'.$iCount.'</div>';
|
||||
}
|
||||
$sReadyScript .= 'ToogleField('.(($iCount == 1) ? 'true': 'false').', \''.$iFormId.'_'.$sAttCode.'\');'."\n";
|
||||
|
||||
@@ -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)
|
||||
@@ -312,7 +312,7 @@ abstract class Dashboard
|
||||
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oPage->add('<h1>'.Dict::S($this->sTitle).'</h1>');
|
||||
$oPage->add('<h1>'.htmlentities(Dict::S($this->sTitle), ENT_QUOTES, 'UTF-8', false).'</h1>');
|
||||
$oLayout = new $this->sLayoutClass;
|
||||
$oLayout->Render($oPage, $this->aCells, $bEditMode, $aExtraParams);
|
||||
if (!$bEditMode)
|
||||
@@ -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('</div>');
|
||||
|
||||
$sRateTitle = addslashes(Dict::S('UI:DashboardEdit:AutoReloadSec+'));
|
||||
$sRateTitle = addslashes(Dict::Format('UI:DashboardEdit:AutoReloadSec+', MetaModel::GetConfig()->Get('min_reload_interval')));
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
// Note: the title gets deleted by the validation mechanism
|
||||
|
||||
@@ -506,11 +506,19 @@ abstract class DashletGroupBy extends Dashlet
|
||||
$sGroupBy = $this->aProperties['group_by'];
|
||||
$sStyle = $this->aProperties['style'];
|
||||
|
||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||
$sClass = $oQuery->GetClass();
|
||||
$sClassAlias = $oQuery->GetClassAlias();
|
||||
|
||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||
try
|
||||
{
|
||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||
$sClass = $oQuery->GetClass();
|
||||
$sClassAlias = $oQuery->GetClassAlias();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Invalid query, let the user edit the dashlet/dashboard anyhow
|
||||
$sClass = '';
|
||||
$sClassAlias = '';
|
||||
}
|
||||
// Check groupby... it can be wrong at this stage
|
||||
if (preg_match('/^(.*):(.*)$/', $sGroupBy, $aMatches))
|
||||
{
|
||||
|
||||
@@ -551,6 +551,7 @@ EOF;
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
var oTable = $('#{$this->iListId} table.listResults');
|
||||
oTable.tableHover();
|
||||
oTable.tablesorter( { $sHeaders widgets: ['myZebra', 'truncatedList']} ).tablesorterPager({container: $('#pager{$this->iListId}'), totalRows:$iCount, size: $iPageSize, filter: '$sOQL', extra_params: '$sExtraParams', select_mode: '$sSelectModeJS', displayKey: $sDisplayKey, columns: $sJSColumns, class_aliases: $sJSClassAliases $sCssCount});
|
||||
EOF
|
||||
);
|
||||
|
||||
@@ -226,7 +226,7 @@ class DisplayBlock
|
||||
if (is_numeric($aExtraParams['auto_reload']) && ($aExtraParams['auto_reload'] > 0))
|
||||
{
|
||||
$bAutoReload = true;
|
||||
$iReloadInterval = max(5, $aExtraParams['auto_reload'])*1000;
|
||||
$iReloadInterval = max(MetaModel::GetConfig()->Get('min_reload_interval'), $aExtraParams['auto_reload'])*1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -783,7 +783,8 @@ class DisplayBlock
|
||||
$sLinkToToggle = $sLinkToToggle.'&advanced=1';
|
||||
$sChecked = '';
|
||||
}
|
||||
|
||||
$sAjaxLink = $sDownloadLink.'&charset=UTF-8'; // Includes &fields_advanced=1 if in advanced mode
|
||||
|
||||
/*
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($this->m_oSet, array('fields_advanced' => $bAdvancedMode));
|
||||
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
|
||||
@@ -833,7 +834,7 @@ class DisplayBlock
|
||||
$sHtml .= "<div id=\"csv_content_loading\"><div style=\"width: 250px; height: 20px; background: url(../setup/orange-progress.gif); border: 1px #999 solid; margin-left:auto; margin-right: auto; text-align: center;\">".Dict::S('UI:Loading')."</div></div><textarea id=\"csv_content\" style=\"display:none;\">\n";
|
||||
//$sHtml .= htmlentities($sCSVData, ENT_QUOTES, 'UTF-8');
|
||||
$sHtml .= "</textarea>\n";
|
||||
$oPage->add_ready_script("$.post('$sDownloadLink', {}, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
$oPage->add_ready_script("$.post('$sAjaxLink', {}, function(data) { $('#csv_content').html(data); $('#csv_content_loading').hide(); $('#csv_content').show();} );");
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
|
||||
@@ -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 = "<span>".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."<input type=\"hidden\" id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."\"/></span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMin = json_encode($this->iMin);
|
||||
$sMax = json_encode($this->iMax);
|
||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$('#$sId').bind('change keyup validate', function() { ValidateInteger('$sId', $sMandatory, '$sFormId', $sMin, $sMax); } );
|
||||
{
|
||||
var myTimer = null;
|
||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$sCSSClasses = '';
|
||||
if (count($this->aCSSClasses) > 0)
|
||||
{
|
||||
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
||||
}
|
||||
$sHtmlValue = "<input type=\"text\" $sCSSClasses id=\"$sId\" name=\"$sName\" value=\"".htmlentities($this->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;
|
||||
|
||||
@@ -305,16 +305,20 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
$this->add("<p>".Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)."</p>\n");
|
||||
}
|
||||
elseif ($oUser->Get('reset_pwd_token') != $sToken)
|
||||
{
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Error-InvalidToken')."</p>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add("<p>".Dict::Format('UI:ResetPwd-Error-EnterPassword', $oUser->GetFriendlyName())."</p>\n");
|
||||
|
||||
$sInconsistenPwdMsg = Dict::S('UI:Login:RetypePwdDoesNotMatch');
|
||||
$this->add_script(
|
||||
$oEncryptedToken = $oUser->Get('reset_pwd_token');
|
||||
|
||||
if (!$oEncryptedToken->CheckPassword($sToken))
|
||||
{
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Error-InvalidToken')."</p>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add("<p>".Dict::Format('UI:ResetPwd-Error-EnterPassword', $oUser->GetFriendlyName())."</p>\n");
|
||||
|
||||
$sInconsistenPwdMsg = Dict::S('UI:Login:RetypePwdDoesNotMatch');
|
||||
$this->add_script(
|
||||
<<<EOF
|
||||
function DoCheckPwd()
|
||||
{
|
||||
@@ -326,18 +330,19 @@ function DoCheckPwd()
|
||||
return true;
|
||||
}
|
||||
EOF
|
||||
);
|
||||
$this->add("<form method=\"post\">\n");
|
||||
$this->add("<table>\n");
|
||||
$this->add("<tr><td style=\"text-align:right\"><label for=\"new_pwd\">".Dict::S('UI:Login:NewPasswordPrompt').":</label></td><td style=\"text-align:left\"><input type=\"password\" id=\"new_pwd\" name=\"new_pwd\" value=\"\" /></td></tr>\n");
|
||||
$this->add("<tr><td style=\"text-align:right\"><label for=\"retype_new_pwd\">".Dict::S('UI:Login:RetypeNewPasswordPrompt').":</label></td><td style=\"text-align:left\"><input type=\"password\" id=\"retype_new_pwd\" name=\"retype_new_pwd\" value=\"\" /></td></tr>\n");
|
||||
$this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"><span class=\"btn_border\"><input type=\"submit\" onClick=\"return DoCheckPwd();\" value=\"".Dict::S('UI:Button:ChangePassword')."\" /></span></td></tr>\n");
|
||||
$this->add("</table>\n");
|
||||
$this->add("<input type=\"hidden\" name=\"loginop\" value=\"do_reset_pwd\" />\n");
|
||||
$this->add("<input type=\"hidden\" name=\"auth_user\" value=\"".htmlentities($sAuthUser, ENT_QUOTES, 'UTF-8')."\" />\n");
|
||||
$this->add("<input type=\"hidden\" name=\"token\" value=\"".htmlentities($sToken, ENT_QUOTES, 'UTF-8')."\" />\n");
|
||||
$this->add("</form>\n");
|
||||
$this->add("</div\n");
|
||||
);
|
||||
$this->add("<form method=\"post\">\n");
|
||||
$this->add("<table>\n");
|
||||
$this->add("<tr><td style=\"text-align:right\"><label for=\"new_pwd\">".Dict::S('UI:Login:NewPasswordPrompt').":</label></td><td style=\"text-align:left\"><input type=\"password\" id=\"new_pwd\" name=\"new_pwd\" value=\"\" /></td></tr>\n");
|
||||
$this->add("<tr><td style=\"text-align:right\"><label for=\"retype_new_pwd\">".Dict::S('UI:Login:RetypeNewPasswordPrompt').":</label></td><td style=\"text-align:left\"><input type=\"password\" id=\"retype_new_pwd\" name=\"retype_new_pwd\" value=\"\" /></td></tr>\n");
|
||||
$this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"><span class=\"btn_border\"><input type=\"submit\" onClick=\"return DoCheckPwd();\" value=\"".Dict::S('UI:Button:ChangePassword')."\" /></span></td></tr>\n");
|
||||
$this->add("</table>\n");
|
||||
$this->add("<input type=\"hidden\" name=\"loginop\" value=\"do_reset_pwd\" />\n");
|
||||
$this->add("<input type=\"hidden\" name=\"auth_user\" value=\"".htmlentities($sAuthUser, ENT_QUOTES, 'UTF-8')."\" />\n");
|
||||
$this->add("<input type=\"hidden\" name=\"token\" value=\"".htmlentities($sToken, ENT_QUOTES, 'UTF-8')."\" />\n");
|
||||
$this->add("</form>\n");
|
||||
$this->add("</div\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,21 +362,25 @@ EOF
|
||||
{
|
||||
$this->add("<p>".Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser)."</p>\n");
|
||||
}
|
||||
elseif ($oUser->Get('reset_pwd_token') != $sToken)
|
||||
{
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Error-InvalidToken')."</p>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trash the token and change the password
|
||||
$oUser->Set('reset_pwd_token', '');
|
||||
$oUser->SetPassword($sNewPwd); // Does record the change into the DB
|
||||
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Ready')."</p>");
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$this->add("<p><a href=\"$sUrl\">".Dict::S('UI:ResetPwd-Login')."</a></p>");
|
||||
$oEncryptedPassword = $oUser->Get('reset_pwd_token');
|
||||
if (!$oEncryptedPassword->CheckPassword($sToken))
|
||||
{
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Error-InvalidToken')."</p>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trash the token and change the password
|
||||
$oUser->Set('reset_pwd_token', '');
|
||||
$oUser->SetPassword($sNewPwd); // Does record the change into the DB
|
||||
|
||||
$this->add("<p>".Dict::S('UI:ResetPwd-Ready')."</p>");
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$this->add("<p><a href=\"$sUrl\">".Dict::S('UI:ResetPwd-Login')."</a></p>");
|
||||
}
|
||||
$this->add("</div\n");
|
||||
}
|
||||
$this->add("</div\n");
|
||||
}
|
||||
|
||||
public function DisplayChangePwdForm($bFailedLogin = false)
|
||||
|
||||
@@ -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(
|
||||
<<<EOF
|
||||
|
||||
@@ -28,10 +28,11 @@ require_once(APPROOT.'/core/cmdbobject.class.inc.php');
|
||||
require_once(APPROOT.'/application/utils.inc.php');
|
||||
session_name('itop-'.md5(APPROOT));
|
||||
session_start();
|
||||
if (isset($_REQUEST['switch_env']))
|
||||
$sSwitchEnv = utils::ReadParam('switch_env', null);
|
||||
if (($sSwitchEnv != null) && (file_exists(APPCONF.$sSwitchEnv.'/'.ITOP_CONFIG_FILE)))
|
||||
{
|
||||
$sEnv = $_REQUEST['switch_env'];
|
||||
$_SESSION['itop_env'] = $sEnv;
|
||||
$_SESSION['itop_env'] = $sSwitchEnv;
|
||||
$sEnv = $sSwitchEnv;
|
||||
// TODO: reset the credentials as well ??
|
||||
}
|
||||
else if (isset($_SESSION['itop_env']))
|
||||
|
||||
@@ -239,7 +239,7 @@ EOF
|
||||
*/
|
||||
protected function DisplayFormTable(WebPage $oP, $aConfig, $aData)
|
||||
{
|
||||
$sHtml = '';
|
||||
$sHtml = "<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\">";
|
||||
$sHtml .= "<table class=\"listResults\">\n";
|
||||
// Header
|
||||
$sHtml .= "<thead>\n";
|
||||
@@ -259,11 +259,11 @@ EOF
|
||||
$sEmptyRowStyle = 'style="display:none;"';
|
||||
}
|
||||
|
||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."<input type=\"hidden\" name=\"attr_{$this->m_sAttCode}{$this->m_sNameSuffix}\" value=\"\"></td></td>";
|
||||
foreach($aData as $iRowId => $aRow)
|
||||
{
|
||||
$sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId);
|
||||
}
|
||||
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
|
||||
$sHtml .= "</tbody>\n";
|
||||
|
||||
// Footer
|
||||
|
||||
@@ -91,6 +91,9 @@ abstract class AsyncTask extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("event_id", array("targetclass"=>"Event", "jointype"=> "", "allowed_values"=>null, "sql"=>"event_id", "is_null_allowed"=>true, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("remaining_retries", array("allowed_values"=>null, "sql"=>"remaining_retries", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("last_error_code", array("allowed_values"=>null, "sql"=>"last_error_code", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("last_attempt", array("allowed_values"=>null, "sql"=>"last_attempt", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,27 +120,34 @@ abstract class AsyncTask extends DBObject
|
||||
{
|
||||
try
|
||||
{
|
||||
$this->Set('status', 'running');
|
||||
$this->Set('started', time());
|
||||
$this->DBUpdate();
|
||||
return self::OK;
|
||||
if ($this->Get('status') == 'running')
|
||||
{
|
||||
return self::ALREADY_RUNNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->Set('status', 'running');
|
||||
$this->Set('started', time());
|
||||
$this->DBUpdate();
|
||||
return self::OK;
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Corrupted task !! (for example: "Failed to reload object")
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - fatal error, deleting the task.');
|
||||
if ($this->Get('event_id') != 0)
|
||||
{
|
||||
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
|
||||
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
|
||||
$oEventLog->DBUpdate();
|
||||
if ($this->Get('event_id') != 0)
|
||||
{
|
||||
$oEventLog = MetaModel::GetObject('Event', $this->Get('event_id'));
|
||||
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
|
||||
$oEventLog->DBUpdate();
|
||||
}
|
||||
$this->DBDelete();
|
||||
return self::DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
public function GetRetryDelay()
|
||||
public function GetRetryDelay($iErrorCode = null)
|
||||
{
|
||||
$iRetryDelay = 600;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
@@ -149,7 +159,7 @@ abstract class AsyncTask extends DBObject
|
||||
return $iRetryDelay;
|
||||
}
|
||||
|
||||
public function GetMaxRetries()
|
||||
public function GetMaxRetries($iErrorCode = null)
|
||||
{
|
||||
$iMaxRetries = 0;
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
@@ -160,10 +170,16 @@ abstract class AsyncTask extends DBObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to notify people that a task cannot be performed
|
||||
*/
|
||||
protected function OnDefinitiveFailure()
|
||||
{
|
||||
}
|
||||
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->Set('created', time());
|
||||
$this->Set('remaining_retries', $this->GetMaxRetries());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,22 +207,7 @@ abstract class AsyncTask extends DBObject
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$iRemaining = $this->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$iRetryDelay = $this->GetRetryDelay();
|
||||
IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage().' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$this->Set('remaining_retries', $iRemaining - 1);
|
||||
$this->Set('status', 'planned');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', time() + $iRetryDelay);
|
||||
$this->DBUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$e->getMessage());
|
||||
}
|
||||
$this->HandleError($e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -217,7 +218,56 @@ abstract class AsyncTask extends DBObject
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridable to extend the behavior in case of error (logging)
|
||||
*/
|
||||
protected function HandleError($sErrorMessage, $iErrorCode)
|
||||
{
|
||||
if ($this->Get('last_attempt') == '')
|
||||
{
|
||||
// First attempt
|
||||
$this->Set('remaining_retries', $this->GetMaxRetries($iErrorCode));
|
||||
}
|
||||
|
||||
$this->Set('last_error', $sErrorMessage);
|
||||
$this->Set('last_error_code', $iErrorCode); // Note: can be ZERO !!!
|
||||
$this->Set('last_attempt', time());
|
||||
|
||||
$iRemaining = $this->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$iRetryDelay = $this->GetRetryDelay($iErrorCode);
|
||||
IssueLog::Info('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage.' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$this->Set('remaining_retries', $iRemaining - 1);
|
||||
$this->Set('status', 'planned');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', time() + $iRetryDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$this->GetKey().' - reason: '.$sErrorMessage);
|
||||
|
||||
$this->Set('status', 'error');
|
||||
$this->Set('started', null);
|
||||
$this->Set('planned', null);
|
||||
$this->OnDefinitiveFailure();
|
||||
}
|
||||
$this->DBUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception (message and code)
|
||||
*/
|
||||
abstract public function DoProcess();
|
||||
|
||||
/**
|
||||
* Describes the error codes that DoProcess can return by the mean of exceptions
|
||||
*/
|
||||
static public function EnumErrorCodes()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -432,7 +432,7 @@ class BulkChange
|
||||
break;
|
||||
|
||||
default:
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $oExtObjects->Count());
|
||||
$aErrors[$sAttCode] = Dict::Format('UI:CSVReport-Value-Issue-FoundMany', $iCount);
|
||||
$aResults[$sAttCode]= new CellStatus_Ambiguous($oTargetObj->Get($sAttCode), $iCount, $sOQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,38 +428,38 @@ abstract class CMDBObject extends DBObject
|
||||
}
|
||||
|
||||
|
||||
public function DBInsert()
|
||||
{
|
||||
return $this->DBInsertTracked_Internal();
|
||||
}
|
||||
|
||||
public function DBInsertTracked(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
||||
{
|
||||
self::SetCurrentChange($oChange);
|
||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||
|
||||
$ret = $this->DBInsertTracked_Internal();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public function DBInsertTrackedNoReload(CMDBChange $oChange, $bSkipStrongSecurity = null)
|
||||
{
|
||||
self::SetCurrentChange($oChange);
|
||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||
|
||||
$ret = $this->DBInsertTracked_Internal(true);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To Be Obsoleted: DO NOT rely on an overload of this method since
|
||||
* DBInsertTracked (resp. DBInsertTrackedNoReload) may call directly
|
||||
* DBInsert (resp. DBInsertNoReload) in future versions of iTop.
|
||||
* @param bool $bDoNotReload
|
||||
* @return integer Identifier of the created object
|
||||
*/
|
||||
protected function DBInsertTracked_Internal($bDoNotReload = false)
|
||||
{
|
||||
if ($bDoNotReload)
|
||||
{
|
||||
$ret = parent::DBInsertNoReload();
|
||||
$ret = $this->DBInsertNoReload();
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = parent::DBInsert();
|
||||
$ret = $this->DBInsert();
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class CMDBSource
|
||||
// Override the default port
|
||||
$sServer = $aConnectInfo[0];
|
||||
$iPort = (int)$aConnectInfo[1];
|
||||
self::$m_oMysqli = new mysqli(self::$m_sDBHost, self::$m_sDBUser, self::$m_sDBPwd, '', $iPort);
|
||||
self::$m_oMysqli = new mysqli($sServer, self::$m_sDBUser, self::$m_sDBPwd, '', $iPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -769,6 +769,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'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)
|
||||
|
||||
@@ -654,7 +654,11 @@ class DBObjectSet
|
||||
else
|
||||
{
|
||||
// Pick the row from the objects added *in memory*
|
||||
$oRetObj = $this->m_aAddedObjects[$this->m_iCurrRow - $this->m_iNumLoadedDBRows][$sRequestedClassAlias];
|
||||
$aRetObjects = array();
|
||||
foreach ($this->m_oFilter->GetSelectedClasses() as $sClassAlias => $sClass)
|
||||
{
|
||||
$aRetObjects[$sClassAlias] = $this->m_aAddedObjects[$this->m_iCurrRow - $this->m_iNumLoadedDBRows][$sClassAlias];
|
||||
}
|
||||
}
|
||||
$this->m_iCurrRow++;
|
||||
return $aRetObjects;
|
||||
@@ -1094,8 +1098,11 @@ class DBObjectSet
|
||||
{
|
||||
foreach($aVals as $sCode => $oExpr)
|
||||
{
|
||||
$oScalarExpr = $oExpr->GetAsScalar($aScalarArgs);
|
||||
$aConst[$sClassAlias][$sCode] = $oScalarExpr->GetValue();
|
||||
if (is_object($oExpr)) // Array_merge_recursive creates an array when the same key is present multiple times... ignore them
|
||||
{
|
||||
$oScalarExpr = $oExpr->GetAsScalar($aScalarArgs);
|
||||
$aConst[$sClassAlias][$sCode] = $oScalarExpr->GetValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aConst;
|
||||
|
||||
@@ -351,7 +351,7 @@ class EventLoginUsage extends Event
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "jointype"=> "", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
$aZList = array('date', 'user_id');
|
||||
if (MetaModel::IsValidAttCode('Contact', 'name'))
|
||||
{
|
||||
|
||||
@@ -299,14 +299,11 @@ class BinaryExpression extends Expression
|
||||
{
|
||||
$aResult[$this->m_oRightExpr->GetParent()][$this->m_oRightExpr->GetName()] = $this->m_oLeftExpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult = array_merge($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields()) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if ($this->m_sOperator == 'AND')
|
||||
{
|
||||
$aResult = array_merge($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields()) ;
|
||||
// Strictly, this should be done only for the AND operator
|
||||
$aResult = array_merge_recursive($this->m_oRightExpr->ListConstantFields(), $this->m_oLeftExpr->ListConstantFields());
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
@@ -835,6 +835,10 @@ abstract class MetaModel
|
||||
final static public function GetAttributeDef($sClass, $sAttCode)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
if (!isset(self::$m_aAttribDefs[$sClass][$sAttCode]))
|
||||
{
|
||||
throw new Exception("Unknown attribute $sAttCode from class $sClass");
|
||||
}
|
||||
return self::$m_aAttribDefs[$sClass][$sAttCode];
|
||||
}
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ class ormCaseLog {
|
||||
}
|
||||
|
||||
|
||||
public function AddLogEntryFromJSON($oJson)
|
||||
public function AddLogEntryFromJSON($oJson, $bCheckUserId = true)
|
||||
{
|
||||
$sText = isset($oJson->message) ? $oJson->message : '';
|
||||
|
||||
@@ -394,16 +394,24 @@ class ormCaseLog {
|
||||
{
|
||||
throw new Exception("Only administrators can set the user id", RestResult::UNAUTHORIZED);
|
||||
}
|
||||
try
|
||||
if ($bCheckUserId)
|
||||
{
|
||||
$oUser = RestUtils::FindObjectFromKey('User', $oJson->user_id);
|
||||
try
|
||||
{
|
||||
$oUser = RestUtils::FindObjectFromKey('User', $oJson->user_id);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
throw new Exception('user_id: '.$e->getMessage(), $e->getCode());
|
||||
}
|
||||
$iUserId = $oUser->GetKey();
|
||||
$sOnBehalfOf = $oUser->GetFriendlyName();
|
||||
}
|
||||
catch(Exception $e)
|
||||
else
|
||||
{
|
||||
throw new Exception('user_id: '.$e->getMessage(), $e->getCode());
|
||||
$iUserId = $oJson->user_id;
|
||||
$sOnBehalfOf = $oJson->user_login;
|
||||
}
|
||||
$iUserId = $oUser->GetKey();
|
||||
$sOnBehalfOf = $oUser->GetFriendlyName();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -371,7 +371,7 @@ abstract class UserInternal extends User
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// When set, this token allows for password reset
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reset_pwd_token", array("allowed_values"=>null, "sql"=>"reset_pwd_token", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeOneWayPassword("reset_pwd_token", array("allowed_values"=>null, "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('contactid', 'first_name', 'email', 'login', 'language', 'profile_list', 'allowed_org_list')); // Attributes to be displayed for the complete details
|
||||
|
||||
@@ -440,7 +440,6 @@ EOF
|
||||
);
|
||||
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
|
||||
$oPage->p('<input type="hidden" id="attachment_plugin" name="attachment_plugin"/>');
|
||||
$oPage->add('</fieldset>');
|
||||
if ($this->m_bDeleteEnabled)
|
||||
{
|
||||
$oPage->add_ready_script('$(".attachment").hover( function() {$(this).children(":button").toggleClass("btn_hidden"); } );');
|
||||
@@ -466,7 +465,9 @@ EOF
|
||||
$oPage->add('<div class="attachment" id="attachment_'.$iAttId.'"><a data-preview="'.$sPreview.'" href="'.$sDownloadLink.'"><img src="'.$sIcon.'"><br/>'.$sFileName.'</a><input type="hidden" name="attachments[]" value="'.$iAttId.'"/><br/> </div>');
|
||||
}
|
||||
}
|
||||
$oPage->add('</span>');
|
||||
}
|
||||
$oPage->add('</fieldset>');
|
||||
$sPreviewNotAvailable = addslashes(Dict::S('Attachments:PreviewNotAvailable'));
|
||||
$oPage->add_ready_script("$(document).tooltip({ items: '.attachment a', position: { my: 'left top', at: 'right top', using: function( position, feedback ) { $( this ).css( position ); }}, content: function() { if ($(this).attr('data-preview') == 'true') { return('<img style=\"max-width:290px\" src=\"'+$(this).attr('href')+'\"></img>');} else { return '$sPreviewNotAvailable'; }}});");
|
||||
}
|
||||
|
||||
@@ -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.',
|
||||
|
||||
|
||||
@@ -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?',
|
||||
|
||||
@@ -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.',
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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' => 'Пожалуйста, заполните все обязательные поля.',
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ $(function()
|
||||
this.datatable.tableHover();
|
||||
this.datatable.find('.selectList'+this.id).bind('change', function() { me._updateButtons(); });
|
||||
},
|
||||
_updateDlgSize: function()
|
||||
_updateDlgPosition: function()
|
||||
{
|
||||
this.oDlg.dialog('option', { position: { my: "center", at: "center", of: window }});
|
||||
},
|
||||
@@ -171,7 +171,7 @@ $(function()
|
||||
});
|
||||
me.indicator.html('');
|
||||
me.oButtons['create'].removeAttr('disabled');
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
});
|
||||
},
|
||||
_selectToAdd: function()
|
||||
@@ -197,20 +197,23 @@ $(function()
|
||||
me.oDlg.find('form').removeAttr('onsubmit').bind('submit', function() { me._onSearchToAdd(); return false; } );
|
||||
me.oDlg.find('button.cancel').unbind('click').click( function() { me.oDlg.dialog('close'); } );
|
||||
me.oDlg.find('button.ok').unbind('click').click( function() { me._onDoAdd(); } );
|
||||
$('#SearchFormToAdd_'+me.id).resize(function() { me._onSearchDlgUpdateSize(); });
|
||||
|
||||
me.oDlg.dialog({
|
||||
title: me.options.labels['selection_title'],
|
||||
modal: true,
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
width: $(window).width()*0.8,
|
||||
height: $(window).height()*0.8,
|
||||
maxHeight: $(window).height() - 50,
|
||||
position: { my: "center", at: "center", of: window },
|
||||
close: function() { me._onDlgClose(); }
|
||||
close: function() { me._onDlgClose(); },
|
||||
resizeStop: function() { me._onSearchDlgUpdateSize(); }
|
||||
});
|
||||
me.indicator.html('');
|
||||
me.oButtons['add'].removeAttr('disabled');
|
||||
me._onSearchToAdd();
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
me._onSearchDlgUpdateSize();
|
||||
});
|
||||
},
|
||||
_onSearchToAdd: function()
|
||||
@@ -255,8 +258,8 @@ $(function()
|
||||
me._onUpdateDlgButtons(c);
|
||||
});
|
||||
$('#SearchResultsToAdd_'+me.id).unblock();
|
||||
me._onSearchDlgUpdateSize();
|
||||
});
|
||||
//alert("C'est parti mon kiki !");
|
||||
return false; // Stay on the page, no submit
|
||||
},
|
||||
_getSelection: function(sName)
|
||||
@@ -373,7 +376,7 @@ $(function()
|
||||
me.oDlg.html(data);
|
||||
me.oDlg.find('form').removeAttr('onsubmit').bind('submit', function() { me._onCreateRow(); return false; } );
|
||||
me.oDlg.find('button.cancel').unbind('click').click( function() { me.oDlg.dialog('close'); } );
|
||||
me._updateDlgSize();
|
||||
me._updateDlgPosition();
|
||||
});
|
||||
},
|
||||
_onCreateRow: function()
|
||||
@@ -426,6 +429,13 @@ $(function()
|
||||
this.oDlg.remove();
|
||||
this.oDlg = null;
|
||||
},
|
||||
_onSearchDlgUpdateSize: function()
|
||||
{
|
||||
var searchHeight = $('#SearchFormToAdd_'+this.id).outerHeight();
|
||||
var dlgHeight = this.oDlg.height();
|
||||
$('.wizContainer', this.oDlg).height(dlgHeight - 20);
|
||||
$('#SearchResultsToAdd_'+this.id).height(dlgHeight - 50 - searchHeight);
|
||||
},
|
||||
_deleteRow: function(oCheckbox)
|
||||
{
|
||||
var iObjKey = parseInt(oCheckbox.val(), 10); // Number in base 10
|
||||
|
||||
@@ -242,7 +242,7 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH
|
||||
if (data != '')
|
||||
{
|
||||
$('#'+me.id+'_empty_row').hide();
|
||||
$('#linkedset_'+me.id+' .listResults tbody').append(data);
|
||||
$('#linkedset_'+me.id+' .listResults tbody').prepend(data);
|
||||
$('#linkedset_'+me.id+' .listResults').trigger('update');
|
||||
$('#linkedset_'+me.id+' .listResults').tableHover();
|
||||
$('#linkedset_'+me.id+' .listResults').trigger('update').trigger("applyWidgets"); // table is already sortable, just refresh it
|
||||
|
||||
@@ -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] = [];
|
||||
|
||||
@@ -834,6 +834,7 @@ try
|
||||
$oMenu = ApplicationMenu::GetMenuNode($idx);
|
||||
$oDashboard = $oMenu->GetDashboard();
|
||||
$oDashboard->Render($oPage, false, $aExtraParams);
|
||||
$oPage->add_ready_script("$('.dashboard_contents table.listResults').tableHover(); $('.dashboard_contents table.listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} );");
|
||||
break;
|
||||
|
||||
case 'dashboard_editor':
|
||||
@@ -1019,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();
|
||||
|
||||
@@ -180,15 +180,15 @@ try
|
||||
if ($sFileName != null)
|
||||
{
|
||||
$oP = new CSVPage("iTop - Export");
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oErrorObjectSet, array('localize_values' => true, 'fields_advanced' => $bAdvanced));
|
||||
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oErrorObjectSet, array('localize_values' => true, 'fields_advanced' => $bAdvanced), $sCharset);
|
||||
if ($sCharset == 'UTF-8')
|
||||
{
|
||||
$sOutputData = UTF8_BOM.iconv('UTF-8', 'UTF-8//IGNORE//TRANSLIT', $sCSVData);
|
||||
$sOutputData = UTF8_BOM.$sCSVData;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOutputData = iconv('UTF-8', $sCharset.'//IGNORE//TRANSLIT', $sCSVData);
|
||||
$sOutputData = $sCSVData;
|
||||
}
|
||||
if ($sFileName == '')
|
||||
{
|
||||
|
||||
@@ -91,6 +91,7 @@ abstract class ModuleInstallerAPI
|
||||
* Helper to modify an enum value
|
||||
* The change is made in the datamodel definition, but the value has to be changed in the DB as well
|
||||
* Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation()
|
||||
* This helper does change ONE value at a time
|
||||
*
|
||||
* @param string $sClass A valid class name
|
||||
* @param string $sAttCode The enum attribute code
|
||||
@@ -112,42 +113,73 @@ abstract class ModuleInstallerAPI
|
||||
$aNewValues = array_keys($oValDef->GetValues(array(), ""));
|
||||
if (in_array($sTo, $aNewValues))
|
||||
{
|
||||
$aAllValues = $aNewValues;
|
||||
$aAllValues[] = $sFrom;
|
||||
$sEnumCol = $oAttDef->Get("sql");
|
||||
$aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `$sTableName` WHERE Field = '$sEnumCol'");
|
||||
if (isset($aFields[0]['Type']))
|
||||
{
|
||||
$sColType = $aFields[0]['Type'];
|
||||
// Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string
|
||||
if (preg_match("/^enum\(\'(.*)\'\)$/", $sColType, $aMatches))
|
||||
{
|
||||
$aCurrentValues = explode("','", $aMatches[1]);
|
||||
}
|
||||
}
|
||||
if (!in_array($sFrom, $aNewValues))
|
||||
{
|
||||
$sEnumCol = $oAttDef->Get("sql");
|
||||
$sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL';
|
||||
|
||||
if (strtolower($sTo) == strtolower($sFrom))
|
||||
if (!in_array($sTo, $aCurrentValues)) // if not already transformed!
|
||||
{
|
||||
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)");
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aNewValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1st - Allow both values in the column definition
|
||||
//
|
||||
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'");
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
|
||||
// 2nd - Change the old value into the new value
|
||||
//
|
||||
$sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'";
|
||||
CMDBSource::Query($sRepair);
|
||||
$iAffectedRows = CMDBSource::AffectedRows();
|
||||
SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated");
|
||||
|
||||
// 3rd - Remove the useless value from the column definition
|
||||
//
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aNewValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'");
|
||||
$sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL';
|
||||
|
||||
if (strtolower($sTo) == strtolower($sFrom))
|
||||
{
|
||||
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)");
|
||||
$aTargetValues = array();
|
||||
foreach ($aCurrentValues as $sValue)
|
||||
{
|
||||
if ($sValue == $sFrom)
|
||||
{
|
||||
$sValue = $sTo;
|
||||
}
|
||||
$aTargetValues[] = $sValue;
|
||||
}
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1st - Allow both values in the column definition
|
||||
//
|
||||
SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'");
|
||||
$aAllValues = $aCurrentValues;
|
||||
$aAllValues[] = $sTo;
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
|
||||
// 2nd - Change the old value into the new value
|
||||
//
|
||||
$sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'";
|
||||
CMDBSource::Query($sRepair);
|
||||
$iAffectedRows = CMDBSource::AffectedRows();
|
||||
SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated");
|
||||
|
||||
// 3rd - Remove the useless value from the column definition
|
||||
//
|
||||
$aTargetValues = array();
|
||||
foreach ($aCurrentValues as $sValue)
|
||||
{
|
||||
if ($sValue == $sFrom)
|
||||
{
|
||||
$sValue = $sTo;
|
||||
}
|
||||
$aTargetValues[] = $sValue;
|
||||
}
|
||||
$sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec";
|
||||
$sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition";
|
||||
CMDBSource::Query($sRepair);
|
||||
SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -223,15 +223,15 @@ if (!empty($sExpression))
|
||||
case 'csv':
|
||||
$oP = new CSVPage("iTop - Export");
|
||||
$sFields = implode(',', $aFields);
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oSet, array('fields' => $sFields, 'fields_advanced' => $bFieldsAdvanced, 'localize_values' => $bLocalize));
|
||||
$sCharset = MetaModel::GetConfig()->Get('csv_file_default_charset');
|
||||
$sCharset = utils::ReadParam('charset', MetaModel::GetConfig()->Get('csv_file_default_charset'), true /* Allow CLI */, 'raw_data');
|
||||
$sCSVData = cmdbAbstractObject::GetSetAsCSV($oSet, array('fields' => $sFields, 'fields_advanced' => $bFieldsAdvanced, 'localize_values' => $bLocalize), $sCharset);
|
||||
if ($sCharset == 'UTF-8')
|
||||
{
|
||||
$sOutputData = UTF8_BOM.iconv('UTF-8', 'UTF-8//IGNORE//TRANSLIT', $sCSVData);
|
||||
$sOutputData = UTF8_BOM.$sCSVData;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sOutputData = iconv('UTF-8', $sCharset.'//IGNORE//TRANSLIT', $sCSVData);
|
||||
$sOutputData = $sCSVData;
|
||||
}
|
||||
if ($sFileName == '')
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user