mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Merge remote-tracking branch 'origin/master' into develop
# Conflicts: # core/expressioncache.class.inc.php
This commit is contained in:
@@ -4222,6 +4222,7 @@ EOF
|
|||||||
$oDummyObj->Set($sAttCode, $currValue);
|
$oDummyObj->Set($sAttCode, $currValue);
|
||||||
/** @var ormTagSet $oTagSet */
|
/** @var ormTagSet $oTagSet */
|
||||||
$oTagSet = $oDummyObj->Get($sAttCode);
|
$oTagSet = $oDummyObj->Get($sAttCode);
|
||||||
|
$oTagSet->SetDisplayPartial(true);
|
||||||
foreach($aKeys as $iIndex => $sValues)
|
foreach($aKeys as $iIndex => $sValues)
|
||||||
{
|
{
|
||||||
if ($iIndex == 0)
|
if ($iIndex == 0)
|
||||||
|
|||||||
@@ -9668,14 +9668,27 @@ class AttributeTagSet extends AttributeSet
|
|||||||
{
|
{
|
||||||
$aJson['partial_values'] = array();
|
$aJson['partial_values'] = array();
|
||||||
$aJson['orig_value'] = array();
|
$aJson['orig_value'] = array();
|
||||||
|
$aJson['added'] = array();
|
||||||
|
$aJson['removed'] = array();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aJson['partial_values'] = $oValue->GetModified();
|
|
||||||
$aJson['orig_value'] = array_merge($oValue->GetValues(), $oValue->GetModified());
|
$aJson['orig_value'] = array_merge($oValue->GetValues(), $oValue->GetModified());
|
||||||
|
$aJson['added'] = $oValue->GetAdded();
|
||||||
|
$aJson['removed'] = $oValue->GetRemoved();
|
||||||
|
|
||||||
|
if ($oValue->DisplayPartial())
|
||||||
|
{
|
||||||
|
// For bulk updates
|
||||||
|
$aJson['partial_values'] = $oValue->GetModified();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For simple updates
|
||||||
|
$aJson['partial_values'] = array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$aJson['added'] = array();
|
|
||||||
$aJson['removed'] = array();
|
|
||||||
|
|
||||||
$iMaxTags = $this->GetMaxItems();
|
$iMaxTags = $this->GetMaxItems();
|
||||||
$aJson['max_items_allowed'] = $iMaxTags;
|
$aJson['max_items_allowed'] = $iMaxTags;
|
||||||
|
|||||||
@@ -1224,6 +1224,10 @@ abstract class DBObject implements iDisplay
|
|||||||
if ($this->InSyncScope())
|
if ($this->InSyncScope())
|
||||||
{
|
{
|
||||||
$iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons);
|
$iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons);
|
||||||
|
if ($iSynchroFlags & OPT_ATT_SLAVE)
|
||||||
|
{
|
||||||
|
$iSynchroFlags |= OPT_ATT_READONLY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $iFlags | $iSynchroFlags; // Combine both sets of flags
|
return $iFlags | $iSynchroFlags; // Combine both sets of flags
|
||||||
}
|
}
|
||||||
@@ -3869,7 +3873,7 @@ abstract class DBObject implements iDisplay
|
|||||||
foreach(MetaModel::ListAttributeDefs($sLinkClass) as $sAttCode => $oAttDef)
|
foreach(MetaModel::ListAttributeDefs($sLinkClass) as $sAttCode => $oAttDef)
|
||||||
{
|
{
|
||||||
// As of now, ignore other attribute (do not attempt to recurse!)
|
// As of now, ignore other attribute (do not attempt to recurse!)
|
||||||
if ($oAttDef->IsScalar())
|
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
|
||||||
{
|
{
|
||||||
$oLinkClone->Set($sAttCode, $oSourceLink->Get($sAttCode));
|
$oLinkClone->Set($sAttCode, $oSourceLink->Get($sAttCode));
|
||||||
}
|
}
|
||||||
@@ -3932,7 +3936,7 @@ abstract class DBObject implements iDisplay
|
|||||||
$oObjectToRead = $aSourceObjects['source'];
|
$oObjectToRead = $aSourceObjects['source'];
|
||||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
||||||
{
|
{
|
||||||
if ($oAttDef->IsScalar())
|
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
|
||||||
{
|
{
|
||||||
$this->CopyAttribute($oObjectToRead, $sAttCode, $sAttCode);
|
$this->CopyAttribute($oObjectToRead, $sAttCode, $sAttCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,11 +77,9 @@ EOF;
|
|||||||
}
|
}
|
||||||
EOF;
|
EOF;
|
||||||
|
|
||||||
file_put_contents($sFilePath, $content);
|
SetupUtils::builddir(dirname($sFilePath));
|
||||||
}
|
file_put_contents($sFilePath, $content);
|
||||||
}
|
}
|
||||||
// Restore original user language
|
|
||||||
Dict::SetUserLanguage($sUserLang);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static private function GetSerializedExpression($sClass, $sAttCode)
|
static private function GetSerializedExpression($sClass, $sAttCode)
|
||||||
|
|||||||
@@ -26,6 +26,9 @@
|
|||||||
*/
|
*/
|
||||||
final class ormTagSet extends ormSet
|
final class ormTagSet extends ormSet
|
||||||
{
|
{
|
||||||
|
private $m_bDisplayPartial = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ormTagSet constructor.
|
* ormTagSet constructor.
|
||||||
*
|
*
|
||||||
@@ -299,6 +302,82 @@ final class ormTagSet extends ormSet
|
|||||||
return $aModifiedTagCodes;
|
return $aModifiedTagCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] list of codes for added entries
|
||||||
|
*/
|
||||||
|
public function GetAdded()
|
||||||
|
{
|
||||||
|
$aAddedTagCodes = array_keys($this->aAdded);
|
||||||
|
sort($aAddedTagCodes);
|
||||||
|
|
||||||
|
return $aAddedTagCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[] list of codes for removed entries
|
||||||
|
*/
|
||||||
|
public function GetRemoved()
|
||||||
|
{
|
||||||
|
$aRemovedTagCodes = array_keys($this->aRemoved);
|
||||||
|
sort($aRemovedTagCodes);
|
||||||
|
|
||||||
|
return $aRemovedTagCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a delta to the current ItemSet
|
||||||
|
* $aDelta['added] = array of added items
|
||||||
|
* $aDelta['removed'] = array of removed items
|
||||||
|
*
|
||||||
|
* @param $aDelta
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public function ApplyDelta($aDelta)
|
||||||
|
{
|
||||||
|
if (isset($aDelta['removed']))
|
||||||
|
{
|
||||||
|
foreach($aDelta['removed'] as $oItem)
|
||||||
|
{
|
||||||
|
$this->Remove($oItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($aDelta['added']))
|
||||||
|
{
|
||||||
|
foreach($aDelta['added'] as $oItem)
|
||||||
|
{
|
||||||
|
$this->Add($oItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates the added and removed arrays for bulk edit
|
||||||
|
*
|
||||||
|
* @param string[] $aItems
|
||||||
|
*
|
||||||
|
* @throws \CoreException
|
||||||
|
*/
|
||||||
|
public function GenerateDiffFromArray($aItems)
|
||||||
|
{
|
||||||
|
foreach($this->GetValues() as $oCurrentItem)
|
||||||
|
{
|
||||||
|
if (!in_array($oCurrentItem, $aItems))
|
||||||
|
{
|
||||||
|
$this->Remove($oCurrentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($aItems as $oNewItem)
|
||||||
|
{
|
||||||
|
$this->Add($oNewItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep only the aModified list
|
||||||
|
$this->aRemoved = array();
|
||||||
|
$this->aAdded = array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a tag code is valid or not for this TagSet
|
* Check whether a tag code is valid or not for this TagSet
|
||||||
*
|
*
|
||||||
@@ -479,4 +558,21 @@ final class ormTagSet extends ormSet
|
|||||||
return TagSetFieldData::GetTagDataClassName($this->sClass, $this->sAttCode);
|
return TagSetFieldData::GetTagDataClassName($this->sClass, $this->sAttCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function DisplayPartial()
|
||||||
|
{
|
||||||
|
return $this->m_bDisplayPartial;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $m_bDisplayPartial
|
||||||
|
*/
|
||||||
|
public function SetDisplayPartial($m_bDisplayPartial)
|
||||||
|
{
|
||||||
|
$this->m_bDisplayPartial = $m_bDisplayPartial;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,31 +47,14 @@ class DBBackupScheduled extends DBBackup
|
|||||||
{
|
{
|
||||||
protected function LogInfo($sMsg)
|
protected function LogInfo($sMsg)
|
||||||
{
|
{
|
||||||
static $bDebug = null;
|
echo $sMsg."\n";
|
||||||
if ($bDebug == null)
|
IssueLog::Info($sMsg);
|
||||||
{
|
|
||||||
$bDebug = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'debug', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($bDebug)
|
|
||||||
{
|
|
||||||
echo $sMsg."\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function LogError($sMsg)
|
protected function LogError($sMsg)
|
||||||
{
|
{
|
||||||
static $bDebug = null;
|
|
||||||
if ($bDebug == null)
|
|
||||||
{
|
|
||||||
$bDebug = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'debug', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
IssueLog::Error($sMsg);
|
IssueLog::Error($sMsg);
|
||||||
if ($bDebug)
|
echo 'Error: '.$sMsg."\n";
|
||||||
{
|
|
||||||
echo 'Error: '.$sMsg."\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ SetupWebPage::AddModule(
|
|||||||
//'file_name_format' => '__DB__-%Y-%m-%d_%H_%M',
|
//'file_name_format' => '__DB__-%Y-%m-%d_%H_%M',
|
||||||
'retention_count' => 5,
|
'retention_count' => 5,
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
'debug' => false,
|
'itop_root' => '',
|
||||||
'itop_backup_incident' => '',
|
'itop_backup_incident' => '',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4561,7 +4561,7 @@
|
|||||||
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
||||||
</item>
|
</item>
|
||||||
<item id="recent_changes" _delta="define">
|
<item id="recent_changes" _delta="define">
|
||||||
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (DATE_ADD(C.end_date, INTERVAL 3 DAY) < NOW())]]></oql>
|
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (C.end_date < NOW() AND C.end_date > DATE_SUB(NOW(), INTERVAL 3 DAY ))]]></oql>
|
||||||
<dict>Tickets:Related:RecentChanges</dict>
|
<dict>Tickets:Related:RecentChanges</dict>
|
||||||
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
||||||
</item>
|
</item>
|
||||||
@@ -4579,7 +4579,7 @@
|
|||||||
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
||||||
</item>
|
</item>
|
||||||
<item id="recent_changes" _delta="define">
|
<item id="recent_changes" _delta="define">
|
||||||
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (DATE_ADD(C.end_date, INTERVAL 3 DAY) < NOW())]]></oql>
|
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (C.end_date < NOW() AND C.end_date > DATE_SUB(NOW(), INTERVAL 3 DAY ))]]></oql>
|
||||||
<dict>Tickets:Related:RecentChanges</dict>
|
<dict>Tickets:Related:RecentChanges</dict>
|
||||||
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
||||||
</item>
|
</item>
|
||||||
@@ -4597,7 +4597,7 @@
|
|||||||
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
||||||
</item>
|
</item>
|
||||||
<item id="recent_changes" _delta="define">
|
<item id="recent_changes" _delta="define">
|
||||||
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (DATE_ADD(C.end_date, INTERVAL 3 DAY) < NOW())]]></oql>
|
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status NOT IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.id != :this->id) AND (C.end_date < NOW() AND C.end_date > DATE_SUB(NOW(), INTERVAL 3 DAY ))]]></oql>
|
||||||
<dict>Tickets:Related:RecentChanges</dict>
|
<dict>Tickets:Related:RecentChanges</dict>
|
||||||
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
||||||
</item>
|
</item>
|
||||||
@@ -4619,7 +4619,7 @@
|
|||||||
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
||||||
</item>
|
</item>
|
||||||
<item id="recent_changes" _delta="define">
|
<item id="recent_changes" _delta="define">
|
||||||
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status IN ('closed')) AND (L.impact_code != 'not_impacted') AND (DATE_ADD(C.end_date, INTERVAL 3 DAY) < NOW())]]></oql>
|
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.end_date < NOW() AND C.end_date > DATE_SUB(NOW(), INTERVAL 3 DAY ))]]></oql>
|
||||||
<dict>Tickets:Related:RecentChanges</dict>
|
<dict>Tickets:Related:RecentChanges</dict>
|
||||||
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
||||||
</item>
|
</item>
|
||||||
@@ -4633,7 +4633,7 @@
|
|||||||
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-ongoing.png</icon>
|
||||||
</item>
|
</item>
|
||||||
<item id="recent_changes" _delta="define">
|
<item id="recent_changes" _delta="define">
|
||||||
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status IN ('closed')) AND (L.impact_code != 'not_impacted') AND (DATE_ADD(C.end_date, INTERVAL 3 DAY) < NOW())]]></oql>
|
<oql><![CDATA[SELECT FCI, C FROM FunctionalCI AS FCI JOIN lnkFunctionalCIToTicket AS L ON L.functionalci_id = FCI.id JOIN Change AS C ON L.ticket_id = C.id WHERE (C.outage = 'yes') AND (C.status IN ('closed')) AND (L.impact_code != 'not_impacted') AND (C.end_date < NOW() AND C.end_date > DATE_SUB(NOW(), INTERVAL 3 DAY ))]]></oql>
|
||||||
<dict>Tickets:Related:RecentChanges</dict>
|
<dict>Tickets:Related:RecentChanges</dict>
|
||||||
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
<icon>itop-change-mgmt-itil/images/change-done.png</icon>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -775,7 +775,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
|||||||
'UI:Title:DeletionOf_Object' => 'Deletion of %1$s',
|
'UI:Title:DeletionOf_Object' => 'Deletion of %1$s',
|
||||||
'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => 'Bulk deletion of %1$d objects of class %2$s',
|
'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => 'Bulk deletion of %1$d objects of class %2$s',
|
||||||
'UI:Delete:NotAllowedToDelete' => 'You are not allowed to delete this object',
|
'UI:Delete:NotAllowedToDelete' => 'You are not allowed to delete this object',
|
||||||
'UI:Delete:NotAllowedToUpdate_Fields' => 'You are not allowed to update the following field(s): %1$s',
|
'UI:Error:ActionNotAllowed' => 'You are not allowed to do this action',
|
||||||
'UI:Error:NotEnoughRightsToDelete' => 'This object could not be deleted because the current user do not have sufficient rights',
|
'UI:Error:NotEnoughRightsToDelete' => 'This object could not be deleted because the current user do not have sufficient rights',
|
||||||
'UI:Error:CannotDeleteBecause' => 'This object could not be deleted because: %1$s',
|
'UI:Error:CannotDeleteBecause' => 'This object could not be deleted because: %1$s',
|
||||||
'UI:Error:CannotDeleteBecauseOfDepencies' => 'This object could not be deleted because some manual operations must be performed prior to that',
|
'UI:Error:CannotDeleteBecauseOfDepencies' => 'This object could not be deleted because some manual operations must be performed prior to that',
|
||||||
|
|||||||
@@ -758,6 +758,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
|||||||
'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => 'Suppression massive de %1$d objets de type %2$s',
|
'UI:Title:BulkDeletionOf_Count_ObjectsOf_Class' => 'Suppression massive de %1$d objets de type %2$s',
|
||||||
'UI:Delete:NotAllowedToDelete' => 'Vous n\'êtes pas autorisé à supprimer cet objet',
|
'UI:Delete:NotAllowedToDelete' => 'Vous n\'êtes pas autorisé à supprimer cet objet',
|
||||||
'UI:Delete:NotAllowedToUpdate_Fields' => 'Vous n\'êtes pas autorisé à mettre à jour les champs suivants : %1$s',
|
'UI:Delete:NotAllowedToUpdate_Fields' => 'Vous n\'êtes pas autorisé à mettre à jour les champs suivants : %1$s',
|
||||||
|
'UI:Error:ActionNotAllowed' => 'Vous n\'êtes pas autorisé à effectuer cette action',
|
||||||
'UI:Error:NotEnoughRightsToDelete' => 'Cet objet ne peut pas être supprimé car l\'utilisateur courant n\'a pas les droits nécessaires.',
|
'UI:Error:NotEnoughRightsToDelete' => 'Cet objet ne peut pas être supprimé car l\'utilisateur courant n\'a pas les droits nécessaires.',
|
||||||
'UI:Error:CannotDeleteBecause' => 'Cet objet ne peut pas être effacé. Raison: %1$s',
|
'UI:Error:CannotDeleteBecause' => 'Cet objet ne peut pas être effacé. Raison: %1$s',
|
||||||
'UI:Error:CannotDeleteBecauseOfDepencies' => 'Cet objet ne peut pas être supprimé, des opérations manuelles sont nécessaire avant sa suppression.',
|
'UI:Error:CannotDeleteBecauseOfDepencies' => 'Cet objet ne peut pas être supprimé, des opérations manuelles sont nécessaire avant sa suppression.',
|
||||||
|
|||||||
@@ -1218,7 +1218,7 @@ class ArchiveTar
|
|||||||
$iBufferLen = strlen("$v_buffer");
|
$iBufferLen = strlen("$v_buffer");
|
||||||
if ($iBufferLen != $iLen)
|
if ($iBufferLen != $iLen)
|
||||||
{
|
{
|
||||||
$iPack = ((int)($iBufferLen / 512) + 1) * 512;
|
$iPack = (ceil($iBufferLen / 512)) * 512;
|
||||||
$sPack = sprintf('a%d', $iPack);
|
$sPack = sprintf('a%d', $iPack);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
17
pages/UI.php
17
pages/UI.php
@@ -1497,7 +1497,15 @@ EOF
|
|||||||
{
|
{
|
||||||
throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'class', 'id', 'stimulus'));
|
throw new ApplicationException(Dict::Format('UI:Error:3ParametersMissing', 'class', 'id', 'stimulus'));
|
||||||
}
|
}
|
||||||
$oObj = MetaModel::GetObject($sClass, $id, false);
|
$aStimuli = MetaModel::EnumStimuli($sClass);
|
||||||
|
if ((get_class($aStimuli[$sStimulus]) !== 'StimulusUserAction') || (UserRights::IsStimulusAllowed($sClass, $sStimulus) === UR_ALLOWED_NO))
|
||||||
|
{
|
||||||
|
$sUser = UserRights::GetUser();
|
||||||
|
IssueLog::Error("UI.php '$operation' : Stimulus '$sStimulus' not allowed ! data: user='$sUser', class='$sClass'");
|
||||||
|
throw new ApplicationException(Dict::S('UI:Error:ActionNotAllowed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$oObj = MetaModel::GetObject($sClass, $id, false);
|
||||||
if ($oObj != null)
|
if ($oObj != null)
|
||||||
{
|
{
|
||||||
$aPrefillFormParam = array( 'user' => $_SESSION["auth_user"],
|
$aPrefillFormParam = array( 'user' => $_SESSION["auth_user"],
|
||||||
@@ -1545,6 +1553,13 @@ EOF
|
|||||||
$sMessage = Dict::S('UI:Error:ObjectAlreadyUpdated');
|
$sMessage = Dict::S('UI:Error:ObjectAlreadyUpdated');
|
||||||
$sSeverity = 'info';
|
$sSeverity = 'info';
|
||||||
}
|
}
|
||||||
|
elseif ((get_class($aStimuli[$sStimulus]) !== 'StimulusUserAction') || (UserRights::IsStimulusAllowed($sClass, $sStimulus) === UR_ALLOWED_NO))
|
||||||
|
{
|
||||||
|
$sUser = UserRights::GetUser();
|
||||||
|
IssueLog::Error("UI.php '$operation' : Stimulus '$sStimulus' not allowed ! data: user='$sUser', class='$sClass'");
|
||||||
|
$sMessage = Dict::S('UI:Error:ActionNotAllowed');
|
||||||
|
$sSeverity = 'error';
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
|
$sActionLabel = $aStimuli[$sStimulus]->GetLabel();
|
||||||
|
|||||||
@@ -147,9 +147,11 @@ header("Expires: Fri, 17 Jul 1970 05:00:00 GMT"); // Date in the past
|
|||||||
$sOperation = Utils::ReadParam('operation', '');
|
$sOperation = Utils::ReadParam('operation', '');
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (is_file(utils::GetConfigFilePath()) && !is_writable(utils::GetConfigFilePath()))
|
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
|
||||||
|
if (!file_exists(APPROOT.'data/setup/authent') || $sAuthent !== file_get_contents(APPROOT.'data/setup/authent'))
|
||||||
{
|
{
|
||||||
throw new Exception('Setup operations are not allowed outside of the setup');
|
throw new SecurityException('Setup operations are not allowed outside of the setup');
|
||||||
|
SetupPage::log_error("Setup operations are not allowed outside of the setup");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($sOperation)
|
switch($sOperation)
|
||||||
|
|||||||
@@ -313,8 +313,11 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
$sTmpFolder = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax());
|
$sTmpFolder = APPROOT.'data/tmp-backup-'.rand(10000, getrandmax());
|
||||||
$aFiles = $this->PrepareFilesToBackup($sSourceConfigFile, $sTmpFolder);
|
$aFiles = $this->PrepareFilesToBackup($sSourceConfigFile, $sTmpFolder);
|
||||||
|
|
||||||
|
$sFilesList = var_export($aFiles, true);
|
||||||
|
$this->LogInfo("backup: adding to archive files '$sFilesList'");
|
||||||
$oArchive->createModify($aFiles, '', $sTmpFolder);
|
$oArchive->createModify($aFiles, '', $sTmpFolder);
|
||||||
|
|
||||||
|
$this->LogInfo("backup: removing tmp folder '$sTmpFolder'");
|
||||||
SetupUtils::rrmdir($sTmpFolder);
|
SetupUtils::rrmdir($sTmpFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +337,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
{
|
{
|
||||||
SetupUtils::rrmdir($sTmpFolder);
|
SetupUtils::rrmdir($sTmpFolder);
|
||||||
}
|
}
|
||||||
|
$this->LogInfo("backup: creating tmp dir '$sTmpFolder'");
|
||||||
@mkdir($sTmpFolder, 0777, true);
|
@mkdir($sTmpFolder, 0777, true);
|
||||||
if (is_null($sSourceConfigFile))
|
if (is_null($sSourceConfigFile))
|
||||||
{
|
{
|
||||||
@@ -342,6 +346,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
if (!empty($sSourceConfigFile))
|
if (!empty($sSourceConfigFile))
|
||||||
{
|
{
|
||||||
$sFile = $sTmpFolder.'/config-itop.php';
|
$sFile = $sTmpFolder.'/config-itop.php';
|
||||||
|
$this->LogInfo("backup: adding resource '$sSourceConfigFile'");
|
||||||
copy($sSourceConfigFile, $sFile);
|
copy($sSourceConfigFile, $sFile);
|
||||||
$aRet[] = $sFile;
|
$aRet[] = $sFile;
|
||||||
}
|
}
|
||||||
@@ -350,6 +355,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
if (file_exists($sDeltaFile))
|
if (file_exists($sDeltaFile))
|
||||||
{
|
{
|
||||||
$sFile = $sTmpFolder.'/delta.xml';
|
$sFile = $sTmpFolder.'/delta.xml';
|
||||||
|
$this->LogInfo("backup: adding resource '$sDeltaFile'");
|
||||||
copy($sDeltaFile, $sFile);
|
copy($sDeltaFile, $sFile);
|
||||||
$aRet[] = $sFile;
|
$aRet[] = $sFile;
|
||||||
}
|
}
|
||||||
@@ -358,6 +364,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
{
|
{
|
||||||
$sModules = utils::GetCurrentEnvironment().'-modules';
|
$sModules = utils::GetCurrentEnvironment().'-modules';
|
||||||
$sFile = $sTmpFolder.'/'.$sModules;
|
$sFile = $sTmpFolder.'/'.$sModules;
|
||||||
|
$this->LogInfo("backup: adding resource '$sExtraDir'");
|
||||||
SetupUtils::copydir($sExtraDir, $sFile);
|
SetupUtils::copydir($sExtraDir, $sFile);
|
||||||
$aRet[] = $sFile;
|
$aRet[] = $sFile;
|
||||||
}
|
}
|
||||||
@@ -434,7 +441,7 @@ if (class_exists('ZipArchive')) // The setup must be able to start even if the "
|
|||||||
$sCommandDisplay = "$sMySQLDump --opt --skip-lock-tables --default-character-set=".$sMysqldumpCharset." --add-drop-database --single-transaction --host=$sHost $sPortOption --user=xxxxx --password=xxxxx $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables";
|
$sCommandDisplay = "$sMySQLDump --opt --skip-lock-tables --default-character-set=".$sMysqldumpCharset." --add-drop-database --single-transaction --host=$sHost $sPortOption --user=xxxxx --password=xxxxx $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables";
|
||||||
|
|
||||||
// Now run the command for real
|
// Now run the command for real
|
||||||
$this->LogInfo("Executing command: $sCommandDisplay");
|
$this->LogInfo("backup: generate data file with command: $sCommandDisplay");
|
||||||
$aOutput = array();
|
$aOutput = array();
|
||||||
$iRetCode = 0;
|
$iRetCode = 0;
|
||||||
exec($sCommand, $aOutput, $iRetCode);
|
exec($sCommand, $aOutput, $iRetCode);
|
||||||
|
|||||||
@@ -333,8 +333,9 @@ EOF;
|
|||||||
$aMenusToLoad[] = $sMenuId;
|
$aMenusToLoad[] = $sMenuId;
|
||||||
}
|
}
|
||||||
$aMenusToLoad = array_unique($aMenusToLoad);
|
$aMenusToLoad = array_unique($aMenusToLoad);
|
||||||
$aMenusForAll = array();
|
$aMenuLinesForAll = array();
|
||||||
$aMenusForAdmins = array();
|
$aMenuLinesForAdmins = array();
|
||||||
|
$aAdminMenus = array();
|
||||||
foreach($aMenusToLoad as $sMenuId)
|
foreach($aMenusToLoad as $sMenuId)
|
||||||
{
|
{
|
||||||
$oMenuNode = $aMenuNodes[$sMenuId];
|
$oMenuNode = $aMenuNodes[$sMenuId];
|
||||||
@@ -365,25 +366,27 @@ EOF;
|
|||||||
{
|
{
|
||||||
throw new Exception("Failed to process menu '$sMenuId', from '$sModuleRootDir': ".$e->getMessage());
|
throw new Exception("Failed to process menu '$sMenuId', from '$sModuleRootDir': ".$e->getMessage());
|
||||||
}
|
}
|
||||||
if ($oMenuNode->GetChildText('enable_admin_only') == '1')
|
$sParent = $oMenuNode->GetChildText('parent', null);
|
||||||
|
if (($oMenuNode->GetChildText('enable_admin_only') == '1') || isset($aAdminMenus[$sParent]))
|
||||||
{
|
{
|
||||||
$aMenusForAdmins = array_merge($aMenusForAdmins, $aMenuLines);
|
$aMenuLinesForAdmins = array_merge($aMenuLinesForAdmins, $aMenuLines);
|
||||||
|
$aAdminMenus[$oMenuNode->getAttribute("id")] = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$aMenusForAll = array_merge($aMenusForAll, $aMenuLines);
|
$aMenuLinesForAll = array_merge($aMenuLinesForAll, $aMenuLines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sIndent = "\t\t";
|
$sIndent = "\t\t";
|
||||||
foreach ($aMenusForAll as $sPHPLine)
|
foreach ($aMenuLinesForAll as $sPHPLine)
|
||||||
{
|
{
|
||||||
$sCompiledCode .= $sIndent.$sPHPLine."\n";
|
$sCompiledCode .= $sIndent.$sPHPLine."\n";
|
||||||
}
|
}
|
||||||
if (count($aMenusForAdmins) > 0)
|
if (count($aMenuLinesForAdmins) > 0)
|
||||||
{
|
{
|
||||||
$sCompiledCode .= $sIndent."if (UserRights::IsAdministrator())\n";
|
$sCompiledCode .= $sIndent."if (UserRights::IsAdministrator())\n";
|
||||||
$sCompiledCode .= $sIndent."{\n";
|
$sCompiledCode .= $sIndent."{\n";
|
||||||
foreach ($aMenusForAdmins as $sPHPLine)
|
foreach ($aMenuLinesForAdmins as $sPHPLine)
|
||||||
{
|
{
|
||||||
$sCompiledCode .= $sIndent."\t".$sPHPLine."\n";
|
$sCompiledCode .= $sIndent."\t".$sPHPLine."\n";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ function WizardAsyncAction(sActionCode, oParams, OnErrorFunction)
|
|||||||
{
|
{
|
||||||
var sStepClass = $('#_class').val();
|
var sStepClass = $('#_class').val();
|
||||||
var sStepState = $('#_state').val();
|
var sStepState = $('#_state').val();
|
||||||
|
var sAuthent = $('#authent_token').val();
|
||||||
|
|
||||||
var oMap = { operation: 'async_action', step_class: sStepClass, step_state: sStepState, code: sActionCode, params: oParams };
|
var oMap = { operation: 'async_action', step_class: sStepClass, step_state: sStepState, code: sActionCode, authent : sAuthent, params: oParams };
|
||||||
|
|
||||||
var ErrorFn = OnErrorFunction;
|
var ErrorFn = OnErrorFunction;
|
||||||
$(document).ajaxError(function(event, request, settings) {
|
$(document).ajaxError(function(event, request, settings) {
|
||||||
|
|||||||
@@ -57,6 +57,13 @@ class WizStepWelcome extends WizardStep
|
|||||||
|
|
||||||
public function ProcessParams($bMoveForward = true)
|
public function ProcessParams($bMoveForward = true)
|
||||||
{
|
{
|
||||||
|
if (!file_exists(APPROOT.'data/setup'))
|
||||||
|
{
|
||||||
|
mkdir(APPROOT.'data/setup');
|
||||||
|
}
|
||||||
|
$sUID = hash('sha256', rand());
|
||||||
|
file_put_contents(APPROOT.'data/setup/authent', $sUID);
|
||||||
|
$this->oWizard->SetParameter('authent', $sUID);
|
||||||
return array('class' => 'WizStepInstallOrUpgrade', 'state' => '');
|
return array('class' => 'WizStepInstallOrUpgrade', 'state' => '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +291,8 @@ class WizStepInstallOrUpgrade extends WizardStep
|
|||||||
$oPage->add('<tr><td colspan="2">');
|
$oPage->add('<tr><td colspan="2">');
|
||||||
$oPage->add($sMySQLDumpMessage.'<br/><span id="backup_info" style="font-size:small;color:#696969;">'.$sMessage.'</span></td></tr>');
|
$oPage->add($sMySQLDumpMessage.'<br/><span id="backup_info" style="font-size:small;color:#696969;">'.$sMessage.'</span></td></tr>');
|
||||||
$oPage->add('</table>');
|
$oPage->add('</table>');
|
||||||
|
$sAuthentToken = $this->oWizard->GetParameter('authent', '');
|
||||||
|
$oPage->add('<input type="hidden" id="authent_token" value="'.$sAuthentToken.'"/>');
|
||||||
//$oPage->add('</fieldset>');
|
//$oPage->add('</fieldset>');
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
@@ -802,6 +811,8 @@ class WizStepDBParams extends WizardStep
|
|||||||
$oPage->add('<table>');
|
$oPage->add('<table>');
|
||||||
SetupUtils::DisplayDBParameters($oPage, true, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTlsEnabled,
|
SetupUtils::DisplayDBParameters($oPage, true, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTlsEnabled,
|
||||||
$sTlsCA, $sNewDBName);
|
$sTlsCA, $sNewDBName);
|
||||||
|
$sAuthentToken = $this->oWizard->GetParameter('authent', '');
|
||||||
|
$oPage->add('<input type="hidden" id="authent_token" value="'.$sAuthentToken.'"/>');
|
||||||
$oPage->add('</table>');
|
$oPage->add('</table>');
|
||||||
$sCreateDB = $this->oWizard->GetParameter('create_db', 'yes');
|
$sCreateDB = $this->oWizard->GetParameter('create_db', 'yes');
|
||||||
if ($sCreateDB == 'no')
|
if ($sCreateDB == 'no')
|
||||||
@@ -996,6 +1007,8 @@ class WizStepMiscParams extends WizardStep
|
|||||||
$sChecked = ($sSampleData == 'no') ? 'checked ' : '';
|
$sChecked = ($sSampleData == 'no') ? 'checked ' : '';
|
||||||
$oPage->p('<input id="sample_data_no" name="sample_data" type="radio" value="no" '.$sChecked.'><label for="sample_data_no"> I am installing a <b>production</b> instance, create an empty database to start from.');
|
$oPage->p('<input id="sample_data_no" name="sample_data" type="radio" value="no" '.$sChecked.'><label for="sample_data_no"> I am installing a <b>production</b> instance, create an empty database to start from.');
|
||||||
$oPage->add('</fieldset>');
|
$oPage->add('</fieldset>');
|
||||||
|
$sAuthentToken = $this->oWizard->GetParameter('authent', '');
|
||||||
|
$oPage->add('<input type="hidden" id="authent_token" value="'.$sAuthentToken.'"/>');
|
||||||
$oPage->add_ready_script(
|
$oPage->add_ready_script(
|
||||||
<<<EOF
|
<<<EOF
|
||||||
$('#application_url').bind('change keyup', function() { WizardUpdateButtons(); } );
|
$('#application_url').bind('change keyup', function() { WizardUpdateButtons(); } );
|
||||||
@@ -2239,7 +2252,10 @@ EOF
|
|||||||
|
|
||||||
$sJSONData = json_encode($aInstallParams);
|
$sJSONData = json_encode($aInstallParams);
|
||||||
$oPage->add('<input type="hidden" id="installer_parameters" value="'.htmlentities($sJSONData, ENT_QUOTES, 'UTF-8').'"/>');
|
$oPage->add('<input type="hidden" id="installer_parameters" value="'.htmlentities($sJSONData, ENT_QUOTES, 'UTF-8').'"/>');
|
||||||
|
|
||||||
|
$sAuthentToken = $this->oWizard->GetParameter('authent', '');
|
||||||
|
$oPage->add('<input type="hidden" id="authent_token" value="'.$sAuthentToken.'"/>');
|
||||||
|
|
||||||
if (!$this->CheckDependencies())
|
if (!$this->CheckDependencies())
|
||||||
{
|
{
|
||||||
$oPage->error($this->sDependencyIssue);
|
$oPage->error($this->sDependencyIssue);
|
||||||
@@ -2494,14 +2510,14 @@ class WizStepDone extends WizardStep
|
|||||||
$oPage->ok("The installation completed successfully.");
|
$oPage->ok("The installation completed successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($this->oWizard->GetParameter('mode', '') == 'upgrade') && $this->oWizard->GetParameter('db_backup', false))
|
if (($this->oWizard->GetParameter('mode', '') == 'upgrade') && $this->oWizard->GetParameter('db_backup', false) && $this->oWizard->GetParameter('authent', false))
|
||||||
{
|
{
|
||||||
$sBackupDestination = $this->oWizard->GetParameter('db_backup_path', '');
|
$sBackupDestination = $this->oWizard->GetParameter('db_backup_path', '');
|
||||||
if (file_exists($sBackupDestination.'.tar.gz'))
|
if (file_exists($sBackupDestination.'.tar.gz'))
|
||||||
{
|
{
|
||||||
// To mitigate security risks: pass only the filename without the extension, the download will add the extension itself
|
// To mitigate security risks: pass only the filename without the extension, the download will add the extension itself
|
||||||
$oPage->p('Your backup is ready');
|
$oPage->p('Your backup is ready');
|
||||||
$oPage->p('<a style="background:transparent;" href="'.utils::GetAbsoluteUrlAppRoot().'setup/ajax.dataloader.php?operation=async_action&step_class=WizStepDone¶ms[backup]='.urlencode($sBackupDestination).'" target="_blank"><img src="../images/tar.png" style="border:0;vertical-align:middle;"> Download '.basename($sBackupDestination).'</a>');
|
$oPage->p('<a style="background:transparent;" href="'.utils::GetAbsoluteUrlAppRoot().'setup/ajax.dataloader.php?operation=async_action&step_class=WizStepDone¶ms[backup]='.urlencode($sBackupDestination).'&authent='.$this->oWizard->GetParameter('authent','').'" target="_blank"><img src="../images/tar.png" style="border:0;vertical-align:middle;"> Download '.basename($sBackupDestination).'</a>');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user