mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 23:44:11 +01:00
Compare commits
68 Commits
2.7.10
...
support/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f80b27044 | ||
|
|
51624dd05e | ||
|
|
89b91fa980 | ||
|
|
ab65135794 | ||
|
|
2d7cdafadc | ||
|
|
c6d6e85b3d | ||
|
|
d4fbc3dc4f | ||
|
|
fce3edca40 | ||
|
|
a099db5350 | ||
|
|
5e25b349bf | ||
|
|
b5793b2129 | ||
|
|
6f3583973b | ||
|
|
23f1e27346 | ||
|
|
ccfc16e296 | ||
|
|
01096e232b | ||
|
|
b3ff892508 | ||
|
|
0841367022 | ||
|
|
0fba65d2c5 | ||
|
|
9aaae9b668 | ||
|
|
c65fb4314b | ||
|
|
e9b579fbbd | ||
|
|
78d211132d | ||
|
|
1ccb78276a | ||
|
|
72cc38aa4b | ||
|
|
3fb7701015 | ||
|
|
91da1583d2 | ||
|
|
0e00a6c526 | ||
|
|
2f1b8d2e71 | ||
|
|
d0280b9672 | ||
|
|
f72e1dd542 | ||
|
|
6703d5621d | ||
|
|
f5e0ff10bb | ||
|
|
ef7d9659fa | ||
|
|
658664a2b2 | ||
|
|
7a86487b33 | ||
|
|
a1d47aac87 | ||
|
|
853a8f0c8f | ||
|
|
39d3ce9e47 | ||
|
|
145b7a81b7 | ||
|
|
1dc59ef7d5 | ||
|
|
cf792822f5 | ||
|
|
6cf3758788 | ||
|
|
093c8a8506 | ||
|
|
2b76c17469 | ||
|
|
b2d6df98ed | ||
|
|
3f4db67b40 | ||
|
|
1943b64b35 | ||
|
|
9cd41efbcd | ||
|
|
5b12bd4c07 | ||
|
|
46f9a1962a | ||
|
|
d527941707 | ||
|
|
b795a20e59 | ||
|
|
2833ef0853 | ||
|
|
1a848fb3cc | ||
|
|
ead3a552e7 | ||
|
|
945b9dc8a9 | ||
|
|
8850d4c460 | ||
|
|
075311b6dd | ||
|
|
1ad81260ae | ||
|
|
f8b36a47a6 | ||
|
|
8b73e2f9bc | ||
|
|
34ad21b7f5 | ||
|
|
1d2fdb1c23 | ||
|
|
92baf53c52 | ||
|
|
6cc0bf5c5a | ||
|
|
a0497cf539 | ||
|
|
a72392d0a8 | ||
|
|
d47609ae03 |
@@ -430,7 +430,7 @@ class URP_ActionGrant extends UserRightsBaseClass
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
@@ -467,7 +467,7 @@ class URP_StimulusGrant extends UserRightsBaseClass
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Common to all grant classes (could be factorized by class inheritence, but this has to be benchmarked)
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("profileid", array("targetclass"=>"URP_Profiles", "jointype"=> "", "allowed_values"=>null, "sql"=>"profileid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("profile", array("allowed_values"=>null, "extkey_attcode"=> 'profileid', "target_attcode"=>"name")));
|
||||
MetaModel::Init_AddAttribute(new AttributeClass("class", array("class_category"=>"", "more_values"=>"", "sql"=>"class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("permission", array("allowed_values"=>new ValueSetEnum('yes,no'), "sql"=>"permission", "default_value"=>"yes", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
@@ -503,7 +503,7 @@ class URP_AttributeGrant extends UserRightsBaseClass
|
||||
MetaModel::Init_Params($aParams);
|
||||
//MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("actiongrantid", array("targetclass"=>"URP_ActionGrant", "jointype"=> "", "allowed_values"=>null, "sql"=>"actiongrantid", "is_null_allowed"=>false, "on_target_delete"=>DEL_MANUAL, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("actiongrantid", array("targetclass"=>"URP_ActionGrant", "jointype"=> "", "allowed_values"=>null, "sql"=>"actiongrantid", "is_null_allowed"=>false, "on_target_delete"=>DEL_SILENT, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("attcode", array("allowed_values"=>null, "sql"=>"attcode", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
|
||||
@@ -450,7 +450,8 @@ class JSPopupMenuItem extends ApplicationPopupMenuItem
|
||||
/** @ignore */
|
||||
public function GetMenuItem()
|
||||
{
|
||||
return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode, 'url' => '#');
|
||||
// Note: the semicolumn is a must here!
|
||||
return array ('label' => $this->GetLabel(), 'onclick' => $this->sJSCode.'; return false;', 'url' => '#');
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
@@ -580,6 +581,14 @@ class RestResult
|
||||
* Result: the input structure is not a valid JSON string
|
||||
*/
|
||||
const INVALID_JSON = 4;
|
||||
/**
|
||||
* Result: the parameter 'auth_user' is missing, authentication aborted
|
||||
*/
|
||||
const MISSING_AUTH_USER = 5;
|
||||
/**
|
||||
* Result: the parameter 'auth_pwd' is missing, authentication aborted
|
||||
*/
|
||||
const MISSING_AUTH_PWD = 6;
|
||||
/**
|
||||
* Result: no operation is available for the specified version
|
||||
*/
|
||||
@@ -944,7 +953,14 @@ class RestUtils
|
||||
foreach ($aFields as $sAttCode => $value)
|
||||
{
|
||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
try
|
||||
{
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
return $oObject;
|
||||
}
|
||||
@@ -964,7 +980,14 @@ class RestUtils
|
||||
foreach ($aFields as $sAttCode => $value)
|
||||
{
|
||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
try
|
||||
{
|
||||
$oObject->Set($sAttCode, $realValue);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw new Exception("$sAttCode: ".$e->getMessage(), $e->getCode());
|
||||
}
|
||||
}
|
||||
return $oObject;
|
||||
}
|
||||
|
||||
@@ -286,6 +286,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
{
|
||||
$sComment = (isset($aExtraParams['fieldsComments'][$sAttCode])) ? $aExtraParams['fieldsComments'][$sAttCode] : '';
|
||||
$this->DisplayCaseLog($oPage, $sAttCode, $sComment, $sPrefix, $bEditMode);
|
||||
$aFieldsMap[$sAttCode] = $this->m_iFormId.'_'.$sAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1225,6 +1226,8 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
|
||||
else
|
||||
{
|
||||
$rawValue = $oObj->Get($sAttCodeEx);
|
||||
// Due to custom formatting rules, empty friendlynames may be rendered as non-empty strings
|
||||
// let's fix this and make sure we render an empty string if the key == 0
|
||||
if ($oAttDef instanceof AttributeFriendlyName)
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
@@ -1430,20 +1433,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
|
||||
{
|
||||
@@ -2118,6 +2125,138 @@ EOF
|
||||
}
|
||||
return $oObj->DisplayModifyForm( $oPage, $aExtraParams);
|
||||
}
|
||||
|
||||
public function DisplayStimulusForm(WebPage $oPage, $sStimulus)
|
||||
{
|
||||
$sClass = get_class($this);
|
||||
$aTransitions = $this->EnumTransitions();
|
||||
$aStimuli = MetaModel::EnumStimuli($sClass);
|
||||
if (!isset($aTransitions[$sStimulus]))
|
||||
{
|
||||
// Invalid stimulus
|
||||
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $this->GetName(), $this->GetStateLabel()));
|
||||
}
|
||||
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
|
||||
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
|
||||
$aTransition = $aTransitions[$sStimulus];
|
||||
$sTargetState = $aTransition['target_state'];
|
||||
$aTargetStates = MetaModel::EnumStates($sClass);
|
||||
$oPage->add("<div class=\"page_header\">\n");
|
||||
$oPage->add("<h1>$sActionLabel - <span class=\"hilite\">{$this->GetName()}</span></h1>\n");
|
||||
$oPage->set_title($sActionLabel);
|
||||
$oPage->add("</div>\n");
|
||||
$aTargetState = $aTargetStates[$sTargetState];
|
||||
$aExpectedAttributes = $aTargetState['attribute_list'];
|
||||
$oPage->add("<h1>$sActionDetails</h1>\n");
|
||||
$sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position');
|
||||
if ($sButtonsPosition == 'bottom')
|
||||
{
|
||||
// bottom: Displays the ticket details BEFORE the actions
|
||||
$oPage->add('<div class="ui-widget-content">');
|
||||
$this->DisplayBareProperties($oPage);
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
$oPage->add("<div class=\"wizContainer\">\n");
|
||||
$oPage->add("<form id=\"apply_stimulus\" method=\"post\" onSubmit=\"return OnSubmit('apply_stimulus');\">\n");
|
||||
$aDetails = array();
|
||||
$iFieldIndex = 0;
|
||||
$aFieldsMap = array();
|
||||
|
||||
$aDetailsList =$this->FlattenZList(MetaModel::GetZListItems($sClass, 'details'));
|
||||
// Order the fields based on their dependencies, set the fields for which there is only one possible value
|
||||
// and perform this in the order of dependencies to avoid dead-ends
|
||||
$aDeps = array();
|
||||
foreach($aDetailsList as $sAttCode)
|
||||
{
|
||||
$aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
|
||||
}
|
||||
$aList =$this->OrderDependentFields($aDeps);
|
||||
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
// Consider only the "expected" fields for the target state
|
||||
if (array_key_exists($sAttCode, $aExpectedAttributes))
|
||||
{
|
||||
$iExpectCode = $aExpectedAttributes[$sAttCode];
|
||||
// Prompt for an attribute if
|
||||
// - the attribute must be changed or must be displayed to the user for confirmation
|
||||
// - or the field is mandatory and currently empty
|
||||
if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) == '')) )
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aArgs = array('this' => $this);
|
||||
// If the field is mandatory, set it to the only possible value
|
||||
if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY))
|
||||
{
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs);
|
||||
if ($oAllowedValues->Count() == 1)
|
||||
{
|
||||
$oRemoteObj = $oAllowedValues->Fetch();
|
||||
$this->Set($sAttCode, $oRemoteObj->GetKey());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
|
||||
if (count($aAllowedValues) == 1)
|
||||
{
|
||||
$aValues = array_keys($aAllowedValues);
|
||||
$this->Set($sAttCode, $aValues[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef,$this->Get($sAttCode),$this->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode, $aArgs);
|
||||
$aDetails[] = array('label' => '<span>'.$oAttDef->GetLabel().'</span>', 'value' => "<span id=\"field_att_$iFieldIndex\">$sHTMLValue</span>");
|
||||
$aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex;
|
||||
$iFieldIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oPage->add('<table><tr><td>');
|
||||
$oPage->details($aDetails);
|
||||
$oPage->add('</td></tr></table>');
|
||||
$oPage->add("<input type=\"hidden\" name=\"id\" value=\"".$this->GetKey()."\" id=\"id\">\n");
|
||||
$aFieldsMap['id'] = 'id';
|
||||
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_stimulus\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"stimulus\" value=\"$sStimulus\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
|
||||
$oAppContext = new ApplicationContext();
|
||||
$oPage->add($oAppContext->GetForForm());
|
||||
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"BackToDetails('$sClass', ".$this->GetKey().")\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oPage->add("<button type=\"submit\" class=\"action\"><span>$sActionLabel</span></button>\n");
|
||||
$oPage->add("</form>\n");
|
||||
$oPage->add("</div>\n");
|
||||
if ($sButtonsPosition != 'top')
|
||||
{
|
||||
// bottom or both: Displays the ticket details AFTER the actions
|
||||
$oPage->add('<div class="ui-widget-content">');
|
||||
$this->DisplayBareProperties($oPage);
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
|
||||
$iFieldsCount = count($aFieldsMap);
|
||||
$sJsonFieldsMap = json_encode($aFieldsMap);
|
||||
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
// Initializes the object once at the beginning of the page...
|
||||
var oWizardHelper = new WizardHelper('$sClass', '', '$sTargetState');
|
||||
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
|
||||
oWizardHelper.SetFieldsCount($iFieldsCount);
|
||||
EOF
|
||||
);
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
// Starts the validation when the page is ready
|
||||
CheckFields('apply_stimulus', false);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
public static function ProcessZlist($aList, $aDetails, $sCurrentTab, $sCurrentCol, $sCurrentSet)
|
||||
{
|
||||
@@ -2709,7 +2848,7 @@ EOF
|
||||
$aFinalValues[$sAttCode] = $aValues[$sAttCode];
|
||||
}
|
||||
$this->UpdateObjectFromArray($aFinalValues);
|
||||
|
||||
|
||||
// Invoke extensions after the update of the object from the form
|
||||
foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance)
|
||||
{
|
||||
@@ -2930,7 +3069,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;
|
||||
}
|
||||
@@ -2962,7 +3101,7 @@ EOF
|
||||
if (!isset($aTransitions[$sStimulus]))
|
||||
{
|
||||
// Invalid stimulus
|
||||
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel()));
|
||||
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus,$this->GetName(),$this->GetStateLabel()));
|
||||
}
|
||||
$aTransition = $aTransitions[$sStimulus];
|
||||
$sTargetState = $aTransition['target_state'];
|
||||
@@ -3107,7 +3246,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
|
||||
@@ -3134,7 +3277,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";
|
||||
@@ -3284,12 +3431,12 @@ EOF
|
||||
{
|
||||
foreach($value as $vKey => $vValue)
|
||||
{
|
||||
$oP->add("<input type=\"hidden\" name=\"{$sKey}[$vKey]\" value=\"$vValue\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"{$sKey}[$vKey]\" value=\"".htmlentities($vValue, ENT_QUOTES, 'UTF-8')."\">\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->add("<input type=\"hidden\" name=\"$sKey\" value=\"$value\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"$sKey\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\">\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
|
||||
{
|
||||
|
||||
@@ -790,6 +790,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;
|
||||
|
||||
@@ -33,6 +33,7 @@ class LoginWebPage extends NiceWebPage
|
||||
{
|
||||
const EXIT_PROMPT = 0;
|
||||
const EXIT_HTTP_401 = 1;
|
||||
const EXIT_RETURN_FALSE = 2;
|
||||
|
||||
protected static $sHandlerClass = __class__;
|
||||
public static function RegisterHandler($sClass)
|
||||
@@ -105,6 +106,7 @@ class LoginWebPage extends NiceWebPage
|
||||
case 'url':
|
||||
$this->add_header('WWW-Authenticate: Basic realm="'.Dict::Format('UI:iTopVersion:Short', ITOP_VERSION));
|
||||
$this->add_header('HTTP/1.0 401 Unauthorized');
|
||||
$this->add_header('Content-type: text/html; charset=iso-8859-1');
|
||||
// Note: displayed when the user will click on Cancel
|
||||
$this->add('<p><strong>'.Dict::S('UI:Login:Error:AccessRestricted').'</strong></p>');
|
||||
break;
|
||||
@@ -190,7 +192,7 @@ class LoginWebPage extends NiceWebPage
|
||||
$this->add("<p>".Dict::S('UI:Login:ForgotPwdForm+')."</p>\n");
|
||||
if ($bFailedToReset)
|
||||
{
|
||||
$this->add("<p class=\"hilite\">".Dict::Format('UI:Login:ResetPwdFailed', $sFailureReason)."</p>\n");
|
||||
$this->add("<p class=\"hilite\">".Dict::Format('UI:Login:ResetPwdFailed', htmlentities($sFailureReason, ENT_QUOTES, 'UTF-8'))."</p>\n");
|
||||
}
|
||||
$sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
|
||||
$this->add("<form method=\"post\">\n");
|
||||
@@ -238,7 +240,12 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
$oEmail = new Email();
|
||||
$oEmail->SetRecipientTO($sTo);
|
||||
$oEmail->SetRecipientFrom($sTo);
|
||||
$sFrom = MetaModel::GetConfig()->Get('forgot_password_from');
|
||||
if ($sFrom == '')
|
||||
{
|
||||
$sFrom = $sTo;
|
||||
}
|
||||
$oEmail->SetRecipientFrom($sFrom);
|
||||
$oEmail->SetSubject(Dict::S('UI:ResetPwd-EmailSubject'));
|
||||
$sResetUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?loginop=reset_pwd&auth_user='.urlencode($oUser->Get('login')).'&token='.urlencode($sToken);
|
||||
$oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl));
|
||||
@@ -419,6 +426,24 @@ EOF
|
||||
return MetaModel::GetConfig()->GetSecureConnectionRequired();
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess if a string looks like an UTF-8 string based on some ranges of multi-bytes encoding
|
||||
* @param string $sString
|
||||
* @return bool True if the string contains some typical UTF-8 multi-byte sequences
|
||||
*/
|
||||
static function LooksLikeUTF8($sString)
|
||||
{
|
||||
return preg_match('%(?:
|
||||
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|
||||
|\xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|
||||
|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|
||||
|\xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|
||||
|\xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|
||||
|[\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|
||||
|\xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
|
||||
)+%xs', $sString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt a login
|
||||
*
|
||||
@@ -484,7 +509,22 @@ EOF
|
||||
else if (isset($_SERVER['PHP_AUTH_USER']))
|
||||
{
|
||||
$sAuthUser = $_SERVER['PHP_AUTH_USER'];
|
||||
// Unfortunately, the RFC is not clear about the encoding...
|
||||
// IE and FF supply the user and password encoded in ISO-8859-1 whereas Chrome provides them encoded in UTF-8
|
||||
// So let's try to guess if it's an UTF-8 string or not... fortunately all encodings share the same ASCII base
|
||||
if (!self::LooksLikeUTF8($sAuthUser))
|
||||
{
|
||||
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
|
||||
// Supposed to be harmless in case of a plain ASCII string...
|
||||
$sAuthUser = iconv('iso-8859-1', 'utf-8', $sAuthUser);
|
||||
}
|
||||
$sAuthPwd = $_SERVER['PHP_AUTH_PW'];
|
||||
if (!self::LooksLikeUTF8($sAuthPwd))
|
||||
{
|
||||
// Does not look like and UTF-8 string, try to convert it from iso-8859-1 to UTF-8
|
||||
// Supposed to be harmless in case of a plain ASCII string...
|
||||
$sAuthPwd = iconv('iso-8859-1', 'utf-8', $sAuthPwd);
|
||||
}
|
||||
$sLoginMode = 'basic';
|
||||
}
|
||||
break;
|
||||
@@ -527,11 +567,17 @@ EOF
|
||||
{
|
||||
$sLoginMode = $aAllowedLoginTypes[0]; // First in the list...
|
||||
}
|
||||
if ($iOnExit == self::EXIT_HTTP_401)
|
||||
if (($iOnExit == self::EXIT_HTTP_401) || ($sLoginMode == 'basic'))
|
||||
{
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
header('WWW-Authenticate: Basic realm="'.Dict::Format('UI:iTopVersion:Short', ITOP_VERSION));
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
header('Content-type: text/html; charset=iso-8859-1');
|
||||
exit;
|
||||
}
|
||||
else if($iOnExit == self::EXIT_RETURN_FALSE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage = self::NewLoginWebPage();
|
||||
@@ -546,11 +592,17 @@ EOF
|
||||
{
|
||||
//echo "Check Credentials returned false for user $sAuthUser!";
|
||||
self::ResetSession();
|
||||
if ($iOnExit == self::EXIT_HTTP_401)
|
||||
if (($iOnExit == self::EXIT_HTTP_401))
|
||||
{
|
||||
header("HTTP/1.0 401 Unauthorized");
|
||||
header('WWW-Authenticate: Basic realm="'.Dict::Format('UI:iTopVersion:Short', ITOP_VERSION));
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
header('Content-type: text/html; charset=iso-8859-1');
|
||||
exit;
|
||||
}
|
||||
else if($iOnExit == self::EXIT_RETURN_FALSE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage = self::NewLoginWebPage();
|
||||
@@ -578,6 +630,7 @@ EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -684,7 +737,7 @@ EOF
|
||||
$sMessage = Dict::S('UI:Login:PasswordChanged');
|
||||
}
|
||||
|
||||
self::Login($iOnExit);
|
||||
$bRet = self::Login($iOnExit);
|
||||
|
||||
if ($bMustBeAdmin && !UserRights::IsAdministrator())
|
||||
{
|
||||
@@ -696,6 +749,13 @@ EOF
|
||||
exit;
|
||||
}
|
||||
call_user_func(array(self::$sHandlerClass, 'ChangeLocation'), $bIsAllowedToPortalUsers);
|
||||
return $sMessage;
|
||||
if ($iOnExit == self::EXIT_RETURN_FALSE)
|
||||
{
|
||||
return $bRet;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sMessage;
|
||||
}
|
||||
}
|
||||
} // End of class
|
||||
|
||||
@@ -324,7 +324,7 @@ EOF
|
||||
|
||||
$sUniqueId = $sClass.$this->GetUniqueId();
|
||||
$this->add("<div id=\"$sUniqueId\">\n"); // The id here MUST be the same as currentId, otherwise the pagination will be broken
|
||||
cmdbAbstractObject::DisplaySet($this, $oSet, array('currentId' => $sUniqueId, 'menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList)));
|
||||
cmdbAbstractObject::DisplaySet($this, $oSet, array('currentId' => $sUniqueId, 'menu' => false, 'toolkit_menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList)));
|
||||
$this->add("</div>\n");
|
||||
}
|
||||
else
|
||||
@@ -420,7 +420,7 @@ EOF
|
||||
}
|
||||
$oObjSearch->AddCondition_ReferencedBy($oLinkSet->GetFilter(), $sRemoteAttCode);
|
||||
|
||||
$aExtraParams = array('menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList));
|
||||
$aExtraParams = array('menu' => false, 'toolkit_menu' => false, 'zlist' => false, 'extra_fields' => implode(',', $aZList));
|
||||
$oBlock = new DisplayBlock($oObjSearch, 'list', false);
|
||||
$oBlock->Display($this, 1, $aExtraParams);
|
||||
}
|
||||
@@ -480,7 +480,9 @@ EOF
|
||||
{
|
||||
try
|
||||
{
|
||||
$oAllowedValues = new DBObjectSet(DBObjectSearch::FromOQL(constant($sFilterDefName)), array(), $aFilterParams);
|
||||
$oFitlerWithParams = DBObjectSearch::FromOQL(constant($sFilterDefName));
|
||||
$sFilterOQL = $oFitlerWithParams->ToOQL(true, $aFilterParams);
|
||||
$oAllowedValues = new DBObjectSet(DBObjectSearch::FromOQL($sFilterOQL), array(), $aFilterParams);
|
||||
}
|
||||
catch(OQLException $e)
|
||||
{
|
||||
@@ -510,7 +512,8 @@ EOF
|
||||
if (is_null($aAllowedValues))
|
||||
{
|
||||
// Any value is possible, display an input box
|
||||
$this->add("<label>".MetaModel::GetFilterLabel($sClass, $sAttSpec).":</label> <input class=\"textSearch\" name=\"$sPrefix$sFieldName\" value=\"$sFilterValue\"/>\n");
|
||||
$sSanitizedValue = htmlentities($sFilterValue, ENT_QUOTES, 'UTF-8');
|
||||
$this->add("<label>".MetaModel::GetFilterLabel($sClass, $sAttSpec).":</label> <input class=\"textSearch\" name=\"$sPrefix$sFieldName\" value=\"$sSanitizedValue\"/>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -793,24 +796,7 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
$sOQL = "SELECT $sClass WHERE org_id = :org_id";
|
||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||
$iUser = UserRights::GetContactId();
|
||||
if ($iUser > 0 && !IsPowerUser())
|
||||
{
|
||||
$oSearch->AddCondition('caller_id', $iUser);
|
||||
}
|
||||
$oSearch->AddCondition('id', $iId);
|
||||
|
||||
$oContact = MetaModel::GetObject('Contact', $iUser, false); // false => Can fail
|
||||
if (!is_object($oContact))
|
||||
{
|
||||
throw new Exception(Dict::S('Portal:ErrorNoContactForThisUser'));
|
||||
}
|
||||
|
||||
$oSet = new DBObjectSet($oSearch, array(), array('org_id' => $oContact->Get('org_id')));
|
||||
|
||||
$oObj = $oSet->Fetch();
|
||||
$oObj = MetaModel::GetObject($sClass, $iId, false);
|
||||
if (!is_object($oObj))
|
||||
{
|
||||
throw new Exception("Could not find the object $sClass/$iId");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -453,7 +453,7 @@ EOF
|
||||
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, $oNewObj, array(), array('formPrefix' => $this->iId, 'noRelations' => true));
|
||||
$oPage->add('</div></div></div>');
|
||||
// $oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: 'auto', autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
|
||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
|
||||
$oPage->add_ready_script("$('#dcr_{$this->iId} form').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);");
|
||||
}
|
||||
|
||||
@@ -318,12 +318,11 @@ class UILinksWidgetDirect
|
||||
{
|
||||
$oFilter->AddCondition('id', $aAlreadyLinked, 'NOTIN');
|
||||
}
|
||||
$aArgs = array();
|
||||
if ($oCurrentObj != null)
|
||||
{
|
||||
$aArgs = $oCurrentObj->ToArgs('this');
|
||||
$aArgs = array_merge($oCurrentObj->ToArgs('this'), $oFilter->GetInternalParams());
|
||||
$oFilter->SetInternalParams($aArgs);
|
||||
}
|
||||
$oFilter->SetInternalParams($aArgs);
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oBlock->Display($oP, "ResultsToAdd_{$this->sInputid}", array('menu' => false, 'cssCount'=> '#count_'.$this->sInputid , 'selection_mode' => true, 'table_id' => 'add_'.$this->sInputid)); // Don't display the 'Actions' menu on the results
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,18 +34,65 @@ class ExecAsyncTask implements iBackgroundProcess
|
||||
|
||||
public function Process($iTimeLimit)
|
||||
{
|
||||
$sOQL = "SELECT AsyncTask WHERE ISNULL(started) AND (ISNULL(planned) OR (planned < NOW()))";
|
||||
$sNow = date('Y-m-d H:i:s');
|
||||
$sOQL = "SELECT AsyncTask WHERE ISNULL(started) AND (ISNULL(planned) OR (planned < '$sNow'))";
|
||||
$oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL), array('created' => true) /* order by*/, array());
|
||||
$iProcessed = 0;
|
||||
while ((time() < $iTimeLimit) && ($oTask = $oSet->Fetch()))
|
||||
{
|
||||
$oTask->Set('started', time());
|
||||
$oTask->DBUpdate();
|
||||
try
|
||||
{
|
||||
$oTask->Set('started', time());
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Corrupted task !! (for example: "Failed to reload object")
|
||||
IssueLog::Error('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage().' - fatal error, deleting the task.');
|
||||
if ($oTask->Get('event_id') != 0)
|
||||
{
|
||||
$oEventLog = MetaModel::GetObject('Event', $oTask->Get('event_id'));
|
||||
$oEventLog->Set('message', 'Failed, corrupted data: '.$e->getMessage());
|
||||
$oEventLog->DBUpdate();
|
||||
}
|
||||
$oTask->DBDelete();
|
||||
continue; // end of processing for this task
|
||||
}
|
||||
|
||||
$oTask->Process();
|
||||
$iProcessed++;
|
||||
try
|
||||
{
|
||||
$oTask->Process();
|
||||
$iProcessed++;
|
||||
|
||||
$oTask->DBDelete();
|
||||
$oTask->DBDelete();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$iRemaining = $oTask->Get('remaining_retries');
|
||||
if ($iRemaining > 0)
|
||||
{
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
if (is_array($aRetries) && array_key_exists(get_class($oTask), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($oTask)];
|
||||
$iRetryDelay = $aConfig['retry_delay'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$iRetryDelay = 600;
|
||||
}
|
||||
IssueLog::Info('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage().' - remaining retries: '.$iRemaining.' - next retry in '.$iRetryDelay.'s');
|
||||
|
||||
$oTask->Set('remaining_retries', $iRemaining - 1);
|
||||
$oTask->Set('started', null);
|
||||
$oTask->Set('planned', time() + $iRetryDelay);
|
||||
$oTask->DBUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
IssueLog::Error('Failed to process async task #'.$oTask->GetKey().' - reason: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($iProcessed == $oSet->Count())
|
||||
{
|
||||
@@ -88,6 +135,8 @@ abstract class AsyncTask extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("planned", array("allowed_values"=>null, "sql"=>"planned", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
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())));
|
||||
|
||||
// Display lists
|
||||
// MetaModel::Init_SetZListItems('details', array()); // Attributes to be displayed for the complete details
|
||||
// MetaModel::Init_SetZListItems('list', array()); // Attributes to be displayed for a list
|
||||
@@ -99,6 +148,14 @@ abstract class AsyncTask extends DBObject
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->Set('created', time());
|
||||
|
||||
$aRetries = MetaModel::GetConfig()->Get('async_task_retries', array());
|
||||
if (is_array($aRetries) && array_key_exists(get_class($this), $aRetries))
|
||||
{
|
||||
$aConfig = $aRetries[get_class($this)];
|
||||
$iRetries = $aConfig['max_retries'];
|
||||
$this->Set('remaining_retries', $iRetries);
|
||||
}
|
||||
}
|
||||
|
||||
public function Process()
|
||||
@@ -140,7 +197,7 @@ class AsyncSendEmail extends AsyncTask
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("version", array("allowed_values"=>null, "sql"=>"version", "default_value"=>Email::ORIGINAL_FORMAT, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("subject", array("allowed_values"=>null, "sql"=>"subject", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeLongText("message", array("allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
|
||||
@@ -1915,7 +1915,12 @@ class AttributeCaseLog extends AttributeLongText
|
||||
// Facilitate things: allow the user to Set the value from a string
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (!($proposedValue instanceof ormCaseLog))
|
||||
if ($proposedValue instanceof ormCaseLog)
|
||||
{
|
||||
// Passthrough
|
||||
$ret = $proposedValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append the new value if an instance of the object is supplied
|
||||
//
|
||||
@@ -1937,13 +1942,21 @@ class AttributeCaseLog extends AttributeLongText
|
||||
{
|
||||
$oCaseLog = new ormCaseLog();
|
||||
}
|
||||
if (strlen($proposedValue) > 0)
|
||||
|
||||
if ($proposedValue instanceof stdClass)
|
||||
{
|
||||
$oCaseLog->AddLogEntry(parent::MakeRealValue($proposedValue, $oHostObj));
|
||||
$oCaseLog->AddLogEntryFromJSON($proposedValue);
|
||||
}
|
||||
return $oCaseLog;
|
||||
else
|
||||
{
|
||||
if (strlen($proposedValue) > 0)
|
||||
{
|
||||
$oCaseLog->AddLogEntry(parent::MakeRealValue($proposedValue, $oHostObj));
|
||||
}
|
||||
}
|
||||
$ret = $oCaseLog;
|
||||
}
|
||||
return $proposedValue;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function GetSQLExpressions($sPrefix = '')
|
||||
@@ -2061,6 +2074,45 @@ class AttributeCaseLog extends AttributeLongText
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get a value that will be JSON encoded
|
||||
* The operation is the opposite to FromJSONToValue
|
||||
*/
|
||||
public function GetForJSON($value)
|
||||
{
|
||||
return $value->GetForJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to form a value, given JSON decoded data
|
||||
* The operation is the opposite to GetForJSON
|
||||
*/
|
||||
public function FromJSONToValue($json)
|
||||
{
|
||||
if (is_string($json))
|
||||
{
|
||||
// Will be correctly handled in MakeRealValue
|
||||
$ret = $json;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($json->add_item))
|
||||
{
|
||||
// Will be correctly handled in MakeRealValue
|
||||
$ret = $json->add_item;
|
||||
if (!isset($ret->message))
|
||||
{
|
||||
throw new Exception("Missing mandatory entry: 'message'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = ormCaseLog::FromJSON($json);
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2087,8 +2139,7 @@ class AttributeEmailAddress extends AttributeString
|
||||
{
|
||||
public function GetValidationPattern()
|
||||
{
|
||||
// return "^([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})$";
|
||||
return "^[a-zA-Z0-9._&-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,}$";
|
||||
return $this->GetOptional('validation_pattern', '^'.utils::GetConfig()->Get('email_validation_pattern').'$');
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true)
|
||||
@@ -2347,6 +2398,15 @@ class AttributeEnum extends AttributeString
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get a value that will be JSON encoded
|
||||
* The operation is the opposite to FromJSONToValue
|
||||
*/
|
||||
public function GetForJSON($value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetAllowedValues($aArgs = array(), $sContains = '')
|
||||
{
|
||||
$aRawValues = parent::GetAllowedValues($aArgs, $sContains);
|
||||
|
||||
@@ -332,6 +332,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'async_task_retries' => array(
|
||||
'type' => 'array',
|
||||
'description' => 'Automatic retries of asynchronous tasks in case of failure (per class)',
|
||||
'default' => array('AsyncSendEmail' => array('max_retries' => 0, 'retry_delay' => 600)),
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'email_asynchronous' => array(
|
||||
'type' => 'bool',
|
||||
'description' => 'If set, the emails are sent off line, which requires cron.php to be activated. Exception: some features like the email test utility will force the serialized mode',
|
||||
@@ -540,6 +548,15 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'forgot_password_from' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Sender email address for the "forgot password" feature. If empty, defaults to the recipient\'s email address.',
|
||||
// examples... not used (nor 'description')
|
||||
'default' => '',
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'deadline_format' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'The format used for displaying "deadline" attributes: any string with the following placeholders: $date$, $difference$',
|
||||
@@ -632,6 +649,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'email_validation_pattern' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Regular expression to validate/detect the format of an eMail address',
|
||||
'default' => "[a-zA-Z0-9._&'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,}",
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'log_kpi_duration' => array(
|
||||
'type' => 'integer',
|
||||
'description' => 'Level of logging for troubleshooting performance issues (1 to enable, 2 +blame callers)',
|
||||
@@ -684,6 +709,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'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)
|
||||
@@ -712,6 +745,8 @@ class Config
|
||||
case 'float':
|
||||
$value = (float) $value;
|
||||
break;
|
||||
case 'array':
|
||||
break;
|
||||
default:
|
||||
throw new CoreException('Unknown type for setting', array('property' => $sPropCode, 'type' => $sType));
|
||||
}
|
||||
@@ -968,7 +1003,14 @@ class Config
|
||||
{
|
||||
if ($this->IsProperty($sPropCode))
|
||||
{
|
||||
$value = trim($rawvalue);
|
||||
if (is_string($rawvalue))
|
||||
{
|
||||
$value = trim($rawvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $rawvalue;
|
||||
}
|
||||
$this->Set($sPropCode, $value, $sConfigFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,16 +400,25 @@ abstract class DBObject
|
||||
{
|
||||
throw new CoreException("Unknown external key '$sExtKeyAttCode' for the class ".get_class($this));
|
||||
}
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
|
||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||
$oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
|
||||
if (is_null($oRemoteObj))
|
||||
|
||||
$oExtFieldAtt = MetaModel::FindExternalField(get_class($this), $sExtKeyAttCode, $sRemoteAttCode);
|
||||
if (!is_null($oExtFieldAtt))
|
||||
{
|
||||
return '';
|
||||
return $this->GetStrict($oExtFieldAtt->GetCode());
|
||||
}
|
||||
else
|
||||
{
|
||||
return $oRemoteObj->Get($sRemoteAttCode);
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
|
||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||
$oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
|
||||
if (is_null($oRemoteObj))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
else
|
||||
{
|
||||
return $oRemoteObj->Get($sRemoteAttCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2042,7 +2051,7 @@ abstract class DBObject
|
||||
{
|
||||
$sRemoteName = $oAttDef->IsIndirect() ? $oAttDef->GetExtKeyToRemote().'_friendlyname' : 'friendlyname';
|
||||
|
||||
$oLinkSet = $this->Get($sAttCode);
|
||||
$oLinkSet = clone $this->Get($sAttCode); // Workaround/Safety net for Trac #887
|
||||
$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
|
||||
if ($iLimit > 0)
|
||||
{
|
||||
|
||||
@@ -418,7 +418,7 @@ class DBObjectSet
|
||||
CMDBSource::FreeResult($resQuery);
|
||||
$this->m_iCount = $aRow['COUNT'];
|
||||
}
|
||||
return $this->m_iCount;
|
||||
return $this->m_iCount; // WARNING this value can be wrong, see Trac #887
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,8 +741,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;
|
||||
}
|
||||
|
||||
@@ -840,6 +840,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];
|
||||
}
|
||||
|
||||
@@ -871,15 +875,32 @@ abstract class MetaModel
|
||||
|
||||
final static public function GetExternalFields($sClass, $sKeyAttCode)
|
||||
{
|
||||
$aExtFields = array();
|
||||
foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt)
|
||||
static $aExtFields = array();
|
||||
if (!isset($aExtFields[$sClass][$sKeyAttCode]))
|
||||
{
|
||||
if ($oAtt->IsExternalField() && ($oAtt->GetKeyAttCode() == $sKeyAttCode))
|
||||
$aExtFields[$sClass][$sKeyAttCode] = array();
|
||||
foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAtt)
|
||||
{
|
||||
$aExtFields[] = $oAtt;
|
||||
if ($oAtt->IsExternalField() && ($oAtt->GetKeyAttCode() == $sKeyAttCode))
|
||||
{
|
||||
$aExtFields[$sClass][$sKeyAttCode][$oAtt->GetExtAttCode()] = $oAtt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aExtFields;
|
||||
return $aExtFields[$sClass][$sKeyAttCode];
|
||||
}
|
||||
|
||||
final static public function FindExternalField($sClass, $sKeyAttCode, $sRemoteAttCode)
|
||||
{
|
||||
$aExtFields = self::GetExternalFields($sClass, $sKeyAttCode);
|
||||
if (isset($aExtFields[$sRemoteAttCode]))
|
||||
{
|
||||
return $aExtFields[$sRemoteAttCode];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final static public function GetExtKeyFriends($sClass, $sExtKeyAttCode)
|
||||
@@ -5121,6 +5142,12 @@ abstract class MetaModel
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* It is not recommended to use this function: call GetLinkClasses instead
|
||||
* Return classes having at least to external keys (thus too many classes as compared to GetLinkClasses)
|
||||
* The only difference with EnumLinkingClasses is the output format
|
||||
*/
|
||||
public static function EnumLinksClasses()
|
||||
{
|
||||
// Returns a flat array of classes having at least two external keys
|
||||
@@ -5143,6 +5170,11 @@ abstract class MetaModel
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
/**
|
||||
* It is not recommended to use this function: call GetLinkClasses instead
|
||||
* Return classes having at least to external keys (thus too many classes as compared to GetLinkClasses)
|
||||
* The only difference with EnumLinksClasses is the output format
|
||||
*/
|
||||
public static function EnumLinkingClasses($sClass = "")
|
||||
{
|
||||
// N-N links, array of sLinkClass => (array of sAttCode=>sClass)
|
||||
@@ -5179,6 +5211,38 @@ abstract class MetaModel
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function has two siblings that will be soon deprecated:
|
||||
* EnumLinkingClasses and EnumLinkClasses
|
||||
*
|
||||
* Using GetLinkClasses is the recommended way to determine if a class is
|
||||
* actually an N-N relation because it is based on the decision made by the
|
||||
* designer the data model
|
||||
*/
|
||||
public static function GetLinkClasses()
|
||||
{
|
||||
$aRet = array();
|
||||
foreach(self::GetClasses() as $sClass)
|
||||
{
|
||||
if (isset(self::$m_aClassParams[$sClass]["is_link"]))
|
||||
{
|
||||
if (self::$m_aClassParams[$sClass]["is_link"])
|
||||
{
|
||||
$aExtKeys = array();
|
||||
foreach (self::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$aExtKeys[$sAttCode] = $oAttDef->GetTargetClass();
|
||||
}
|
||||
}
|
||||
$aRet[$sClass] = $aExtKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
public static function GetLinkLabel($sLinkClass, $sAttCode)
|
||||
{
|
||||
self::_check_subclass($sLinkClass);
|
||||
@@ -5248,18 +5312,27 @@ abstract class MetaModel
|
||||
$sEnvironment = MetaModel::GetEnvironmentId();
|
||||
}
|
||||
$aEntries = array();
|
||||
$aCacheUserData = @apc_cache_info('user');
|
||||
if (extension_loaded('apcu'))
|
||||
{
|
||||
// Beware: APCu behaves slightly differently from APC !!
|
||||
$aCacheUserData = @apc_cache_info();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aCacheUserData = @apc_cache_info('user');
|
||||
}
|
||||
if (is_array($aCacheUserData) && isset($aCacheUserData['cache_list']))
|
||||
{
|
||||
$sPrefix = 'itop-'.$sEnvironment.'-';
|
||||
|
||||
foreach($aCacheUserData['cache_list'] as $i => $aEntry)
|
||||
{
|
||||
$sEntryKey = $aEntry['info'];
|
||||
$sEntryKey = array_key_exists('info', $aEntry) ? $aEntry['info'] : $aEntry['key'];
|
||||
if (strpos($sEntryKey, $sPrefix) === 0)
|
||||
{
|
||||
$sCleanKey = substr($sEntryKey, strlen($sPrefix));
|
||||
$aEntries[$sCleanKey] = $aEntry;
|
||||
$aEntries[$sCleanKey]['info'] = $sEntryKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class ModelReflectionRuntime extends ModelReflection
|
||||
$aClasses = MetaModel::GetClasses($sCategories);
|
||||
if ($bExcludeLinks)
|
||||
{
|
||||
$aExcluded = ProfilesConfig::GetLinkClasses(); // table computed at compile time
|
||||
$aExcluded = MetaModel::GetLinkClasses();
|
||||
$aRes = array();
|
||||
foreach ($aClasses as $sClass)
|
||||
{
|
||||
|
||||
@@ -31,12 +31,20 @@ class iTopMutex
|
||||
{
|
||||
protected $sName;
|
||||
protected $hDBLink;
|
||||
protected $bLocked; // Whether or not this instance of the Mutex is locked
|
||||
static protected $aAcquiredLocks = array(); // Number of instances of the Mutex, having the lock, in this page
|
||||
|
||||
public function __construct($sName)
|
||||
{
|
||||
// Compute the name of a lock for mysql
|
||||
// Note: the name is server-wide!!!
|
||||
$this->sName = 'itop.'.$sName;
|
||||
$this->bLocked = false; // Not yet locked
|
||||
|
||||
if (!array_key_exists($this->sName, self::$aAcquiredLocks))
|
||||
{
|
||||
self::$aAcquiredLocks[$this->sName] = 0;
|
||||
}
|
||||
|
||||
// It is a MUST to create a dedicated session each time a lock is required, because
|
||||
// using GET_LOCK anytime on the same session will RELEASE the current and unique session lock (known issue)
|
||||
@@ -46,7 +54,10 @@ class iTopMutex
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->Unlock();
|
||||
if ($this->bLocked)
|
||||
{
|
||||
$this->Unlock();
|
||||
}
|
||||
mysqli_close($this->hDBLink);
|
||||
}
|
||||
|
||||
@@ -55,17 +66,27 @@ class iTopMutex
|
||||
*/
|
||||
public function Lock()
|
||||
{
|
||||
do
|
||||
if ($this->bLocked)
|
||||
{
|
||||
$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 3600)");
|
||||
if (is_null($res))
|
||||
{
|
||||
throw new Exception("Failed to acquire the lock '".$this->sName."'");
|
||||
}
|
||||
// $res === '1' means I hold the lock
|
||||
// $res === '0' means it timed out
|
||||
// Lock already acquired
|
||||
return;
|
||||
}
|
||||
while ($res !== '1');
|
||||
if (self::$aAcquiredLocks[$this->sName] == 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 3600)");
|
||||
if (is_null($res))
|
||||
{
|
||||
throw new Exception("Failed to acquire the lock '".$this->sName."'");
|
||||
}
|
||||
// $res === '1' means I hold the lock
|
||||
// $res === '0' means it timed out
|
||||
}
|
||||
while ($res !== '1');
|
||||
}
|
||||
$this->bLocked = true;
|
||||
self::$aAcquiredLocks[$this->sName]++;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,6 +95,17 @@ class iTopMutex
|
||||
*/
|
||||
public function TryLock()
|
||||
{
|
||||
if ($this->bLocked)
|
||||
{
|
||||
return true; // Already acquired
|
||||
}
|
||||
if (self::$aAcquiredLocks[$this->sName] > 0)
|
||||
{
|
||||
self::$aAcquiredLocks[$this->sName]++;
|
||||
$this->bLocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
$res = $this->QueryToScalar("SELECT GET_LOCK('".$this->sName."', 0)");
|
||||
if (is_null($res))
|
||||
{
|
||||
@@ -81,6 +113,11 @@ class iTopMutex
|
||||
}
|
||||
// $res === '1' means I hold the lock
|
||||
// $res === '0' means it timed out
|
||||
if ($res === '1')
|
||||
{
|
||||
$this->bLocked = true;
|
||||
self::$aAcquiredLocks[$this->sName]++;
|
||||
}
|
||||
return ($res === '1');
|
||||
}
|
||||
|
||||
@@ -89,7 +126,22 @@ class iTopMutex
|
||||
*/
|
||||
public function Unlock()
|
||||
{
|
||||
$res = $this->QueryToScalar("SELECT RELEASE_LOCK('".$this->sName."')");
|
||||
if (!$this->bLocked)
|
||||
{
|
||||
// ??? the lock is not acquired, exit
|
||||
return;
|
||||
}
|
||||
if (self::$aAcquiredLocks[$this->sName] == 0)
|
||||
{
|
||||
return; // Safety net
|
||||
}
|
||||
|
||||
if (self::$aAcquiredLocks[$this->sName] == 1)
|
||||
{
|
||||
$res = $this->QueryToScalar("SELECT RELEASE_LOCK('".$this->sName."')");
|
||||
}
|
||||
$this->bLocked = false;
|
||||
self::$aAcquiredLocks[$this->sName]--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,80 @@ class ormCaseLog {
|
||||
return $this->m_sLog;
|
||||
}
|
||||
|
||||
public static function FromJSON($oJson)
|
||||
{
|
||||
if (!isset($oJson->items))
|
||||
{
|
||||
throw new Exception("Missing 'items' elements");
|
||||
}
|
||||
$oCaseLog = new ormCaseLog();
|
||||
foreach($oJson->items as $oItem)
|
||||
{
|
||||
$oCaseLog->AddLogEntryFromJSON($oItem);
|
||||
}
|
||||
return $oCaseLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a value that will be further JSON encoded
|
||||
*/
|
||||
public function GetForJSON()
|
||||
{
|
||||
$aEntries = array();
|
||||
$iPos = 0;
|
||||
for($index=count($this->m_aIndex)-1 ; $index >= 0 ; $index--)
|
||||
{
|
||||
$iPos += $this->m_aIndex[$index]['separator_length'];
|
||||
$sTextEntry = substr($this->m_sLog, $iPos, $this->m_aIndex[$index]['text_length']);
|
||||
$iPos += $this->m_aIndex[$index]['text_length'];
|
||||
|
||||
// Workaround: PHP < 5.3 cannot unserialize correctly DateTime objects,
|
||||
// therefore we have changed the format. To preserve the compatibility with existing
|
||||
// installations of iTop, both format are allowed:
|
||||
// the 'date' item is either a DateTime object, or a unix timestamp
|
||||
if (is_int($this->m_aIndex[$index]['date']))
|
||||
{
|
||||
// Unix timestamp
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'),$this->m_aIndex[$index]['date']);
|
||||
}
|
||||
elseif (is_object($this->m_aIndex[$index]['date']))
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>='))
|
||||
{
|
||||
// DateTime
|
||||
$sDate = $this->m_aIndex[$index]['date']->format(Dict::S('UI:CaseLog:DateFormat'));
|
||||
}
|
||||
else
|
||||
{
|
||||
// No Warning... but the date is unknown
|
||||
$sDate = '';
|
||||
}
|
||||
}
|
||||
$aEntries[] = array(
|
||||
'date' => $sDate,
|
||||
'user_login' => $this->m_aIndex[$index]['user_name'],
|
||||
'user_id' => $this->m_aIndex[$index]['user_id'],
|
||||
'message' => $sTextEntry
|
||||
);
|
||||
}
|
||||
|
||||
// Process the case of an eventual remainder (quick migration of AttributeText fields)
|
||||
if ($iPos < (strlen($this->m_sLog) - 1))
|
||||
{
|
||||
$sTextEntry = substr($this->m_sLog, $iPos);
|
||||
|
||||
$aEntries[] = array(
|
||||
'date' => '',
|
||||
'user_login' => '',
|
||||
'message' => $sTextEntry
|
||||
);
|
||||
}
|
||||
|
||||
// Order by ascending date
|
||||
$aRet = array('entries' => array_reverse($aEntries));
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
public function GetIndex()
|
||||
{
|
||||
return $this->m_aIndex;
|
||||
@@ -230,7 +304,62 @@ class ormCaseLog {
|
||||
}
|
||||
$this->m_bModified = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function AddLogEntryFromJSON($oJson)
|
||||
{
|
||||
$sText = isset($oJson->message) ? $oJson->message : '';
|
||||
|
||||
if (isset($oJson->user_id))
|
||||
{
|
||||
if (!UserRights::IsAdministrator())
|
||||
{
|
||||
throw new Exception("Only administrators can set the user id", RestResult::UNAUTHORIZED);
|
||||
}
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
$iUserId = UserRights::GetUserId();
|
||||
$sOnBehalfOf = UserRights::GetUserFriendlyName();
|
||||
}
|
||||
|
||||
if (isset($oJson->date))
|
||||
{
|
||||
$oDate = new DateTime($oJson->date);
|
||||
$iDate = (int) $oDate->format('U');
|
||||
}
|
||||
else
|
||||
{
|
||||
$iDate = time();
|
||||
}
|
||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'), $iDate);
|
||||
|
||||
$sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId);
|
||||
$iSepLength = strlen($sSeparator);
|
||||
$iTextlength = strlen($sText);
|
||||
$this->m_sLog = $sSeparator.$sText.$this->m_sLog; // Latest entry printed first
|
||||
$this->m_aIndex[] = array(
|
||||
'user_name' => $sOnBehalfOf,
|
||||
'user_id' => $iUserId,
|
||||
'date' => $iDate,
|
||||
'text_length' => $iTextlength,
|
||||
'separator_length' => $iSepLength,
|
||||
);
|
||||
|
||||
$this->m_bModified = true;
|
||||
}
|
||||
|
||||
|
||||
public function GetModifiedEntry()
|
||||
{
|
||||
$sModifiedEntry = '';
|
||||
|
||||
@@ -117,7 +117,18 @@ class ormDocument
|
||||
{
|
||||
return "<a href=\"".utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode\">".$this->GetFileName()."</a>\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an URL to download a document like an image (uses HTTP caching)
|
||||
* @return string
|
||||
*/
|
||||
public function GetDownloadURL($sClass, $Id, $sAttCode)
|
||||
{
|
||||
// Compute a signature to reset the cache anytime the data changes (this is acceptable if used only with icon files)
|
||||
$sSignature = md5($this->GetData());
|
||||
return utils::GetAbsoluteUrlAppRoot()."pages/ajax.render.php?operation=download_document&class=$sClass&id=$Id&field=$sAttCode&s=$sSignature&cache=86400";
|
||||
}
|
||||
|
||||
|
||||
public function IsPreviewAvailable()
|
||||
{
|
||||
|
||||
@@ -258,16 +258,22 @@ class ormStopWatch
|
||||
public function Reset($oObject, $oAttDef)
|
||||
{
|
||||
$this->iTimeSpent = 0;
|
||||
$this->iStarted = null;
|
||||
$this->iLastStart = null;
|
||||
$this->iStopped = null;
|
||||
$this->iStarted = null;
|
||||
|
||||
foreach ($this->aThresholds as $iPercent => &$aThresholdData)
|
||||
{
|
||||
$aThresholdData['triggered'] = false;
|
||||
$aThresholdData['deadline'] = null;
|
||||
$aThresholdData['overrun'] = null;
|
||||
}
|
||||
|
||||
if (!is_null($this->iLastStart))
|
||||
{
|
||||
// Currently running... starting again from now!
|
||||
$this->iStarted = time();
|
||||
$this->iLastStart = time();
|
||||
$this->ComputeDeadlines($oObject, $oAttDef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,36 +16,17 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Stephan Rosenke <stephan.rosenke@itomig.de>
|
||||
* @author Stephan Rosenke <stephan.rosenke@itomig.de>
|
||||
* @author David M. Gümbel <david.guembel@itomig.de>
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:UserLocal' => 'iTop-Benutzer',
|
||||
'Class:UserLocal+' => 'Benutzer von iTop authentifiziert',
|
||||
'Class:UserLocal/Attribute:password' => 'Passwort',
|
||||
'Class:UserLocal/Attribute:password+' => 'Benutzerpasswort',
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
?>
|
||||
51
datamodels/1.x/authent-local/es_cr.dict.authent-local.php
Normal file
51
datamodels/1.x/authent-local/es_cr.dict.authent-local.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2013 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2013 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @traductor Miguel Turrubiates <miguel_tf@yahoo.com>
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Class:UserLocal' => 'Usuario de iTop',
|
||||
'Class:UserLocal+' => 'Usuario Autenticado vía iTop',
|
||||
'Class:UserLocal/Attribute:password' => 'Contraseña',
|
||||
'Class:UserLocal/Attribute:password+' => 'Contraseña',
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
@@ -1,51 +1,32 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Hirofumi Kosaka <kosaka@rworks.jp>
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Class:UserLocal' => 'iTopユーザー', // 'iTop user',
|
||||
'Class:UserLocal+' => 'iTopローカル認証ユーザー', // 'User authentified by iTop',
|
||||
'Class:UserLocal/Attribute:password' => 'パスワード', // 'Password',
|
||||
'Class:UserLocal/Attribute:password+' => '認証文字列', // 'user authentication string',
|
||||
));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
<?php
|
||||
// Copyright (C) 2010-2012 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* @author Hirofumi Kosaka <kosaka@rworks.jp>
|
||||
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Class:UserLocal' => 'iTopユーザー',
|
||||
'Class:UserLocal+' => 'iTopローカル認証ユーザー',
|
||||
'Class:UserLocal/Attribute:password' => 'パスワード',
|
||||
'Class:UserLocal/Attribute:password+' => '認証文字列',
|
||||
));
|
||||
?>
|
||||
@@ -74,7 +74,10 @@ class UserLocal extends UserInternal
|
||||
|
||||
public function CanChangePassword()
|
||||
{
|
||||
// For now everyone can change their password..
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,18 +88,47 @@ class UserLocal extends UserInternal
|
||||
// Let's ask the password to compare the hashed values
|
||||
if ($oPassword->CheckPassword($sOldPassword))
|
||||
{
|
||||
$this->Set('password', $sNewPassword);
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$sUserString = CMDBChange::GetCurrentUserName();
|
||||
$oChange->Set("userinfo", $sUserString);
|
||||
$oChange->DBInsert();
|
||||
$this->DBUpdateTracked($oChange, true);
|
||||
$this->SetPassword($sNewPassword);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use with care!
|
||||
*/
|
||||
public function SetPassword($sNewPassword)
|
||||
{
|
||||
$this->Set('password', $sNewPassword);
|
||||
$oChange = MetaModel::NewObject("CMDBChange");
|
||||
$oChange->Set("date", time());
|
||||
$sUserString = CMDBChange::GetCurrentUserName();
|
||||
$oChange->Set("userinfo", $sUserString);
|
||||
$oChange->DBInsert();
|
||||
$this->DBUpdateTracked($oChange, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of flags (OPT_ATT_HIDDEN, OPT_ATT_READONLY, OPT_ATT_MANDATORY...)
|
||||
* for the given attribute in the current state of the object
|
||||
* @param $sAttCode string $sAttCode The code of the attribute
|
||||
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
|
||||
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
|
||||
* @return integer Flags: the binary combination of the flags applicable to this attribute
|
||||
*/
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
if (MetaModel::GetConfig()->Get('demo_mode'))
|
||||
{
|
||||
if (strpos('contactid,login,language,password,profile_list,allowed_org_list', $sAttCode) !== false)
|
||||
{
|
||||
// contactid and allowed_org_list are disabled to make sure the portal remains accessible
|
||||
$aReasons[] = 'Sorry, this attribute is read-only in the demonstration mode!';
|
||||
$iFlags |= OPT_ATT_READONLY;
|
||||
}
|
||||
}
|
||||
return $iFlags;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -17,32 +17,16 @@
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @author Vladimir Shilov <shilow@ukr.net>
|
||||
* @author Vladimir Shilov <shilow@ukr.net>
|
||||
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
// Dictionnay conventions
|
||||
// Class:<class_name>
|
||||
// Class:<class_name>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>
|
||||
// Class:<class_name>/Attribute:<attribute_code>+
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>
|
||||
// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>
|
||||
// Class:<class_name>/Stimulus:<stimulus_code>+
|
||||
|
||||
//
|
||||
// Class: UserLocal
|
||||
//
|
||||
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:UserLocal' => 'Пользователь iTop',
|
||||
'Class:UserLocal+' => 'Пользователь аутентифицированный iTop',
|
||||
'Class:UserLocal/Attribute:password' => 'Пароль',
|
||||
'Class:UserLocal/Attribute:password+' => 'строка аутентификации пользователя',
|
||||
));
|
||||
|
||||
?>
|
||||
?>
|
||||
@@ -350,7 +350,8 @@ EOF
|
||||
$oPage->add('</span>');
|
||||
$oPage->add('<div style="clear:both"></div>');
|
||||
$sMaxUpload = $this->GetMaxUpload();
|
||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||
$oPage->add_ready_script('$("#file").off("change.itop-attachments").on("change.itop-attachments", function() {ajaxFileUpload();});'); // Workaround for a Chrome 36 bug causing multiple (12!) times the same upload. See http://www.redmine.org/issues/17151
|
||||
$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>');
|
||||
|
||||
@@ -352,7 +352,8 @@ EOF
|
||||
$oPage->add('</span>');
|
||||
$oPage->add('<div style="clear:both"></div>');
|
||||
$sMaxUpload = $this->GetMaxUpload();
|
||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||
$oPage->add_ready_script('$("#file").off("change.itop-attachments").on("change.itop-attachments", function() {ajaxFileUpload();});'); // Workaround for a Chrome 36 bug causing multiple (12!) times the same upload. See http://www.redmine.org/issues/17151
|
||||
$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>');
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<constants>
|
||||
<constant id="PORTAL_TYPE_TO_CLASS" xsi:type="string" _delta="redefine"><![CDATA[{"service_request":"UserRequest","incident":"Incident"}]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_TYPE" xsi:type="string" _delta="define"><![CDATA[]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Incident WHERE org_id = :contact->org_id]]></constant>
|
||||
</constants>
|
||||
<classes>
|
||||
<class id="Incident" _delta="define">
|
||||
<parent>Ticket</parent>
|
||||
@@ -227,7 +239,7 @@
|
||||
</field>
|
||||
<field id="sla_tto_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_tto_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
@@ -239,7 +251,7 @@
|
||||
</field>
|
||||
<field id="sla_ttr_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_ttr_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<constants>
|
||||
<constant id="PORTAL_POWER_USER_PROFILE" xsi:type="string" _delta="define"><![CDATA[Portal power user]]></constant>
|
||||
<constant id="PORTAL_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_SERVICE_SUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory WHERE service_id = :svc_id AND ServiceSubcategory.status != "obsolete"]]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id AND Sub.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_ALL_PARAMS" xsi:type="string" _delta="define"><![CDATA[from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,emergency,moreinfo,caller_id,start_date,end_date,duration,impact_duration]]></constant>
|
||||
<constant id="PORTAL_SET_TYPE_FROM" xsi:type="string" _delta="define"><![CDATA[request_type]]></constant>
|
||||
<constant id="PORTAL_TYPE_TO_CLASS" xsi:type="string" _delta="define"><![CDATA[{"service_request":"UserRequest","incident":"Incident"}]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_CRITERIA" xsi:type="string" _delta="define"><![CDATA[ref,start_date,close_date,service_id,caller_id]]></constant>
|
||||
<constant id="PORTAL_TYPE_TO_CLASS" xsi:type="string" _delta="redefine"><![CDATA[{"service_request":"UserRequest","incident":"Incident"}]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
|
||||
@@ -17,15 +9,8 @@
|
||||
<constant id="PORTAL_USERREQUEST_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_TYPE" xsi:type="string" _delta="define"><![CDATA[]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
|
||||
<constant id="PORTAL_INCIDENT_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
|
||||
</constants>
|
||||
<classes>
|
||||
<class id="UserRequest" _delta="define">
|
||||
@@ -281,7 +266,7 @@
|
||||
</field>
|
||||
<field id="sla_tto_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_tto_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
@@ -293,7 +278,7 @@
|
||||
</field>
|
||||
<field id="sla_ttr_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_ttr_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<constants>
|
||||
<constant id="PORTAL_POWER_USER_PROFILE" xsi:type="string" _delta="define"><![CDATA[Portal power user]]></constant>
|
||||
<constant id="PORTAL_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_SERVICE_SUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory WHERE service_id = :svc_id AND ServiceSubcategory.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id AND Sub.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_ALL_PARAMS" xsi:type="string" _delta="define"><![CDATA[from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,emergency,moreinfo,caller_id,start_date,end_date,duration,impact_duration]]></constant>
|
||||
<constant id="PORTAL_SET_TYPE_FROM" xsi:type="string" _delta="define"><![CDATA[request_type]]></constant>
|
||||
<constant id="PORTAL_TYPE_TO_CLASS" xsi:type="string" _delta="define"><![CDATA[]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_PUBLIC_LOG" xsi:type="string" _delta="define"><![CDATA[public_log]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_USER_COMMENT" xsi:type="string" _delta="define"><![CDATA[user_comment]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_FORM_ATTRIBUTES" xsi:type="string" _delta="define"><![CDATA[title,description,impact,urgency]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_TYPE" xsi:type="string" _delta="define"><![CDATA[request_type]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_LIST_ZLIST" xsi:type="string" _delta="define"><![CDATA[finalclass,title,start_date,status,servicesubcategory_id,priority,caller_id]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_CRITERIA" xsi:type="string" _delta="define"><![CDATA[ref,start_date,close_date,service_id,caller_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_CLOSED_ZLIST" xsi:type="string" _delta="define"><![CDATA[title,start_date,close_date,servicesubcategory_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DETAILS_ZLIST" xsi:type="string" _delta="define"><![CDATA[{"col:left":["ref","caller_id","servicesubcategory_id","title","description","solution"],"col:right":["status","priority","start_date","resolution_date","last_update","agent_id"]}]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DISPLAY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id AND caller_id = :contact->id]]></constant>
|
||||
<constant id="PORTAL_USERREQUEST_DISPLAY_POWERUSER_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT UserRequest WHERE org_id = :contact->org_id]]></constant>
|
||||
</constants>
|
||||
<classes>
|
||||
<class id="UserRequest" _delta="define">
|
||||
@@ -280,7 +271,7 @@
|
||||
</field>
|
||||
<field id="sla_tto_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_tto_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>tto</target_attcode>
|
||||
@@ -292,7 +283,7 @@
|
||||
</field>
|
||||
<field id="sla_ttr_passed" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
<item_code>100_passed</item_code>
|
||||
<item_code>100_triggered</item_code>
|
||||
</field>
|
||||
<field id="sla_ttr_over" xsi:type="AttributeSubItem">
|
||||
<target_attcode>ttr</target_attcode>
|
||||
|
||||
@@ -253,7 +253,6 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Portal:ShowServices' => 'Service-Katalog',
|
||||
'Portal:SelectRequestType' => 'Wählen Sie den Typ der Anfrage',
|
||||
'Portal:SelectServiceElementFrom_Service' => 'Wählen Sie ein Service-Element für %1$s',
|
||||
'Portal:SelectRequestTemplate' => 'Wählen Sie eine Template für %1$s',
|
||||
'Portal:ListServices' => 'Liste der Services',
|
||||
'Portal:TitleDetailsFor_Service' => 'Details für Service',
|
||||
'Portal:Button:CreateRequestFromService' => 'EIne Benutzeranfrage betreffend dieses Diensts erzeugen',
|
||||
|
||||
@@ -275,7 +275,6 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Portal:ShowServices' => 'Service catalogue',
|
||||
'Portal:SelectRequestType' => 'Select a type of request',
|
||||
'Portal:SelectServiceElementFrom_Service' => 'Select a service element for %1$s',
|
||||
'Portal:SelectRequestTemplate' => 'Select a template for %1$s',
|
||||
'Portal:ListServices' => 'List of services',
|
||||
'Portal:TitleDetailsFor_Service' => 'Details for Service',
|
||||
'Portal:Button:CreateRequestFromService' => 'Create a Request for this service',
|
||||
|
||||
@@ -279,7 +279,6 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Portal:ShowServices' => 'Catálogo de Servicios',
|
||||
'Portal:SelectRequestType' => 'Seleccione un Tipo de Solicitud',
|
||||
'Portal:SelectServiceElementFrom_Service' => 'Seleccione un Elemento de Servicio para %1$s',
|
||||
'Portal:SelectRequestTemplate' => 'Seleccione una Plantilla para %1$s',
|
||||
'Portal:ListServices' => 'Lista de Servicios',
|
||||
'Portal:TitleDetailsFor_Service' => 'Detalles para el Servicio',
|
||||
'Portal:Button:CreateRequestFromService' => 'Crear una Solicitud para este Servicio',
|
||||
|
||||
@@ -264,7 +264,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Portal:ShowServices' => 'Catalogue de service',
|
||||
'Portal:SelectRequestType' => 'Sélectionnez un type de requête',
|
||||
'Portal:SelectServiceElementFrom_Service' => 'Sélectionnez un élément de service pour %1$s',
|
||||
'Portal:SelectRequestTemplate' => 'Sélectionnez un modèle de requête pour %1$s',
|
||||
'Portal:ListServices' => 'Liste des services',
|
||||
'Portal:TitleDetailsFor_Service' => 'Détail d\'un service',
|
||||
'Portal:Button:CreateRequestFromService' => 'Créer une requête pour ce service',
|
||||
|
||||
@@ -250,7 +250,6 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Portal:ShowServices' => 'サービスカタログ',
|
||||
'Portal:SelectRequestType' => '要求のタイプを選択',
|
||||
'Portal:SelectServiceElementFrom_Service' => '%1$s のサービス要素を選択',
|
||||
'Portal:SelectRequestTemplate' => 'Select a template for %1$s のテンプレートを選択',
|
||||
'Portal:ListServices' => 'サービスのリスト',
|
||||
'Portal:TitleDetailsFor_Service' => 'サービスの詳細',
|
||||
'Portal:Button:CreateRequestFromService' => 'このサービスへの要求を作成',
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
|
||||
<constants>
|
||||
<constant id="RESPONSE_TICKET_SLT_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT SLT AS slt JOIN lnkSLAToSLT AS l1 ON l1.slt_id=slt.id JOIN SLA AS sla ON l1.sla_id=sla.id JOIN lnkCustomerContractToService AS l2 ON l2.sla_id=sla.id JOIN CustomerContract AS sc ON l2.customercontract_id=sc.id WHERE slt.metric = :metric AND l2.service_id = :this->service_id AND sc.org_id = :this->org_id AND slt.request_type = :request_type AND slt.priority = :this->priority]]></constant>
|
||||
<constant id="PORTAL_POWER_USER_PROFILE" xsi:type="string" _delta="define"><![CDATA[Portal power user]]></constant>
|
||||
<constant id="PORTAL_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_SERVICE_SUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory WHERE service_id = :svc_id AND ServiceSubcategory.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICECATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.id = :id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY" xsi:type="string" _delta="define"><![CDATA[SELECT ServiceSubcategory AS Sub JOIN Service AS Svc ON Sub.service_id = Svc.id WHERE Sub.id=:id AND Sub.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_ALL_PARAMS" xsi:type="string" _delta="define"><![CDATA[from_service_id,org_id,caller_id,service_id,servicesubcategory_id,title,description,impact,emergency,moreinfo,caller_id,start_date,end_date,duration,impact_duration]]></constant>
|
||||
<constant id="PORTAL_SET_TYPE_FROM" xsi:type="string" _delta="define"><![CDATA[request_type]]></constant>
|
||||
<constant id="PORTAL_TYPE_TO_CLASS" xsi:type="string" _delta="define"><![CDATA[]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_CRITERIA" xsi:type="string" _delta="define"><![CDATA[ref,start_date,close_date,service_id,caller_id]]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_service_id" xsi:type="string" _delta="define"><![CDATA[SELECT Service AS s JOIN lnkCustomerContractToService AS l1 ON l1.service_id=s.id JOIN CustomerContract AS cc ON l1.customercontract_id=cc.id WHERE cc.org_id = :org_id AND s.status != 'obsolete']]></constant>
|
||||
<constant id="PORTAL_TICKETS_SEARCH_FILTER_caller_id" xsi:type="string" _delta="define"><![CDATA[SELECT Person WHERE org_id = :org_id]]></constant>
|
||||
</constants>
|
||||
<classes>
|
||||
<class id="Ticket" _delta="define">
|
||||
|
||||
@@ -810,6 +810,7 @@ Wenn Aktionen mit Trigger verknüpft sind, bekommt jede Aktion eine Auftragsnumm
|
||||
'Portal:AddAttachment' => ' Attachment hinzufügen',
|
||||
'Portal:RemoveAttachment' => 'Attachment entfernen',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => 'Attachment #%1$d an %2$s (%3$s)',
|
||||
'Portal:SelectRequestTemplate' => 'Wählen Sie eine Template für %1$s',
|
||||
'Enum:Undefined' => 'Nicht definiert',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s Tage %2$s Stunden %3$s Minuten %4$s Sekunden',
|
||||
'UI:ModifyAllPageTitle' => 'Alle modifizieren',
|
||||
|
||||
@@ -996,6 +996,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'Portal:AddAttachment' => ' Add Attachment ',
|
||||
'Portal:RemoveAttachment' => ' Remove Attachment ',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => 'Attachment #%1$d to %2$s (%3$s)',
|
||||
'Portal:SelectRequestTemplate' => 'Select a template for %1$s',
|
||||
'Enum:Undefined' => 'Undefined',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s Days %2$s Hours %3$s Minutes %4$s Seconds',
|
||||
'UI:ModifyAllPageTitle' => 'Modify All',
|
||||
@@ -1085,7 +1086,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',
|
||||
@@ -1185,7 +1186,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.',
|
||||
|
||||
|
||||
@@ -995,6 +995,7 @@ Cuando se asocien con un disparador, cada acción recibe un número de "orden",
|
||||
'Portal:AddAttachment' => 'Agregar Anexo',
|
||||
'Portal:RemoveAttachment' => 'Borrar Anexo',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => 'Anexo #%1$d to %2$s (%3$s)',
|
||||
'Portal:SelectRequestTemplate' => 'Seleccione una Plantilla para %1$s',
|
||||
'Enum:Undefined' => 'No Definido',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s Días %2$s Hrs. %3$s Mins. %4$s Segs.',
|
||||
'UI:ModifyAllPageTitle' => 'Modificar Todos',
|
||||
@@ -1084,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',
|
||||
@@ -1183,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?',
|
||||
|
||||
@@ -544,11 +544,11 @@ Opérateurs :<br/>
|
||||
'Class:Trigger/Attribute:action_list+' => '',
|
||||
'Class:Trigger/Attribute:finalclass' => 'Type',
|
||||
'Class:Trigger/Attribute:finalclass+' => '',
|
||||
'Class:TriggerOnObject' => 'Trigger on a class of objects',
|
||||
'Class:TriggerOnObject' => 'Déclencheur sur modification de données',
|
||||
'Class:TriggerOnObject+' => '',
|
||||
'Class:TriggerOnObject/Attribute:target_class' => 'Classe cible',
|
||||
'Class:TriggerOnObject/Attribute:target_class+' => 'label',
|
||||
'Class:TriggerOnStateChange' => 'Trigger on object state change',
|
||||
'Class:TriggerOnStateChange' => 'Déclencheur sur changement d\'état',
|
||||
'Class:TriggerOnStateChange+' => '',
|
||||
'Class:TriggerOnStateChange/Attribute:state' => 'Etat',
|
||||
'Class:TriggerOnStateChange/Attribute:state+' => 'label',
|
||||
|
||||
@@ -839,6 +839,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
'Portal:AddAttachment' => ' Ajouter une pièce jointe ',
|
||||
'Portal:RemoveAttachment' => ' Enlever la pièce jointe ',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => 'Pièce jointe #%1$d à %2$s (%3$s)',
|
||||
'Portal:SelectRequestTemplate' => 'Sélectionnez un modèle de requête pour %1$s',
|
||||
'Enum:Undefined' => 'Non défini',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s J %2$s H %3$s min %4$s s',
|
||||
'UI:ModifyAllPageTitle' => 'Modification par lots',
|
||||
@@ -927,7 +928,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',
|
||||
@@ -1026,7 +1027,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.',
|
||||
|
||||
|
||||
@@ -816,6 +816,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Portal:AddAttachment' => ' 添付を追加 ',
|
||||
'Portal:RemoveAttachment' => ' 添付を削除 ',
|
||||
'Portal:Attachment_No_To_Ticket_Name' => '$2$s ($3$s)への添付 #%1$d',
|
||||
'Portal:SelectRequestTemplate' => 'Select a template for %1$s のテンプレートを選択',
|
||||
'Enum:Undefined' => '未定義',
|
||||
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s 日 %2$s 時 %3$s 分 %4$s 秒',
|
||||
'UI:ModifyAllPageTitle' => '全てを修正',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -891,11 +891,16 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'UI:DashletCreation:EditNow' => 'Edit the Dashboard~~',
|
||||
'UI:DashboardEdit:Title' => 'Dashboard Editor~~',
|
||||
'UI:DashboardEdit:DashboardTitle' => 'Заголовок',
|
||||
'UI:DashboardEdit:Layout' => 'Слой',
|
||||
'UI:DashboardEdit:Properties' => 'Dashboard Properties~~',
|
||||
'UI:DashboardEdit:Dashlets' => 'Available Dashlets~~',
|
||||
'UI:DashboardEdit:DashletProperties' => 'Dashlet Properties~~',
|
||||
'UI:Form:Property' => 'Свойства',
|
||||
'UI:DashboardEdit:AutoReload' => 'Обновлять автоматически',
|
||||
'UI:DashboardEdit:AutoReloadSec' => 'Интервал обновления (секунды)',
|
||||
'UI:DashboardEdit:AutoReloadSec+' => 'Минимальный интервал %1$d секунд',
|
||||
|
||||
'UI:DashboardEdit:Layout' => 'Макет',
|
||||
'UI:DashboardEdit:Properties' => 'Свойства дашборда',
|
||||
'UI:DashboardEdit:Dashlets' => 'Доступные дашлеты',
|
||||
'UI:DashboardEdit:DashletProperties' => 'Свойства дашлета',
|
||||
|
||||
'UI:Form:Property' => 'Свойство',
|
||||
'UI:Form:Value' => 'Значение',
|
||||
'UI:DashletPlainText:Label' => 'Текст',
|
||||
'UI:DashletPlainText:Description' => 'Plain text (no formatting)~~',
|
||||
@@ -950,5 +955,56 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'DayOfWeek-Thursday' => 'Четверг',
|
||||
'DayOfWeek-Friday' => 'Пятница',
|
||||
'DayOfWeek-Saturday' => 'Суббота',
|
||||
'Month-01' => 'Январь',
|
||||
'Month-02' => 'Февраль',
|
||||
'Month-03' => 'Март',
|
||||
'Month-04' => 'Апрель',
|
||||
'Month-05' => 'Май',
|
||||
'Month-06' => 'Июнь',
|
||||
'Month-07' => 'Июль',
|
||||
'Month-08' => 'Август',
|
||||
'Month-09' => 'Сентябрь',
|
||||
'Month-10' => 'Октябрь',
|
||||
'Month-11' => 'Ноябрь',
|
||||
'Month-12' => 'Декабрь',
|
||||
|
||||
'UI:Menu:ShortcutList' => 'Добавить в избранное...',
|
||||
'UI:ShortcutRenameDlg:Title' => 'Переименовать ссылку',
|
||||
'UI:ShortcutListDlg:Title' => 'Добавить в избранное ссылку на список',
|
||||
'UI:ShortcutDelete:Confirm' => 'Подтвердите удаление ссылки (ссылок).',
|
||||
'Menu:MyShortcuts' => 'Избранное',
|
||||
'Class:Shortcut' => 'Ссылка',
|
||||
'Class:Shortcut+' => '',
|
||||
'Class:Shortcut/Attribute:name' => 'Название',
|
||||
'Class:Shortcut/Attribute:name+' => 'Label used in the menu and page title',
|
||||
'Class:ShortcutOQL' => 'Search result shortcut~~',
|
||||
'Class:ShortcutOQL+' => '',
|
||||
'Class:ShortcutOQL/Attribute:oql' => 'Запрос',
|
||||
'Class:ShortcutOQL/Attribute:oql+' => 'OQL defining the list of objects to search for',
|
||||
'Class:ShortcutOQL/Attribute:auto_reload' => 'Automatic refresh',
|
||||
'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/tip' => 'The minimum allowed is %1$d seconds',
|
||||
|
||||
'UI:FillAllMandatoryFields' => 'Пожалуйста, заполните все обязательные поля.',
|
||||
|
||||
'UI:CSVImportConfirmTitle' => 'Please confirm the operation',
|
||||
'UI:CSVImportConfirmMessage' => 'Are you sure you want to do this?',
|
||||
'UI:CSVImportError_items' => 'Errors: %1$d',
|
||||
'UI:CSVImportCreated_items' => 'Created: %1$d',
|
||||
'UI:CSVImportModified_items' => 'Modified: %1$d',
|
||||
'UI:CSVImportUnchanged_items' => 'Unchanged: %1$d',
|
||||
|
||||
'UI:Button:Remove' => 'Remove',
|
||||
'UI:AddAnExisting_Class' => 'Add objects of type %1$s...',
|
||||
'UI:SelectionOf_Class' => 'Selection of objects of type %1$s',
|
||||
|
||||
'UI:AboutBox' => 'Об этом iTop...',
|
||||
'UI:About:Title' => 'Об этом iTop',
|
||||
'UI:About:DataModel' => 'Модель данных',
|
||||
'UI:About:Support' => 'Информация для технической поддержки',
|
||||
'UI:About:Licenses' => 'Лицензии',
|
||||
'UI:About:Modules' => 'Установленные модули',
|
||||
));
|
||||
?>
|
||||
@@ -29,7 +29,7 @@ jQuery.extend(
|
||||
var fileId = 'jUploadFile' + id;
|
||||
var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
|
||||
var oldElement = jQuery('#' + fileElementId);
|
||||
var newElement = jQuery(oldElement).clone();
|
||||
var newElement = jQuery(oldElement).clone(true);
|
||||
jQuery(oldElement).attr('id', fileId);
|
||||
jQuery(oldElement).before(newElement);
|
||||
jQuery(oldElement).appendTo(form);
|
||||
@@ -131,12 +131,12 @@ jQuery.extend(
|
||||
jQuery.handleError(s, xml, null, e);
|
||||
}
|
||||
|
||||
}, 100)
|
||||
}, 100);
|
||||
|
||||
xml = null
|
||||
xml = null;
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
// Timeout checker
|
||||
if ( s.timeout > 0 )
|
||||
{
|
||||
@@ -197,7 +197,9 @@ jQuery.extend({
|
||||
s.error( xhr, status, e );
|
||||
// If we have some XML response text (e.g. from an AJAX call) then log it in the console
|
||||
else if(xhr.responseText)
|
||||
console.log(xhr.responseText);
|
||||
{
|
||||
//console.log(xhr.responseText);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -447,59 +447,70 @@ function sprintf(format, etc) {
|
||||
|
||||
this.construct = function(settings) {
|
||||
|
||||
return this.each(function() {
|
||||
|
||||
config = $.extend(this.config, $.tablesorterPager.defaults, settings);
|
||||
return this.each(function() {
|
||||
|
||||
var table = this, pager = config.container;
|
||||
try
|
||||
{
|
||||
config = $.extend(this.config, $.tablesorterPager.defaults, settings);
|
||||
|
||||
var table = this, pager = config.container;
|
||||
|
||||
this.ajax_request = null;
|
||||
this.ajax_request = null;
|
||||
|
||||
config.selectedSize = parseInt($(".pagesize",pager).val());
|
||||
setPageSize(table,config.selectedSize, false);
|
||||
restoreParams(table, config);
|
||||
|
||||
//$(this).trigger("appendCache"); // Load the data
|
||||
//console.log($.tablesorterPager);
|
||||
applySelection(table);
|
||||
config.selectedSize = parseInt($(".pagesize",pager).val());
|
||||
|
||||
$('.gotopage',pager).click(function() {
|
||||
var idx = $(this).attr('page');
|
||||
table.config.page = idx;
|
||||
moveToPage(table);
|
||||
});
|
||||
|
||||
$(config.cssFirst,pager).click(function() {
|
||||
moveToFirstPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssNext,pager).click(function() {
|
||||
moveToNextPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssPrev,pager).click(function() {
|
||||
moveToPrevPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssLast,pager).click(function() {
|
||||
moveToLastPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssPageSize,pager).change(function() {
|
||||
setPageSize(table,parseInt($(this).val()), true);
|
||||
return false;
|
||||
});
|
||||
$(table).find(':checkbox.checkAll').removeAttr('onclick').click(function() {
|
||||
return checkAll(table, pager, this.checked);
|
||||
});
|
||||
setPageSize(table,config.selectedSize, false);
|
||||
restoreParams(table, config);
|
||||
|
||||
$(table).bind('load_selection', function() {
|
||||
loadSelection(table, pager);
|
||||
//$(this).trigger("appendCache"); // Load the data
|
||||
//console.log($.tablesorterPager);
|
||||
applySelection(table);
|
||||
});
|
||||
$(table).bind('check_all', function() {
|
||||
checkAll(table, pager, true);
|
||||
});
|
||||
|
||||
$('.gotopage',pager).click(function() {
|
||||
var idx = $(this).attr('page');
|
||||
table.config.page = idx;
|
||||
moveToPage(table);
|
||||
});
|
||||
|
||||
$(config.cssFirst,pager).click(function() {
|
||||
moveToFirstPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssNext,pager).click(function() {
|
||||
moveToNextPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssPrev,pager).click(function() {
|
||||
moveToPrevPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssLast,pager).click(function() {
|
||||
moveToLastPage(table);
|
||||
return false;
|
||||
});
|
||||
$(config.cssPageSize,pager).change(function() {
|
||||
setPageSize(table,parseInt($(this).val()), true);
|
||||
return false;
|
||||
});
|
||||
$(table).find(':checkbox.checkAll').removeAttr('onclick').click(function() {
|
||||
return checkAll(table, pager, this.checked);
|
||||
});
|
||||
|
||||
$(table).bind('load_selection', function() {
|
||||
loadSelection(table, pager);
|
||||
applySelection(table);
|
||||
});
|
||||
$(table).bind('check_all', function() {
|
||||
checkAll(table, pager, true);
|
||||
});
|
||||
}
|
||||
catch(err)
|
||||
{
|
||||
if (console && console.log)
|
||||
{
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,19 +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()
|
||||
@@ -254,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)
|
||||
@@ -372,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()
|
||||
@@ -425,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] = [];
|
||||
|
||||
178
pages/UI.php
178
pages/UI.php
@@ -398,6 +398,7 @@ try
|
||||
case 'form_for_modify_all': // Form to modify multiple objects (bulk modify)
|
||||
case 'bulk_stimulus': // For to apply a stimulus to multiple objects
|
||||
case 'stimulus': // Form displayed when applying a stimulus (state change)
|
||||
case 'apply_stimulus': // Form displayed when applying a stimulus (state change)
|
||||
$oP->add_linked_script("../js/json.js");
|
||||
$oP->add_linked_script("../js/forms-json-utils.js");
|
||||
$oP->add_linked_script("../js/wizardhelper.js");
|
||||
@@ -1381,132 +1382,7 @@ EOF
|
||||
$oObj = MetaModel::GetObject($sClass, $id, false);
|
||||
if ($oObj != null)
|
||||
{
|
||||
$aTransitions = $oObj->EnumTransitions();
|
||||
$aStimuli = MetaModel::EnumStimuli($sClass);
|
||||
if (!isset($aTransitions[$sStimulus]))
|
||||
{
|
||||
// Invalid stimulus
|
||||
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel()));
|
||||
}
|
||||
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
|
||||
$sActionDetails = $aStimuli[$sStimulus]->GetDescription();
|
||||
$aTransition = $aTransitions[$sStimulus];
|
||||
$sTargetState = $aTransition['target_state'];
|
||||
$aTargetStates = MetaModel::EnumStates($sClass);
|
||||
$oP->add("<div class=\"page_header\">\n");
|
||||
$oP->add("<h1>$sActionLabel - <span class=\"hilite\">{$oObj->GetName()}</span></h1>\n");
|
||||
$oP->set_title($sActionLabel);
|
||||
$oP->add("</div>\n");
|
||||
$aTargetState = $aTargetStates[$sTargetState];
|
||||
$aExpectedAttributes = $aTargetState['attribute_list'];
|
||||
$oP->add("<h1>$sActionDetails</h1>\n");
|
||||
$sButtonsPosition = MetaModel::GetConfig()->Get('buttons_position');
|
||||
if ($sButtonsPosition == 'bottom')
|
||||
{
|
||||
// bottom: Displays the ticket details BEFORE the actions
|
||||
$oP->add('<div class="ui-widget-content">');
|
||||
$oObj->DisplayBareProperties($oP);
|
||||
$oP->add('</div>');
|
||||
}
|
||||
$oP->add("<div class=\"wizContainer\">\n");
|
||||
$oP->add("<form id=\"apply_stimulus\" method=\"post\" onSubmit=\"return OnSubmit('apply_stimulus');\">\n");
|
||||
$aDetails = array();
|
||||
$iFieldIndex = 0;
|
||||
$aFieldsMap = array();
|
||||
|
||||
$aDetailsList = $oObj->FlattenZList(MetaModel::GetZListItems($sClass, 'details'));
|
||||
// Order the fields based on their dependencies, set the fields for which there is only one possible value
|
||||
// and perform this in the order of dependencies to avoid dead-ends
|
||||
$aDeps = array();
|
||||
foreach($aDetailsList as $sAttCode)
|
||||
{
|
||||
$aDeps[$sAttCode] = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
|
||||
}
|
||||
$aList = $oObj->OrderDependentFields($aDeps);
|
||||
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
// Consider only the "expected" fields for the target state
|
||||
if (array_key_exists($sAttCode, $aExpectedAttributes))
|
||||
{
|
||||
$iExpectCode = $aExpectedAttributes[$sAttCode];
|
||||
// Prompt for an attribute if
|
||||
// - the attribute must be changed or must be displayed to the user for confirmation
|
||||
// - or the field is mandatory and currently empty
|
||||
if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && ($oObj->Get($sAttCode) == '')) )
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
$aArgs = array('this' => $oObj);
|
||||
// If the field is mandatory, set it to the only possible value
|
||||
if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY))
|
||||
{
|
||||
if ($oAttDef->IsExternalKey())
|
||||
{
|
||||
$oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs);
|
||||
if ($oAllowedValues->Count() == 1)
|
||||
{
|
||||
$oRemoteObj = $oAllowedValues->Fetch();
|
||||
$oObj->Set($sAttCode, $oRemoteObj->GetKey());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
|
||||
if (count($aAllowedValues) == 1)
|
||||
{
|
||||
$aValues = array_keys($aAllowedValues);
|
||||
$oObj->Set($sAttCode, $aValues[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $oObj->Get($sAttCode), $oObj->GetEditValue($sAttCode), 'att_'.$iFieldIndex, '', $iExpectCode, $aArgs);
|
||||
$aDetails[] = array('label' => '<span>'.$oAttDef->GetLabel().'</span>', 'value' => "<span id=\"field_att_$iFieldIndex\">$sHTMLValue</span>");
|
||||
$aFieldsMap[$sAttCode] = 'att_'.$iFieldIndex;
|
||||
$iFieldIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oP->add('<table><tr><td>');
|
||||
$oP->details($aDetails);
|
||||
$oP->add('</td></tr></table>');
|
||||
$oP->add("<input type=\"hidden\" name=\"id\" value=\"$id\" id=\"id\">\n");
|
||||
$aFieldsMap['id'] = 'id';
|
||||
$oP->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"operation\" value=\"apply_stimulus\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"stimulus\" value=\"$sStimulus\">\n");
|
||||
$oP->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
|
||||
$oP->add($oAppContext->GetForForm());
|
||||
$oP->add("<button type=\"button\" class=\"action\" onClick=\"BackToDetails('$sClass', $id)\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oP->add("<button type=\"submit\" class=\"action\"><span>$sActionLabel</span></button>\n");
|
||||
$oP->add("</form>\n");
|
||||
$oP->add("</div>\n");
|
||||
if ($sButtonsPosition != 'top')
|
||||
{
|
||||
// bottom or both: Displays the ticket details AFTER the actions
|
||||
$oP->add('<div class="ui-widget-content">');
|
||||
$oObj->DisplayBareProperties($oP);
|
||||
$oP->add('</div>');
|
||||
}
|
||||
|
||||
$iFieldsCount = count($aFieldsMap);
|
||||
$sJsonFieldsMap = json_encode($aFieldsMap);
|
||||
|
||||
$oP->add_script(
|
||||
<<<EOF
|
||||
// Initializes the object once at the beginning of the page...
|
||||
var oWizardHelper = new WizardHelper('$sClass', '', '$sTargetState');
|
||||
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
|
||||
oWizardHelper.SetFieldsCount($iFieldsCount);
|
||||
EOF
|
||||
);
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
// Starts the validation when the page is ready
|
||||
CheckFields('apply_stimulus', false);
|
||||
EOF
|
||||
);
|
||||
$oObj->DisplayStimulusForm($oP, $sStimulus);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1533,6 +1409,7 @@ EOF
|
||||
$aStimuli = MetaModel::EnumStimuli($sClass);
|
||||
$sMessage = '';
|
||||
$sSeverity = 'ok';
|
||||
$bDisplayDetails = true;
|
||||
if (!isset($aTransitions[$sStimulus]))
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel()));
|
||||
@@ -1568,20 +1445,52 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
$oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState);
|
||||
$oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState);
|
||||
|
||||
if (count($aErrors) == 0)
|
||||
{
|
||||
if ($oObj->ApplyStimulus($sStimulus))
|
||||
$sIssues = '';
|
||||
$bApplyStimulus = true;
|
||||
list($bRes, $aIssues) = $oObj->CheckToWrite(); // Check before trying to write the object
|
||||
if ($bRes)
|
||||
{
|
||||
$oObj->DBUpdate();
|
||||
$sMessage = Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName());
|
||||
$sSeverity = 'ok';
|
||||
try
|
||||
{
|
||||
$bApplyStimulus = $oObj->ApplyStimulus($sStimulus); // will write the object in the DB
|
||||
}
|
||||
catch(CoreException $e)
|
||||
{
|
||||
// Rollback to the previous state... by reloading the object from the database and applying the modifications again
|
||||
$oObj = MetaModel::GetObject(get_class($oObj), $oObj->GetKey());
|
||||
$oObj->UpdateObjectFromPostedForm('', array_keys($aExpectedAttributes), $sTargetState);
|
||||
$aData = $e->getContextData();
|
||||
$sIssues = (array_key_exists('issues', $aData)) ? $aData['issues'] : 'Unknown error...';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sIssues = implode(' ', $aIssues);
|
||||
}
|
||||
|
||||
if (!$bApplyStimulus)
|
||||
{
|
||||
$sMessage = Dict::S('UI:FailedToApplyStimuli');
|
||||
$sSeverity = 'error';
|
||||
$sSeverity = 'error';
|
||||
}
|
||||
else if ($sIssues != '')
|
||||
{
|
||||
$bDisplayDetails = false;
|
||||
// Found issues, explain and give the user a second chance
|
||||
//
|
||||
$oObj->DisplayStimulusForm($oP, $sStimulus);
|
||||
$sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten',$sIssues);
|
||||
$oP->add_ready_script("alert('".addslashes($sIssueDesc)."');");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMessage = Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName());
|
||||
$sSeverity = 'ok';
|
||||
utils::RemoveTransaction($sTransactionId);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1590,7 +1499,10 @@ EOF
|
||||
$sSeverity = 'error';
|
||||
}
|
||||
}
|
||||
ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity);
|
||||
if ($bDisplayDetails)
|
||||
{
|
||||
ReloadAndDisplay($oP, $oObj, 'apply_stimulus', $sMessage, $sSeverity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ try
|
||||
case 'pagination':
|
||||
$oPage->SetContentType('text/html');
|
||||
$extraParams = utils::ReadParam('extra_param', '', false, 'raw_data');
|
||||
$aExtraParams = array();
|
||||
if (is_array($extraParams))
|
||||
{
|
||||
$aExtraParams = $extraParams;
|
||||
@@ -64,10 +65,13 @@ try
|
||||
else
|
||||
{
|
||||
$sExtraParams = stripslashes($extraParams);
|
||||
$aExtraParams = array();
|
||||
if (!empty($sExtraParams))
|
||||
{
|
||||
$aExtraParams = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */);
|
||||
$val = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */);
|
||||
if ($val !== null)
|
||||
{
|
||||
$aExtraParams = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($sEncoding == 'oql')
|
||||
@@ -766,9 +770,15 @@ try
|
||||
case 'download_document':
|
||||
$id = utils::ReadParam('id', '');
|
||||
$sField = utils::ReadParam('field', '');
|
||||
$iCacheSec = (int) utils::ReadParam('cache', 0);
|
||||
if (!empty($sClass) && !empty($id) && !empty($sField))
|
||||
{
|
||||
DownloadDocument($oPage, $sClass, $id, $sField, 'attachment');
|
||||
if ($iCacheSec > 0)
|
||||
{
|
||||
$oPage->add_header("Expires: "); // Reset the value set in ajax_page
|
||||
$oPage->add_header("Cache-Control: no-transform,public,max-age=$iCacheSec,s-maxage=$iCacheSec");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -816,6 +826,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':
|
||||
@@ -1001,7 +1012,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();
|
||||
@@ -1042,6 +1053,7 @@ EOF
|
||||
|
||||
case 'shortcut_delete_go':
|
||||
$oSearch = new DBObjectSearch('Shortcut');
|
||||
$oSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$aShortcuts = utils::ReadMultipleSelection($oSearch);
|
||||
foreach ($aShortcuts as $iShortcut)
|
||||
{
|
||||
|
||||
@@ -50,6 +50,46 @@ function GetTicketClasses()
|
||||
return $aClasses;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to protect the portal against malicious usages
|
||||
* Throws an exception if the current user is not allowed to view the object details
|
||||
*/
|
||||
function ValidateObject($oObject)
|
||||
{
|
||||
if (IsPowerUser())
|
||||
{
|
||||
$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_POWERUSER_QUERY';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sValidationDefine = 'PORTAL_'.strtoupper(get_class($oObject)).'_DISPLAY_QUERY';
|
||||
}
|
||||
if (defined($sValidationDefine))
|
||||
{
|
||||
$sValidationOql = constant($sValidationDefine);
|
||||
$oSearch = DBObjectSearch::FromOQL($sValidationOql);
|
||||
$oSearch->AddCondition('id', $oObject->GetKey());
|
||||
|
||||
if ($iUser = UserRights::GetContactId())
|
||||
{
|
||||
$oContact = MetaModel::GetObject('Contact', $iUser);
|
||||
$aArgs = $oContact->ToArgs('contact');
|
||||
}
|
||||
else
|
||||
{
|
||||
$aArgs = array();
|
||||
}
|
||||
|
||||
$oSet = new DBObjectSet($oSearch, array(), $aArgs);
|
||||
if ($oSet->Count() == 0)
|
||||
{
|
||||
throw new SecurityException('You are not allowed to access the object '.get_class($oObject).'::'.$oObject->GetKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to get the relevant constant
|
||||
*/
|
||||
@@ -481,22 +521,19 @@ function RequestCreationForm($oP, $oUserOrg, $iSvcId = null, $iSubSvcId = null,
|
||||
$sValue = "<span id=\"field_{$sInputId}\">".$oRequest->GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $value, '', 'attr_'.$sAttCode, '', $iFlags, $aArgs).'</span>';
|
||||
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sValue);
|
||||
}
|
||||
|
||||
$aHidden = array();
|
||||
if (!empty($aTemplateFields))
|
||||
{
|
||||
foreach ($aTemplateFields as $sAttCode => $oField)
|
||||
{
|
||||
if (!in_array($sAttCode, $aList))
|
||||
$sValue = $oField->GetFormElement($oP, $sClass);
|
||||
if ($oField->Get('input_type') == 'hidden')
|
||||
{
|
||||
$sValue = $oField->GetFormElement($oP, $sClass);
|
||||
if ($oField->Get('input_type') == 'hidden')
|
||||
{
|
||||
$aHidden[] = $sValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aDetails[] = array('label' => $oField->GetAsHTML('label'), 'value' => $sValue);
|
||||
}
|
||||
$aHidden[] = $sValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aDetails[] = array('label' => $oField->GetAsHTML('label'), 'value' => $sValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -536,7 +573,11 @@ EOF
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($aParameters['template_id']) && ($aParameters['template_id'] != 0))
|
||||
{
|
||||
$oP->add("<input type=\"hidden\" name=\"attr_template_id\" value=\"{$aParameters['template_id']}\">");
|
||||
}
|
||||
$oP->add(implode("\n", $aHidden));
|
||||
$oAttPlugin = new AttachmentPlugIn();
|
||||
$oAttPlugin->OnDisplayRelations($oRequest, $oP, true /* edit */);
|
||||
|
||||
@@ -610,9 +651,11 @@ function DoCreateRequest($oP, $oUserOrg)
|
||||
|
||||
$sClass = ComputeClass($oServiceSubCategory->GetKey());
|
||||
$oRequest = MetaModel::NewObject($sClass);
|
||||
$aAttList = array_merge(explode(',', GetConstant($sClass, 'FORM_ATTRIBUTES')), array('service_id', 'servicesubcategory_id'));
|
||||
$oRequest->UpdateObjectFromPostedForm('' /* form prefix */, $aAttList);
|
||||
$oRequest->Set('org_id', $oUserOrg->GetKey());
|
||||
$oRequest->Set('caller_id', UserRights::GetContactId());
|
||||
$oRequest->UpdateObjectFromPostedForm();
|
||||
|
||||
if (isset($aParameters['moreinfo']))
|
||||
{
|
||||
// There is a template, insert it into the description
|
||||
@@ -872,6 +915,8 @@ function ShowDetailsRequest(WebPage $oP, $oObj)
|
||||
case 'assigned':
|
||||
case 'frozen':
|
||||
case 'pending':
|
||||
case 'dispatched':
|
||||
case 'redispatched':
|
||||
$aEditAtt = array(
|
||||
$sLogAttCode => '????'
|
||||
);
|
||||
@@ -1119,9 +1164,17 @@ function MakeStimulusForm(WebPage $oP, $oObj, $sStimulusCode, $aEditAtt)
|
||||
|
||||
function RunStimulusDialog(sStimulusCode, sTitle, sOkButtonLabel)
|
||||
{
|
||||
var sWidth = 'auto';
|
||||
if (sStimulusCode == 'ev_reopen')
|
||||
{
|
||||
// Avoid having a dialog spanning the complete width of the window
|
||||
// just because it contains a CaseLog entry
|
||||
sWidth = '80%';
|
||||
}
|
||||
|
||||
$('#'+sStimulusCode+'_dialog').dialog({
|
||||
height: 'auto',
|
||||
width: 'auto',
|
||||
width: sWidth,
|
||||
modal: true,
|
||||
title: sTitle,
|
||||
buttons: [
|
||||
@@ -1130,8 +1183,13 @@ function RunStimulusDialog(sStimulusCode, sTitle, sOkButtonLabel)
|
||||
} },
|
||||
{ text: "$sCancelButtonLabel", click: function() {
|
||||
$(this).dialog( "close" );
|
||||
} },
|
||||
],
|
||||
} }
|
||||
]
|
||||
});
|
||||
// Start the validation
|
||||
CheckFields(sStimulusCode+'_form', false);
|
||||
$('#'+sStimulusCode+'_form').submit( function() {
|
||||
return OnSubmit(sStimulusCode+'_form');
|
||||
});
|
||||
}
|
||||
EOF
|
||||
@@ -1243,6 +1301,7 @@ try
|
||||
$oP->set_title(Dict::S('Portal:TitleDetailsFor_Request'));
|
||||
DisplayMainMenu($oP);
|
||||
$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
|
||||
ValidateObject($oObj);
|
||||
DisplayObject($oP, $oObj, $oUserOrg);
|
||||
break;
|
||||
|
||||
@@ -1252,6 +1311,7 @@ try
|
||||
if (!MetaModel::DBIsReadOnly())
|
||||
{
|
||||
$oObj = $oP->FindObjectFromArgs(GetTicketClasses());
|
||||
ValidateObject($oObj);
|
||||
$aAttList = array(
|
||||
GetConstant(get_class($oObj), 'PUBLIC_LOG'),
|
||||
'user_satisfaction',
|
||||
|
||||
@@ -41,6 +41,8 @@ PORTAL_<TICKET-CLASS>_TYPE: optional attribute to be set with the value of "requ
|
||||
PORTAL_<TICKET-CLASS>_LIST_ZLIST: list of attribute displayed in the lists (opened and resolved)
|
||||
PORTAL_<TICKET-CLASS>_CLOSED_ZLIST: list of attribute displayed in the list of closed tickets
|
||||
PORTAL_<TICKET-CLASS>_DETAILS_ZLIST: selection and presentation of attributes in the page that shows their details
|
||||
PORTAL_<TICKET-CLASS>_DISPLAY_QUERY: selection of displayable objects (use parameters contact->attcode to check things against the user/contact)
|
||||
PORTAL_<TICKET-CLASS>_DISPLAY_POWERUSER_QUERY: selection of displayable objects for power users (use parameters contact->attcode to check things against the user/contact)
|
||||
|
||||
|
||||
How to add a type of ticket (example: Incident)
|
||||
|
||||
@@ -617,7 +617,11 @@ EOF;
|
||||
$aClassParams = array();
|
||||
$aClassParams['category'] = $this->GetPropString($oProperties, 'category', '');
|
||||
$aClassParams['key_type'] = "'autoincrement'";
|
||||
|
||||
if ((bool) $this->GetPropNumber($oProperties, 'is_link', 0))
|
||||
{
|
||||
$aClassParams['is_link'] = 'true';
|
||||
}
|
||||
|
||||
if ($oNaming = $oProperties->GetOptionalElement('naming'))
|
||||
{
|
||||
$oNameAttributes = $oNaming->GetUniqueElement('attributes');
|
||||
@@ -1462,6 +1466,8 @@ class ProfilesConfig
|
||||
|
||||
protected static \$aLINKTOCLASSES = $sLinkToClasses;
|
||||
|
||||
// Now replaced by MetaModel::GetLinkClasses (working with 1.x)
|
||||
// This function could be deprecated
|
||||
public static function GetLinkClasses()
|
||||
{
|
||||
return self::\$aLINKTOCLASSES;
|
||||
|
||||
@@ -57,12 +57,6 @@ class ModuleInstallation extends cmdbAbstractObject
|
||||
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
protected function OnInsert()
|
||||
{
|
||||
$this->Set('installed', time());
|
||||
parent::OnInsert();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -466,11 +466,13 @@ class RunTimeEnvironment
|
||||
$aData = array(
|
||||
'source_dir' => $oConfig->Get('source_dir'),
|
||||
);
|
||||
$iInstallationTime = time(); // Make sure that all modules record the same installation time
|
||||
$oInstallRec = new ModuleInstallation();
|
||||
$oInstallRec->Set('name', DATAMODEL_MODULE);
|
||||
$oInstallRec->Set('version', $sDataModelVersion);
|
||||
$oInstallRec->Set('comment', json_encode($aData));
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$oInstallRec->Set('installed', $iInstallationTime);
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
// Record main installation
|
||||
@@ -479,6 +481,7 @@ class RunTimeEnvironment
|
||||
$oInstallRec->Set('version', ITOP_VERSION.'.'.ITOP_REVISION);
|
||||
$oInstallRec->Set('comment', "Done by the setup program\nBuilt on ".ITOP_BUILD_DATE);
|
||||
$oInstallRec->Set('parent_id', 0); // root module
|
||||
$oInstallRec->Set('installed', $iInstallationTime);
|
||||
$iMainItopRecord = $oInstallRec->DBInsertNoReload();
|
||||
|
||||
|
||||
@@ -519,6 +522,7 @@ class RunTimeEnvironment
|
||||
$oInstallRec->Set('version', $sVersion);
|
||||
$oInstallRec->Set('comment', $sComment);
|
||||
$oInstallRec->Set('parent_id', $iMainItopRecord);
|
||||
$oInstallRec->Set('installed', $iInstallationTime);
|
||||
$oInstallRec->DBInsertNoReload();
|
||||
}
|
||||
// Database is created, installation has been tracked into it
|
||||
|
||||
@@ -1205,13 +1205,14 @@ EOF
|
||||
|
||||
protected function GetDefaults($aInfo, &$aDefaults, $aModules, $sParentId = '')
|
||||
{
|
||||
$iScore = 0;
|
||||
$aRetScore = array();
|
||||
$aScores = array();
|
||||
|
||||
$aOptions = isset($aInfo['options']) ? $aInfo['options'] : array();
|
||||
foreach($aOptions as $index => $aChoice)
|
||||
{
|
||||
$sChoiceId = $sParentId.self::$SEP.$index;
|
||||
$aScores[$sChoiceId] = 0;
|
||||
$aScores[$sChoiceId] = array();
|
||||
if (!$this->bUpgrade && isset($aChoice['default']) && $aChoice['default'])
|
||||
{
|
||||
$aDefaults[$sChoiceId] = $sChoiceId;
|
||||
@@ -1223,34 +1224,32 @@ EOF
|
||||
{
|
||||
if ($aModules[$sModuleId]['version_db'] != '')
|
||||
{
|
||||
// A module corresponding to this choice is installed, the whole choice is selected
|
||||
if (!isset($aScores[$sChoiceId])) $aScores[$sChoiceId] = 0;
|
||||
$aScores[$sChoiceId]++;
|
||||
// A module corresponding to this choice is installed
|
||||
$aScores[$sChoiceId][$sModuleId] = true;
|
||||
}
|
||||
}
|
||||
if ($aScores[$sChoiceId] == count($aChoice['modules']))
|
||||
if (count($aScores[$sChoiceId]) == count($aChoice['modules']))
|
||||
{
|
||||
$iScore += 100; // Bonus for the parent when the whole choice is selected
|
||||
// All the modules are installed, this choice is selected
|
||||
$aDefaults[$sChoiceId] = $sChoiceId;
|
||||
}
|
||||
$iScore += $aScores[$sChoiceId];
|
||||
$aRetScore = array_merge($aRetScore, $aScores[$sChoiceId]);
|
||||
}
|
||||
|
||||
if (isset($aChoice['sub_options']))
|
||||
{
|
||||
$aScores[$sChoiceId] = $this->GetDefaults($aChoice['sub_options'], $aDefaults, $sChoiceId);
|
||||
$aScores[$sChoiceId] = array_merge($aScores[$sChoiceId], $this->GetDefaults($aChoice['sub_options'], $aDefaults, $sChoiceId));
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
|
||||
$aAlternatives = isset($aInfo['alternatives']) ? $aInfo['alternatives'] : array();
|
||||
$sChoiceName = null;
|
||||
$aScores = array();
|
||||
$sChoiceIdNone = null;
|
||||
foreach($aAlternatives as $index => $aChoice)
|
||||
{
|
||||
$sChoiceId = $sParentId.self::$SEP.$index;
|
||||
$aScores[$sChoiceId] = 0;
|
||||
$aScores[$sChoiceId] = array();
|
||||
if ($sChoiceName == null)
|
||||
{
|
||||
$sChoiceName = $sChoiceId;
|
||||
@@ -1288,30 +1287,36 @@ EOF
|
||||
if ($aModules[$sModuleId]['version_db'] != '')
|
||||
{
|
||||
// A module corresponding to this choice is installed, increase the score of this choice
|
||||
if (!isset($aScores[$sChoiceId])) $aScores[$sChoiceId] = 0;
|
||||
$aScores[$sChoiceId]++;
|
||||
$iMaxScore = max($iMaxScore, $aScores[$sChoiceId]);
|
||||
if (!isset($aScores[$sChoiceId])) $aScores[$sChoiceId] = array();
|
||||
$aScores[$sChoiceId][$sModuleId] = true;
|
||||
$iMaxScore = max($iMaxScore, count($aScores[$sChoiceId]));
|
||||
}
|
||||
}
|
||||
if ($aScores[$sChoiceId] == count($aChoice['modules']))
|
||||
{
|
||||
$iScore += 100; // Bonus for the parent when a choice is complete
|
||||
}
|
||||
$iScore += $aScores[$sChoiceId];
|
||||
//if (count($aScores[$sChoiceId]) == count($aChoice['modules']))
|
||||
//{
|
||||
// $iScore += 100; // Bonus for the parent when a choice is complete
|
||||
//}
|
||||
$aRetScore = array_merge($aRetScore, $aScores[$sChoiceId]);
|
||||
}
|
||||
$iMaxScore = max($iMaxScore, isset($aScores[$sChoiceId]) ? $aScores[$sChoiceId] : 0);
|
||||
$iMaxScore = max($iMaxScore, isset($aScores[$sChoiceId]) ? count($aScores[$sChoiceId]) : 0);
|
||||
}
|
||||
}
|
||||
if ($iMaxScore > 0)
|
||||
{
|
||||
//echo "Scores: <pre>".print_r($aScores, true)."</pre><br/>";
|
||||
$aNumericScores = array();
|
||||
foreach($aScores as $sChoiceId => $aModules)
|
||||
{
|
||||
$aNumericScores[$sChoiceId] = count($aModules);
|
||||
}
|
||||
// The choice with the bigger score wins !
|
||||
asort($aScores, SORT_NUMERIC);
|
||||
$aKeys = array_keys($aScores);
|
||||
asort($aNumericScores, SORT_NUMERIC);
|
||||
$aKeys = array_keys($aNumericScores);
|
||||
$sBetterChoiceId = array_pop($aKeys);
|
||||
$aDefaults[$sChoiceName] = $sBetterChoiceId;
|
||||
}
|
||||
return $iScore;
|
||||
// echo "Scores: <pre>".print_r($aScores, true)."</pre><br/>";
|
||||
// echo "Defaults: <pre>".print_r($aDefaults, true)."</pre><br/>";
|
||||
return $aRetScore;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -125,6 +125,7 @@ if (!empty($sExpression))
|
||||
|
||||
// Check and adjust column names
|
||||
//
|
||||
$aAliasToFields = array();
|
||||
foreach($aFields as $index => $sField)
|
||||
{
|
||||
if (preg_match('/^(.*)\.(.*)$/', $sField, $aMatches))
|
||||
@@ -136,13 +137,25 @@ if (!empty($sExpression))
|
||||
{
|
||||
$sClassAlias = $oFilter->GetClassAlias();
|
||||
$sAttCode = $sField;
|
||||
// Disambiguate the class alias
|
||||
$aFields[$index] = $sClassAlias.'.'.$sAttCode;
|
||||
}
|
||||
$aAliasToFields[$sClassAlias][] = $sAttCode;
|
||||
|
||||
$sClass = $oFilter->GetClassName($sClassAlias);
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
|
||||
{
|
||||
throw new CoreException("Invalid field specification $sField: $sAttCode is not a valid attribute for $sClass");
|
||||
}
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeSubItem)
|
||||
{
|
||||
$aAliasToFields[$sClassAlias][] = $oAttDef->GetParentAttCode();
|
||||
}
|
||||
else if($oAttDef instanceof AttributeFriendlyname)
|
||||
{
|
||||
$aAliasToFields[$sClassAlias][] = $oAttDef->GetKeyAttCode();
|
||||
}
|
||||
}
|
||||
|
||||
// Read query parameters
|
||||
@@ -161,6 +174,7 @@ if (!empty($sExpression))
|
||||
if ($oFilter)
|
||||
{
|
||||
$oSet = new CMDBObjectSet($oFilter, array(), $aArgs);
|
||||
$oSet->OptimizeColumnLoad($aAliasToFields);
|
||||
switch($sFormat)
|
||||
{
|
||||
case 'html':
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
@@ -95,15 +96,26 @@ try
|
||||
{
|
||||
utils::UseParamFile();
|
||||
|
||||
$sAuthUser = utils::ReadParam('auth_user', null, false, 'raw_data');
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
if (!LoginWebPage::DoLogin(false, false, LoginWebPage::EXIT_RETURN_FALSE))
|
||||
{
|
||||
UserRights::Login($sAuthUser); // Login & set the user's language
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid login '$sAuthUser'", RestResult::UNAUTHORIZED);
|
||||
$sAuthUser = utils::ReadParam('auth_user', null, false, 'raw_data');
|
||||
if ($sAuthUser === null)
|
||||
{
|
||||
throw new Exception("Missing parameter 'auth_user'", RestResult::MISSING_AUTH_USER);
|
||||
}
|
||||
$sAuthPwd = utils::ReadParam('auth_pwd', null, false, 'raw_data');
|
||||
if ($sAuthPwd === null)
|
||||
{
|
||||
throw new Exception("Missing parameter 'auth_pwd'", RestResult::MISSING_AUTH_PWD);
|
||||
}
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
{
|
||||
UserRights::Login($sAuthUser); // Login & set the user's language
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid login '$sAuthUser'", RestResult::UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
$sVersion = utils::ReadParam('version', null, false, 'raw_data');
|
||||
|
||||
Reference in New Issue
Block a user