mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 18:48:51 +02:00
Compare commits
37 Commits
support/2.
...
support/2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
89e98a4ad7 | ||
|
|
649a9833e9 | ||
|
|
b3c2396da8 | ||
|
|
5717ae1889 | ||
|
|
823b33b0f5 | ||
|
|
9561ae6292 | ||
|
|
e25a89dac1 | ||
|
|
cc7f3d46a6 | ||
|
|
95d6b640b1 | ||
|
|
4ee0c62701 | ||
|
|
15f521d470 | ||
|
|
86e6c8295f | ||
|
|
9f1338ee2a | ||
|
|
96c8ee5e4d | ||
|
|
8e863d4890 | ||
|
|
cd769d5e49 | ||
|
|
04677fc2c7 | ||
|
|
ed6a464d8b | ||
|
|
5794f7d1ca | ||
|
|
7d42aa48cd | ||
|
|
614dd21aa9 | ||
|
|
706e6c56ff | ||
|
|
f048c6cb1f | ||
|
|
1804903ee4 | ||
|
|
17a8a896dc | ||
|
|
ed85260bb3 | ||
|
|
3c7fac7504 | ||
|
|
93feb700e8 | ||
|
|
48456082a9 | ||
|
|
fbc0456496 | ||
|
|
0fc3ee12b1 | ||
|
|
ce5f8c93cd | ||
|
|
b38eb97323 | ||
|
|
e6eb32cd21 | ||
|
|
c2429f2d05 | ||
|
|
4e4f2b4db9 | ||
|
|
2d7f963316 |
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2015 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -781,7 +781,7 @@ class RestUtils
|
|||||||
$oSearch = new DBObjectSearch($sClass);
|
$oSearch = new DBObjectSearch($sClass);
|
||||||
foreach ($oCriteria as $sAttCode => $value)
|
foreach ($oCriteria as $sAttCode => $value)
|
||||||
{
|
{
|
||||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||||
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
||||||
if (is_object($value) || is_array($value))
|
if (is_object($value) || is_array($value))
|
||||||
{
|
{
|
||||||
@@ -818,7 +818,7 @@ class RestUtils
|
|||||||
{
|
{
|
||||||
if (is_object($key))
|
if (is_object($key))
|
||||||
{
|
{
|
||||||
$res = self::FindObjectFromCriteria($sClass, $key);
|
$res = static::FindObjectFromCriteria($sClass, $key);
|
||||||
}
|
}
|
||||||
elseif (is_numeric($key))
|
elseif (is_numeric($key))
|
||||||
{
|
{
|
||||||
@@ -882,7 +882,7 @@ class RestUtils
|
|||||||
$oSearch = new DBObjectSearch($sClass);
|
$oSearch = new DBObjectSearch($sClass);
|
||||||
foreach ($key as $sAttCode => $value)
|
foreach ($key as $sAttCode => $value)
|
||||||
{
|
{
|
||||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||||
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
$oSearch->AddCondition($sAttCode, $realValue, '=');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -926,7 +926,7 @@ class RestUtils
|
|||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||||
if ($oAttDef instanceof AttributeExternalKey)
|
if ($oAttDef instanceof AttributeExternalKey)
|
||||||
{
|
{
|
||||||
$oExtKeyObject = self::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
|
$oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true /* allow null */);
|
||||||
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
|
$value = ($oExtKeyObject != null) ? $oExtKeyObject->GetKey() : 0;
|
||||||
}
|
}
|
||||||
elseif ($oAttDef instanceof AttributeLinkedSet)
|
elseif ($oAttDef instanceof AttributeLinkedSet)
|
||||||
@@ -939,7 +939,7 @@ class RestUtils
|
|||||||
$aLinks = array();
|
$aLinks = array();
|
||||||
foreach($value as $oValues)
|
foreach($value as $oValues)
|
||||||
{
|
{
|
||||||
$oLnk = self::MakeObjectFromFields($sLnkClass, $oValues);
|
$oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
|
||||||
$aLinks[] = $oLnk;
|
$aLinks[] = $oLnk;
|
||||||
}
|
}
|
||||||
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
|
$value = DBObjectSet::FromArray($sLnkClass, $aLinks);
|
||||||
@@ -970,7 +970,7 @@ class RestUtils
|
|||||||
$oObject = MetaModel::NewObject($sClass);
|
$oObject = MetaModel::NewObject($sClass);
|
||||||
foreach ($aFields as $sAttCode => $value)
|
foreach ($aFields as $sAttCode => $value)
|
||||||
{
|
{
|
||||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oObject->Set($sAttCode, $realValue);
|
$oObject->Set($sAttCode, $realValue);
|
||||||
@@ -997,7 +997,7 @@ class RestUtils
|
|||||||
$sClass = get_class($oObject);
|
$sClass = get_class($oObject);
|
||||||
foreach ($aFields as $sAttCode => $value)
|
foreach ($aFields as $sAttCode => $value)
|
||||||
{
|
{
|
||||||
$realValue = self::MakeValue($sClass, $sAttCode, $value);
|
$realValue = static::MakeValue($sClass, $sAttCode, $value);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oObject->Set($sAttCode, $realValue);
|
$oObject->Set($sAttCode, $realValue);
|
||||||
|
|||||||
@@ -1571,7 +1571,7 @@ class DashletBadge extends Dashlet
|
|||||||
$oPage->add('<p>');
|
$oPage->add('<p>');
|
||||||
$oPage->add(' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>');
|
$oPage->add(' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>');
|
||||||
$oPage->add(' <br/>');
|
$oPage->add(' <br/>');
|
||||||
$oPage->add(' <a>'.Dict::Format('UI:SearchFor_Class', $sClassLabel).'</a>');
|
$oPage->add(' <a>Search for Server objects</a>');
|
||||||
$oPage->add('</p>');
|
$oPage->add('</p>');
|
||||||
$oPage->add('</div>');
|
$oPage->add('</div>');
|
||||||
|
|
||||||
|
|||||||
@@ -867,11 +867,13 @@ class DesignerTextField extends DesignerFormField
|
|||||||
{
|
{
|
||||||
protected $sValidationPattern;
|
protected $sValidationPattern;
|
||||||
protected $aForbiddenValues;
|
protected $aForbiddenValues;
|
||||||
|
protected $sExplainForbiddenValues;
|
||||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||||
{
|
{
|
||||||
parent::__construct($sCode, $sLabel, $defaultValue);
|
parent::__construct($sCode, $sLabel, $defaultValue);
|
||||||
$this->sValidationPattern = '';
|
$this->sValidationPattern = '';
|
||||||
$this->aForbiddenValues = array();
|
$this->aForbiddenValues = null;
|
||||||
|
$this->sExplainForbiddenValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetValidationPattern($sValidationPattern)
|
public function SetValidationPattern($sValidationPattern)
|
||||||
@@ -881,17 +883,17 @@ class DesignerTextField extends DesignerFormField
|
|||||||
|
|
||||||
public function SetForbiddenValues($aValues, $sExplain)
|
public function SetForbiddenValues($aValues, $sExplain)
|
||||||
{
|
{
|
||||||
$aForbiddenValues = $aValues;
|
$this->aForbiddenValues = $aValues;
|
||||||
|
|
||||||
$iDefaultKey = array_search($this->defaultValue, $aForbiddenValues);
|
$iDefaultKey = array_search($this->defaultValue, $this->aForbiddenValues);
|
||||||
if ($iDefaultKey !== false)
|
if ($iDefaultKey !== false)
|
||||||
{
|
{
|
||||||
// The default (current) value is always allowed...
|
// The default (current) value is always allowed...
|
||||||
unset($aForbiddenValues[$iDefaultKey]);
|
unset($this->aForbiddenValues[$iDefaultKey]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->aForbiddenValues[] = array('values' => $aForbiddenValues, 'message' => $sExplain);
|
$this->sExplainForbiddenValues = $sExplain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||||
@@ -909,15 +911,17 @@ class DesignerTextField extends DesignerFormField
|
|||||||
if (is_array($this->aForbiddenValues))
|
if (is_array($this->aForbiddenValues))
|
||||||
{
|
{
|
||||||
$sForbiddenValues = json_encode($this->aForbiddenValues);
|
$sForbiddenValues = json_encode($this->aForbiddenValues);
|
||||||
|
$sExplainForbiddenValues = addslashes($this->sExplainForbiddenValues);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sForbiddenValues = '[]'; //Empty JS array
|
$sForbiddenValues = 'null';
|
||||||
|
$sExplainForbiddenValues = 'null';
|
||||||
}
|
}
|
||||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||||
$oP->add_ready_script(
|
$oP->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues, '$sExplainForbiddenValues'); } );
|
||||||
{
|
{
|
||||||
var myTimer = null;
|
var myTimer = null;
|
||||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||||
@@ -960,35 +964,30 @@ class DesignerLongTextField extends DesignerTextField
|
|||||||
if (is_array($this->aForbiddenValues))
|
if (is_array($this->aForbiddenValues))
|
||||||
{
|
{
|
||||||
$sForbiddenValues = json_encode($this->aForbiddenValues);
|
$sForbiddenValues = json_encode($this->aForbiddenValues);
|
||||||
|
$sExplainForbiddenValues = addslashes($this->sExplainForbiddenValues);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sForbiddenValues = '[]'; //Empty JS array
|
$sForbiddenValues = 'null';
|
||||||
|
$sExplainForbiddenValues = 'null';
|
||||||
}
|
}
|
||||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||||
$sCSSClasses = '';
|
$sReadOnly = $this->IsReadOnly() ? 'readonly' : '';
|
||||||
if (count($this->aCSSClasses) > 0)
|
$oP->add_ready_script(
|
||||||
{
|
|
||||||
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
|
||||||
}
|
|
||||||
if (!$this->IsReadOnly())
|
|
||||||
{
|
|
||||||
$oP->add_ready_script(
|
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues); } );
|
$('#$sId').bind('change keyup validate', function() { ValidateWithPattern('$sId', $sMandatory, '$sPattern', $(this).closest('form').attr('id'), $sForbiddenValues, '$sExplainForbiddenValues'); } );
|
||||||
{
|
{
|
||||||
var myTimer = null;
|
var myTimer = null;
|
||||||
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
$('#$sId').bind('keyup', function() { clearTimeout(myTimer); myTimer = setTimeout(function() { $('#$sId').trigger('change', {} ); }, 100); });
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
$sValue = "<textarea $sCSSClasses id=\"$sId\" name=\"$sName\">".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."</textarea>";
|
$sCSSClasses = '';
|
||||||
}
|
if (count($this->aCSSClasses) > 0)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
$sValue = "<div $sCSSClasses id=\"$sId\">".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."</div>";
|
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
||||||
}
|
}
|
||||||
return array('label' => $this->sLabel, 'value' => $sValue);
|
return array('label' => $this->sLabel, 'value' => "<textarea $sCSSClasses id=\"$sId\" $sReadOnly name=\"$sName\">".htmlentities($this->defaultValue, ENT_QUOTES, 'UTF-8')."</textarea>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,7 +1065,6 @@ class DesignerComboField extends DesignerFormField
|
|||||||
protected $bMultipleSelection;
|
protected $bMultipleSelection;
|
||||||
protected $bOtherChoices;
|
protected $bOtherChoices;
|
||||||
protected $sNullLabel;
|
protected $sNullLabel;
|
||||||
protected $bSorted;
|
|
||||||
|
|
||||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||||
{
|
{
|
||||||
@@ -1077,7 +1075,6 @@ class DesignerComboField extends DesignerFormField
|
|||||||
$this->sNullLabel = Dict::S('UI:SelectOne');
|
$this->sNullLabel = Dict::S('UI:SelectOne');
|
||||||
|
|
||||||
$this->bAutoApply = true;
|
$this->bAutoApply = true;
|
||||||
$this->bSorted = true; // Sorted by default
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetAllowedValues($aAllowedValues)
|
public function SetAllowedValues($aAllowedValues)
|
||||||
@@ -1103,16 +1100,6 @@ class DesignerComboField extends DesignerFormField
|
|||||||
$this->sNullLabel = $sLabel;
|
$this->sNullLabel = $sLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsSorted()
|
|
||||||
{
|
|
||||||
return $this->bSorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function SetSorted($bSorted)
|
|
||||||
{
|
|
||||||
$this->bSorted = $bSorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
public function Render(WebPage $oP, $sFormId, $sRenderMode='dialog')
|
||||||
{
|
{
|
||||||
$sId = $this->oForm->GetFieldId($this->sCode);
|
$sId = $this->oForm->GetFieldId($this->sCode);
|
||||||
@@ -1120,10 +1107,6 @@ class DesignerComboField extends DesignerFormField
|
|||||||
$sChecked = $this->defaultValue ? 'checked' : '';
|
$sChecked = $this->defaultValue ? 'checked' : '';
|
||||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||||
if ($this->IsSorted())
|
|
||||||
{
|
|
||||||
asort($this->aAllowedValues);
|
|
||||||
}
|
|
||||||
$sCSSClasses = '';
|
$sCSSClasses = '';
|
||||||
if (count($this->aCSSClasses) > 0)
|
if (count($this->aCSSClasses) > 0)
|
||||||
{
|
{
|
||||||
@@ -1445,37 +1428,13 @@ class DesignerFormSelectorField extends DesignerFormField
|
|||||||
{
|
{
|
||||||
protected $aSubForms;
|
protected $aSubForms;
|
||||||
protected $defaultRealValue; // What's stored as default value is actually the index
|
protected $defaultRealValue; // What's stored as default value is actually the index
|
||||||
protected $bSorted;
|
|
||||||
|
|
||||||
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
public function __construct($sCode, $sLabel = '', $defaultValue = '')
|
||||||
{
|
{
|
||||||
parent::__construct($sCode, $sLabel, 0);
|
parent::__construct($sCode, $sLabel, 0);
|
||||||
$this->defaultRealValue = $defaultValue;
|
$this->defaultRealValue = $defaultValue;
|
||||||
$this->aSubForms = array();
|
$this->aSubForms = array();
|
||||||
$this->bSorted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function IsSorted()
|
|
||||||
{
|
|
||||||
return $this->bSorted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function SetSorted($bSorted)
|
|
||||||
{
|
|
||||||
$this->bSorted = $bSorted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for sorting an array of $aFormData based ont he labels of the subforms
|
|
||||||
* @param unknown $aItem1
|
|
||||||
* @param unknown $aItem2
|
|
||||||
* @return number
|
|
||||||
*/
|
|
||||||
static function SortOnFormLabel($aItem1, $aItem2)
|
|
||||||
{
|
|
||||||
return strcasecmp($aItem1['label'], $aItem2['label']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetWidgetClass()
|
public function GetWidgetClass()
|
||||||
{
|
{
|
||||||
return 'selector_property_field';
|
return 'selector_property_field';
|
||||||
@@ -1506,10 +1465,6 @@ class DesignerFormSelectorField extends DesignerFormField
|
|||||||
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
$sCSSClasses = 'class="'.implode(' ', $this->aCSSClasses).'"';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->IsSorted())
|
|
||||||
{
|
|
||||||
uasort($this->aSubForms, array(get_class($this), 'SortOnFormLabel'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->IsReadOnly())
|
if ($this->IsReadOnly())
|
||||||
{
|
{
|
||||||
@@ -1535,10 +1490,9 @@ class DesignerFormSelectorField extends DesignerFormField
|
|||||||
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
$sHtml = "<select $sCSSClasses id=\"$sId\" name=\"$sName\" $sReadOnly>";
|
||||||
foreach($this->aSubForms as $iKey => $aFormData)
|
foreach($this->aSubForms as $iKey => $aFormData)
|
||||||
{
|
{
|
||||||
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');
|
$sDisplayValue = htmlentities($aFormData['label'], ENT_QUOTES, 'UTF-8');;
|
||||||
$sValue = htmlentities($aFormData['value'], ENT_QUOTES, 'UTF-8');
|
|
||||||
$sSelected = ($iKey == $this->defaultValue) ? 'selected' : '';
|
$sSelected = ($iKey == $this->defaultValue) ? 'selected' : '';
|
||||||
$sHtml .= "<option data-value=\"$sValue\" value=\"$iKey\" $sSelected>".$sDisplayValue."</option>";
|
$sHtml .= "<option value=\"$iKey\" $sSelected>".$sDisplayValue."</option>";
|
||||||
}
|
}
|
||||||
$sHtml .= "</select>";
|
$sHtml .= "</select>";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ class PortalWebPage extends NiceWebPage
|
|||||||
$this->add_linked_script("../js/jquery.qtip-1.0.min.js");
|
$this->add_linked_script("../js/jquery.qtip-1.0.min.js");
|
||||||
$this->add_linked_script('../js/jquery.multiselect.min.js');
|
$this->add_linked_script('../js/jquery.multiselect.min.js');
|
||||||
$this->add_linked_script("../js/ajaxfileupload.js");
|
$this->add_linked_script("../js/ajaxfileupload.js");
|
||||||
|
$this->add_linked_script("../js/ckeditor/ckeditor.js");
|
||||||
|
$this->add_linked_script("../js/ckeditor/adapters/jquery.js");
|
||||||
$this->add_ready_script(
|
$this->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
try
|
try
|
||||||
@@ -231,6 +233,20 @@ EOF
|
|||||||
var next_step = $('input[id=next_step]');
|
var next_step = $('input[id=next_step]');
|
||||||
next_step.val(sStep);
|
next_step.val(sStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For disabling the CKEditor at init time when the corresponding textarea is disabled !
|
||||||
|
CKEDITOR.plugins.add( 'disabler',
|
||||||
|
{
|
||||||
|
init : function( editor )
|
||||||
|
{
|
||||||
|
editor.on( 'instanceReady', function(e)
|
||||||
|
{
|
||||||
|
e.removeListener();
|
||||||
|
$('#'+ editor.name).trigger('update');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class UIHTMLEditorWidget
|
|||||||
|
|
||||||
// Could also be bound to 'instanceReady.ckeditor'
|
// Could also be bound to 'instanceReady.ckeditor'
|
||||||
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
|
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
|
||||||
$oPage->add_ready_script("$('#$iId').bind('update', function() { BlockField('cke_$iId', $('#$iId').attr('disabled')); } );\n");
|
$oPage->add_ready_script("$('#$iId').bind('update', function() { BlockField('cke_$iId', $('#$iId').attr('disabled')); $(this).data('ckeditorInstance').setReadOnly($(this).prop('disabled')); } );\n");
|
||||||
|
|
||||||
return $sHtmlValue;
|
return $sHtmlValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -487,35 +487,6 @@ abstract class AttributeDefinition
|
|||||||
{
|
{
|
||||||
return $this->GetAsHTML($sValue, $oHostObject, $bLocalize);
|
return $this->GetAsHTML($sValue, $oHostObject, $bLocalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get various representations of the value, for insertion into a template (e.g. in Notifications)
|
|
||||||
* @param $value mixed The current value of the field
|
|
||||||
* @param $sVerb string The verb specifying the representation of the value
|
|
||||||
* @param $oHostObject DBObject The object
|
|
||||||
* @param $bLocalize bool Whether or not to localize the value
|
|
||||||
*/
|
|
||||||
public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true)
|
|
||||||
{
|
|
||||||
if ($this->IsScalar())
|
|
||||||
{
|
|
||||||
switch ($sVerb)
|
|
||||||
{
|
|
||||||
case '':
|
|
||||||
return $value;
|
|
||||||
|
|
||||||
case 'html':
|
|
||||||
return $this->GetAsHtml($value, $oHostObject, $bLocalize);
|
|
||||||
|
|
||||||
case 'label':
|
|
||||||
return $this->GetEditValue($value);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function GetAllowedValues($aArgs = array(), $sContains = '')
|
public function GetAllowedValues($aArgs = array(), $sContains = '')
|
||||||
{
|
{
|
||||||
@@ -760,46 +731,6 @@ class AttributeLinkedSet extends AttributeDefinition
|
|||||||
return $sRes;
|
return $sRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get various representations of the value, for insertion into a template (e.g. in Notifications)
|
|
||||||
* @param $value mixed The current value of the field
|
|
||||||
* @param $sVerb string The verb specifying the representation of the value
|
|
||||||
* @param $oHostObject DBObject The object
|
|
||||||
* @param $bLocalize bool Whether or not to localize the value
|
|
||||||
*/
|
|
||||||
public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true)
|
|
||||||
{
|
|
||||||
$sRemoteName = $this->IsIndirect() ? $this->GetExtKeyToRemote().'_friendlyname' : 'friendlyname';
|
|
||||||
|
|
||||||
$oLinkSet = clone $value; // Workaround/Safety net for Trac #887
|
|
||||||
$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
|
|
||||||
if ($iLimit > 0)
|
|
||||||
{
|
|
||||||
$oLinkSet->SetLimit($iLimit);
|
|
||||||
}
|
|
||||||
$aNames = $oLinkSet->GetColumnAsArray($sRemoteName);
|
|
||||||
if ($iLimit > 0)
|
|
||||||
{
|
|
||||||
$iTotal = $oLinkSet->Count();
|
|
||||||
if ($iTotal > count($aNames))
|
|
||||||
{
|
|
||||||
$aNames[] = '... '.Dict::Format('UI:TruncatedResults', count($aNames), $iTotal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($sVerb)
|
|
||||||
{
|
|
||||||
case '':
|
|
||||||
return implode("\n", $aNames);
|
|
||||||
|
|
||||||
case 'html':
|
|
||||||
return '<ul><li>'.implode("</li><li>", $aNames).'</li></ul>';
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function DuplicatesAllowed() {return false;} // No duplicates for 1:n links, never
|
public function DuplicatesAllowed() {return false;} // No duplicates for 1:n links, never
|
||||||
|
|
||||||
public function GetImportColumns()
|
public function GetImportColumns()
|
||||||
@@ -961,6 +892,106 @@ class AttributeLinkedSet extends AttributeDefinition
|
|||||||
return $oSet;
|
return $oSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get a value that will be JSON encoded
|
||||||
|
* The operation is the opposite to FromJSONToValue
|
||||||
|
*/
|
||||||
|
public function GetForJSON($value)
|
||||||
|
{
|
||||||
|
$aRet = array();
|
||||||
|
if (is_object($value) && ($value instanceof DBObjectSet))
|
||||||
|
{
|
||||||
|
$value->Rewind();
|
||||||
|
while ($oObj = $value->Fetch())
|
||||||
|
{
|
||||||
|
$sObjClass = get_class($oObj);
|
||||||
|
// Show only relevant information (hide the external key to the current object)
|
||||||
|
$aAttributes = array();
|
||||||
|
foreach(MetaModel::ListAttributeDefs($sObjClass) as $sAttCode => $oAttDef)
|
||||||
|
{
|
||||||
|
if ($sAttCode == 'finalclass')
|
||||||
|
{
|
||||||
|
if ($sObjClass == $this->GetLinkedClass())
|
||||||
|
{
|
||||||
|
// Simplify the output if the exact class could be determined implicitely
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($sAttCode == $this->GetExtKeyToMe()) continue;
|
||||||
|
if ($oAttDef->IsExternalField()) continue;
|
||||||
|
if (!$oAttDef->IsDirectField()) continue;
|
||||||
|
if (!$oAttDef->IsScalar()) continue;
|
||||||
|
$attValue = $oObj->Get($sAttCode);
|
||||||
|
$aAttributes[$sAttCode] = $oAttDef->GetForJSON($attValue);
|
||||||
|
}
|
||||||
|
$aRet[] = $aAttributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $aRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to form a value, given JSON decoded data
|
||||||
|
* The operation is the opposite to GetForJSON
|
||||||
|
*/
|
||||||
|
public function FromJSONToValue($json)
|
||||||
|
{
|
||||||
|
$sTargetClass = $this->Get('linked_class');
|
||||||
|
|
||||||
|
$aLinks = array();
|
||||||
|
foreach($json as $aValues)
|
||||||
|
{
|
||||||
|
if (isset($aValues['finalclass']))
|
||||||
|
{
|
||||||
|
$sLinkClass = $aValues['finalclass'];
|
||||||
|
if (!is_subclass_of($sLinkClass, $sTargetClass))
|
||||||
|
{
|
||||||
|
throw new CoreException('Wrong class for link attribute specification', array('requested_class' => $sLinkClass, 'expected_class' => $sTargetClass));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (MetaModel::IsAbstract($sTargetClass))
|
||||||
|
{
|
||||||
|
throw new CoreException('Missing finalclass for link attribute specification');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sLinkClass = $sTargetClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oLink = MetaModel::NewObject($sLinkClass);
|
||||||
|
foreach ($aValues as $sAttCode => $sValue)
|
||||||
|
{
|
||||||
|
$oLink->Set($sAttCode, $sValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check (roughly) if such a link is valid
|
||||||
|
$aErrors = array();
|
||||||
|
foreach(MetaModel::ListAttributeDefs($sTargetClass) as $sAttCode => $oAttDef)
|
||||||
|
{
|
||||||
|
if ($oAttDef->IsExternalKey())
|
||||||
|
{
|
||||||
|
if (($oAttDef->GetTargetClass() == $this->GetHostClass()) || (is_subclass_of($this->GetHostClass(), $oAttDef->GetTargetClass())))
|
||||||
|
{
|
||||||
|
continue; // Don't check the key to self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($oAttDef->IsWritable() && $oAttDef->IsNull($oLink->Get($sAttCode)) && !$oAttDef->IsNullAllowed())
|
||||||
|
{
|
||||||
|
$aErrors[] = $sAttCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($aErrors) > 0)
|
||||||
|
{
|
||||||
|
throw new CoreException("Missing value for mandatory attribute(s): ".implode(', ', $aErrors));
|
||||||
|
}
|
||||||
|
|
||||||
|
$aLinks[] = $oLink;
|
||||||
|
}
|
||||||
|
$oSet = DBObjectSet::FromArray($sTargetClass, $aLinks);
|
||||||
|
return $oSet;
|
||||||
|
}
|
||||||
|
|
||||||
public function Equals($val1, $val2)
|
public function Equals($val1, $val2)
|
||||||
{
|
{
|
||||||
if ($val1 === $val2) return true;
|
if ($val1 === $val2) return true;
|
||||||
@@ -2163,35 +2194,6 @@ class AttributeCaseLog extends AttributeLongText
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get various representations of the value, for insertion into a template (e.g. in Notifications)
|
|
||||||
* @param $value mixed The current value of the field
|
|
||||||
* @param $sVerb string The verb specifying the representation of the value
|
|
||||||
* @param $oHostObject DBObject The object
|
|
||||||
* @param $bLocalize bool Whether or not to localize the value
|
|
||||||
*/
|
|
||||||
public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true)
|
|
||||||
{
|
|
||||||
switch($sVerb)
|
|
||||||
{
|
|
||||||
case '':
|
|
||||||
return $value->GetText();
|
|
||||||
|
|
||||||
case 'head':
|
|
||||||
return $value->GetLatestEntry();
|
|
||||||
|
|
||||||
case 'head_html':
|
|
||||||
return '<div class="caselog_entry">'.str_replace( array( "\r\n", "\n", "\r"), "<br/>", htmlentities($value->GetLatestEntry(), ENT_QUOTES, 'UTF-8')).'</div>';
|
|
||||||
|
|
||||||
case 'html':
|
|
||||||
return $value->GetAsEmailHtml();
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to get a value that will be JSON encoded
|
* Helper to get a value that will be JSON encoded
|
||||||
* The operation is the opposite to FromJSONToValue
|
* The operation is the opposite to FromJSONToValue
|
||||||
|
|||||||
@@ -833,30 +833,6 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => false,
|
'show_in_conf_sample' => false,
|
||||||
),
|
),
|
||||||
'concurrent_lock_enabled' => array(
|
|
||||||
'type' => 'bool',
|
|
||||||
'description' => 'Whether or not to activate the locking mechanism in order to prevent concurrent edition of the same object.',
|
|
||||||
'default' => true,
|
|
||||||
'value' => '',
|
|
||||||
'source_of_value' => '',
|
|
||||||
'show_in_conf_sample' => true,
|
|
||||||
),
|
|
||||||
'concurrent_lock_expiration_delay' => array(
|
|
||||||
'type' => 'integer',
|
|
||||||
'description' => 'Delay (in seconds) for a concurrent lock to expire',
|
|
||||||
'default' => 120,
|
|
||||||
'value' => '',
|
|
||||||
'source_of_value' => '',
|
|
||||||
'show_in_conf_sample' => false,
|
|
||||||
),
|
|
||||||
'concurrent_lock_override_profiles' => array(
|
|
||||||
'type' => 'array',
|
|
||||||
'description' => 'The list of profiles allowed to "kill" a lock',
|
|
||||||
'default' => array('Administrator'),
|
|
||||||
'value' => '',
|
|
||||||
'source_of_value' => '',
|
|
||||||
'show_in_conf_sample' => false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
public function IsProperty($sPropCode)
|
public function IsProperty($sPropCode)
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ abstract class DBObject implements iDisplay
|
|||||||
protected $m_aCheckIssues = null;
|
protected $m_aCheckIssues = null;
|
||||||
protected $m_aDeleteIssues = null;
|
protected $m_aDeleteIssues = null;
|
||||||
|
|
||||||
|
protected $m_aAsArgs = null; // The current object as a standard argument (cache)
|
||||||
|
|
||||||
private $m_bFullyLoaded = false; // Compound objects can be partially loaded
|
private $m_bFullyLoaded = false; // Compound objects can be partially loaded
|
||||||
private $m_aLoadedAtt = array(); // Compound objects can be partially loaded, array of sAttCode
|
private $m_aLoadedAtt = array(); // Compound objects can be partially loaded, array of sAttCode
|
||||||
protected $m_aModifiedAtt = array(); // list of (potentially) modified sAttCodes
|
protected $m_aModifiedAtt = array(); // list of (potentially) modified sAttCodes
|
||||||
@@ -411,6 +413,7 @@ abstract class DBObject implements iDisplay
|
|||||||
|
|
||||||
// The object has changed, reset caches
|
// The object has changed, reset caches
|
||||||
$this->m_bCheckStatus = null;
|
$this->m_bCheckStatus = null;
|
||||||
|
$this->m_aAsArgs = null;
|
||||||
|
|
||||||
// Make sure we do not reload it anymore... before saving it
|
// Make sure we do not reload it anymore... before saving it
|
||||||
$this->RegisterAsDirty();
|
$this->RegisterAsDirty();
|
||||||
@@ -1567,6 +1570,9 @@ abstract class DBObject implements iDisplay
|
|||||||
$this->DBWriteLinks();
|
$this->DBWriteLinks();
|
||||||
$this->m_bIsInDB = true;
|
$this->m_bIsInDB = true;
|
||||||
$this->m_bDirty = false;
|
$this->m_bDirty = false;
|
||||||
|
|
||||||
|
// Arg cache invalidated (in particular, it needs the object key -could be improved later)
|
||||||
|
$this->m_aAsArgs = null;
|
||||||
|
|
||||||
$this->AfterInsert();
|
$this->AfterInsert();
|
||||||
|
|
||||||
@@ -2082,12 +2088,12 @@ abstract class DBObject implements iDisplay
|
|||||||
{
|
{
|
||||||
if (is_string($actionHandler))
|
if (is_string($actionHandler))
|
||||||
{
|
{
|
||||||
// Old (pre-2.1.0) action definition without any parameter
|
// Old (pre-2.1.0 modules) action definition without any parameter
|
||||||
$aActionCallSpec = array($this, $sActionHandler);
|
$aActionCallSpec = array($this, $actionHandler);
|
||||||
|
|
||||||
if (!is_callable($aActionCallSpec))
|
if (!is_callable($aActionCallSpec))
|
||||||
{
|
{
|
||||||
throw new CoreException("Unable to call action: ".get_class($this)."::$sActionHandler");
|
throw new CoreException("Unable to call action: ".get_class($this)."::$actionHandler");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
|
$bRet = call_user_func($aActionCallSpec, $sStimulusCode);
|
||||||
@@ -2264,94 +2270,84 @@ abstract class DBObject implements iDisplay
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Create query parameters (SELECT ... WHERE service = :this->service_id)
|
* Create query parameters (SELECT ... WHERE service = :this->service_id)
|
||||||
* to be used with the APIs DBObjectSearch/DBObjectSet
|
* to be used with the APIs DBObjectSearch/DBObjectSet
|
||||||
*
|
*
|
||||||
* Starting 2.0.2 the parameters are computed on demand, at the lowest level,
|
* Starting 2.0.2 the parameters are computed on demand, at the lowest level,
|
||||||
* in VariableExpression::Render()
|
* in VariableExpression::Render()
|
||||||
*/
|
*/
|
||||||
public function ToArgsForQuery($sArgName = 'this')
|
public function ToArgsForQuery($sArgName = 'this')
|
||||||
{
|
{
|
||||||
return array($sArgName.'->object()' => $this);
|
return array($sArgName.'->object()' => $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Create template placeholders: now equivalent to ToArgsForQuery since the actual
|
* Create template placeholders
|
||||||
* template placeholders are computed on demand.
|
* An improvement could be to compute the values on demand
|
||||||
*/
|
* (i.e. interpret the template to determine the placeholders)
|
||||||
|
*/
|
||||||
public function ToArgs($sArgName = 'this')
|
public function ToArgs($sArgName = 'this')
|
||||||
{
|
{
|
||||||
return $this->ToArgsForQuery($sArgName);
|
if (is_null($this->m_aAsArgs))
|
||||||
}
|
|
||||||
|
|
||||||
public function GetForTemplate($sPlaceholderAttCode)
|
|
||||||
{
|
|
||||||
$ret = null;
|
|
||||||
if (($iPos = strpos($sPlaceholderAttCode, '->')) !== false)
|
|
||||||
{
|
{
|
||||||
$sExtKeyAttCode = substr($sPlaceholderAttCode, 0, $iPos);
|
$oKPI = new ExecutionKPI();
|
||||||
$sRemoteAttCode = substr($sPlaceholderAttCode, $iPos + 2);
|
$aScalarArgs = $this->ToArgsForQuery($sArgName);
|
||||||
if (!MetaModel::IsValidAttCode(get_class($this), $sExtKeyAttCode))
|
$aScalarArgs[$sArgName] = $this->GetKey();
|
||||||
{
|
$aScalarArgs[$sArgName.'->id'] = $this->GetKey();
|
||||||
throw new CoreException("Unknown attribute '$sExtKeyAttCode' for the class ".get_class($this));
|
$aScalarArgs[$sArgName.'->hyperlink()'] = $this->GetHyperlink('iTopStandardURLMaker', false);
|
||||||
}
|
$aScalarArgs[$sArgName.'->hyperlink(portal)'] = $this->GetHyperlink('PortalURLMaker', false);
|
||||||
|
$aScalarArgs[$sArgName.'->name()'] = $this->GetName();
|
||||||
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
|
|
||||||
if (!$oKeyAttDef instanceof AttributeExternalKey)
|
|
||||||
{
|
|
||||||
throw new CoreException("'$sExtKeyAttCode' is not an external key of the class ".get_class($this));
|
|
||||||
}
|
|
||||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
|
||||||
$oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
|
|
||||||
if (is_null($oRemoteObj))
|
|
||||||
{
|
|
||||||
$ret = Dict::S('UI:UndefinedObject');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Recurse
|
|
||||||
$ret = $oRemoteObj->GetForTemplate($sRemoteAttCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch($sPlaceholderAttCode)
|
|
||||||
{
|
|
||||||
case 'id':
|
|
||||||
$ret = $this->GetKey();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'hyperlink()':
|
|
||||||
$ret = $this->GetHyperlink('iTopStandardURLMaker', false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'hyperlink(portal)':
|
$sClass = get_class($this);
|
||||||
$ret = $this->GetHyperlink('PortalURLMaker', false);
|
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||||
break;
|
{
|
||||||
|
if ($oAttDef instanceof AttributeCaseLog)
|
||||||
case 'name()':
|
|
||||||
$ret = $this->GetName();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (preg_match('/^([^(]+)\\((.+)\\)$/', $sPlaceholderAttCode, $aMatches))
|
|
||||||
{
|
{
|
||||||
$sVerb = $aMatches[1];
|
$oCaseLog = $this->Get($sAttCode);
|
||||||
$sAttCode = $aMatches[2];
|
$aScalarArgs[$sArgName.'->'.$sAttCode] = $oCaseLog->GetText();
|
||||||
|
$sHead = $oCaseLog->GetLatestEntry();
|
||||||
|
$aScalarArgs[$sArgName.'->head('.$sAttCode.')'] = $sHead;
|
||||||
|
$aScalarArgs[$sArgName.'->head_html('.$sAttCode.')'] = '<div class="caselog_entry">'.str_replace(array("\r\n", "\n", "\r"), "<br/>", htmlentities($sHead, ENT_QUOTES, 'UTF-8')).'</div>';
|
||||||
|
$aScalarArgs[$sArgName.'->html('.$sAttCode.')'] = $oCaseLog->GetAsEmailHtml();
|
||||||
}
|
}
|
||||||
else
|
elseif ($oAttDef->IsScalar())
|
||||||
{
|
{
|
||||||
$sVerb = '';
|
$aScalarArgs[$sArgName.'->'.$sAttCode] = $this->Get($sAttCode);
|
||||||
$sAttCode = $sPlaceholderAttCode;
|
// #@# Note: This has been proven to be quite slow, this can slow down bulk load
|
||||||
|
$sAsHtml = $this->GetAsHtml($sAttCode);
|
||||||
|
$aScalarArgs[$sArgName.'->html('.$sAttCode.')'] = $sAsHtml;
|
||||||
|
$aScalarArgs[$sArgName.'->label('.$sAttCode.')'] = $this->GetEditValue($sAttCode); // "Nice" display value, but without HTML tags and entities
|
||||||
|
}
|
||||||
|
elseif ($oAttDef->IsLinkSet())
|
||||||
|
{
|
||||||
|
$sRemoteName = $oAttDef->IsIndirect() ? $oAttDef->GetExtKeyToRemote().'_friendlyname' : 'friendlyname';
|
||||||
|
|
||||||
|
$oLinkSet = clone $this->Get($sAttCode); // Workaround/Safety net for Trac #887
|
||||||
|
$iLimit = MetaModel::GetConfig()->Get('max_linkset_output');
|
||||||
|
if ($iLimit > 0)
|
||||||
|
{
|
||||||
|
$oLinkSet->SetLimit($iLimit);
|
||||||
|
}
|
||||||
|
$aNames = $oLinkSet->GetColumnAsArray($sRemoteName);
|
||||||
|
if ($iLimit > 0)
|
||||||
|
{
|
||||||
|
$iTotal = $oLinkSet->Count();
|
||||||
|
if ($iTotal > count($aNames))
|
||||||
|
{
|
||||||
|
$aNames[] = '... '.Dict::Format('UI:TruncatedResults', count($aNames), $iTotal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sNames = implode("\n", $aNames);
|
||||||
|
$aScalarArgs[$sArgName.'->'.$sAttCode] = $sNames;
|
||||||
|
$aScalarArgs[$sArgName.'->html('.$sAttCode.')'] = '<ul><li>'.implode("</li><li>", $aNames).'</li></ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
|
||||||
$ret = $oAttDef->GetForTemplate($this->Get($sAttCode), $sVerb, $this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->m_aAsArgs = $aScalarArgs;
|
||||||
|
$oKPI->ComputeStats('ToArgs', get_class($this));
|
||||||
}
|
}
|
||||||
return $ret;
|
return $this->m_aAsArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be optionaly overloaded
|
// To be optionaly overloaded
|
||||||
|
|||||||
@@ -5420,7 +5420,7 @@ abstract class MetaModel
|
|||||||
/**
|
/**
|
||||||
* Replaces all the parameters by the values passed in the hash array
|
* Replaces all the parameters by the values passed in the hash array
|
||||||
*/
|
*/
|
||||||
static public function ApplyParams($sInput, $aParams)
|
static public function ApplyParams($aInput, $aParams)
|
||||||
{
|
{
|
||||||
// Declare magic parameters
|
// Declare magic parameters
|
||||||
$aParams['APP_URL'] = utils::GetAbsoluteUrlAppRoot();
|
$aParams['APP_URL'] = utils::GetAbsoluteUrlAppRoot();
|
||||||
@@ -5431,45 +5431,14 @@ abstract class MetaModel
|
|||||||
foreach($aParams as $sSearch => $replace)
|
foreach($aParams as $sSearch => $replace)
|
||||||
{
|
{
|
||||||
// Some environment parameters are objects, we just need scalars
|
// Some environment parameters are objects, we just need scalars
|
||||||
if (is_object($replace))
|
if (is_object($replace)) continue;
|
||||||
{
|
|
||||||
$iPos = strpos($sSearch, '->object()');
|
|
||||||
if ($iPos !== false)
|
|
||||||
{
|
|
||||||
// Expand the parameters for the object
|
|
||||||
$sName = substr($sSearch, 0, $iPos);
|
|
||||||
if (preg_match_all('/\\$'.$sName.'->([^\\$]+)\\$/', $sInput, $aMatches))
|
|
||||||
{
|
|
||||||
foreach($aMatches[1] as $sPlaceholderAttCode)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$sReplacement = $replace->GetForTemplate($sPlaceholderAttCode);
|
|
||||||
if ($sReplacement !== null)
|
|
||||||
{
|
|
||||||
$aReplacements[] = $sReplacement;
|
|
||||||
$aSearches[] = '$'.$sName.'->'.$sPlaceholderAttCode.'$';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
// No replacement will occur
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
continue; // Ignore this non-scalar value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aSearches[] = '$'.$sSearch.'$';
|
$aSearches[] = '$'.$sSearch.'$';
|
||||||
$aReplacements[] = (string) $replace;
|
$aReplacements[] = (string) $replace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str_replace($aSearches, $aReplacements, $sInput);
|
return str_replace($aSearches, $aReplacements, $aInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ abstract class QueryReflection
|
|||||||
/**
|
/**
|
||||||
* Throws an exception in case of an invalid syntax
|
* Throws an exception in case of an invalid syntax
|
||||||
*/
|
*/
|
||||||
abstract public function __construct($sOQL, ModelReflection $oModelReflection);
|
abstract public function __construct($sOQL);
|
||||||
|
|
||||||
abstract public function GetClass();
|
abstract public function GetClass();
|
||||||
abstract public function GetClassAlias();
|
abstract public function GetClassAlias();
|
||||||
@@ -222,7 +222,7 @@ class ModelReflectionRuntime extends ModelReflection
|
|||||||
|
|
||||||
public function GetQuery($sOQL)
|
public function GetQuery($sOQL)
|
||||||
{
|
{
|
||||||
return new QueryReflectionRuntime($sOQL, $this);
|
return new QueryReflectionRuntime($sOQL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DictString($sStringCode, $sDefault = null, $bUserLanguageOnly = false)
|
public function DictString($sStringCode, $sDefault = null, $bUserLanguageOnly = false)
|
||||||
@@ -244,7 +244,7 @@ class QueryReflectionRuntime extends QueryReflection
|
|||||||
/**
|
/**
|
||||||
* throws an exception in case of a wrong syntax
|
* throws an exception in case of a wrong syntax
|
||||||
*/
|
*/
|
||||||
public function __construct($sOQL, ModelReflection $oModelReflection)
|
public function __construct($sOQL)
|
||||||
{
|
{
|
||||||
$this->oFilter = DBObjectSearch::FromOQL($sOQL);
|
$this->oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,19 @@ class iTopMutex
|
|||||||
public function __construct($sName, $sDBHost = null, $sDBUser = null, $sDBPwd = null)
|
public function __construct($sName, $sDBHost = null, $sDBUser = null, $sDBPwd = null)
|
||||||
{
|
{
|
||||||
// Compute the name of a lock for mysql
|
// Compute the name of a lock for mysql
|
||||||
// Note: the name is server-wide!!!
|
// Note: names are server-wide!!! So let's make the name specific to this iTop instance
|
||||||
|
$oConfig = utils::GetConfig(); // Will return an empty config when called during the setup
|
||||||
|
$sDBName = $oConfig->GetDBName();
|
||||||
|
$sDBSubname = $oConfig->GetDBSubname();
|
||||||
$this->sName = 'itop.'.$sName;
|
$this->sName = 'itop.'.$sName;
|
||||||
|
if (substr($sName, -strlen($sDBName.$sDBSubname)) != $sDBName.$sDBSubname)
|
||||||
|
{
|
||||||
|
// If the name supplied already ends with the expected suffix
|
||||||
|
// don't add it twice, since the setup may try to detect an already
|
||||||
|
// running cron job by its mutex, without knowing if the config already exists or not
|
||||||
|
$this->sName .= $sDBName.$sDBSubname;
|
||||||
|
}
|
||||||
|
|
||||||
$this->bLocked = false; // Not yet locked
|
$this->bLocked = false; // Not yet locked
|
||||||
|
|
||||||
if (!array_key_exists($this->sName, self::$aAcquiredLocks))
|
if (!array_key_exists($this->sName, self::$aAcquiredLocks))
|
||||||
@@ -48,7 +59,6 @@ class iTopMutex
|
|||||||
|
|
||||||
// It is a MUST to create a dedicated session each time a lock is required, because
|
// 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)
|
// using GET_LOCK anytime on the same session will RELEASE the current and unique session lock (known issue)
|
||||||
$oConfig = utils::GetConfig();
|
|
||||||
$sDBHost = is_null($sDBHost) ? $oConfig->GetDBHost() : $sDBHost;
|
$sDBHost = is_null($sDBHost) ? $oConfig->GetDBHost() : $sDBHost;
|
||||||
$sDBUser = is_null($sDBUser) ? $oConfig->GetDBUser() : $sDBUser;
|
$sDBUser = is_null($sDBUser) ? $oConfig->GetDBUser() : $sDBUser;
|
||||||
$sDBPwd = is_null($sDBPwd) ? $oConfig->GetDBPwd() : $sDBPwd;
|
$sDBPwd = is_null($sDBPwd) ? $oConfig->GetDBPwd() : $sDBPwd;
|
||||||
@@ -123,7 +133,9 @@ class iTopMutex
|
|||||||
}
|
}
|
||||||
if (($res !== '1') && ($res !== '0'))
|
if (($res !== '1') && ($res !== '0'))
|
||||||
{
|
{
|
||||||
IssueLog::Error('GET_LOCK('.$this->sName.', 0) returned: '.var_export($res, true).'. Expected values are: 0, 1 or null !!');
|
$sMsg = 'GET_LOCK('.$this->sName.', 0) returned: '.var_export($res, true).'. Expected values are: 0, 1 or null';
|
||||||
|
IssueLog::Error($sMsg);
|
||||||
|
throw new Exception($sMsg);
|
||||||
}
|
}
|
||||||
return ($res !== '0');
|
return ($res !== '0');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2015 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -23,7 +23,7 @@ define('CASELOG_SEPARATOR', "\n".'========== %1$s : %2$s (%3$d) ============'."\
|
|||||||
/**
|
/**
|
||||||
* Class to store a "case log" in a structured way, keeping track of its successive entries
|
* Class to store a "case log" in a structured way, keeping track of its successive entries
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
class ormCaseLog {
|
class ormCaseLog {
|
||||||
@@ -394,7 +394,7 @@ class ormCaseLog {
|
|||||||
{
|
{
|
||||||
throw new Exception("Only administrators can set the user id", RestResult::UNAUTHORIZED);
|
throw new Exception("Only administrators can set the user id", RestResult::UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
if ($bCheckUserId)
|
if ($bCheckUserId && ($oJson->user_id != 0))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1303,8 +1303,9 @@ class CAS_SelfRegister implements iSelfRegister
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No membership required, anybody will pass
|
// No membership: no way to create the user that should exist prior to authentication
|
||||||
$bFound = true;
|
phpCAS::log("User ".phpCAS::getUser().": missing user account in iTop (or iTop badly configured, Cf setting cas_memberof)");
|
||||||
|
$bFound = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$bFound)
|
if (!$bFound)
|
||||||
|
|||||||
@@ -206,6 +206,11 @@ legend.transparent {
|
|||||||
padding-left:14px;
|
padding-left:14px;
|
||||||
background: url(../images/mini-arrow-orange.gif) no-repeat left;
|
background: url(../images/mini-arrow-orange.gif) no-repeat left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-widget-content td a.cke_toolbox_collapser {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
p a:hover, td a:hover {
|
p a:hover, td a:hover {
|
||||||
text-decoration:underline;
|
text-decoration:underline;
|
||||||
color:#EB8F00;
|
color:#EB8F00;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Backup from an interactive session
|
* Backup from an interactive session
|
||||||
|
*
|
||||||
* @copyright Copyright (C) 2013-2016 Combodo SARL
|
* @copyright Copyright (C) 2013-2016 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
@@ -117,7 +118,9 @@ EOF
|
|||||||
{
|
{
|
||||||
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
|
$sEnvironment = utils::ReadParam('environment', 'production', false, 'raw_data');
|
||||||
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
|
$oRestoreMutex = new iTopMutex('restore.'.$sEnvironment);
|
||||||
|
IssueLog::Info("Backup Restore - Acquiring the LOCK 'restore.$sEnvironment'");
|
||||||
$oRestoreMutex->Lock();
|
$oRestoreMutex->Lock();
|
||||||
|
IssueLog::Info('Backup Restore - LOCK acquired, executing...');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
@@ -142,6 +145,7 @@ EOF
|
|||||||
$sBackupFile = $sBackupDir.$sFile;
|
$sBackupFile = $sBackupDir.$sFile;
|
||||||
$sRes = $oDBRS->RestoreFromZip($sBackupFile, $sEnvironment);
|
$sRes = $oDBRS->RestoreFromZip($sBackupFile, $sEnvironment);
|
||||||
|
|
||||||
|
IssueLog::Info('Backup Restore - Done, releasing the LOCK');
|
||||||
$oRestoreMutex->Unlock();
|
$oRestoreMutex->Unlock();
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
|
|||||||
@@ -26,19 +26,19 @@ class BackupHandler extends ModuleHandlerAPI
|
|||||||
{
|
{
|
||||||
public static function OnMetaModelStarted()
|
public static function OnMetaModelStarted()
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
$oRestoreMutex = new iTopMutex('restore.'.utils::GetCurrentEnvironment());
|
||||||
if ($oRestoreMutex->IsLocked())
|
if ($oRestoreMutex->IsLocked())
|
||||||
{
|
{
|
||||||
|
IssueLog::Info(__class__.'::'.__function__.' A user is trying to use iTop while a restore is running. The requested page is in read-only mode.');
|
||||||
MetaModel::GetConfig()->Set('access_mode', ACCESS_READONLY, 'itop-backup');
|
MetaModel::GetConfig()->Set('access_mode', ACCESS_READONLY, 'itop-backup');
|
||||||
MetaModel::GetConfig()->Set('access_message', ' - '.dict::S('bkp-restore-running'), 'itop-backup');
|
MetaModel::GetConfig()->Set('access_message', ' - '.dict::S('bkp-restore-running'), 'itop-backup');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
|
IssueLog::Error(__class__.'::'.__function__.' Failed to check if a backup/restore is running: '.$e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -746,16 +746,6 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>deny</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeStopWatch"/>
|
|
||||||
<type id="AttributeSubItem"/>
|
|
||||||
<type id="AttributeExternalField"/>
|
|
||||||
<type id="AttributeLinkedSetIndirect"/>
|
|
||||||
<type id="AttributeLinkedSet"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
<argument id="2">
|
<argument id="2">
|
||||||
<type>string</type>
|
<type>string</type>
|
||||||
@@ -768,14 +758,6 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>allow</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeDate"/>
|
|
||||||
<type id="AttributeDateTime"/>
|
|
||||||
<type id="AttributeString"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</method>
|
</method>
|
||||||
@@ -784,14 +766,6 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>allow</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeExternalKey"/>
|
|
||||||
<type id="AttributeInteger"/>
|
|
||||||
<type id="AttributeString"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</method>
|
</method>
|
||||||
@@ -800,23 +774,10 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>allow</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeDuration"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
<argument id="2">
|
<argument id="2">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>allow</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeDate"/>
|
|
||||||
<type id="AttributeDateTime"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
<argument id="3">
|
<argument id="3">
|
||||||
<type>string</type>
|
<type>string</type>
|
||||||
@@ -829,28 +790,6 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>deny</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeStopWatch"/>
|
|
||||||
<type id="AttributeSubItem"/>
|
|
||||||
<type id="AttributeExternalField"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
|
||||||
</arguments>
|
|
||||||
</method>
|
|
||||||
<method id="ResetStopWatch">
|
|
||||||
<arguments>
|
|
||||||
<argument id="1">
|
|
||||||
<type>attcode</type>
|
|
||||||
<mandatory>true</mandatory>
|
|
||||||
<type_restrictions>
|
|
||||||
<operation>allow</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeStopWatch"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
</arguments>
|
</arguments>
|
||||||
</method>
|
</method>
|
||||||
@@ -859,14 +798,6 @@
|
|||||||
<argument id="1">
|
<argument id="1">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
<mandatory>true</mandatory>
|
<mandatory>true</mandatory>
|
||||||
<type_restrictions>
|
|
||||||
<operation>deny</operation>
|
|
||||||
<types>
|
|
||||||
<type id="AttributeStopWatch"/>
|
|
||||||
<type id="AttributeSubItem"/>
|
|
||||||
<type id="AttributeExternalField"/>
|
|
||||||
</types>
|
|
||||||
</type_restrictions>
|
|
||||||
</argument>
|
</argument>
|
||||||
<argument id="2">
|
<argument id="2">
|
||||||
<type>attcode</type>
|
<type>attcode</type>
|
||||||
|
|||||||
@@ -230,25 +230,32 @@ function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
|||||||
var bValid;
|
var bValid;
|
||||||
var sTextContent;
|
var sTextContent;
|
||||||
|
|
||||||
// Get the contents without the tags
|
if ($('#'+sFieldId).attr('disabled'))
|
||||||
var oFormattedContents = $("#cke_"+sFieldId+" iframe");
|
|
||||||
if (oFormattedContents.length == 0)
|
|
||||||
{
|
{
|
||||||
var oSourceContents = $("#cke_"+sFieldId+" textarea.cke_source");
|
bValid = true; // disabled fields are not checked
|
||||||
sTextContent = oSourceContents.val();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sTextContent = oFormattedContents.contents().find("body").text();
|
// Get the contents without the tags
|
||||||
}
|
var oFormattedContents = $("#cke_"+sFieldId+" iframe");
|
||||||
|
if (oFormattedContents.length == 0)
|
||||||
if (bMandatory && (sTextContent == ''))
|
{
|
||||||
{
|
var oSourceContents = $("#cke_"+sFieldId+" textarea.cke_source");
|
||||||
bValid = false;
|
sTextContent = oSourceContents.val();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bValid = true;
|
sTextContent = oFormattedContents.contents().find("body").text();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bMandatory && (sTextContent == ''))
|
||||||
|
{
|
||||||
|
bValid = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bValid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportFieldValidationStatus(sFieldId, sFormId, bValid, '');
|
ReportFieldValidationStatus(sFieldId, sFormId, bValid, '');
|
||||||
|
|||||||
@@ -225,7 +225,6 @@ $(function()
|
|||||||
_do_submit: function()
|
_do_submit: function()
|
||||||
{
|
{
|
||||||
var oData = {};
|
var oData = {};
|
||||||
var me = this;
|
|
||||||
this.element.closest('form').find(':input[type=hidden]').each(function()
|
this.element.closest('form').find(':input[type=hidden]').each(function()
|
||||||
{
|
{
|
||||||
// Hidden form fields
|
// Hidden form fields
|
||||||
@@ -233,7 +232,7 @@ $(function()
|
|||||||
});
|
});
|
||||||
this.element.closest('form').find('.itop-property-field').each(function()
|
this.element.closest('form').find('.itop-property-field').each(function()
|
||||||
{
|
{
|
||||||
var oWidget = me._get_widget($(this));
|
var oWidget = $(this).data('itopProperty_field');
|
||||||
if (oWidget && oWidget._is_visible())
|
if (oWidget && oWidget._is_visible())
|
||||||
{
|
{
|
||||||
var oVal = oWidget._get_committed_value();
|
var oVal = oWidget._get_committed_value();
|
||||||
@@ -265,15 +264,6 @@ $(function()
|
|||||||
{
|
{
|
||||||
var oField = $('#'+this.options.field_id, this.element);
|
var oField = $('#'+this.options.field_id, this.element);
|
||||||
oField.trigger('validate');
|
oField.trigger('validate');
|
||||||
},
|
|
||||||
_get_widget: function(element)
|
|
||||||
{
|
|
||||||
var oWidget = element.data('itopProperty_field');
|
|
||||||
if (oWidget == undefined)
|
|
||||||
{
|
|
||||||
oWidget = element.data('itopSelector_property_field');
|
|
||||||
}
|
|
||||||
return oWidget;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -341,19 +331,9 @@ $(function()
|
|||||||
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
||||||
if($(this).is(':visible'))
|
if($(this).is(':visible'))
|
||||||
{
|
{
|
||||||
var oWidget = me._get_widget($(this).closest('.itop-property-field'));
|
var oPropField = $(this).closest('.itop-property-field');
|
||||||
if (oWidget)
|
oPropField.property_field('option', {can_apply: !me.bModified, parent_selector: '#'+me.element.attr('id') });
|
||||||
{
|
oPropField.property_field('validate');
|
||||||
try
|
|
||||||
{
|
|
||||||
oWidget._setOptions({can_apply: !me.bModified, parent_selector: '#'+me.element.attr('id') });
|
|
||||||
oWidget.validate();
|
|
||||||
}
|
|
||||||
catch(e)
|
|
||||||
{
|
|
||||||
// Do nothing, form in read-only mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -405,21 +385,21 @@ $(function()
|
|||||||
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
||||||
if($(this).is(':visible'))
|
if($(this).is(':visible'))
|
||||||
{
|
{
|
||||||
var oWidget = me._get_widget($(this).closest('.itop-property-field'));
|
var sName = $(this).closest('.itop-property-field').property_field('mark_as_applied').property_field('get_field_name');
|
||||||
if (oWidget)
|
if (typeof sName == 'string')
|
||||||
{
|
{
|
||||||
oWidget.mark_as_applied();
|
aUpdated.push(sName);
|
||||||
sName = oWidget.get_field_name();
|
|
||||||
if (typeof sName == 'string')
|
|
||||||
{
|
|
||||||
aUpdated.push(sName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.element.closest('form').find('.itop-property-field').each(function()
|
this.element.closest('form').find('.itop-property-field').each(function()
|
||||||
{
|
{
|
||||||
var oWidget = me._get_widget($(this));
|
var oWidget = $(this).data('itopProperty_field');
|
||||||
|
if (!oWidget)
|
||||||
|
{
|
||||||
|
// try the form selector widget
|
||||||
|
oWidget = $(this).data('itopSelector_property_field');
|
||||||
|
}
|
||||||
if (oWidget && oWidget._is_visible())
|
if (oWidget && oWidget._is_visible())
|
||||||
{
|
{
|
||||||
var oVal = oWidget._get_committed_value();
|
var oVal = oWidget._get_committed_value();
|
||||||
@@ -446,16 +426,12 @@ $(function()
|
|||||||
sFormId = this.element.closest('form').attr('id');
|
sFormId = this.element.closest('form').attr('id');
|
||||||
oFormValidation[sFormId] = [];
|
oFormValidation[sFormId] = [];
|
||||||
this.options.can_apply = true;
|
this.options.can_apply = true;
|
||||||
var sSelector = this.options.data_selector;
|
var sSelector = this.options.data_selector
|
||||||
var me = this;
|
|
||||||
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
$('tr[data-path^="'+sSelector+'"]').each(function() {
|
||||||
if($(this).is(':visible'))
|
if($(this).is(':visible'))
|
||||||
{
|
{
|
||||||
var oWidget = me._get_widget($(this).closest('.itop-property-field'));
|
var oPropField = $(this).closest('.itop-property-field');
|
||||||
if (oWidget)
|
oPropField.property_field('validate');
|
||||||
{
|
|
||||||
oWidget.validate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.options.can_apply = (oFormValidation[sFormId].length == 0); // apply allowed only if no error
|
this.options.can_apply = (oFormValidation[sFormId].length == 0); // apply allowed only if no error
|
||||||
@@ -466,7 +442,7 @@ $(function()
|
|||||||
|
|
||||||
var oFormValidation = {};
|
var oFormValidation = {};
|
||||||
|
|
||||||
function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbiddenValues)
|
function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbiddenValues, sExplainForbiddenValues)
|
||||||
{
|
{
|
||||||
var currentVal = $('#'+sFieldId).val();
|
var currentVal = $('#'+sFieldId).val();
|
||||||
var bValid = true;
|
var bValid = true;
|
||||||
@@ -485,14 +461,11 @@ function ValidateWithPattern(sFieldId, bMandatory, sPattern, sFormId, aForbidden
|
|||||||
{
|
{
|
||||||
for(var i in aForbiddenValues)
|
for(var i in aForbiddenValues)
|
||||||
{
|
{
|
||||||
for(j in aForbiddenValues[i].values)
|
if (aForbiddenValues[i] == currentVal)
|
||||||
{
|
{
|
||||||
if (aForbiddenValues[i].values[j] == currentVal)
|
bValid = false;
|
||||||
{
|
sMessage = sExplainForbiddenValues;
|
||||||
bValid = false;
|
break;
|
||||||
sMessage = aForbiddenValues[i].message;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -625,7 +598,7 @@ function ReadFormParams(sFormId)
|
|||||||
{
|
{
|
||||||
var oMap = { };
|
var oMap = { };
|
||||||
$('#'+sFormId+' :input').each( function() {
|
$('#'+sFormId+' :input').each( function() {
|
||||||
if ($(this).parent().is(':visible') && !$(this).prop('disabled'))
|
if ($(this).parent().is(':visible'))
|
||||||
{
|
{
|
||||||
var sName = $(this).attr('name');
|
var sName = $(this).attr('name');
|
||||||
if (sName && sName != '')
|
if (sName && sName != '')
|
||||||
|
|||||||
@@ -1732,8 +1732,7 @@ catch (Exception $e)
|
|||||||
{
|
{
|
||||||
// note: transform to cope with XSS attacks
|
// note: transform to cope with XSS attacks
|
||||||
echo htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8');
|
echo htmlentities($e->GetMessage(), ENT_QUOTES, 'utf-8');
|
||||||
echo "<p>Debug trace: <pre>".$e->getTraceAsString()."</pre></p>\n";
|
IssueLog::Error($e->getMessage()."\nDebug trace:\n".$e->getTraceAsString()); // Do NOT display the call stack since it may contain sensitive information
|
||||||
IssueLog::Error($e->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2012 Combodo SARL
|
// Copyright (C) 2010-2016 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -224,6 +224,12 @@ class DBBackup
|
|||||||
}
|
}
|
||||||
if ($iRetCode != 0)
|
if ($iRetCode != 0)
|
||||||
{
|
{
|
||||||
|
// Cleanup residual output (Happens with Error 2020: Got packet bigger than 'maxallowedpacket' bytes...)
|
||||||
|
if (file_exists($sBackupFileName))
|
||||||
|
{
|
||||||
|
unlink($sBackupFileName);
|
||||||
|
}
|
||||||
|
|
||||||
$this->LogError("Failed to execute: $sCommandDisplay. The command returned:$iRetCode");
|
$this->LogError("Failed to execute: $sCommandDisplay. The command returned:$iRetCode");
|
||||||
foreach($aOutput as $sLine)
|
foreach($aOutput as $sLine)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -272,10 +272,11 @@ class ModelFactory
|
|||||||
|
|
||||||
if (($oSourceNode->tagName == 'class') && ($oSourceNode->parentNode->tagName == 'classes') && ($oSourceNode->parentNode->parentNode->tagName == 'itop_design'))
|
if (($oSourceNode->tagName == 'class') && ($oSourceNode->parentNode->tagName == 'classes') && ($oSourceNode->parentNode->parentNode->tagName == 'itop_design'))
|
||||||
{
|
{
|
||||||
$sParentId = $oSourceNode->GetChildText('parent');
|
|
||||||
if ($oSourceNode->getAttribute('_delta') == 'define')
|
if ($oSourceNode->getAttribute('_delta') == 'define')
|
||||||
{
|
{
|
||||||
// This tag is organized in hierarchy: determine the real parent node (as a subnode of the current node)
|
// This tag is organized in hierarchy: determine the real parent node (as a subnode of the current node)
|
||||||
|
$sParentId = $oSourceNode->GetChildText('parent');
|
||||||
|
|
||||||
$oTargetParentNode = $oTarget->GetNodeById('/itop_design/classes//class', $sParentId)->item(0);
|
$oTargetParentNode = $oTarget->GetNodeById('/itop_design/classes//class', $sParentId)->item(0);
|
||||||
|
|
||||||
if (!$oTargetParentNode)
|
if (!$oTargetParentNode)
|
||||||
@@ -297,13 +298,6 @@ class ModelFactory
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
$oTargetParentNode = $oTargetNode->parentNode;
|
$oTargetParentNode = $oTargetNode->parentNode;
|
||||||
if (($oSourceNode->getAttribute('_delta') == 'redefine') && ($oTargetParentNode->getAttribute('id') != $sParentId))
|
|
||||||
{
|
|
||||||
// A class that has moved <=> deletion and creation elsewhere
|
|
||||||
$oTargetParentNode = $oTarget->GetNodeById('/itop_design/classes//class', $sParentId)->item(0);
|
|
||||||
$oTargetNode->Delete();
|
|
||||||
$oSourceNode->setAttribute('_delta', 'define');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -866,56 +860,19 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Import the node into the delta
|
|
||||||
*/
|
|
||||||
protected function SetDeltaFlags($oNodeClone)
|
|
||||||
{
|
|
||||||
$sAlteration = $oNodeClone->getAttribute('_alteration');
|
|
||||||
$oNodeClone->removeAttribute('_alteration');
|
|
||||||
if ($oNodeClone->hasAttribute('_old_id'))
|
|
||||||
{
|
|
||||||
$oNodeClone->setAttribute('_rename_from', $oNodeClone->getAttribute('_old_id'));
|
|
||||||
$oNodeClone->removeAttribute('_old_id');
|
|
||||||
}
|
|
||||||
switch ($sAlteration)
|
|
||||||
{
|
|
||||||
case '':
|
|
||||||
if ($oNodeClone->hasAttribute('id'))
|
|
||||||
{
|
|
||||||
$oNodeClone->setAttribute('_delta', 'must_exist');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'added':
|
|
||||||
$oNodeClone->setAttribute('_delta', 'define');
|
|
||||||
break;
|
|
||||||
case 'replaced':
|
|
||||||
$oNodeClone->setAttribute('_delta', 'redefine');
|
|
||||||
break;
|
|
||||||
case 'removed':
|
|
||||||
$oNodeClone->setAttribute('_delta', 'delete');
|
|
||||||
break;
|
|
||||||
case 'needed':
|
|
||||||
$oNodeClone->setAttribute('_delta', 'define_if_not_exists');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return $oNodeClone;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create path for the delta
|
* Create path for the delta
|
||||||
* @param Array aMovedClasses The classes that have been moved in the hierarchy (deleted + created elsewhere)
|
|
||||||
* @param DOMDocument oTargetDoc Where to attach the top of the hierarchy
|
* @param DOMDocument oTargetDoc Where to attach the top of the hierarchy
|
||||||
* @param MFElement oNode The node to import with its path
|
* @param MFElement oNode The node to import with its path
|
||||||
*/
|
*/
|
||||||
protected function ImportNodeAndPathDelta($aMovedClasses, $oTargetDoc, $oNode)
|
protected function ImportNodeAndPathDelta($oTargetDoc, $oNode)
|
||||||
{
|
{
|
||||||
// Preliminary: skip the parent if this node is organized hierarchically into the DOM
|
// Preliminary: skip the parent if this node is organized hierarchically into the DOM
|
||||||
// Only class nodes are organized this way
|
// Only class nodes are organized this way
|
||||||
$oParent = $oNode->parentNode;
|
$oParent = $oNode->parentNode;
|
||||||
if ($oNode->IsClassNode())
|
if ($oNode->tagName == 'class')
|
||||||
{
|
{
|
||||||
while (($oParent instanceof DOMElement) && ($oParent->IsClassNode()))
|
while (($oParent instanceof DOMElement) && ($oParent->tagName == $oNode->tagName) && $oParent->hasAttribute('id'))
|
||||||
{
|
{
|
||||||
$oParent = $oParent->parentNode;
|
$oParent = $oParent->parentNode;
|
||||||
}
|
}
|
||||||
@@ -923,71 +880,64 @@ EOF
|
|||||||
// Recursively create the path for the parent
|
// Recursively create the path for the parent
|
||||||
if ($oParent instanceof DOMElement)
|
if ($oParent instanceof DOMElement)
|
||||||
{
|
{
|
||||||
$oParentClone = $this->ImportNodeAndPathDelta($aMovedClasses, $oTargetDoc, $oParent);
|
$oParentClone = $this->ImportNodeAndPathDelta($oTargetDoc, $oParent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We've reached the top let's add the node into the root recipient
|
// We've reached the top let's add the node into the root recipient
|
||||||
$oParentClone = $oTargetDoc;
|
$oParentClone = $oTargetDoc;
|
||||||
}
|
}
|
||||||
|
// Look for the node into the parent node
|
||||||
$sAlteration = $oNode->getAttribute('_alteration');
|
// Note: this is an identified weakness of the algorithm,
|
||||||
if ($oNode->IsClassNode() && ($sAlteration != ''))
|
// because for each node modified, and each node of its path
|
||||||
|
// we will have to lookup for the existing entry
|
||||||
|
// Anyhow, this loop is quite quick to execute because in the delta
|
||||||
|
// the number of nodes is limited
|
||||||
|
$oNodeClone = null;
|
||||||
|
foreach ($oParentClone->childNodes as $oChild)
|
||||||
{
|
{
|
||||||
// Handle the moved classes
|
if (($oChild instanceof DOMElement) && ($oChild->tagName == $oNode->tagName))
|
||||||
//
|
{
|
||||||
// Import the whole root node
|
if (!$oNode->hasAttribute('id') || ($oNode->getAttribute('id') == $oChild->getAttribute('id')))
|
||||||
$oNodeClone = $oTargetDoc->importNode($oNode->cloneNode(true), true);
|
{
|
||||||
|
$oNodeClone = $oChild;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$oNodeClone)
|
||||||
|
{
|
||||||
|
$sAlteration = $oNode->getAttribute('_alteration');
|
||||||
|
$bCopyContents = ($sAlteration == 'replaced') || ($sAlteration == 'added') || ($sAlteration == 'needed');
|
||||||
|
$oNodeClone = $oTargetDoc->importNode($oNode->cloneNode($bCopyContents), $bCopyContents);
|
||||||
|
$oNodeClone->removeAttribute('_alteration');
|
||||||
|
if ($oNodeClone->hasAttribute('_old_id'))
|
||||||
|
{
|
||||||
|
$oNodeClone->setAttribute('_rename_from', $oNodeClone->getAttribute('_old_id'));
|
||||||
|
$oNodeClone->removeAttribute('_old_id');
|
||||||
|
}
|
||||||
|
switch ($sAlteration)
|
||||||
|
{
|
||||||
|
case '':
|
||||||
|
if ($oNodeClone->hasAttribute('id'))
|
||||||
|
{
|
||||||
|
$oNodeClone->setAttribute('_delta', 'must_exist');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'added':
|
||||||
|
$oNodeClone->setAttribute('_delta', 'define');
|
||||||
|
break;
|
||||||
|
case 'replaced':
|
||||||
|
$oNodeClone->setAttribute('_delta', 'redefine');
|
||||||
|
break;
|
||||||
|
case 'removed':
|
||||||
|
$oNodeClone->setAttribute('_delta', 'delete');
|
||||||
|
break;
|
||||||
|
case 'needed':
|
||||||
|
$oNodeClone->setAttribute('_delta', 'define_if_not_exists');
|
||||||
|
break;
|
||||||
|
}
|
||||||
$oParentClone->appendChild($oNodeClone);
|
$oParentClone->appendChild($oNodeClone);
|
||||||
$this->SetDeltaFlags($oNodeClone);
|
|
||||||
|
|
||||||
// Handle the moved classes found under the root node (or the root node itself)
|
|
||||||
foreach($oNodeClone->GetNodes("descendant-or-self::class[@id]", false) as $oClassNode)
|
|
||||||
{
|
|
||||||
if (array_key_exists($oClassNode->getAttribute('id'), $aMovedClasses))
|
|
||||||
{
|
|
||||||
if ($sAlteration == 'removed')
|
|
||||||
{
|
|
||||||
// Remove that node: this specification will be overriden by the 'replaced' spec (see below)
|
|
||||||
$oClassNode->parentNode->removeChild($oClassNode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Move the class at the root, with the flag 'modified'
|
|
||||||
$oParentClone->appendChild($oClassNode);
|
|
||||||
$oClassNode->setAttribute('_alteration', 'replaced');
|
|
||||||
$this->SetDeltaFlags($oClassNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Look for the node into the parent node
|
|
||||||
// Note: this is an identified weakness of the algorithm,
|
|
||||||
// because for each node modified, and each node of its path
|
|
||||||
// we will have to lookup for the existing entry
|
|
||||||
// Anyhow, this loop is quite quick to execute because in the delta
|
|
||||||
// the number of nodes is limited
|
|
||||||
$oNodeClone = null;
|
|
||||||
foreach ($oParentClone->childNodes as $oChild)
|
|
||||||
{
|
|
||||||
if (($oChild instanceof DOMElement) && ($oChild->tagName == $oNode->tagName))
|
|
||||||
{
|
|
||||||
if (!$oNode->hasAttribute('id') || ($oNode->getAttribute('id') == $oChild->getAttribute('id')))
|
|
||||||
{
|
|
||||||
$oNodeClone = $oChild;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$oNodeClone)
|
|
||||||
{
|
|
||||||
$bCopyContents = ($sAlteration == 'replaced') || ($sAlteration == 'added') || ($sAlteration == 'needed');
|
|
||||||
$oNodeClone = $oTargetDoc->importNode($oNode->cloneNode($bCopyContents), $bCopyContents);
|
|
||||||
$this->SetDeltaFlags($oNodeClone);
|
|
||||||
$oParentClone->appendChild($oNodeClone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $oNodeClone;
|
return $oNodeClone;
|
||||||
}
|
}
|
||||||
@@ -1012,24 +962,9 @@ EOF
|
|||||||
public function GetDeltaDocument($aNodesToIgnore = array(), $aAttributes = null)
|
public function GetDeltaDocument($aNodesToIgnore = array(), $aAttributes = null)
|
||||||
{
|
{
|
||||||
$oDelta = new MFDocument();
|
$oDelta = new MFDocument();
|
||||||
|
|
||||||
// Handle classes moved from one parent to another
|
|
||||||
// This will be done in two steps:
|
|
||||||
// 1) Identify the moved classes (marked as deleted under the original parent, and created under the new parent)
|
|
||||||
// 2) When importing those "moved" classes into the delta (see ImportNodeAndPathDelta), extract them from the hierarchy (the alteration can be done at an upper level in the hierarchy) and mark them as "modified"
|
|
||||||
$aMovedClasses = array();
|
|
||||||
foreach($this->GetNodes("/itop_design/classes//class/class[@_alteration='removed']", null, false) as $oNode)
|
|
||||||
{
|
|
||||||
$sId = $oNode->getAttribute('id');
|
|
||||||
if ($this->GetNodes("/itop_design/classes//class/class[@id='$sId']/properties", null, false)->length > 0)
|
|
||||||
{
|
|
||||||
$aMovedClasses[$sId] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->ListChanges() as $oAlteredNode)
|
foreach($this->ListChanges() as $oAlteredNode)
|
||||||
{
|
{
|
||||||
$this->ImportNodeAndPathDelta($aMovedClasses, $oDelta, $oAlteredNode);
|
$this->ImportNodeAndPathDelta($oDelta, $oAlteredNode);
|
||||||
}
|
}
|
||||||
foreach($aNodesToIgnore as $sXPath)
|
foreach($aNodesToIgnore as $sXPath)
|
||||||
{
|
{
|
||||||
@@ -1238,9 +1173,9 @@ EOF;
|
|||||||
* @param string $sXPath A XPath expression
|
* @param string $sXPath A XPath expression
|
||||||
* @return DOMNodeList
|
* @return DOMNodeList
|
||||||
*/
|
*/
|
||||||
public function GetNodes($sXPath, $oContextNode = null, $bSafe = true)
|
public function GetNodes($sXPath, $oContextNode = null)
|
||||||
{
|
{
|
||||||
return $this->oDOMDocument->GetNodes($sXPath, $oContextNode, $bSafe);
|
return $this->oDOMDocument->GetNodes($sXPath, $oContextNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1264,9 +1199,9 @@ class MFElement extends DOMElement
|
|||||||
* @param string $sXPath A XPath expression
|
* @param string $sXPath A XPath expression
|
||||||
* @return DOMNodeList
|
* @return DOMNodeList
|
||||||
*/
|
*/
|
||||||
public function GetNodes($sXPath, $bSafe = true)
|
public function GetNodes($sXPath)
|
||||||
{
|
{
|
||||||
return $this->ownerDocument->GetNodes($sXPath, $this, $bSafe);
|
return $this->ownerDocument->GetNodes($sXPath, $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1339,7 +1274,7 @@ class MFElement extends DOMElement
|
|||||||
$sText = null;
|
$sText = null;
|
||||||
foreach($this->childNodes as $oChildNode)
|
foreach($this->childNodes as $oChildNode)
|
||||||
{
|
{
|
||||||
if ($oChildNode instanceof DOMText)
|
if ($oChildNode instanceof DOMCharacterData) // Base class of DOMText and DOMCdataSection
|
||||||
{
|
{
|
||||||
if (is_null($sText)) $sText = '';
|
if (is_null($sText)) $sText = '';
|
||||||
$sText .= $oChildNode->wholeText;
|
$sText .= $oChildNode->wholeText;
|
||||||
@@ -1679,16 +1614,16 @@ class MFElement extends DOMElement
|
|||||||
/**
|
/**
|
||||||
* Check that the current node is actually a class node, under classes
|
* Check that the current node is actually a class node, under classes
|
||||||
*/
|
*/
|
||||||
public function IsClassNode()
|
protected function IsClassNode()
|
||||||
{
|
{
|
||||||
if ($this->tagName == 'class')
|
if ($this->tagName == 'class')
|
||||||
{
|
{
|
||||||
if (($this->parentNode->tagName == 'classes') && ($this->parentNode->parentNode->tagName == 'itop_design') ) // Beware: classes/class also exists in the group definition
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return $this->parentNode->IsClassNode();
|
return $this->parentNode->IsClassNode();
|
||||||
}
|
}
|
||||||
|
elseif (($this->tagName == 'classes') && ($this->parentNode->tagName == 'itop_design') ) // Beware: classes/class also exists in the group definition
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class CheckResult
|
|||||||
|
|
||||||
class SetupUtils
|
class SetupUtils
|
||||||
{
|
{
|
||||||
const PHP_MIN_VERSION = '5.2.0';
|
const PHP_MIN_VERSION = '5.3.0';
|
||||||
const MYSQL_MIN_VERSION = '5.0.0';
|
const MYSQL_MIN_VERSION = '5.0.0';
|
||||||
const MIN_MEMORY_LIMIT = 33554432; // = 32*1024*1024 Beware: Computations are not allowed in defining constants
|
const MIN_MEMORY_LIMIT = 33554432; // = 32*1024*1024 Beware: Computations are not allowed in defining constants
|
||||||
const SUHOSIN_GET_MAX_VALUE_LENGTH = 2048;
|
const SUHOSIN_GET_MAX_VALUE_LENGTH = 2048;
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ EOF
|
|||||||
);
|
);
|
||||||
|
|
||||||
$oMutex = new iTopMutex(
|
$oMutex = new iTopMutex(
|
||||||
'cron.'.$this->oWizard->GetParameter('db_name', '').'_'.$this->oWizard->GetParameter('db_prefix', ''),
|
'cron'.$this->oWizard->GetParameter('db_name', '').$this->oWizard->GetParameter('db_prefix', ''),
|
||||||
$this->oWizard->GetParameter('db_server', ''),
|
$this->oWizard->GetParameter('db_server', ''),
|
||||||
$this->oWizard->GetParameter('db_user', ''),
|
$this->oWizard->GetParameter('db_user', ''),
|
||||||
$this->oWizard->GetParameter('db_pwd', '')
|
$this->oWizard->GetParameter('db_pwd', '')
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ try
|
|||||||
// Prepare insert columns
|
// Prepare insert columns
|
||||||
$sInsertColumns = '`'.implode('`, `', $aInputColumns).'`';
|
$sInsertColumns = '`'.implode('`, `', $aInputColumns).'`';
|
||||||
|
|
||||||
$oMutex = new iTopMutex('synchro_import_'.$oDataSource->GetKey().'_'.MetaModel::GetConfig()->GetDBName().'_'.MetaModel::GetConfig()->GetDBSubname());
|
$oMutex = new iTopMutex('synchro_import_'.$oDataSource->GetKey());
|
||||||
$oMutex->Lock();
|
$oMutex->Lock();
|
||||||
foreach($aData as $iRow => $aRow)
|
foreach($aData as $iRow => $aRow)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2415,7 +2415,7 @@ class SynchroExecution
|
|||||||
|
|
||||||
self::$m_oCurrentTask = $this->m_oDataSource;
|
self::$m_oCurrentTask = $this->m_oDataSource;
|
||||||
|
|
||||||
$oMutex = new iTopMutex('synchro_process_'.$this->m_oDataSource->GetKey().'_'.MetaModel::GetConfig()->GetDBName().'_'.MetaModel::GetConfig()->GetDBSubname());
|
$oMutex = new iTopMutex('synchro_process_'.$this->m_oDataSource->GetKey());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oMutex->Lock();
|
$oMutex->Lock();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
// Copyright (C) 2010-2013 Combodo SARL
|
// Copyright (C) 2010-2016 Combodo SARL
|
||||||
//
|
//
|
||||||
// This file is part of iTop.
|
// This file is part of iTop.
|
||||||
//
|
//
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
/**
|
/**
|
||||||
* Heart beat of the application (process asynchron tasks such as broadcasting email)
|
* Heart beat of the application (process asynchron tasks such as broadcasting email)
|
||||||
*
|
*
|
||||||
* @copyright Copyright (C) 2010-2013 Combodo SARL
|
* @copyright Copyright (C) 2010-2016 Combodo SARL
|
||||||
* @license http://opensource.org/licenses/AGPL-3.0
|
* @license http://opensource.org/licenses/AGPL-3.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -71,49 +71,49 @@ function UsageAndExit($oP)
|
|||||||
|
|
||||||
function RunTask($oProcess, BackgroundTask $oTask, $oStartDate, $iTimeLimit)
|
function RunTask($oProcess, BackgroundTask $oTask, $oStartDate, $iTimeLimit)
|
||||||
{
|
{
|
||||||
|
$oNow = new DateTime();
|
||||||
|
$fStart = microtime(true);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oNow = new DateTime();
|
|
||||||
$fStart = microtime(true);
|
|
||||||
$sMessage = $oProcess->Process($iTimeLimit);
|
$sMessage = $oProcess->Process($iTimeLimit);
|
||||||
$fDuration = microtime(true) - $fStart;
|
|
||||||
if ($oTask->Get('total_exec_count') == 0)
|
|
||||||
{
|
|
||||||
// First execution
|
|
||||||
$oTask->Set('first_run_date', $oNow->format('Y-m-d H:i:s'));
|
|
||||||
}
|
|
||||||
$oTask->ComputeDurations($fDuration); // does increment the counter and compute statistics
|
|
||||||
$oTask->Set('latest_run_date', $oNow->format('Y-m-d H:i:s'));
|
|
||||||
|
|
||||||
$oRefClass = new ReflectionClass(get_class($oProcess));
|
|
||||||
if ($oRefClass->implementsInterface('iScheduledProcess'))
|
|
||||||
{
|
|
||||||
// Schedules process do repeat at specific moments
|
|
||||||
$oPlannedStart = $oProcess->GetNextOccurrence();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Background processes do repeat periodically
|
|
||||||
$oPlannedStart = new DateTime($oTask->Get('latest_run_date'));
|
|
||||||
// Let's assume that the task was started exactly when planned so that the schedule does no shift each time
|
|
||||||
// this allows to schedule a task everyday "around" 11:30PM for example
|
|
||||||
$oPlannedStart->modify('+'.$oProcess->GetPeriodicity().' seconds');
|
|
||||||
$oEnd = new DateTime();
|
|
||||||
if ($oPlannedStart->format('U') < $oEnd->format('U'))
|
|
||||||
{
|
|
||||||
// Huh, next planned start is already in the past, shift it of the periodicity !
|
|
||||||
$oPlannedStart = $oEnd->modify('+'.$oProcess->GetPeriodicity().' seconds');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$oTask->Set('next_run_date', $oPlannedStart->format('Y-m-d H:i:s'));
|
|
||||||
$oTask->DBUpdate();
|
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
$sMessage = 'Processing failed, the following exception occured: '.$e->getMessage();
|
$sMessage = 'Processing failed with message: '.$e->getMessage();
|
||||||
}
|
}
|
||||||
return $sMessage;
|
$fDuration = microtime(true) - $fStart;
|
||||||
|
if ($oTask->Get('total_exec_count') == 0)
|
||||||
|
{
|
||||||
|
// First execution
|
||||||
|
$oTask->Set('first_run_date', $oNow->format('Y-m-d H:i:s'));
|
||||||
|
}
|
||||||
|
$oTask->ComputeDurations($fDuration); // does increment the counter and compute statistics
|
||||||
|
$oTask->Set('latest_run_date', $oNow->format('Y-m-d H:i:s'));
|
||||||
|
|
||||||
|
$oRefClass = new ReflectionClass(get_class($oProcess));
|
||||||
|
if ($oRefClass->implementsInterface('iScheduledProcess'))
|
||||||
|
{
|
||||||
|
// Schedules process do repeat at specific moments
|
||||||
|
$oPlannedStart = $oProcess->GetNextOccurrence();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Background processes do repeat periodically
|
||||||
|
$oPlannedStart = new DateTime($oTask->Get('latest_run_date'));
|
||||||
|
// Let's assume that the task was started exactly when planned so that the schedule does no shift each time
|
||||||
|
// this allows to schedule a task everyday "around" 11:30PM for example
|
||||||
|
$oPlannedStart->modify('+'.$oProcess->GetPeriodicity().' seconds');
|
||||||
|
$oEnd = new DateTime();
|
||||||
|
if ($oPlannedStart->format('U') < $oEnd->format('U'))
|
||||||
|
{
|
||||||
|
// Huh, next planned start is already in the past, shift it of the periodicity !
|
||||||
|
$oPlannedStart = $oEnd->modify('+'.$oProcess->GetPeriodicity().' seconds');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$oTask->Set('next_run_date', $oPlannedStart->format('Y-m-d H:i:s'));
|
||||||
|
$oTask->DBUpdate();
|
||||||
|
return $sMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
function CronExec($oP, $aProcesses, $bVerbose)
|
function CronExec($oP, $aProcesses, $bVerbose)
|
||||||
@@ -354,7 +354,7 @@ $oP->p("Starting: ".time().' ('.date('Y-m-d H:i:s').')');
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oConfig = utils::GetConfig();
|
$oConfig = utils::GetConfig();
|
||||||
$oMutex = new iTopMutex('cron.'.$oConfig->GetDBName().'_'.$oConfig->GetDBSubname());
|
$oMutex = new iTopMutex('cron');
|
||||||
if ($oMutex->TryLock())
|
if ($oMutex->TryLock())
|
||||||
{
|
{
|
||||||
// Note: testing this now in case some of the background processes forces the read-only mode for a while
|
// Note: testing this now in case some of the background processes forces the read-only mode for a while
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ else
|
|||||||
$sRawFile = WebServicesBase::GetWSDLContents();
|
$sRawFile = WebServicesBase::GetWSDLContents();
|
||||||
}
|
}
|
||||||
|
|
||||||
$sServerURI = 'http'.(utils::IsConnectionSecure() ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/soapserver.php';
|
$sServerURI = utils::GetAbsoluteUrlAppRoot().'webservices/soapserver.php';
|
||||||
if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category'])))
|
if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category'])))
|
||||||
{
|
{
|
||||||
$sServerURI .= "?service_category=".$_REQUEST['service_category'];
|
$sServerURI .= "?service_category=".$_REQUEST['service_category'];
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ require_once(APPROOT.'/application/application.inc.php');
|
|||||||
require_once(APPROOT.'/application/startup.inc.php');
|
require_once(APPROOT.'/application/startup.inc.php');
|
||||||
|
|
||||||
// this file is generated dynamically with location = here
|
// this file is generated dynamically with location = here
|
||||||
$sWsdlUri = 'http'.(utils::IsConnectionSecure() ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/itop.wsdl.php';
|
$sWsdlUri = utils::GetAbsoluteUrlAppRoot().'webservices/itop.wsdl.php';
|
||||||
if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category'])))
|
if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category'])))
|
||||||
{
|
{
|
||||||
$sWsdlUri .= "soapserver.php?service_category=".$_REQUEST['service_category'];
|
$sWsdlUri .= "?service_category=".$_REQUEST['service_category'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ else
|
|||||||
if (is_subclass_of($sPHPClass, 'WebServicesBase'))
|
if (is_subclass_of($sPHPClass, 'WebServicesBase'))
|
||||||
{
|
{
|
||||||
$sServiceCategory = $sPHPClass;
|
$sServiceCategory = $sPHPClass;
|
||||||
$sSoapServerUri = 'http'.(utils::IsConnectionSecure() ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/soapserver.php';
|
$sSoapServerUri = utils::GetAbsoluteUrlAppRoot().'webservices/soapserver.php';
|
||||||
$sSoapServerUri .= "?service_category=$sServiceCategory";
|
$sSoapServerUri .= "?service_category=$sServiceCategory";
|
||||||
echo "<li><a href=\"$sSoapServerUri\">$sServiceCategory</a></li>\n";
|
echo "<li><a href=\"$sSoapServerUri\">$sServiceCategory</a></li>\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user