mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-20 00:58:48 +02:00
Compare commits
50 Commits
feature/re
...
support/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6437a615 | ||
|
|
78e173d5fb | ||
|
|
6b8abce03a | ||
|
|
33a7005069 | ||
|
|
006a6037d1 | ||
|
|
e2f8be1745 | ||
|
|
ebae45f6a5 | ||
|
|
0685835d49 | ||
|
|
1b1e88f9a4 | ||
|
|
b90f443e75 | ||
|
|
4da64a64b1 | ||
|
|
6673e171dc | ||
|
|
afee7297cc | ||
|
|
3cc8b5b88a | ||
|
|
b2e6981b24 | ||
|
|
c0a79fa573 | ||
|
|
02ad6d19fe | ||
|
|
d16308ab62 | ||
|
|
4598959bc2 | ||
|
|
65a3755f81 | ||
|
|
dc46c65499 | ||
|
|
9d691c8e56 | ||
|
|
99f897bff7 | ||
|
|
8d83447222 | ||
|
|
dcc8ad08a4 | ||
|
|
c1b0b73b51 | ||
|
|
81173decca | ||
|
|
9aca062bf5 | ||
|
|
09aba95d0a | ||
|
|
1683ca2dd6 | ||
|
|
9e732d6045 | ||
|
|
69df343bd2 | ||
|
|
eb8f49ebfe | ||
|
|
398e294604 | ||
|
|
d04c6bccd5 | ||
|
|
f00c7c6bc2 | ||
|
|
d30e8c359f | ||
|
|
2bd4a61c00 | ||
|
|
e35c8323df | ||
|
|
e4e814281d | ||
|
|
635cb424a2 | ||
|
|
e95aa6cc69 | ||
|
|
c58fd17fc9 | ||
|
|
efdec7a343 | ||
|
|
2352c05d36 | ||
|
|
23634964a5 | ||
|
|
619252db99 | ||
|
|
ca4dbd833c | ||
|
|
f62a3b22a3 | ||
|
|
88416bca5d |
@@ -557,6 +557,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
|||||||
{
|
{
|
||||||
$oContact->Set('org_id', $iOrgId);
|
$oContact->Set('org_id', $iOrgId);
|
||||||
}
|
}
|
||||||
|
if (MetaModel::IsValidAttCode('Person', 'phone'))
|
||||||
|
{
|
||||||
|
$oContact->Set('phone', '+00 000 000 000');
|
||||||
|
}
|
||||||
$oContact->Set('email', 'my.email@foo.org');
|
$oContact->Set('email', 'my.email@foo.org');
|
||||||
$iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
$iContactId = $oContact->DBInsertTrackedNoReload($oChange, true /* skip security */);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1565,8 +1565,9 @@ EOF
|
|||||||
case 'LinkedSet':
|
case 'LinkedSet':
|
||||||
$aEventsList[] ='validate';
|
$aEventsList[] ='validate';
|
||||||
$aEventsList[] ='change';
|
$aEventsList[] ='change';
|
||||||
$oWidget = new UILinksWidget($sClass, $sAttCode, $iId, $sNameSuffix, $oAttDef->DuplicatesAllowed());
|
$oWidget = new UILinksWidget($sClass, $sAttCode, $iId, $sNameSuffix, $oAttDef->DuplicatesAllowed(), $aArgs);
|
||||||
$sHTMLValue = $oWidget->Display($oPage, $value);
|
$oObj = isset($aArgs['this']) ? $aArgs['this'] : null;
|
||||||
|
$sHTMLValue = $oWidget->Display($oPage, $value, array(), $sFormPrefix, $oObj);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Document':
|
case 'Document':
|
||||||
@@ -1733,7 +1734,7 @@ EOF
|
|||||||
if ($iKey > 0)
|
if ($iKey > 0)
|
||||||
{
|
{
|
||||||
// The object already exists in the database, it's a modification
|
// The object already exists in the database, it's a modification
|
||||||
$sButtons = "<input type=\"hidden\" name=\"id\" value=\"$iKey\">\n";
|
$sButtons = "<input id=\"{$sPrefix}_id\" type=\"hidden\" name=\"id\" value=\"$iKey\">\n";
|
||||||
$sButtons .= "<input type=\"hidden\" name=\"operation\" value=\"{$sOperation}\">\n";
|
$sButtons .= "<input type=\"hidden\" name=\"operation\" value=\"{$sOperation}\">\n";
|
||||||
$sButtons .= "<button type=\"button\" class=\"action cancel\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n";
|
$sButtons .= "<button type=\"button\" class=\"action cancel\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n";
|
||||||
$sButtons .= "<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n";
|
$sButtons .= "<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n";
|
||||||
@@ -1819,6 +1820,10 @@ EOF
|
|||||||
$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
|
$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
|
||||||
|
|
||||||
$aFieldsMap = $this->DisplayBareProperties($oPage, true, $sPrefix, $aExtraParams);
|
$aFieldsMap = $this->DisplayBareProperties($oPage, true, $sPrefix, $aExtraParams);
|
||||||
|
if ($iKey > 0)
|
||||||
|
{
|
||||||
|
$aFieldsMap['id'] = $sPrefix.'_id';
|
||||||
|
}
|
||||||
// Now display the relations, one tab per relation
|
// Now display the relations, one tab per relation
|
||||||
if (!isset($aExtraParams['noRelations']))
|
if (!isset($aExtraParams['noRelations']))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1107,7 +1107,7 @@ class MenuBlock extends DisplayBlock
|
|||||||
if (count($aTransitions))
|
if (count($aTransitions))
|
||||||
{
|
{
|
||||||
$this->AddMenuSeparator($aActions);
|
$this->AddMenuSeparator($aActions);
|
||||||
$aStimuli = Metamodel::EnumStimuli($sClass);
|
$aStimuli = Metamodel::EnumStimuli(get_class($oObj));
|
||||||
foreach($aTransitions as $sStimulusCode => $aTransitionDef)
|
foreach($aTransitions as $sStimulusCode => $aTransitionDef)
|
||||||
{
|
{
|
||||||
$iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet) : UR_ALLOWED_NO;
|
$iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet) : UR_ALLOWED_NO;
|
||||||
|
|||||||
@@ -146,7 +146,12 @@ class iTopWebPage extends NiceWebPage
|
|||||||
// that the tabs aren't changed on click, and any custom event name can be
|
// that the tabs aren't changed on click, and any custom event name can be
|
||||||
// specified. Note that if you define a callback for the 'select' event, it
|
// specified. Note that if you define a callback for the 'select' event, it
|
||||||
// will be executed for the selected tab whenever the hash changes.
|
// will be executed for the selected tab whenever the hash changes.
|
||||||
tabs.tabs({ event: 'change'});
|
tabs.tabs({ event: 'change', 'show': function(event, ui) {
|
||||||
|
$('.resizable', ui.panel).resizable(); // Make resizable everything that claims to be resizable !
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.resizable').filter(':visible').resizable();
|
||||||
}
|
}
|
||||||
catch(err)
|
catch(err)
|
||||||
{
|
{
|
||||||
@@ -198,7 +203,6 @@ EOF
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.resizable').resizable(); // Make resizable everything that claims to be resizable !
|
|
||||||
// Adjust initial size
|
// Adjust initial size
|
||||||
$('.v-resizable').each( function()
|
$('.v-resizable').each( function()
|
||||||
{
|
{
|
||||||
@@ -589,13 +593,13 @@ EOF
|
|||||||
{
|
{
|
||||||
// Make sure that the URL to the script contains the application's version number
|
// Make sure that the URL to the script contains the application's version number
|
||||||
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
||||||
if (strpos('?', $s_script) === false)
|
if (strpos($s_script, '?') === false)
|
||||||
{
|
{
|
||||||
$s_script .= "?version=".ITOP_VERSION;
|
$s_script .= "?itopversion=".ITOP_VERSION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$s_script .= "&version=".ITOP_VERSION;
|
$s_script .= "&itopversion=".ITOP_VERSION;
|
||||||
}
|
}
|
||||||
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
||||||
}
|
}
|
||||||
@@ -624,6 +628,8 @@ EOF
|
|||||||
echo "</style>\n";
|
echo "</style>\n";
|
||||||
}
|
}
|
||||||
echo "<link rel=\"search\" type=\"application/opensearchdescription+xml\" title=\"iTop\" href=\"".utils::GetAbsoluteUrlAppRoot()."pages/opensearch.xml.php\" />\n";
|
echo "<link rel=\"search\" type=\"application/opensearchdescription+xml\" title=\"iTop\" href=\"".utils::GetAbsoluteUrlAppRoot()."pages/opensearch.xml.php\" />\n";
|
||||||
|
echo "<link rel=\"shortcut icon\" href=\"".utils::GetAbsoluteUrlAppRoot()."images/favicon.ico\" />\n";
|
||||||
|
|
||||||
echo "</head>\n";
|
echo "</head>\n";
|
||||||
echo "<body>\n";
|
echo "<body>\n";
|
||||||
|
|
||||||
|
|||||||
@@ -271,23 +271,52 @@ EOF
|
|||||||
$aFilteredGroupNames = array();
|
$aFilteredGroupNames = array();
|
||||||
foreach($aMemberOf as $sGroupName)
|
foreach($aMemberOf as $sGroupName)
|
||||||
{
|
{
|
||||||
|
phpCAS::log("Info: user if a member of the group: ".$sGroupName);
|
||||||
$sGroupName = trim(iconv('UTF-8', 'ASCII//TRANSLIT', $sGroupName)); // Remove accents and spaces as well
|
$sGroupName = trim(iconv('UTF-8', 'ASCII//TRANSLIT', $sGroupName)); // Remove accents and spaces as well
|
||||||
$aFilteredGroupNames[] = $sGroupName;
|
$aFilteredGroupNames[] = $sGroupName;
|
||||||
if (in_array($sGroupName, $aCASMemberships))
|
$bIsMember = false;
|
||||||
|
foreach($aCASMemberships as $sCASPattern)
|
||||||
{
|
{
|
||||||
|
if (self::IsPattern($sCASPattern))
|
||||||
|
{
|
||||||
|
if (preg_match($sCASPattern, $sGroupName))
|
||||||
|
{
|
||||||
|
$bIsMember = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($sPattern == $sGroupName)
|
||||||
|
{
|
||||||
|
$bIsMember = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($bIsMember)
|
||||||
|
{
|
||||||
|
$bCASUserSynchro = MetaModel::GetConfig()->Get('cas_user_synchro');
|
||||||
|
if ($bCASUserSynchro)
|
||||||
|
{
|
||||||
|
// If needed create a new user for this email/profile
|
||||||
|
phpCAS::log('Info: cas_user_synchro is ON');
|
||||||
|
self::CreateCASUser(phpCAS::getUser(), $aMemberOf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phpCAS::log('Info: cas_user_synchro is OFF');
|
||||||
|
}
|
||||||
$bFound = true;
|
$bFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!$bFound)
|
if(!$bFound)
|
||||||
{
|
{
|
||||||
phpCAS :: log("User ".phpCAS::getUser().", none of his/her groups (".implode('; ', $aFilteredGroupNames).") match any of the required groups: ".implode('; ', $aCASMemberships));
|
phpCAS::log("User ".phpCAS::getUser().", none of his/her groups (".implode('; ', $aFilteredGroupNames).") match any of the required groups: ".implode('; ', $aCASMemberships));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Too bad, the user is not part of any of the group => not allowed
|
// Too bad, the user is not part of any of the group => not allowed
|
||||||
phpCAS :: log("No 'memberOf' attribute found for user ".phpCAS::getUser().". Are you using the SAML protocol (S1) ?");
|
phpCAS::log("No 'memberOf' attribute found for user ".phpCAS::getUser().". Are you using the SAML protocol (S1) ?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -498,6 +527,123 @@ EOF
|
|||||||
}
|
}
|
||||||
return $sMessage;
|
return $sMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function CreateCASUser($sEmail, $aGroups)
|
||||||
|
{
|
||||||
|
if (!MetaModel::IsValidClass('URP_Profiles'))
|
||||||
|
{
|
||||||
|
phpCAS::log("URP_Profiles is not a valid class. Automatic creation of Users is not supported in this context, sorry.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read all the existing profiles
|
||||||
|
$oProfilesSearch = new DBObjectSearch('URP_Profiles');
|
||||||
|
$oProfilesSet = new DBObjectSet($oProfilesSearch);
|
||||||
|
$aAllProfiles = array();
|
||||||
|
while($oProfile = $oProfilesSet->Fetch())
|
||||||
|
{
|
||||||
|
$aAllProfiles[strtolower($oProfile->GetName())] = $oProfile->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate the CAS/LDAP group names into iTop profile names
|
||||||
|
$aProfiles = array();
|
||||||
|
$sPattern = MetaModel::GetConfig()->Get('cas_profile_pattern');
|
||||||
|
foreach($aGroups as $sGroupName)
|
||||||
|
{
|
||||||
|
if (preg_match($sPattern, $sGroupName, $aMatches))
|
||||||
|
{
|
||||||
|
if (array_key_exists(strtolower($aMatches[1]), $aAllProfiles))
|
||||||
|
{
|
||||||
|
$aProfiles[] = $aAllProfiles[strtolower($aMatches[1])];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phpCAS::log("Warning: {$aMatches[1]} is not a valid iTop profile (extracted from group name: '$sGroupName'). Ignored.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count($aProfiles) == 0)
|
||||||
|
{
|
||||||
|
phpCAS::log("Error: no group name matches the pattern: '$sPattern'. The user '$sEmail' has no profiles in iTop, and therefore cannot be created.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oUser = MetaModel::GetObjectByName('UserExternal', $sEmail, false);
|
||||||
|
if ($oUser == null)
|
||||||
|
{
|
||||||
|
// Create the user, link it to a contact
|
||||||
|
phpCAS::log("Info: the user '$sEmail' does not exist. A new UserExternal will be created.");
|
||||||
|
$oSearch = new DBObjectSearch('Person');
|
||||||
|
$oSearch->AddCondition('email', $sEmail);
|
||||||
|
$oSet = new DBObjectSet($oSearch);
|
||||||
|
$iContactId = 0;
|
||||||
|
switch($oSet->Count())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
phpCAS::log("Error: found no contact with the email: '$sEmail'. Cannot create the user in iTop.");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
$oContact = $oSet->Fetch();
|
||||||
|
$iContactId = $oContact->GetKey();
|
||||||
|
phpCAS::log("Info: Found 1 contact '".$oContact->GetName()."' (id=$iContactId) corresponding to the email '$sEmail'.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
phpCAS::log("Error: ".$oSet->Count()." contacts have the same email: '$sEmail'. Cannot create a user for this email.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oUser = new UserExternal();
|
||||||
|
$oUser->Set('login', $sEmail);
|
||||||
|
$oUser->Set('contactid', $iContactId);
|
||||||
|
$oUser->Set('language', MetaModel::GetConfig()->GetDefaultLanguage());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
phpCAS::log("Info: the user '$sEmail' already exists (id=".$oUser->GetKey().").");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now synchronize the profiles
|
||||||
|
$oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
|
||||||
|
foreach($aProfiles as $iProfileId)
|
||||||
|
{
|
||||||
|
$oLink = new URP_UserProfile();
|
||||||
|
$oLink->Set('profileid', $iProfileId);
|
||||||
|
$oLink->Set('reason', 'CAS/LDAP Synchro');
|
||||||
|
$oProfilesSet->AddObject($oLink);
|
||||||
|
}
|
||||||
|
$oUser->Set('profile_list', $oProfilesSet);
|
||||||
|
phpCAS::log("Info: the user $sEmail (id=".$oUser->GetKey().") now has the following profiles: '".implode("', '", $aProfiles)."'.");
|
||||||
|
|
||||||
|
if ($oUser->IsNew() || $oUser->IsModified())
|
||||||
|
{
|
||||||
|
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||||
|
$oMyChange->Set("date", time());
|
||||||
|
$oMyChange->Set("userinfo", 'CAS/LDAP Synchro');
|
||||||
|
$oMyChange->DBInsert();
|
||||||
|
if ($oUser->IsNew())
|
||||||
|
{
|
||||||
|
$oUser->DBInsertTracked($oMyChange);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oUser->DBUpdateTracked($oMyChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function IsPattern($sCASPattern)
|
||||||
|
{
|
||||||
|
if ((substr($sCASPattern, 0, 1) == '/') && (substr($sCASPattern, -1) == '/'))
|
||||||
|
{
|
||||||
|
// the string is enclosed by slashes, let's assume it's a pattern
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // End of class
|
} // End of class
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class UILinksWidget
|
|||||||
protected $m_iInputId;
|
protected $m_iInputId;
|
||||||
protected $m_aAttributes;
|
protected $m_aAttributes;
|
||||||
protected $m_sExtKeyToRemote;
|
protected $m_sExtKeyToRemote;
|
||||||
|
protected $m_sExtKeyToMe;
|
||||||
protected $m_sLinkedClass;
|
protected $m_sLinkedClass;
|
||||||
protected $m_sRemoteClass;
|
protected $m_sRemoteClass;
|
||||||
protected $m_bDuplicatesAllowed;
|
protected $m_bDuplicatesAllowed;
|
||||||
@@ -50,6 +51,7 @@ class UILinksWidget
|
|||||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sAttCode);
|
||||||
$this->m_sLinkedClass = $oAttDef->GetLinkedClass();
|
$this->m_sLinkedClass = $oAttDef->GetLinkedClass();
|
||||||
$this->m_sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
$this->m_sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||||
|
$this->m_sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
||||||
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
|
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
|
||||||
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
|
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
|
||||||
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
||||||
@@ -97,7 +99,7 @@ class UILinksWidget
|
|||||||
* @param Hash $aArgs Extra context arguments
|
* @param Hash $aArgs Extra context arguments
|
||||||
* @return string The HTML fragment of the one-row form
|
* @return string The HTML fragment of the one-row form
|
||||||
*/
|
*/
|
||||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId = null, $aArgs = array() )
|
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId = null, $aArgs = array(), $oCurrentObj )
|
||||||
{
|
{
|
||||||
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
|
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
|
||||||
$aRow = array();
|
$aRow = array();
|
||||||
@@ -107,6 +109,7 @@ class UILinksWidget
|
|||||||
$sPrefix .= "[$key][";
|
$sPrefix .= "[$key][";
|
||||||
$sNameSuffix = "]"; // To make a tabular form
|
$sNameSuffix = "]"; // To make a tabular form
|
||||||
$aArgs['prefix'] = $sPrefix;
|
$aArgs['prefix'] = $sPrefix;
|
||||||
|
$aArgs['this'] = $linkObjOrId;
|
||||||
$aRow['form::checkbox'] = "<input class=\"selection\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$key\">";
|
$aRow['form::checkbox'] = "<input class=\"selection\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$key\">";
|
||||||
$aRow['form::checkbox'] .= "<input type=\"hidden\" name=\"attr_{$sPrefix}id{$sNameSuffix}\" value=\"$key\">";
|
$aRow['form::checkbox'] .= "<input type=\"hidden\" name=\"attr_{$sPrefix}id{$sNameSuffix}\" value=\"$key\">";
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach($this->m_aEditableFields as $sFieldCode)
|
||||||
@@ -121,8 +124,13 @@ class UILinksWidget
|
|||||||
{
|
{
|
||||||
// form for creating a new record
|
// form for creating a new record
|
||||||
$sPrefix .= "[$linkObjOrId][";
|
$sPrefix .= "[$linkObjOrId][";
|
||||||
|
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
|
||||||
|
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, -$linkObjOrId);
|
||||||
|
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
|
||||||
|
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object alsoo fills the related external fields
|
||||||
$sNameSuffix = "]"; // To make a tabular form
|
$sNameSuffix = "]"; // To make a tabular form
|
||||||
$aArgs['prefix'] = $sPrefix;
|
$aArgs['prefix'] = $sPrefix;
|
||||||
|
$aArgs['this'] = $oNewLinkObj;
|
||||||
$aRow['form::checkbox'] = "<input class=\"selection\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$linkObjOrId\">";
|
$aRow['form::checkbox'] = "<input class=\"selection\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$linkObjOrId\">";
|
||||||
$aRow['form::checkbox'] .= "<input type=\"hidden\" name=\"attr_{$sPrefix}id{$sNameSuffix}\" value=\"\">";
|
$aRow['form::checkbox'] .= "<input type=\"hidden\" name=\"attr_{$sPrefix}id{$sNameSuffix}\" value=\"\">";
|
||||||
foreach($this->m_aEditableFields as $sFieldCode)
|
foreach($this->m_aEditableFields as $sFieldCode)
|
||||||
@@ -207,9 +215,11 @@ class UILinksWidget
|
|||||||
* @param WebPage $oP The web page used for all the output
|
* @param WebPage $oP The web page used for all the output
|
||||||
* @param DBObjectSet The initial value of the linked set
|
* @param DBObjectSet The initial value of the linked set
|
||||||
* @param Hash $aArgs Extra context arguments
|
* @param Hash $aArgs Extra context arguments
|
||||||
|
* @param string $sFormPrefix prefix of the fields in the current form
|
||||||
|
* @param DBObject $oCurrentObj the current object to which the linkset is related
|
||||||
* @return string The HTML fragment to be inserted into the page
|
* @return string The HTML fragment to be inserted into the page
|
||||||
*/
|
*/
|
||||||
public function Display(WebPage $oPage, DBObjectSet $oValue, $aArgs = array())
|
public function Display(WebPage $oPage, DBObjectSet $oValue, $aArgs = array(), $sFormPrefix, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$sHtmlValue = '';
|
$sHtmlValue = '';
|
||||||
$sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode);
|
$sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode);
|
||||||
@@ -223,19 +233,20 @@ class UILinksWidget
|
|||||||
if ($oCurrentLink->IsNew())
|
if ($oCurrentLink->IsNew())
|
||||||
{
|
{
|
||||||
$key = -$oLinkedObj->GetKey();
|
$key = -$oLinkedObj->GetKey();
|
||||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $key, $aArgs);
|
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $key, $aArgs, $oCurrentObj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$key = $oCurrentLink->GetKey();
|
$key = $oCurrentLink->GetKey();
|
||||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs);
|
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
$sHtmlValue .= $this->DisplayFormTable($oPage, $this->m_aTableConfig, $aForm);
|
||||||
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
$sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false';
|
||||||
|
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
|
||||||
$oPage->add_ready_script(<<<EOF
|
$oPage->add_ready_script(<<<EOF
|
||||||
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates);
|
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper);
|
||||||
oWidget{$this->m_iInputId}.Init();
|
oWidget{$this->m_iInputId}.Init();
|
||||||
EOF
|
EOF
|
||||||
);
|
);
|
||||||
@@ -344,7 +355,7 @@ EOF
|
|||||||
$oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true)); // Don't display the 'Actions' menu on the results
|
$oBlock->Display($oP, "ResultsToAdd_{$this->m_sAttCode}", array('menu' => false, 'cssCount'=> '#count_'.$this->m_sAttCode.$this->m_sNameSuffix , 'selection_mode' => true)); // Don't display the 'Actions' menu on the results
|
||||||
}
|
}
|
||||||
|
|
||||||
public function DoAddObjects(WebPage $oP, $oFullSetFilter)
|
public function DoAddObjects(WebPage $oP, $oFullSetFilter, $oCurrentObj)
|
||||||
{
|
{
|
||||||
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
$aLinkedObjectIds = utils::ReadMultipleSelection($oFullSetFilter);
|
||||||
|
|
||||||
@@ -353,7 +364,7 @@ EOF
|
|||||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId);
|
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $iObjectId);
|
||||||
if (is_object($oLinkedObj))
|
if (is_object($oLinkedObj))
|
||||||
{
|
{
|
||||||
$aRow = $this->GetFormRow($oP, $oLinkedObj, -$iObjectId ); // Not yet created link get negative Ids
|
$aRow = $this->GetFormRow($oP, $oLinkedObj, -$iObjectId, array(), $oCurrentObj ); // Not yet created link get negative Ids
|
||||||
$oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iObjectId));
|
$oP->add($this->DisplayFormRow($oP, $this->m_aTableConfig, $aRow, -$iObjectId));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -372,13 +372,13 @@ class WebPage
|
|||||||
{
|
{
|
||||||
// Make sure that the URL to the script contains the application's version number
|
// Make sure that the URL to the script contains the application's version number
|
||||||
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
// so that the new script do NOT get reloaded from the cache when the application is upgraded
|
||||||
if (strpos('?', $s_script) === false)
|
if (strpos($s_script, '?') === false)
|
||||||
{
|
{
|
||||||
$s_script .= "?version=".ITOP_VERSION;
|
$s_script .= "?itopversion=".ITOP_VERSION;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$s_script .= "&version=".ITOP_VERSION;
|
$s_script .= "&itopversion=".ITOP_VERSION;
|
||||||
}
|
}
|
||||||
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
echo "<script type=\"text/javascript\" src=\"$s_script\"></script>\n";
|
||||||
}
|
}
|
||||||
@@ -413,6 +413,10 @@ class WebPage
|
|||||||
}
|
}
|
||||||
echo "</style>\n";
|
echo "</style>\n";
|
||||||
}
|
}
|
||||||
|
if (class_exists('MetaModel') && MetaModel::GetConfig())
|
||||||
|
{
|
||||||
|
echo "<link rel=\"shortcut icon\" href=\"".utils::GetAbsoluteUrlAppRoot()."images/favicon.ico\" />\n";
|
||||||
|
}
|
||||||
echo "</head>\n";
|
echo "</head>\n";
|
||||||
echo "<body>\n";
|
echo "<body>\n";
|
||||||
echo self::FilterXSS($this->s_content);
|
echo self::FilterXSS($this->s_content);
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ class ActionEmail extends ActionNotification
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
$oSearch = DBObjectSearch::FromOQL($sOQL);
|
||||||
|
$oSearch->AllowAllData();
|
||||||
}
|
}
|
||||||
catch (OQLException $e)
|
catch (OQLException $e)
|
||||||
{
|
{
|
||||||
@@ -275,6 +276,7 @@ class ActionEmail extends ActionNotification
|
|||||||
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
|
protected function _DoExecute($oTrigger, $aContextArgs, &$oLog)
|
||||||
{
|
{
|
||||||
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();
|
$sPreviousUrlMaker = ApplicationContext::SetUrlMakerClass();
|
||||||
|
$aHeaders = array();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->m_iRecipients = 0;
|
$this->m_iRecipients = 0;
|
||||||
@@ -294,7 +296,9 @@ class ActionEmail extends ActionNotification
|
|||||||
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
||||||
|
|
||||||
$oObj = $aContextArgs['this->object()'];
|
$oObj = $aContextArgs['this->object()'];
|
||||||
$sReference = '<iTop/'.get_class($oObj).'/'.$oObj->GetKey().'>';
|
$sMessageId = sprintf('<iTop_%s_%d_%f@%s.openitop.org>', get_class($oObj), $oObj->GetKey(), microtime(true /* get as float*/), MetaModel::GetConfig()->Get('session_name'));
|
||||||
|
$sReference = $sMessageId;
|
||||||
|
$aHeaders['Message-ID'] = $sMessageId;
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
@@ -315,7 +319,7 @@ class ActionEmail extends ActionNotification
|
|||||||
if (isset($sBody)) $oLog->Set('body', $sBody);
|
if (isset($sBody)) $oLog->Set('body', $sBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
$oEmail = new EMail();
|
$oEmail = new EMail('', '', '', $aHeaders);
|
||||||
|
|
||||||
if ($this->IsBeingTested())
|
if ($this->IsBeingTested())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -206,6 +206,15 @@ abstract class AttributeDefinition
|
|||||||
}
|
}
|
||||||
return $sLabel;
|
return $sLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the label corresponding to the given value
|
||||||
|
* To be overloaded for localized enums
|
||||||
|
*/
|
||||||
|
public function GetValueLabel($sValue)
|
||||||
|
{
|
||||||
|
return GetAsHTML($sValue);
|
||||||
|
}
|
||||||
|
|
||||||
public function GetLabel_Obsolete()
|
public function GetLabel_Obsolete()
|
||||||
{
|
{
|
||||||
@@ -1333,7 +1342,12 @@ class AttributeFinalClass extends AttributeString
|
|||||||
{
|
{
|
||||||
return '=';
|
return '=';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function GetValueLabel($sValue)
|
||||||
|
{
|
||||||
|
if (empty($sValue)) return '';
|
||||||
|
return MetaModel::GetName($sValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ require_once('cmdbchangeop.class.inc.php');
|
|||||||
// Romain: temporary moved into application.inc.php (see explanations there)
|
// Romain: temporary moved into application.inc.php (see explanations there)
|
||||||
//require_once('event.class.inc.php');
|
//require_once('event.class.inc.php');
|
||||||
|
|
||||||
|
require_once('templatestring.class.inc.php');
|
||||||
require_once('csvparser.class.inc.php');
|
require_once('csvparser.class.inc.php');
|
||||||
require_once('bulkchange.class.inc.php');
|
require_once('bulkchange.class.inc.php');
|
||||||
|
|
||||||
@@ -279,9 +280,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
{
|
{
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||||
|
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$ret = $this->DBInsertTracked_Internal();
|
$ret = $this->DBInsertTracked_Internal();
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,9 +291,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
{
|
{
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||||
|
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$ret = $this->DBInsertTracked_Internal(true);
|
$ret = $this->DBInsertTracked_Internal(true);
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,9 +323,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
|
|
||||||
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
|
public function DBCloneTracked(CMDBChange $oChange, $newKey = null)
|
||||||
{
|
{
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$this->DBCloneTracked_Internal($newKey);
|
$this->DBCloneTracked_Internal($newKey);
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function DBCloneTracked_Internal($newKey = null)
|
protected function DBCloneTracked_Internal($newKey = null)
|
||||||
@@ -347,9 +351,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
{
|
{
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_MODIFY);
|
||||||
|
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$this->DBUpdateTracked_Internal();
|
$this->DBUpdateTracked_Internal();
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function DBUpdateTracked_Internal()
|
protected function DBUpdateTracked_Internal()
|
||||||
@@ -382,9 +387,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
{
|
{
|
||||||
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_DELETE);
|
$this->CheckUserRights($bSkipStrongSecurity, UR_ACTION_DELETE);
|
||||||
|
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$this->DBDeleteTracked_Internal($oDeletionPlan);
|
$this->DBDeleteTracked_Internal($oDeletionPlan);
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
|
protected function DBDeleteTracked_Internal(&$oDeletionPlan = null)
|
||||||
@@ -406,9 +412,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
|
|
||||||
public static function BulkDeleteTracked(CMDBChange $oChange, DBObjectSearch $oFilter)
|
public static function BulkDeleteTracked(CMDBChange $oChange, DBObjectSearch $oFilter)
|
||||||
{
|
{
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$this->BulkDeleteTracked_Internal($oFilter);
|
$this->BulkDeleteTracked_Internal($oFilter);
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function BulkDeleteTracked_Internal(DBObjectSearch $oFilter)
|
protected static function BulkDeleteTracked_Internal(DBObjectSearch $oFilter)
|
||||||
@@ -445,9 +452,10 @@ abstract class CMDBObject extends DBObject
|
|||||||
|
|
||||||
public static function BulkUpdateTracked(CMDBChange $oChange, DBObjectSearch $oFilter, array $aValues)
|
public static function BulkUpdateTracked(CMDBChange $oChange, DBObjectSearch $oFilter, array $aValues)
|
||||||
{
|
{
|
||||||
|
$oPreviousChange = self::$m_oCurrChange;
|
||||||
self::$m_oCurrChange = $oChange;
|
self::$m_oCurrChange = $oChange;
|
||||||
$this->BulkUpdateTracked_Internal($oFilter, $aValues);
|
$this->BulkUpdateTracked_Internal($oFilter, $aValues);
|
||||||
self::$m_oCurrChange = null;
|
self::$m_oCurrChange = $oPreviousChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function BulkUpdateTracked_Internal(DBObjectSearch $oFilter, array $aValues)
|
protected static function BulkUpdateTracked_Internal(DBObjectSearch $oFilter, array $aValues)
|
||||||
|
|||||||
@@ -383,6 +383,24 @@ class Config
|
|||||||
'source_of_value' => '',
|
'source_of_value' => '',
|
||||||
'show_in_conf_sample' => true,
|
'show_in_conf_sample' => true,
|
||||||
),
|
),
|
||||||
|
'cas_user_synchro' => array(
|
||||||
|
'type' => 'bool',
|
||||||
|
'description' => 'Whether or not to synchronize users with CAS/LDAP',
|
||||||
|
// examples... not used (nor 'description')
|
||||||
|
'default' => 0,
|
||||||
|
'value' => 0,
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => true,
|
||||||
|
),
|
||||||
|
'cas_profile_pattern' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'description' => 'A regular expression pattern to extract the name of the iTop profile from the name of an LDAP/CAS group',
|
||||||
|
// examples... not used (nor 'description')
|
||||||
|
'default' => '/^cn=([^,]+),/',
|
||||||
|
'value' => '/^cn=([^,]+),/',
|
||||||
|
'source_of_value' => '',
|
||||||
|
'show_in_conf_sample' => true,
|
||||||
|
),
|
||||||
'cas_debug' => array(
|
'cas_debug' => array(
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
'description' => 'Activate the CAS debug',
|
'description' => 'Activate the CAS debug',
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ abstract class DBObject
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function Reload()
|
public function Reload()
|
||||||
{
|
{
|
||||||
assert($this->m_bIsInDB);
|
assert($this->m_bIsInDB);
|
||||||
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey, false/*, $this->m_bAllowAllData*/);
|
$aRow = MetaModel::MakeSingleRow(get_class($this), $this->m_iKey, false/*, $this->m_bAllowAllData*/);
|
||||||
@@ -367,6 +367,34 @@ abstract class DBObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function Get($sAttCode)
|
public function Get($sAttCode)
|
||||||
|
{
|
||||||
|
if (($iPos = strpos($sAttCode, '->')) === false)
|
||||||
|
{
|
||||||
|
return $this->GetStrict($sAttCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sExtKeyAttCode = substr($sAttCode, 0, $iPos);
|
||||||
|
$sRemoteAttCode = substr($sAttCode, $iPos + 2);
|
||||||
|
if (!MetaModel::IsValidAttCode(get_class($this), $sExtKeyAttCode))
|
||||||
|
{
|
||||||
|
throw new CoreException("Unknown external key '$sExtKeyAttCode' for the class ".get_class($this));
|
||||||
|
}
|
||||||
|
$oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
|
||||||
|
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||||
|
$oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
|
||||||
|
if (is_null($oRemoteObj))
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $oRemoteObj->Get($sRemoteAttCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetStrict($sAttCode)
|
||||||
{
|
{
|
||||||
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
|
if (!array_key_exists($sAttCode, MetaModel::ListAttributeDefs(get_class($this))))
|
||||||
{
|
{
|
||||||
@@ -1580,19 +1608,22 @@ abstract class DBObject
|
|||||||
if (!$bRet) $bSuccess = false;
|
if (!$bRet) $bSuccess = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change state triggers...
|
if ($bSuccess)
|
||||||
$sClass = get_class($this);
|
|
||||||
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
|
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sPreviousState'"));
|
|
||||||
while ($oTrigger = $oSet->Fetch())
|
|
||||||
{
|
{
|
||||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
// Change state triggers...
|
||||||
}
|
$sClass = get_class($this);
|
||||||
|
$sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
|
||||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sNewState'"));
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sPreviousState'"));
|
||||||
while ($oTrigger = $oSet->Fetch())
|
while ($oTrigger = $oSet->Fetch())
|
||||||
{
|
{
|
||||||
$oTrigger->DoActivate($this->ToArgs('this'));
|
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('$sClassList') AND t.state='$sNewState'"));
|
||||||
|
while ($oTrigger = $oSet->Fetch())
|
||||||
|
{
|
||||||
|
$oTrigger->DoActivate($this->ToArgs('this'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $bSuccess;
|
return $bSuccess;
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class Dict
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function GetCurrentLanguage()
|
public static function GetUserLanguage()
|
||||||
{
|
{
|
||||||
if (self::$m_sCurrentLanguage == null) // May happen when no user is logged in (i.e login screen, non authentifed page)
|
if (self::$m_sCurrentLanguage == null) // May happen when no user is logged in (i.e login screen, non authentifed page)
|
||||||
{
|
{
|
||||||
@@ -124,12 +124,12 @@ class Dict
|
|||||||
{
|
{
|
||||||
// Attempt to find the string in the user language
|
// Attempt to find the string in the user language
|
||||||
//
|
//
|
||||||
if (!array_key_exists(self::GetCurrentLanguage(), self::$m_aData))
|
if (!array_key_exists(self::GetUserLanguage(), self::$m_aData))
|
||||||
{
|
{
|
||||||
// It may happen, when something happens before the dictionnaries get loaded
|
// It may happen, when something happens before the dictionnaries get loaded
|
||||||
return $sStringCode;
|
return $sStringCode;
|
||||||
}
|
}
|
||||||
$aCurrentDictionary = self::$m_aData[self::GetCurrentLanguage()];
|
$aCurrentDictionary = self::$m_aData[self::GetUserLanguage()];
|
||||||
if (array_key_exists($sStringCode, $aCurrentDictionary))
|
if (array_key_exists($sStringCode, $aCurrentDictionary))
|
||||||
{
|
{
|
||||||
return $aCurrentDictionary[$sStringCode];
|
return $aCurrentDictionary[$sStringCode];
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class EMail
|
|||||||
protected $m_sSubject;
|
protected $m_sSubject;
|
||||||
protected $m_sTo;
|
protected $m_sTo;
|
||||||
protected $m_aHeaders; // array of key=>value
|
protected $m_aHeaders; // array of key=>value
|
||||||
|
protected $m_aAttachments;
|
||||||
|
|
||||||
public function __construct($sTo = '', $sSubject = '', $sBody = '', $aHeaders = array())
|
public function __construct($sTo = '', $sSubject = '', $sBody = '', $aHeaders = array())
|
||||||
{
|
{
|
||||||
@@ -42,6 +43,7 @@ class EMail
|
|||||||
$this->m_sSubject = $sSubject;
|
$this->m_sSubject = $sSubject;
|
||||||
$this->m_sBody = $sBody;
|
$this->m_sBody = $sBody;
|
||||||
$this->m_aHeaders = $aHeaders;
|
$this->m_aHeaders = $aHeaders;
|
||||||
|
$this->m_aAttachments = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errors management : not that simple because we need that function to be
|
// Errors management : not that simple because we need that function to be
|
||||||
@@ -73,8 +75,14 @@ class EMail
|
|||||||
{
|
{
|
||||||
$sHeaders = 'MIME-Version: 1.0' . "\r\n";
|
$sHeaders = 'MIME-Version: 1.0' . "\r\n";
|
||||||
// ! the case is important for MS-Outlook
|
// ! the case is important for MS-Outlook
|
||||||
$sHeaders .= 'Content-Type: text/html; charset=UTF-8' . "\r\n";
|
if (!array_key_exists('Content-Type', $this->m_aHeaders))
|
||||||
$sHeaders .= 'Content-Transfer-Encoding: 8bit' . "\r\n";
|
{
|
||||||
|
$sHeaders .= 'Content-Type: text/html; charset=UTF-8' . "\r\n";
|
||||||
|
}
|
||||||
|
if (!array_key_exists('Content-Transfer-Encoding', $this->m_aHeaders))
|
||||||
|
{
|
||||||
|
$sHeaders .= 'Content-Transfer-Encoding: 8bit' . "\r\n";
|
||||||
|
}
|
||||||
foreach ($this->m_aHeaders as $sKey => $sValue)
|
foreach ($this->m_aHeaders as $sKey => $sValue)
|
||||||
{
|
{
|
||||||
$sHeaders .= "$sKey: $sValue\r\n";
|
$sHeaders .= "$sKey: $sValue\r\n";
|
||||||
@@ -110,6 +118,7 @@ class EMail
|
|||||||
|
|
||||||
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
|
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
|
||||||
{
|
{
|
||||||
|
$this->BuildMessage(); // assemble the attachments into the header/body structure
|
||||||
if ($bForceSynchronous)
|
if ($bForceSynchronous)
|
||||||
{
|
{
|
||||||
return $this->SendSynchronous($aIssues, $oLog);
|
return $this->SendSynchronous($aIssues, $oLog);
|
||||||
@@ -181,6 +190,36 @@ class EMail
|
|||||||
$this->AddToHeader('Reply-To', $sAddress);
|
$this->AddToHeader('Reply-To', $sAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function AddAttachment($data, $sFileName, $sMimeType)
|
||||||
|
{
|
||||||
|
$this->m_aAttachments[] = array('data' => $data, 'filename' => $sFileName, 'mimeType' => $sMimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes care of the attachments (if any) to build the header/body of the message before storing or sending it
|
||||||
|
*/
|
||||||
|
protected function BuildMessage()
|
||||||
|
{
|
||||||
|
if (count($this->m_aAttachments) == 0) return; // Nothing to do if there are no attachments
|
||||||
|
|
||||||
|
$sDelimiter = '== iTopEmailPart---'.md5(date('r', time()))." ==";
|
||||||
|
$sContentType = isset($this->m_aHeaders['Content-Type']) ? $this->m_aHeaders['Content-Type'] : 'text/html';
|
||||||
|
$sContentHeader = "Content-Type: $sContentType\r\n";
|
||||||
|
$this->m_aHeaders['Content-Type'] = "multipart/mixed; boundary=\"{$sDelimiter}\"";
|
||||||
|
|
||||||
|
$aAttachments = array();
|
||||||
|
foreach($this->m_aAttachments as $aAttach)
|
||||||
|
{
|
||||||
|
$sAttachmentHeader = "Content-Type: {$aAttach['mimeType']};\r\n Name=\"{$aAttach['filename']}\"\r\n";
|
||||||
|
$sAttachmentHeader .= "Content-Transfer-Encoding: base64\r\nContent-Disposition: attachment;\r\n filename=\"{$aAttach['filename']}\"\r\n";
|
||||||
|
$sAttachmentHeader .= "\r\n";
|
||||||
|
$sAttachment = chunk_split(base64_encode($aAttach['data']));
|
||||||
|
$aAttachments[] = $sAttachmentHeader.$sAttachment."\r\n";
|
||||||
|
}
|
||||||
|
$this->m_sBody = "This is a multi-part message in MIME format.\r\n--".$sDelimiter."\r\n".$sContentHeader."\r\n".$this->m_sBody."\r\n--".$sDelimiter."\r\n";
|
||||||
|
$this->m_sBody .= implode("--".$sDelimiter."\r\n", $aAttachments);
|
||||||
|
$this->m_sBody .= "--".$sDelimiter."--";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -676,10 +676,38 @@ abstract class MetaModel
|
|||||||
if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) return false;
|
if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) return false;
|
||||||
return (self::$m_aAttribDefs[$sClass][$sAttCode]->IsExternalKey());
|
return (self::$m_aAttribDefs[$sClass][$sAttCode]->IsExternalKey());
|
||||||
}
|
}
|
||||||
final static public function IsValidAttCode($sClass, $sAttCode)
|
final static public function IsValidAttCode($sClass, $sAttCode, $bExtended = false)
|
||||||
{
|
{
|
||||||
if (!array_key_exists($sClass, self::$m_aAttribDefs)) return false;
|
if (!array_key_exists($sClass, self::$m_aAttribDefs)) return false;
|
||||||
return (array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]));
|
|
||||||
|
if ($bExtended)
|
||||||
|
{
|
||||||
|
if (($iPos = strpos($sAttCode, '->')) === false)
|
||||||
|
{
|
||||||
|
$bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$sExtKeyAttCode = substr($sAttCode, 0, $iPos);
|
||||||
|
$sRemoteAttCode = substr($sAttCode, $iPos + 2);
|
||||||
|
if (MetaModel::IsValidAttCode($sClass, $sExtKeyAttCode))
|
||||||
|
{
|
||||||
|
$oKeyAttDef = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode);
|
||||||
|
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||||
|
$bRes = MetaModel::IsValidAttCode($sRemoteClass, $sRemoteAttCode, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$bRes = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bRes;
|
||||||
}
|
}
|
||||||
final static public function IsAttributeOrigin($sClass, $sAttCode)
|
final static public function IsAttributeOrigin($sClass, $sAttCode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -153,16 +153,25 @@ class ormCaseLog {
|
|||||||
* Add a new entry to the log and updates the internal index
|
* Add a new entry to the log and updates the internal index
|
||||||
* @param $sText string The text of the new entry
|
* @param $sText string The text of the new entry
|
||||||
*/
|
*/
|
||||||
public function AddLogEntry($sText)
|
public function AddLogEntry($sText, $sOnBehalfOf = '')
|
||||||
{
|
{
|
||||||
$sDate = date(Dict::S('UI:CaseLog:DateFormat'));
|
$sDate = date(Dict::S('UI:CaseLog:DateFormat'));
|
||||||
$sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, UserRights::GetUserFriendlyName(), UserRights::GetUserId());
|
if ($sOnBehalfOf == '')
|
||||||
|
{
|
||||||
|
$sOnBehalfOf = UserRights::GetUserFriendlyName();
|
||||||
|
$iUserId = UserRights::GetUserId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$iUserId = null;
|
||||||
|
}
|
||||||
|
$sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId);
|
||||||
$iSepLength = strlen($sSeparator);
|
$iSepLength = strlen($sSeparator);
|
||||||
$iTextlength = strlen($sText);
|
$iTextlength = strlen($sText);
|
||||||
$this->m_sLog = $sSeparator.$sText.$this->m_sLog; // Latest entry printed first
|
$this->m_sLog = $sSeparator.$sText.$this->m_sLog; // Latest entry printed first
|
||||||
$this->m_aIndex[] = array(
|
$this->m_aIndex[] = array(
|
||||||
'user_name' => UserRights::GetUserFriendlyName(),
|
'user_name' => $sOnBehalfOf,
|
||||||
'user_id' => UserRights::GetUserId(),
|
'user_id' => $iUserId,
|
||||||
'date' => time(),
|
'date' => time(),
|
||||||
'text_length' => $iTextlength,
|
'text_length' => $iTextlength,
|
||||||
'separator_length' => $iSepLength,
|
'separator_length' => $iSepLength,
|
||||||
|
|||||||
177
core/templatestring.class.inc.php
Normal file
177
core/templatestring.class.inc.php
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
<?php
|
||||||
|
// Copyright (C) 2010 Combodo SARL
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; version 3 of the License.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple helper class to interpret and transform a template string
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* $oString = new TemplateString("Blah $this->friendlyname$ is in location $this->location_id->name$ ('$this->location_id->org_id->name$)");
|
||||||
|
* echo $oString->Render(array('this' => $oContact));
|
||||||
|
|
||||||
|
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||||
|
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||||
|
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||||
|
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class
|
||||||
|
*/
|
||||||
|
class TemplateStringPlaceholder
|
||||||
|
{
|
||||||
|
public $sToken;
|
||||||
|
public $sAttCode;
|
||||||
|
public $sFunction;
|
||||||
|
public $sParamName;
|
||||||
|
public $bIsValid;
|
||||||
|
|
||||||
|
public function __construct($sToken)
|
||||||
|
{
|
||||||
|
$this->sToken = $sToken;
|
||||||
|
$this->sAttcode = '';
|
||||||
|
$this->sFunction = '';
|
||||||
|
$this->sParamName = '';
|
||||||
|
$this->bIsValid = false; // Validity may be false in general, but it can work anyway (thanks to specialization) when rendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class TemplateString
|
||||||
|
*/
|
||||||
|
class TemplateString
|
||||||
|
{
|
||||||
|
protected $m_sRaw;
|
||||||
|
protected $m_aPlaceholders;
|
||||||
|
|
||||||
|
public function __construct($sRaw)
|
||||||
|
{
|
||||||
|
$this->m_sRaw = $sRaw;
|
||||||
|
$this->m_aPlaceholders = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the string into placholders
|
||||||
|
* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function Analyze($aParamTypes = array())
|
||||||
|
{
|
||||||
|
if (!is_null($this->m_aPlaceholders)) return;
|
||||||
|
|
||||||
|
$this->m_aPlaceholders = array();
|
||||||
|
if (preg_match_all('/\\$([a-z0-9_]+(->[a-z0-9_]+)*)\\$/', $this->m_sRaw, $aMatches))
|
||||||
|
{
|
||||||
|
foreach($aMatches[1] as $sPlaceholder)
|
||||||
|
{
|
||||||
|
$oPlaceholder = new TemplateStringPlaceholder($sPlaceholder);
|
||||||
|
$oPlaceholder->bIsValid = false;
|
||||||
|
foreach ($aParamTypes as $sParamName => $sClass)
|
||||||
|
{
|
||||||
|
$sParamPrefix = $sParamName.'->';
|
||||||
|
if (substr($sPlaceholder, 0, strlen($sParamPrefix)) == $sParamPrefix)
|
||||||
|
{
|
||||||
|
// Todo - detect functions (label...)
|
||||||
|
$oPlaceholder->sFunction = '';
|
||||||
|
|
||||||
|
$oPlaceholder->sParamName = $sParamName;
|
||||||
|
$sAttcode = substr($sPlaceholder, strlen($sParamPrefix));
|
||||||
|
$oPlaceholder->sAttcode = $sAttcode;
|
||||||
|
$oPlaceholder->bIsValid = MetaModel::IsValidAttCode($sClass, $sAttcode, true /* extended */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->m_aPlaceholders[] = $oPlaceholder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the placeholders (for reporting purposes)
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function GetPlaceholders()
|
||||||
|
{
|
||||||
|
return $this->m_aPlaceholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the format when possible
|
||||||
|
* @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function IsValid($aParamTypes = array())
|
||||||
|
{
|
||||||
|
$this->Analyze($aParamTypes);
|
||||||
|
|
||||||
|
foreach($this->m_aPlaceholders as $oPlaceholder)
|
||||||
|
{
|
||||||
|
if (!$oPlaceholder->bIsValid)
|
||||||
|
{
|
||||||
|
if (count($aParamTypes) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (array_key_exists($oPlaceholder->sParamName, $aParamTypes))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the given parameters to replace the placeholders
|
||||||
|
* @param Hash $aParamValues Value of the expected parameters: hash array of '<param_id>' => '<value>'
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function Render($aParamValues = array())
|
||||||
|
{
|
||||||
|
$aParamTypes = array();
|
||||||
|
foreach($aParamValues as $sParamName => $value)
|
||||||
|
{
|
||||||
|
$aParamTypes[$sParamName] = get_class($value);
|
||||||
|
}
|
||||||
|
$this->Analyze($aParamTypes);
|
||||||
|
|
||||||
|
$aSearch = array();
|
||||||
|
$aReplace = array();
|
||||||
|
foreach($this->m_aPlaceholders as $oPlaceholder)
|
||||||
|
{
|
||||||
|
if (array_key_exists($oPlaceholder->sParamName, $aParamValues))
|
||||||
|
{
|
||||||
|
$oRef = $aParamValues[$oPlaceholder->sParamName];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$value = $oRef->Get($oPlaceholder->sAttcode);
|
||||||
|
$aSearch[] = '$'.$oPlaceholder->sToken.'$';
|
||||||
|
$aReplace[] = $value;
|
||||||
|
$oPlaceholder->bIsValid = true;
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
$oPlaceholder->bIsValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oPlaceholder->bIsValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str_replace($aSearch, $aReplace, $this->m_sRaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -625,10 +625,6 @@ class UserRights
|
|||||||
|
|
||||||
if (MetaModel::HasCategory($sClass, 'bizmodel'))
|
if (MetaModel::HasCategory($sClass, 'bizmodel'))
|
||||||
{
|
{
|
||||||
// #@# Temporary?????
|
|
||||||
// The read access is controlled in MetaModel::MakeSelectQuery()
|
|
||||||
if ($iActionCode == UR_ACTION_READ) return true;
|
|
||||||
|
|
||||||
if (is_null($oUser))
|
if (is_null($oUser))
|
||||||
{
|
{
|
||||||
$oUser = self::$m_oUser;
|
$oUser = self::$m_oUser;
|
||||||
|
|||||||
@@ -176,6 +176,10 @@ legend {
|
|||||||
-webkit-border-radius: 6px;
|
-webkit-border-radius: 6px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
.ui-widget-content td legend a, .ui-widget-content td legend a:hover, .ui-widget-content td legend a:visited {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.ui-widget-content td a, p a, p a:visited, td a, td a:visited {
|
.ui-widget-content td a, p a, p a:visited, td a, td a:visited {
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
color: #1C94C4;
|
color: #1C94C4;
|
||||||
@@ -1104,4 +1108,7 @@ div.actions_button a, .actions_button a:hover, .actions_button a:visited {
|
|||||||
height:17px;
|
height:17px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
display: block;
|
display: block;
|
||||||
|
}
|
||||||
|
select#org_id {
|
||||||
|
max-width: 90%;
|
||||||
}
|
}
|
||||||
@@ -639,7 +639,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
|||||||
'Core:SyncDataSourceObsolete' => 'The data source is marked as obsolete. Operation cancelled.',
|
'Core:SyncDataSourceObsolete' => 'The data source is marked as obsolete. Operation cancelled.',
|
||||||
'Core:SyncDataSourceAccessRestriction' => 'Only adminstrators or the user specified in the data source can execute this operation. Operation cancelled.',
|
'Core:SyncDataSourceAccessRestriction' => 'Only adminstrators or the user specified in the data source can execute this operation. Operation cancelled.',
|
||||||
'Core:SyncTooManyMissingReplicas' => 'All records have been untouched for some time (all of the objects could be deleted). Please check that the process that writes into the synchronization table is still running. Operation cancelled.',
|
'Core:SyncTooManyMissingReplicas' => 'All records have been untouched for some time (all of the objects could be deleted). Please check that the process that writes into the synchronization table is still running. Operation cancelled.',
|
||||||
|
'Core:Synchro:ListReplicas_AllReplicas_Errors_Warnings' => '%1$s replicas, %2$s error(s), %3$s warning(s).',
|
||||||
|
'Core:SynchroReplica:TargetObject' => 'Synchronized Object: %1$s',
|
||||||
'Class:AsyncSendEmail' => 'Email (asynchronous)',
|
'Class:AsyncSendEmail' => 'Email (asynchronous)',
|
||||||
'Class:AsyncSendEmail/Attribute:to' => 'To',
|
'Class:AsyncSendEmail/Attribute:to' => 'To',
|
||||||
'Class:AsyncSendEmail/Attribute:subject' => 'Subject',
|
'Class:AsyncSendEmail/Attribute:subject' => 'Subject',
|
||||||
@@ -717,7 +718,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
|||||||
'Class:SynchroReplica/Attribute:sync_source_id' => 'Synchro Data Source',
|
'Class:SynchroReplica/Attribute:sync_source_id' => 'Synchro Data Source',
|
||||||
'Class:SynchroReplica/Attribute:dest_id' => 'Destination object (ID)',
|
'Class:SynchroReplica/Attribute:dest_id' => 'Destination object (ID)',
|
||||||
'Class:SynchroReplica/Attribute:dest_class' => 'Destination type',
|
'Class:SynchroReplica/Attribute:dest_class' => 'Destination type',
|
||||||
'Class:SynchroReplica/Attribute:status_last_seen' => 'Lat seen',
|
'Class:SynchroReplica/Attribute:status_last_seen' => 'Last seen',
|
||||||
'Class:SynchroReplica/Attribute:status' => 'Status',
|
'Class:SynchroReplica/Attribute:status' => 'Status',
|
||||||
'Class:SynchroReplica/Attribute:status/Value:modified' => 'Modified',
|
'Class:SynchroReplica/Attribute:status/Value:modified' => 'Modified',
|
||||||
'Class:SynchroReplica/Attribute:status/Value:new' => 'New',
|
'Class:SynchroReplica/Attribute:status/Value:new' => 'New',
|
||||||
@@ -726,6 +727,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
|||||||
'Class:SynchroReplica/Attribute:status/Value:synchronized' => 'Synchronized',
|
'Class:SynchroReplica/Attribute:status/Value:synchronized' => 'Synchronized',
|
||||||
'Class:SynchroReplica/Attribute:status_dest_creator' => 'Object Created ?',
|
'Class:SynchroReplica/Attribute:status_dest_creator' => 'Object Created ?',
|
||||||
'Class:SynchroReplica/Attribute:status_last_error' => 'Last Error',
|
'Class:SynchroReplica/Attribute:status_last_error' => 'Last Error',
|
||||||
|
'Class:SynchroReplica/Attribute:status_last_warning' => 'Warnings',
|
||||||
'Class:SynchroReplica/Attribute:info_creation_date' => 'Creation Date',
|
'Class:SynchroReplica/Attribute:info_creation_date' => 'Creation Date',
|
||||||
'Class:SynchroReplica/Attribute:info_last_modified' => 'Last Modified Date',
|
'Class:SynchroReplica/Attribute:info_last_modified' => 'Last Modified Date',
|
||||||
'Class:appUserPreferences' => 'User Preferences',
|
'Class:appUserPreferences' => 'User Preferences',
|
||||||
|
|||||||
@@ -532,7 +532,9 @@ Dict::Add('EN US', 'English', 'English', array(
|
|||||||
'UI:Audit:HeaderNbObjects' => '# Objects',
|
'UI:Audit:HeaderNbObjects' => '# Objects',
|
||||||
'UI:Audit:HeaderNbErrors' => '# Errors',
|
'UI:Audit:HeaderNbErrors' => '# Errors',
|
||||||
'UI:Audit:PercentageOk' => '% Ok',
|
'UI:Audit:PercentageOk' => '% Ok',
|
||||||
|
'UI:Audit:ErrorIn_Rule_Reason' => 'OQL Error in the Rule %1$s: %2$s.',
|
||||||
|
'UI:Audit:ErrorIn_Category_Reason' => 'OQL Error in the Category %1$s: %2$s.',
|
||||||
|
|
||||||
'UI:RunQuery:Title' => 'iTop - OQL Query Evaluation',
|
'UI:RunQuery:Title' => 'iTop - OQL Query Evaluation',
|
||||||
'UI:RunQuery:QueryExamples' => 'Query Examples',
|
'UI:RunQuery:QueryExamples' => 'Query Examples',
|
||||||
'UI:RunQuery:HeaderPurpose' => 'Purpose',
|
'UI:RunQuery:HeaderPurpose' => 'Purpose',
|
||||||
|
|||||||
@@ -386,6 +386,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
|||||||
'Class:SynchroReplica/Attribute:status_dest_creator+' => '',
|
'Class:SynchroReplica/Attribute:status_dest_creator+' => '',
|
||||||
'Class:SynchroReplica/Attribute:status_last_error' => 'Dernière erreur',
|
'Class:SynchroReplica/Attribute:status_last_error' => 'Dernière erreur',
|
||||||
'Class:SynchroReplica/Attribute:status_last_error+' => '',
|
'Class:SynchroReplica/Attribute:status_last_error+' => '',
|
||||||
|
'Class:SynchroReplica/Attribute:status_last_warning' => 'Avertissements',
|
||||||
|
'Class:SynchroReplica/Attribute:status_last_warning+' => '',
|
||||||
'Class:SynchroReplica/Attribute:info_creation_date' => 'Date de création',
|
'Class:SynchroReplica/Attribute:info_creation_date' => 'Date de création',
|
||||||
'Class:SynchroReplica/Attribute:info_creation_date+' => '',
|
'Class:SynchroReplica/Attribute:info_creation_date+' => '',
|
||||||
'Class:SynchroReplica/Attribute:info_last_modified' => 'Date de dernière modification',
|
'Class:SynchroReplica/Attribute:info_last_modified' => 'Date de dernière modification',
|
||||||
@@ -605,6 +607,8 @@ Opérateurs :<br/>
|
|||||||
'Core:SyncDataSourceObsolete' => 'Cette source de données est obsolète. Opération annulée.',
|
'Core:SyncDataSourceObsolete' => 'Cette source de données est obsolète. Opération annulée.',
|
||||||
'Core:SyncDataSourceAccessRestriction' => 'Seuls les administrateurs et l\'utilisateur spécifié dans la source de données peuvent exécuter cette synchronisation. Opération annulée.',
|
'Core:SyncDataSourceAccessRestriction' => 'Seuls les administrateurs et l\'utilisateur spécifié dans la source de données peuvent exécuter cette synchronisation. Opération annulée.',
|
||||||
'Core:SyncTooManyMissingReplicas' => 'Tous les réplicas sont absents de l\'import. L\'import a-t-il réellement tourné. Opération annulée.',
|
'Core:SyncTooManyMissingReplicas' => 'Tous les réplicas sont absents de l\'import. L\'import a-t-il réellement tourné. Opération annulée.',
|
||||||
|
'Core:Synchro:ListReplicas_AllReplicas_Errors_Warnings' => '%1$s replicas, %2$s erreur(s), %3$s avertissement(s).',
|
||||||
|
'Core:SynchroReplica:TargetObject' => 'Objet Synchronisé : %1$s',
|
||||||
'Core:Duration_Seconds' => '%1$ds',
|
'Core:Duration_Seconds' => '%1$ds',
|
||||||
'Core:Duration_Minutes_Seconds' => '%1$dmin %2$ds',
|
'Core:Duration_Minutes_Seconds' => '%1$dmin %2$ds',
|
||||||
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
|
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
|||||||
'Class:URP_UserProfile/Attribute:reason' => 'Raison',
|
'Class:URP_UserProfile/Attribute:reason' => 'Raison',
|
||||||
'Class:URP_UserProfile/Attribute:reason+' => 'Justifie le rôle affecté à cet utilisateur',
|
'Class:URP_UserProfile/Attribute:reason+' => 'Justifie le rôle affecté à cet utilisateur',
|
||||||
'Class:URP_UserOrg' => 'Utilisateur/Organisation',
|
'Class:URP_UserOrg' => 'Utilisateur/Organisation',
|
||||||
'Class:URP_UserOrg+' => 'Organizations permises pour l\'utilisateur',
|
'Class:URP_UserOrg+' => 'Organisations permises pour l\'utilisateur',
|
||||||
'Class:URP_UserOrg/Attribute:userid' => 'Utilisateur',
|
'Class:URP_UserOrg/Attribute:userid' => 'Utilisateur',
|
||||||
'Class:URP_UserOrg/Attribute:userid+' => '',
|
'Class:URP_UserOrg/Attribute:userid+' => '',
|
||||||
'Class:URP_UserOrg/Attribute:userlogin' => 'Login',
|
'Class:URP_UserOrg/Attribute:userlogin' => 'Login',
|
||||||
@@ -215,7 +215,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
|||||||
'UI:WelcomeMenu:OpenIncidents' => 'Incidents en cours: %1$d',
|
'UI:WelcomeMenu:OpenIncidents' => 'Incidents en cours: %1$d',
|
||||||
'UI:WelcomeMenu:AllConfigItems' => 'Actifs: %1$d',
|
'UI:WelcomeMenu:AllConfigItems' => 'Actifs: %1$d',
|
||||||
'UI:WelcomeMenu:MyIncidents' => 'Mes Incidents',
|
'UI:WelcomeMenu:MyIncidents' => 'Mes Incidents',
|
||||||
'UI:AllOrganizations' => ' Toutes les Organizations ',
|
'UI:AllOrganizations' => ' Toutes les Organisations ',
|
||||||
'UI:YourSearch' => 'Votre recherche',
|
'UI:YourSearch' => 'Votre recherche',
|
||||||
'UI:LoggedAsMessage' => 'Connecté comme: %1$s',
|
'UI:LoggedAsMessage' => 'Connecté comme: %1$s',
|
||||||
'UI:LoggedAsMessage+Admin' => 'Connecté comme: %1$s (Administrateur)',
|
'UI:LoggedAsMessage+Admin' => 'Connecté comme: %1$s (Administrateur)',
|
||||||
@@ -416,6 +416,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
|||||||
'UI:Audit:HeaderNbObjects' => 'Nb d\'Objets',
|
'UI:Audit:HeaderNbObjects' => 'Nb d\'Objets',
|
||||||
'UI:Audit:HeaderNbErrors' => 'Nb d\'Erreurs',
|
'UI:Audit:HeaderNbErrors' => 'Nb d\'Erreurs',
|
||||||
'UI:Audit:PercentageOk' => '% Ok',
|
'UI:Audit:PercentageOk' => '% Ok',
|
||||||
|
'UI:Audit:ErrorIn_Rule_Reason' => 'Erreur OQL dans la règle %1$s: %2$s.',
|
||||||
|
'UI:Audit:ErrorIn_Category_Reason' => 'Erreur OQL dans la catégorie %1$s: %2$s.',
|
||||||
'UI:RunQuery:Title' => 'iTop - Evaluation de requêtes OQL',
|
'UI:RunQuery:Title' => 'iTop - Evaluation de requêtes OQL',
|
||||||
'UI:RunQuery:QueryExamples' => 'Exemples de requêtes',
|
'UI:RunQuery:QueryExamples' => 'Exemples de requêtes',
|
||||||
'UI:RunQuery:HeaderPurpose' => 'Objectif',
|
'UI:RunQuery:HeaderPurpose' => 'Objectif',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// JavaScript Document
|
// JavaScript Document
|
||||||
function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates)
|
function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizHelper)
|
||||||
{
|
{
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.iInputId = iInputId;
|
this.iInputId = iInputId;
|
||||||
@@ -7,6 +7,7 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates)
|
|||||||
this.sAttCode = sAttCode;
|
this.sAttCode = sAttCode;
|
||||||
this.sSuffix = sSuffix;
|
this.sSuffix = sSuffix;
|
||||||
this.bDuplicates = bDuplicates;
|
this.bDuplicates = bDuplicates;
|
||||||
|
this.oWizardHelper = oWizHelper;
|
||||||
var me = this;
|
var me = this;
|
||||||
this.Init = function()
|
this.Init = function()
|
||||||
{
|
{
|
||||||
@@ -202,6 +203,16 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
theMap['operation'] = 'doAddObjects';
|
theMap['operation'] = 'doAddObjects';
|
||||||
|
if (me.oWizardHelper == null)
|
||||||
|
{
|
||||||
|
theMap['json'] = '';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not inside a "search form", updating a real object
|
||||||
|
me.oWizardHelper.UpdateWizard();
|
||||||
|
theMap['json'] = me.oWizardHelper.ToJSON();
|
||||||
|
}
|
||||||
$('#busy_'+me.iInputId).html(' <img src="../images/indicator.gif"/>');
|
$('#busy_'+me.iInputId).html(' <img src="../images/indicator.gif"/>');
|
||||||
// Run the query and display the results
|
// Run the query and display the results
|
||||||
$.post( GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', theMap,
|
$.post( GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', theMap,
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
|
$('#attachment_'+att_id).attr('name', 'removed_attachments[]');
|
||||||
$('#display_attachment_'+att_id).hide();
|
$('#display_attachment_'+att_id).hide();
|
||||||
|
$('#attachment_plugin').trigger('remove_attachment', [att_id]);
|
||||||
return false; // Do not submit the form !
|
return false; // Do not submit the form !
|
||||||
}
|
}
|
||||||
function ajaxFileUpload()
|
function ajaxFileUpload()
|
||||||
@@ -433,6 +434,8 @@ EOF
|
|||||||
{
|
{
|
||||||
$('#display_attachment_'+data.att_id).hover( function() { $(this).children(':button').toggleClass('btn_hidden'); } );
|
$('#display_attachment_'+data.att_id).hover( function() { $(this).children(':button').toggleClass('btn_hidden'); } );
|
||||||
}
|
}
|
||||||
|
$('#attachment_plugin').trigger('add_attachment', [data.att_id, data.msg]);
|
||||||
|
|
||||||
//alert(data.msg);
|
//alert(data.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -465,6 +468,7 @@ EOF
|
|||||||
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
$oPage->p(Dict::S('Attachments:AddAttachment').'<input type="file" name="file" id="file" onChange="ajaxFileUpload();"><span style="display:none;" id="attachment_loading"> <img src="../images/indicator.gif"></span> '.$sMaxUpload);
|
||||||
//$oPage->p('<input type="button" onClick="ajaxFileUpload();" value=" Upload !">');
|
//$oPage->p('<input type="button" onClick="ajaxFileUpload();" value=" Upload !">');
|
||||||
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
|
$oPage->p('<span style="display:none;" id="attachment_loading">Loading, please wait...</span>');
|
||||||
|
$oPage->p('<input type="hidden" id="attachment_plugin"/>');
|
||||||
$oPage->add('</fieldset>');
|
$oPage->add('</fieldset>');
|
||||||
if ($this->m_bDeleteEnabled)
|
if ($this->m_bDeleteEnabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,24 +63,4 @@ class ItopWelcome extends ModuleHandlerAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Direct end-users to the standard Portal application
|
|
||||||
*/
|
|
||||||
class MyPortalURLMaker implements iDBObjectURLMaker
|
|
||||||
{
|
|
||||||
public static function MakeObjectURL($sClass, $iId)
|
|
||||||
{
|
|
||||||
switch($sClass)
|
|
||||||
{
|
|
||||||
case 'UserRequest':
|
|
||||||
$sAbsoluteUrl = utils::GetAbsoluteUrlAppRoot();
|
|
||||||
$sUrl = "{$sAbsoluteUrl}portal/index.php?operation=details&class=$sClass&id=$iId";
|
|
||||||
return $sUrl;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
15
pages/UI.php
15
pages/UI.php
@@ -393,6 +393,7 @@ function ApplyNextAction(Webpage $oP, CMDBObject $oObj, $sNextAction, $oMyChange
|
|||||||
}
|
}
|
||||||
$oObj->DBUpdateTracked($oMyChange);
|
$oObj->DBUpdateTracked($oMyChange);
|
||||||
}
|
}
|
||||||
|
$oObj->Reload();
|
||||||
$oObj->DisplayDetails($oP);
|
$oObj->DisplayDetails($oP);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -842,7 +843,7 @@ try
|
|||||||
$currValue = $oObj->Get($sAttCode);
|
$currValue = $oObj->Get($sAttCode);
|
||||||
if ($oAttDef instanceof AttributeCaseLog)
|
if ($oAttDef instanceof AttributeCaseLog)
|
||||||
{
|
{
|
||||||
$currValue = '';
|
$currValue = ' '; // Don't put an empty string, in case the field would be considered as mandatory...
|
||||||
}
|
}
|
||||||
if (is_object($currValue)) continue; // Skip non scalar values...
|
if (is_object($currValue)) continue; // Skip non scalar values...
|
||||||
if(!array_key_exists($currValue, $aValues[$sAttCode]))
|
if(!array_key_exists($currValue, $aValues[$sAttCode]))
|
||||||
@@ -935,6 +936,7 @@ try
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sTip .= "</ul></p>";
|
$sTip .= "</ul></p>";
|
||||||
|
$sTip = addslashes($sTip);
|
||||||
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
|
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
|
||||||
|
|
||||||
$oDummyObj->Set($sAttCode, null);
|
$oDummyObj->Set($sAttCode, null);
|
||||||
@@ -1578,12 +1580,7 @@ EOF
|
|||||||
{
|
{
|
||||||
$sDisplayValue = empty($aVal['display']) ? '<i>'.Dict::S('Enum:Undefined').'</i>' : str_replace(array("\n", "\r"), " ", $aVal['display']);
|
$sDisplayValue = empty($aVal['display']) ? '<i>'.Dict::S('Enum:Undefined').'</i>' : str_replace(array("\n", "\r"), " ", $aVal['display']);
|
||||||
$sTip .= "<li>".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])."</li>";
|
$sTip .= "<li>".Dict::Format('UI:BulkModify:Value_Exists_N_Times', $sDisplayValue, $aVal['count'])."</li>";
|
||||||
$index++;
|
$index++;
|
||||||
if ($iMaxCount == $index)
|
|
||||||
{
|
|
||||||
$sTip .= "<li>".(count($aMultiValues) - $iMaxCount)." more different values...</li>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ($iMaxCount == $index)
|
if ($iMaxCount == $index)
|
||||||
{
|
{
|
||||||
$sTip .= "<li>".Dict::Format('UI:BulkModify:N_MoreValues', count($aValues[$sAttCode]) - $iMaxCount)."</li>";
|
$sTip .= "<li>".Dict::Format('UI:BulkModify:N_MoreValues', count($aValues[$sAttCode]) - $iMaxCount)."</li>";
|
||||||
@@ -1591,6 +1588,7 @@ EOF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$sTip .= "</ul></p>";
|
$sTip .= "</ul></p>";
|
||||||
|
$sTip = addslashes($sTip);
|
||||||
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );\n";
|
$sReadyScript .= "$('#multi_values_$sAttCode').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );\n";
|
||||||
$sComments .= '<div class="multi_values" id="multi_values_'.$sAttCode.'">'.count($aValues[$sAttCode]).'</div>';
|
$sComments .= '<div class="multi_values" id="multi_values_'.$sAttCode.'">'.count($aValues[$sAttCode]).'</div>';
|
||||||
}
|
}
|
||||||
@@ -2011,6 +2009,7 @@ EOF
|
|||||||
$oP->p(implode('</p><p>', $aErrors));
|
$oP->p(implode('</p><p>', $aErrors));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$oObj->Reload();
|
||||||
$oObj->DisplayDetails($oP);
|
$oObj->DisplayDetails($oP);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2070,8 +2069,6 @@ EOF
|
|||||||
$('#impacted_objects').empty();
|
$('#impacted_objects').empty();
|
||||||
$('#impacted_objects').append(data);
|
$('#impacted_objects').append(data);
|
||||||
$('#impacted_objects').unblock();
|
$('#impacted_objects').unblock();
|
||||||
$('#impacted_objects .listResults').tablesorter( { widgets: ['myZebra', 'truncatedList']} ); // sortable and zebra tables
|
|
||||||
$('#impacted_objects table.listResults').tableHover(); // hover tables
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,6 +297,9 @@ try
|
|||||||
$sSuffix = utils::ReadParam('sSuffix', '');
|
$sSuffix = utils::ReadParam('sSuffix', '');
|
||||||
$sRemoteClass = utils::ReadParam('sRemoteClass', $sClass, false, 'class');
|
$sRemoteClass = utils::ReadParam('sRemoteClass', $sClass, false, 'class');
|
||||||
$bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true;
|
$bDuplicates = (utils::ReadParam('bDuplicates', 'false') == 'false') ? false : true;
|
||||||
|
$sJson = utils::ReadParam('json', '', false, 'raw_data');
|
||||||
|
$oWizardHelper = WizardHelper::FromJSON($sJson);
|
||||||
|
$oObj = $oWizardHelper->GetTargetObject();
|
||||||
$oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates);
|
$oWidget = new UILinksWidget($sClass, $sAttCode, $iInputId, $sSuffix, $bDuplicates);
|
||||||
if ($sFilter != '')
|
if ($sFilter != '')
|
||||||
{
|
{
|
||||||
@@ -306,7 +309,7 @@ try
|
|||||||
{
|
{
|
||||||
$oFullSetFilter = new DBObjectSearch($sRemoteClass);
|
$oFullSetFilter = new DBObjectSearch($sRemoteClass);
|
||||||
}
|
}
|
||||||
$oWidget->DoAddObjects($oPage, $oFullSetFilter);
|
$oWidget->DoAddObjects($oPage, $oFullSetFilter, $oObj);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'wizard_helper_preview':
|
case 'wizard_helper_preview':
|
||||||
|
|||||||
105
pages/audit.php
105
pages/audit.php
@@ -177,52 +177,77 @@ try
|
|||||||
$oP->add("</tr>\n");
|
$oP->add("</tr>\n");
|
||||||
while($oAuditCategory = $oCategoriesSet->fetch())
|
while($oAuditCategory = $oCategoriesSet->fetch())
|
||||||
{
|
{
|
||||||
$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
|
try
|
||||||
FilterByContext($oDefinitionFilter, $oAppContext);
|
|
||||||
|
|
||||||
$aObjectsWithErrors = array();
|
|
||||||
if (!empty($currentOrganization))
|
|
||||||
{
|
{
|
||||||
if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id'))
|
$oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set'));
|
||||||
|
FilterByContext($oDefinitionFilter, $oAppContext);
|
||||||
|
|
||||||
|
$aObjectsWithErrors = array();
|
||||||
|
if (!empty($currentOrganization))
|
||||||
{
|
{
|
||||||
$oDefinitionFilter->AddCondition('org_id', $currentOrganization, '=');
|
if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id'))
|
||||||
|
{
|
||||||
|
$oDefinitionFilter->AddCondition('org_id', $currentOrganization, '=');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aResults = array();
|
||||||
|
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
|
||||||
|
$iCount = $oDefinitionSet->Count();
|
||||||
|
$oRulesFilter = new CMDBSearchFilter('AuditRule');
|
||||||
|
$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey(), '=');
|
||||||
|
$oRulesSet = new DBObjectSet($oRulesFilter);
|
||||||
|
while($oAuditRule = $oRulesSet->fetch() )
|
||||||
|
{
|
||||||
|
$aRow = array();
|
||||||
|
$aRow['description'] = $oAuditRule->GetName();
|
||||||
|
if ($iCount == 0)
|
||||||
|
{
|
||||||
|
// nothing to check, really !
|
||||||
|
$aRow['nb_errors'] = "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."\">0</a>";
|
||||||
|
$aRow['percent_ok'] = '100.00';
|
||||||
|
$aRow['class'] = GetReportColor($iCount, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$oRuleFilter = DBObjectSearch::FromOQL($oAuditRule->Get('query'));
|
||||||
|
$oErrorObjectSet = GetRuleResultSet($oAuditRule->GetKey(), $oDefinitionFilter, $oAppContext);
|
||||||
|
$iErrorsCount = $oErrorObjectSet->Count();
|
||||||
|
while($oObj = $oErrorObjectSet->Fetch())
|
||||||
|
{
|
||||||
|
$aObjectsWithErrors[$oObj->GetKey()] = true;
|
||||||
|
}
|
||||||
|
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\">$iErrorsCount</a>";
|
||||||
|
$aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount));
|
||||||
|
$aRow['class'] = GetReportColor($iCount, $iErrorsCount);
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
$aRow['nb_errors'] = "OQL Error";
|
||||||
|
$aRow['percent_ok'] = 'n/a';
|
||||||
|
$aRow['class'] = 'red';
|
||||||
|
$sMessage = Dict::Format('UI:Audit:ErrorIn_Rule_Reason', $oAuditRule->GetHyperlink(), $e->getMessage());
|
||||||
|
$oP->p("<img style=\"vertical-align:middle\" src=\"../images/stop-mid.png\"/> ".$sMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aResults[] = $aRow;
|
||||||
|
$iTotalErrors = count($aObjectsWithErrors);
|
||||||
|
$sOverallPercentOk = ($iCount == 0) ? '100.00' : sprintf('%.2f', 100.0 * (($iCount - $iTotalErrors) / $iCount));
|
||||||
|
$sClass = GetReportColor($iCount, $iTotalErrors);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$aResults = array();
|
catch(Exception $e)
|
||||||
$oDefinitionSet = new CMDBObjectSet($oDefinitionFilter);
|
|
||||||
$iCount = $oDefinitionSet->Count();
|
|
||||||
$oRulesFilter = new CMDBSearchFilter('AuditRule');
|
|
||||||
$oRulesFilter->AddCondition('category_id', $oAuditCategory->GetKey(), '=');
|
|
||||||
$oRulesSet = new DBObjectSet($oRulesFilter);
|
|
||||||
while($oAuditRule = $oRulesSet->fetch() )
|
|
||||||
{
|
{
|
||||||
$aRow = array();
|
$aRow = array();
|
||||||
$aRow['description'] = $oAuditRule->GetName();
|
$aRow['description'] = "OQL error";
|
||||||
if ($iCount == 0)
|
$aRow['nb_errors'] = "n/a";
|
||||||
{
|
$aRow['percent_ok'] = '';
|
||||||
// nothing to check, really !
|
$aRow['class'] = 'red';
|
||||||
$aRow['nb_errors'] = "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."\">0</a>";
|
$sMessage = Dict::Format('UI:Audit:ErrorIn_Category_Reason', $oAuditCategory->GetHyperlink(), $e->getMessage());
|
||||||
$aRow['percent_ok'] = '100.00';
|
$oP->p("<img style=\"vertical-align:middle\" src=\"../images/stop-mid.png\"/> ".$sMessage);
|
||||||
$aRow['class'] = GetReportColor($iCount, 0);
|
$aResults[] = $aRow;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$oRuleFilter = DBObjectSearch::FromOQL($oAuditRule->Get('query'));
|
|
||||||
$oErrorObjectSet = GetRuleResultSet($oAuditRule->GetKey(), $oDefinitionFilter, $oAppContext);
|
|
||||||
$iErrorsCount = $oErrorObjectSet->Count();
|
|
||||||
while($oObj = $oErrorObjectSet->Fetch())
|
|
||||||
{
|
|
||||||
$aObjectsWithErrors[$oObj->GetKey()] = true;
|
|
||||||
}
|
|
||||||
$aRow['nb_errors'] = ($iErrorsCount == 0) ? '0' : "<a href=\"?operation=errors&category=".$oAuditCategory->GetKey()."&rule=".$oAuditRule->GetKey()."&".$oAppContext->GetForLink()."\">$iErrorsCount</a>";
|
|
||||||
$aRow['percent_ok'] = sprintf('%.2f', 100.0 * (($iCount - $iErrorsCount) / $iCount));
|
|
||||||
$aRow['class'] = GetReportColor($iCount, $iErrorsCount);
|
|
||||||
}
|
|
||||||
$aResults[] = $aRow;
|
|
||||||
$iTotalErrors = count($aObjectsWithErrors);
|
|
||||||
$sOverallPercentOk = ($iCount == 0) ? '100.00' : sprintf('%.2f', 100.0 * (($iCount - $iTotalErrors) / $iCount));
|
|
||||||
$sClass = GetReportColor($iCount, $iTotalErrors);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
$oP->add("<tr>\n");
|
$oP->add("<tr>\n");
|
||||||
$oP->add("<th><img src=\"../images/minus.gif\"></th><th class=\"alignLeft\">".$oAuditCategory->GetName()."</th><th class=\"alignRight\">$iCount</th><th class=\"alignRight\">$iTotalErrors</th><th class=\"alignRight $sClass\">$sOverallPercentOk %</th>\n");
|
$oP->add("<th><img src=\"../images/minus.gif\"></th><th class=\"alignLeft\">".$oAuditCategory->GetName()."</th><th class=\"alignRight\">$iCount</th><th class=\"alignRight\">$iTotalErrors</th><th class=\"alignRight $sClass\">$sOverallPercentOk %</th>\n");
|
||||||
|
|||||||
1120
portal/index.php
1120
portal/index.php
File diff suppressed because it is too large
Load Diff
@@ -7,98 +7,72 @@ html, body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
#content {
|
#content {
|
||||||
margin: auto;
|
margin: 10px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
no.max-width: 90%;
|
|
||||||
min-width: 960px;
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
display: block;
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
div#portal #welcome {
|
|
||||||
display: none;
|
|
||||||
background: url("./images/dockbar_bg.png") repeat-x scroll 0 0 #97A1AE;
|
|
||||||
border-bottom: 1px solid #636364;
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 1px 5px;
|
|
||||||
position: relative;
|
|
||||||
z-index: 300;
|
|
||||||
text-align:right;
|
|
||||||
color: #2C2F34;
|
|
||||||
font-weight: bold;
|
|
||||||
text-shadow: 1px 1px #FFFFFF;
|
|
||||||
}
|
}
|
||||||
div#portal #banner {
|
div#portal #banner {
|
||||||
background-color: #F6F6F1;
|
|
||||||
display: block;
|
|
||||||
height: 60px;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
height: 60px;
|
||||||
div#portal #logo {
|
display: block;
|
||||||
background: url("../images/itop-logo.png") no-repeat scroll 0 0 transparent;
|
vertical-align:middle;
|
||||||
border: 0 none;
|
background-color: #f6f6f1;
|
||||||
display: inline-block;
|
|
||||||
height: 116px;
|
|
||||||
line-height: 48px;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-right: 20px;
|
|
||||||
padding-right: 50px;
|
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
width: 240px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#portal #logo {
|
||||||
|
width: 126px;
|
||||||
|
background: url(../images/itop-logo.png) 0 0 no-repeat;
|
||||||
|
margin-left:20px;
|
||||||
|
margin-right:20px;
|
||||||
|
height: 60px;
|
||||||
|
border: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 48px;
|
||||||
|
padding-right:50px;
|
||||||
|
}
|
||||||
div#menu {
|
div#menu {
|
||||||
display: block;
|
display: block;
|
||||||
height: 48px;
|
|
||||||
left: 200px;
|
|
||||||
line-height: 48px;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
width: auto;
|
width: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 200px;
|
||||||
|
right: 0px;
|
||||||
|
line-height: 48px;
|
||||||
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#portal_menu {
|
#portal_menu {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#change_pwd {
|
|
||||||
background: url("../images/password.png") no-repeat scroll 0 0 transparent;
|
|
||||||
display: block;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#logoff {
|
|
||||||
background: url("../images/logoff.png") no-repeat scroll 0 0 transparent;
|
|
||||||
display: block;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
#logoff span {
|
|
||||||
}
|
|
||||||
|
|
||||||
div.button {
|
div.button {
|
||||||
font-size: 1.1em;
|
margin-left:20px;
|
||||||
font-weight: bold;
|
margin-right:20px;
|
||||||
text-decoration: none;
|
height: 60px;
|
||||||
}
|
border: 0;
|
||||||
a.button, a.button:visited {
|
vertical-align: middle;
|
||||||
color: #1C94C4;
|
text-align: center;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 48px;
|
|
||||||
line-height: 48px;
|
line-height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button , a.button:visited {
|
||||||
|
color: #1C94C4;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
height: 48px;
|
||||||
|
line-height: 48px;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.button span {
|
a.button span {
|
||||||
margin-left: 50px;
|
vertical-align:middle;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
vertical-align: middle;
|
margin-left: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#close_form_table {
|
#close_form_table {
|
||||||
@@ -106,117 +80,66 @@ a.button span {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#request_details td {
|
#logoff {
|
||||||
text-align:left;
|
display: block;
|
||||||
|
float: right;
|
||||||
|
background: url(../images/logoff.png) right center no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
#request_details td fieldset{
|
#logoff span {
|
||||||
xxxheight:100%;
|
margin-right: 50px;
|
||||||
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#cancel {
|
||||||
|
background: url(../images/stop-mid.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#create {
|
||||||
|
background: url(../modules/itop-request-mgmt-1.0.0/images/user-request.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
#user_info {
|
||||||
|
background: url(../images/clean-mid.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
#change_pwd {
|
||||||
|
background: url(../images/password.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
#back {
|
||||||
|
background: url(../images/back.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
#back span {
|
||||||
|
margin-left: 54px;
|
||||||
|
}
|
||||||
|
#refresh {
|
||||||
|
background: url(../images/refresh.png) 0 0 no-repeat;
|
||||||
|
margin-right: 40px;
|
||||||
|
}
|
||||||
|
#refresh span {
|
||||||
|
margin-left: 54px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
#request_details {
|
||||||
|
display: inline-block;
|
||||||
|
width:800px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
#form_close_request {
|
||||||
|
display: inline-block;
|
||||||
|
width:800px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
#request_details_log {
|
||||||
|
width:774px;
|
||||||
|
}
|
||||||
|
#request_details table {
|
||||||
|
border: #f1f1f6 2px solid;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
#form_details {
|
#form_details {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizContainer table {
|
.wizContainer table {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#user_request_comment {
|
|
||||||
width: 30em;
|
|
||||||
height: 20em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#buttons {
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
div#buttons #btn_cancel {
|
|
||||||
margin-right: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#buttons #btn_back {
|
|
||||||
margin-left: 50px;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#buttons #btn_next {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#buttons #btn_finish {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
table.listContainer {
|
|
||||||
clear: both;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-weight: bold;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 5px;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.DrawerHandle {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
div.HRDrawer {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
height: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.SearchDrawer {
|
|
||||||
background-color: #F9EDBF;
|
|
||||||
border: 0;
|
|
||||||
-moz-border-radius: 4px 4px 4px 4px;
|
|
||||||
}
|
|
||||||
.SearchDrawer label {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
#open_incidents, #open_requests, #open_changes, #request_details {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
legend {
|
|
||||||
background: url("./images/header_bg.png") repeat-x scroll 0 0 #D4D4D4;
|
|
||||||
border-color: #C8C9CA #9E9E9E #9E9E9E #C8C9CA;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #222222;
|
|
||||||
font-weight: bold;
|
|
||||||
text-shadow: 1px 1px #FFFFFF;
|
|
||||||
padding: 5px;
|
|
||||||
-moz-border-radius: 4px 4px 4px 4px;
|
|
||||||
margin-top:0;
|
|
||||||
}
|
|
||||||
table.details > tbody > tr > td {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
padding-top: 3px;
|
|
||||||
padding-right: 5px;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
.label {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.caselog {
|
|
||||||
display:block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.caselog textarea {
|
|
||||||
resize: none;
|
|
||||||
}
|
|
||||||
.edit_item {
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
div.edit_item span div table {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
div.edit_item span div table tbody tr td textarea{
|
|
||||||
width: 99%;
|
|
||||||
}
|
|
||||||
div#ticket_shortcuts form {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
@@ -37,7 +37,7 @@ define('FINAL_CONFIG_FILE', APPROOT.'/config-itop.php');
|
|||||||
define('PHP_MIN_VERSION', '5.2.0');
|
define('PHP_MIN_VERSION', '5.2.0');
|
||||||
define('MYSQL_MIN_VERSION', '5.0.0');
|
define('MYSQL_MIN_VERSION', '5.0.0');
|
||||||
define('MIN_MEMORY_LIMIT', 32*1024*1024);
|
define('MIN_MEMORY_LIMIT', 32*1024*1024);
|
||||||
define('SUHOSIN_GET_MAX_VALUE_LENGTH', 1024);
|
define('SUHOSIN_GET_MAX_VALUE_LENGTH', 2048);
|
||||||
|
|
||||||
$sOperation = Utils::ReadParam('operation', 'step0');
|
$sOperation = Utils::ReadParam('operation', 'step0');
|
||||||
$oP = new SetupWebPage('iTop configuration wizard');
|
$oP = new SetupWebPage('iTop configuration wizard');
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ try
|
|||||||
{
|
{
|
||||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql'));
|
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql'));
|
||||||
}
|
}
|
||||||
|
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||||
|
$oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu'=>false));
|
||||||
|
$oBlock1->Display($oP, 0);
|
||||||
$oP->add('<p class="page-header">'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'</p>');
|
$oP->add('<p class="page-header">'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'</p>');
|
||||||
$iSourceId = utils::ReadParam('datasource', null);
|
$iSourceId = utils::ReadParam('datasource', null);
|
||||||
if ($iSourceId != null)
|
if ($iSourceId != null)
|
||||||
@@ -60,7 +63,6 @@ try
|
|||||||
$oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId);
|
$oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId);
|
||||||
$oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>');
|
$oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>');
|
||||||
}
|
}
|
||||||
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
|
||||||
$oBlock = new DisplayBlock($oFilter, 'list', false, array('menu'=>false));
|
$oBlock = new DisplayBlock($oFilter, 'list', false, array('menu'=>false));
|
||||||
$oBlock->Display($oP, 1);
|
$oBlock->Display($oP, 1);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -166,12 +166,12 @@ foreach(explode(',', $sDataSourcesList) as $iSDS)
|
|||||||
$oP->p("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors'));
|
$oP->p("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors'));
|
||||||
$oP->p("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted'));
|
$oP->p("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted'));
|
||||||
$oP->p("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors'));
|
$oP->p("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors'));
|
||||||
$oP->p("Objects created: ".$oStatLog->Get('stats_nb_obj_created'));
|
$oP->p("Objects created: ".$oStatLog->Get('stats_nb_obj_created')." (".$oStatLog->Get('stats_nb_obj_created_warnings')." warnings)");
|
||||||
$oP->p("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors'));
|
$oP->p("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors'));
|
||||||
$oP->p("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated'));
|
$oP->p("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')." (".$oStatLog->Get('stats_nb_obj_updated_warnings')." warnings)");
|
||||||
$oP->p("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors'));
|
$oP->p("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors'));
|
||||||
$oP->p("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated'));
|
$oP->p("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)");
|
||||||
$oP->p("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged'));
|
$oP->p("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)");
|
||||||
$oP->p("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors'));
|
$oP->p("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors'));
|
||||||
$oP->p("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action'));
|
$oP->p("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -633,12 +633,12 @@ try
|
|||||||
$oP->add_comment("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors'));
|
$oP->add_comment("Objects deletion errors: ".$oStatLog->Get('stats_nb_obj_deleted_errors'));
|
||||||
$oP->add_comment("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted'));
|
$oP->add_comment("Objects obsoleted: ".$oStatLog->Get('stats_nb_obj_obsoleted'));
|
||||||
$oP->add_comment("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors'));
|
$oP->add_comment("Objects obsolescence errors: ".$oStatLog->Get('stats_nb_obj_obsoleted_errors'));
|
||||||
$oP->add_comment("Objects created: ".$oStatLog->Get('stats_nb_obj_created'));
|
$oP->add_comment("Objects created: ".$oStatLog->Get('stats_nb_obj_created')." (".$oStatLog->Get('stats_nb_obj_created_warnings')." warnings)");
|
||||||
$oP->add_comment("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors'));
|
$oP->add_comment("Objects creation errors: ".$oStatLog->Get('stats_nb_obj_created_errors'));
|
||||||
$oP->add_comment("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated'));
|
$oP->add_comment("Objects updated: ".$oStatLog->Get('stats_nb_obj_updated')." (".$oStatLog->Get('stats_nb_obj_updated_warnings')." warnings)");
|
||||||
$oP->add_comment("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors'));
|
$oP->add_comment("Objects update errors: ".$oStatLog->Get('stats_nb_obj_updated_errors'));
|
||||||
$oP->add_comment("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated'));
|
$oP->add_comment("Objects reconciled (updated): ".$oStatLog->Get('stats_nb_obj_new_updated')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)");
|
||||||
$oP->add_comment("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged'));
|
$oP->add_comment("Objects reconciled (unchanged): ".$oStatLog->Get('stats_nb_obj_new_unchanged')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)");
|
||||||
$oP->add_comment("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors'));
|
$oP->add_comment("Objects reconciliation errors: ".$oStatLog->Get('stats_nb_replica_reconciled_errors'));
|
||||||
$oP->add_comment("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action'));
|
$oP->add_comment("Replica disappeared, no action taken: ".$oStatLog->Get('stats_nb_replica_disappeared_no_action'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,19 @@ class SynchroDataSource extends cmdbAbstractObject
|
|||||||
$sEndDate = $oLastLog->Get('end_date');
|
$sEndDate = $oLastLog->Get('end_date');
|
||||||
$iLastLog = $oLastLog->GetKey();
|
$iLastLog = $oLastLog->GetKey();
|
||||||
$oPage->p('<h2>'.Dict::Format('Core:Synchro:SynchroEndedOn_Date', $sEndDate).'</h2>');
|
$oPage->p('<h2>'.Dict::Format('Core:Synchro:SynchroEndedOn_Date', $sEndDate).'</h2>');
|
||||||
|
$sOQL = "SELECT SynchroReplica WHERE sync_source_id=$iDSid";
|
||||||
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
|
||||||
|
$iCountAllReplicas = $oSet->Count();
|
||||||
|
$sAllReplicas = "<a href=\"../synchro/replica.php?operation=oql&datasource=$iDSid&oql=$sOQL\">$iCountAllReplicas</a>";
|
||||||
|
$sOQL = "SELECT SynchroReplica WHERE sync_source_id=$iDSid AND status_last_error !=''";
|
||||||
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
|
||||||
|
$iCountAllErrors = $oSet->Count();
|
||||||
|
$sAllErrors = "<a href=\"../synchro/replica.php?operation=oql&datasource=$iDSid&oql=$sOQL\">$iCountAllErrors</a>";
|
||||||
|
$sOQL = "SELECT SynchroReplica WHERE sync_source_id=$iDSid AND status_last_warning !=''";
|
||||||
|
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
|
||||||
|
$iCountAllWarnings = $oSet->Count();
|
||||||
|
$sAllWarnings = "<a href=\"../synchro/replica.php?operation=oql&datasource=$iDSid&oql=$sOQL\">$iCountAllWarnings</a>";
|
||||||
|
$oPage->p('<h2>'.Dict::Format('Core:Synchro:ListReplicas_AllReplicas_Errors_Warnings', $sAllReplicas, $sAllErrors, $sAllWarnings).'</h2>');
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPage->add('<table class="synoptics"><tr><td style="color:#333;vertical-align:top">');
|
$oPage->add('<table class="synoptics"><tr><td style="color:#333;vertical-align:top">');
|
||||||
@@ -273,6 +286,18 @@ class SynchroDataSource extends cmdbAbstractObject
|
|||||||
$sScript .= "};\n";
|
$sScript .= "};\n";
|
||||||
$sScript .= <<<EOF
|
$sScript .= <<<EOF
|
||||||
var sLastLog = '$iLastLog';
|
var sLastLog = '$iLastLog';
|
||||||
|
function ToggleSynoptics(sId, bShow)
|
||||||
|
{
|
||||||
|
if (bShow)
|
||||||
|
{
|
||||||
|
$(sId).show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$(sId).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function UpdateSynoptics(id)
|
function UpdateSynoptics(id)
|
||||||
{
|
{
|
||||||
var aValues = aSynchroLog[id];
|
var aValues = aSynchroLog[id];
|
||||||
@@ -310,6 +335,12 @@ class SynchroDataSource extends cmdbAbstractObject
|
|||||||
{
|
{
|
||||||
$('#disappeared_errors_link').hide();
|
$('#disappeared_errors_link').hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToggleSynoptics('#cw_obj_created_warnings', aValues['obj_created_warnings'] > 0);
|
||||||
|
ToggleSynoptics('#cw_obj_new_updated_warnings', aValues['obj_new_updated_warnings'] > 0);
|
||||||
|
ToggleSynoptics('#cw_obj_new_unchanged_warnings', aValues['obj_new_unchanged_warnings'] > 0);
|
||||||
|
ToggleSynoptics('#cw_obj_updated_warnings', aValues['obj_updated_warnings'] > 0);
|
||||||
|
ToggleSynoptics('#cw_obj_unchanged_warnings', aValues['obj_unchanged_warnings'] > 0);
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
;
|
;
|
||||||
@@ -375,6 +406,10 @@ EOF
|
|||||||
$sCount = "<span id=\"c_{$sId}\">$iCount</span>";
|
$sCount = "<span id=\"c_{$sId}\">$iCount</span>";
|
||||||
$sLabel = Dict::Format('Core:Synchro:label_'.$sId, $sCount);
|
$sLabel = Dict::Format('Core:Synchro:label_'.$sId, $sCount);
|
||||||
$sOpacity = ($iCount==0) ? "opacity:0.3;" : "";
|
$sOpacity = ($iCount==0) ? "opacity:0.3;" : "";
|
||||||
|
if (isset($aData[$sId.'_warnings']))
|
||||||
|
{
|
||||||
|
$sLabel .= " <span id=\"cw_{$sId}_warnings\"><img src=\"../images/error.png\" style=\"vertical-align:middle\"/> (<span id=\"c_{$sId}_warnings\">".$aData[$sId.'_warnings']."</span>)</span>";
|
||||||
|
}
|
||||||
|
|
||||||
return "<td id=\"$sId\" style=\"background-color:$sColor;$sOpacity;\" {$sHTMLAttribs}>{$sLabel}{$sErrorLink}</td>";
|
return "<td id=\"$sId\" style=\"background-color:$sColor;$sOpacity;\" {$sHTMLAttribs}>{$sLabel}{$sErrorLink}</td>";
|
||||||
}
|
}
|
||||||
@@ -387,11 +422,15 @@ EOF
|
|||||||
'obj_disappeared_errors' => $oLastLog->Get('stats_nb_obj_obsoleted_errors') + $oLastLog->Get('stats_nb_obj_deleted_errors'),
|
'obj_disappeared_errors' => $oLastLog->Get('stats_nb_obj_obsoleted_errors') + $oLastLog->Get('stats_nb_obj_deleted_errors'),
|
||||||
'obj_disappeared_no_action' => $oLastLog->Get('stats_nb_replica_disappeared_no_action'),
|
'obj_disappeared_no_action' => $oLastLog->Get('stats_nb_replica_disappeared_no_action'),
|
||||||
'obj_updated' => $oLastLog->Get('stats_nb_obj_updated'),
|
'obj_updated' => $oLastLog->Get('stats_nb_obj_updated'),
|
||||||
|
'obj_updated_warnings' => $oLastLog->Get('stats_nb_obj_updated_warnings'),
|
||||||
'obj_updated_errors' => $oLastLog->Get('stats_nb_obj_updated_errors'),
|
'obj_updated_errors' => $oLastLog->Get('stats_nb_obj_updated_errors'),
|
||||||
'obj_new_updated' => $oLastLog->Get('stats_nb_obj_new_updated'),
|
'obj_new_updated' => $oLastLog->Get('stats_nb_obj_new_updated'),
|
||||||
|
'obj_new_updated_warnings' => $oLastLog->Get('stats_nb_obj_new_updated_warnings'),
|
||||||
'obj_new_unchanged' => $oLastLog->Get('stats_nb_obj_new_unchanged'),
|
'obj_new_unchanged' => $oLastLog->Get('stats_nb_obj_new_unchanged'),
|
||||||
'obj_created' => $oLastLog->Get('stats_nb_obj_created'),
|
'obj_created' => $oLastLog->Get('stats_nb_obj_created'),
|
||||||
|
'obj_created_warnings' => $oLastLog->Get('stats_nb_obj_created_warnings'),
|
||||||
'obj_created_errors' => $oLastLog->Get('stats_nb_obj_created_errors'),
|
'obj_created_errors' => $oLastLog->Get('stats_nb_obj_created_errors'),
|
||||||
|
'obj_unchanged_warnings' => $oLastLog->Get('stats_nb_obj_unchanged_warnings'),
|
||||||
);
|
);
|
||||||
$iReconciledErrors = $oLastLog->Get('stats_nb_replica_reconciled_errors');
|
$iReconciledErrors = $oLastLog->Get('stats_nb_replica_reconciled_errors');
|
||||||
$iDisappeared = $aData['obj_disappeared_errors'] + $aData['obj_obsoleted'] + $aData['obj_deleted'] + $aData['obj_disappeared_no_action'];
|
$iDisappeared = $aData['obj_disappeared_errors'] + $aData['obj_obsoleted'] + $aData['obj_deleted'] + $aData['obj_disappeared_no_action'];
|
||||||
@@ -949,13 +988,18 @@ EOF
|
|||||||
$oStatLog->Set('stats_nb_obj_obsoleted_errors', 0);
|
$oStatLog->Set('stats_nb_obj_obsoleted_errors', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_created', 0);
|
$oStatLog->Set('stats_nb_obj_created', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_created_errors', 0);
|
$oStatLog->Set('stats_nb_obj_created_errors', 0);
|
||||||
|
$oStatLog->Set('stats_nb_obj_created_warnings', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_updated', 0);
|
$oStatLog->Set('stats_nb_obj_updated', 0);
|
||||||
|
$oStatLog->Set('stats_nb_obj_updated_warnings', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_updated_errors', 0);
|
$oStatLog->Set('stats_nb_obj_updated_errors', 0);
|
||||||
// $oStatLog->Set('stats_nb_replica_reconciled', 0);
|
$oStatLog->Set('stats_nb_obj_unchanged_warnings', 0);
|
||||||
|
// $oStatLog->Set('stats_nb_replica_reconciled', 0);
|
||||||
$oStatLog->Set('stats_nb_replica_reconciled_errors', 0);
|
$oStatLog->Set('stats_nb_replica_reconciled_errors', 0);
|
||||||
$oStatLog->Set('stats_nb_replica_disappeared_no_action', 0);
|
$oStatLog->Set('stats_nb_replica_disappeared_no_action', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_new_updated', 0);
|
$oStatLog->Set('stats_nb_obj_new_updated', 0);
|
||||||
|
$oStatLog->Set('stats_nb_obj_new_updated_warnings', 0);
|
||||||
$oStatLog->Set('stats_nb_obj_new_unchanged',0);
|
$oStatLog->Set('stats_nb_obj_new_unchanged',0);
|
||||||
|
$oStatLog->Set('stats_nb_obj_new_unchanged_warnings',0);
|
||||||
|
|
||||||
$sSelectTotal = "SELECT SynchroReplica WHERE sync_source_id = :source_id";
|
$sSelectTotal = "SELECT SynchroReplica WHERE sync_source_id = :source_id";
|
||||||
$oSetTotal = new DBObjectSet(DBObjectSearch::FromOQL($sSelectTotal), array() /* order by*/, array('source_id' => $this->GetKey()));
|
$oSetTotal = new DBObjectSet(DBObjectSearch::FromOQL($sSelectTotal), array() /* order by*/, array('source_id' => $this->GetKey()));
|
||||||
@@ -989,14 +1033,14 @@ EOF
|
|||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_deleted_errors').": ".$oStatLog->Get('stats_nb_obj_deleted_errors')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_deleted_errors').": ".$oStatLog->Get('stats_nb_obj_deleted_errors')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_obsoleted').": ".$oStatLog->Get('stats_nb_obj_obsoleted')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_obsoleted').": ".$oStatLog->Get('stats_nb_obj_obsoleted')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_obsoleted_errors').": ".$oStatLog->Get('stats_nb_obj_obsoleted_errors')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_obsoleted_errors').": ".$oStatLog->Get('stats_nb_obj_obsoleted_errors')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_created').": ".$oStatLog->Get('stats_nb_obj_created')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_created').": ".$oStatLog->Get('stats_nb_obj_created')." (".$oStatLog->Get('stats_nb_obj_created_warnings')." warnings)"."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_created_errors').": ".$oStatLog->Get('stats_nb_obj_created_errors')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_created_errors').": ".$oStatLog->Get('stats_nb_obj_created_errors')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_updated').": ".$oStatLog->Get('stats_nb_obj_updated')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_updated').": ".$oStatLog->Get('stats_nb_obj_updated')." (".$oStatLog->Get('stats_nb_obj_updated_warnings')." warnings)"."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_updated_errors').": ".$oStatLog->Get('stats_nb_obj_updated_errors')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_updated_errors').": ".$oStatLog->Get('stats_nb_obj_updated_errors')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_replica_reconciled_errors').": ".$oStatLog->Get('stats_nb_replica_reconciled_errors')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_replica_reconciled_errors').": ".$oStatLog->Get('stats_nb_replica_reconciled_errors')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_replica_disappeared_no_action').": ".$oStatLog->Get('stats_nb_replica_disappeared_no_action')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_replica_disappeared_no_action').": ".$oStatLog->Get('stats_nb_replica_disappeared_no_action')."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_new_updated').": ".$oStatLog->Get('stats_nb_obj_new_updated')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_new_updated').": ".$oStatLog->Get('stats_nb_obj_new_updated')." (".$oStatLog->Get('stats_nb_obj_new_updated_warnings')." warnings)"."</li>\n";
|
||||||
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_new_unchanged').": ".$oStatLog->Get('stats_nb_obj_new_unchanged')."</li>\n";
|
$sStatistics .= "<li>".$oStatLog->GetLabel('stats_nb_obj_new_unchanged').": ".$oStatLog->Get('stats_nb_obj_new_unchanged')." (".$oStatLog->Get('stats_nb_obj_new_unchanged_warnings')." warnings)"."</li>\n";
|
||||||
$sStatistics .= "</ul>\n";
|
$sStatistics .= "</ul>\n";
|
||||||
|
|
||||||
$this->SendNotification("errors ($iErrors)", "<p>The synchronization has been executed, $iErrors errors have been encountered. Click <a href=\"$sIssuesURL\">here</a> to see the records being currently in error.</p>".$sStatistics);
|
$this->SendNotification("errors ($iErrors)", "<p>The synchronization has been executed, $iErrors errors have been encountered. Click <a href=\"$sIssuesURL\">here</a> to see the records being currently in error.</p>".$sStatistics);
|
||||||
@@ -1180,10 +1224,10 @@ EOF
|
|||||||
$oSetSeen = new DBObjectSet(DBObjectSearch::FromOQL($sSelectSeen), array() /* order by*/, array('source_id' => $this->GetKey(), 'last_import' => $sLimitDate));
|
$oSetSeen = new DBObjectSet(DBObjectSearch::FromOQL($sSelectSeen), array() /* order by*/, array('source_id' => $this->GetKey(), 'last_import' => $sLimitDate));
|
||||||
$oStatLog->Set('stats_nb_replica_seen', $oSetSeen->Count());
|
$oStatLog->Set('stats_nb_replica_seen', $oSetSeen->Count());
|
||||||
|
|
||||||
// Get all the replicas that are 'new' or modified
|
// Get all the replicas that are 'new' or modified or synchronized with a warning
|
||||||
//
|
//
|
||||||
$sSelectToSync = "SELECT SynchroReplica WHERE (status = 'new' OR status = 'modified') AND sync_source_id = :source_id";
|
$sSelectToSync = "SELECT SynchroReplica WHERE (status = 'new' OR status = 'modified' OR (status = 'synchronized' AND status_last_warning != '')) AND sync_source_id = :source_id AND status_last_seen >= :last_import";
|
||||||
$oSetToSync = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToSync), array() /* order by*/, array('source_id' => $this->GetKey()) /* aArgs */, $aExtDataSpec, 0 /* limitCount */, 0 /* limitStart */);
|
$oSetToSync = new DBObjectSet(DBObjectSearch::FromOQL($sSelectToSync), array() /* order by*/, array('source_id' => $this->GetKey(), 'last_import' => $sLimitDate) /* aArgs */, $aExtDataSpec, 0 /* limitCount */, 0 /* limitStart */);
|
||||||
|
|
||||||
while($oReplica = $oSetToSync->Fetch())
|
while($oReplica = $oSetToSync->Fetch())
|
||||||
{
|
{
|
||||||
@@ -1484,15 +1528,20 @@ class SynchroLog extends DBObject
|
|||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_obsoleted_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_obsoleted_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_obsoleted_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_obsoleted_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_created_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_created_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated_errors", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
// MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_updated_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_updated_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_unchanged_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_unchanged_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
// MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled_errors", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_reconciled_errors", array("allowed_values"=>null, "sql"=>"stats_nb_replica_reconciled_errors", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_disappeared_no_action", array("allowed_values"=>null, "sql"=>"stats_nb_replica_disappeared_no_action", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_replica_disappeared_no_action", array("allowed_values"=>null, "sql"=>"stats_nb_replica_disappeared_no_action", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged_warnings", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged_warnings", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeText("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeText("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeLongText("traces", array("allowed_values"=>null, "sql"=>"traces", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeLongText("traces", array("allowed_values"=>null, "sql"=>"traces", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
@@ -1596,6 +1645,7 @@ class SynchroLog extends DBObject
|
|||||||
class SynchroReplica extends DBObject implements iDisplay
|
class SynchroReplica extends DBObject implements iDisplay
|
||||||
{
|
{
|
||||||
static $aSearches = array(); // Cache of OQL queries used for reconciliation (per data source)
|
static $aSearches = array(); // Cache of OQL queries used for reconciliation (per data source)
|
||||||
|
protected $aWarnings;
|
||||||
|
|
||||||
public static function Init()
|
public static function Init()
|
||||||
{
|
{
|
||||||
@@ -1624,7 +1674,8 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('new,synchronized,modified,orphan,obsolete'), "sql"=>"status", "default_value"=>"new", "is_null_allowed"=>false, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('new,synchronized,modified,orphan,obsolete'), "sql"=>"status", "default_value"=>"new", "is_null_allowed"=>false, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeBoolean("status_dest_creator", array("allowed_values"=>null, "sql"=>"status_dest_creator", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeBoolean("status_dest_creator", array("allowed_values"=>null, "sql"=>"status_dest_creator", "default_value"=>0, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeString("status_last_error", array("allowed_values"=>null, "sql"=>"status_last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeString("status_last_error", array("allowed_values"=>null, "sql"=>"status_last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
MetaModel::Init_AddAttribute(new AttributeString("status_last_warning", array("allowed_values"=>null, "sql"=>"status_last_warning", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
MetaModel::Init_AddAttribute(new AttributeDateTime("info_creation_date", array("allowed_values"=>null, "sql"=>"info_creation_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeDateTime("info_creation_date", array("allowed_values"=>null, "sql"=>"info_creation_date", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
MetaModel::Init_AddAttribute(new AttributeDateTime("info_last_modified", array("allowed_values"=>null, "sql"=>"info_last_modified", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
MetaModel::Init_AddAttribute(new AttributeDateTime("info_last_modified", array("allowed_values"=>null, "sql"=>"info_last_modified", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||||
|
|
||||||
@@ -1632,17 +1683,65 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
MetaModel::Init_SetZListItems('details', array('' .
|
MetaModel::Init_SetZListItems('details', array('' .
|
||||||
'col:0'=> array(
|
'col:0'=> array(
|
||||||
'fieldset:SynchroDataSource:Definition' => array('sync_source_id','dest_id','dest_class'),
|
'fieldset:SynchroDataSource:Definition' => array('sync_source_id','dest_id','dest_class'),
|
||||||
'fieldset:SynchroDataSource:Status' => array('status','status_last_seen','status_dest_creator','status_last_error'),
|
'fieldset:SynchroDataSource:Status' => array('status','status_last_seen','status_dest_creator','status_last_error','status_last_warning'),
|
||||||
'fieldset:SynchroDataSource:Information' => array('info_creation_date','info_last_modified'))
|
'fieldset:SynchroDataSource:Information' => array('info_creation_date','info_last_modified'))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
MetaModel::Init_SetZListItems('list', array('sync_source_id', 'dest_id', 'dest_class', 'status_last_seen', 'status', 'status_dest_creator', 'status_last_error')); // Attributes to be displayed for a list
|
MetaModel::Init_SetZListItems('list', array('sync_source_id', 'dest_id', 'dest_class', 'status_last_seen', 'status', 'status_dest_creator', 'status_last_error', 'status_last_warning')); // Attributes to be displayed for a list
|
||||||
// Search criteria
|
// Search criteria
|
||||||
MetaModel::Init_SetZListItems('standard_search', array('sync_source_id', 'status_last_seen', 'status', 'status_dest_creator', 'dest_class', 'dest_id', 'status_last_error')); // Criteria of the std search form
|
MetaModel::Init_SetZListItems('standard_search', array('sync_source_id', 'status_last_seen', 'status', 'status_dest_creator', 'dest_class', 'dest_id', 'status_last_error', 'status_last_warning')); // Criteria of the std search form
|
||||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function __construct($aRow = null, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
|
||||||
|
{
|
||||||
|
parent::__construct($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
|
||||||
|
$this->aWarnings = array();
|
||||||
|
}
|
||||||
|
|
||||||
public function DBInsert()
|
protected function AddWarning($sWarningMessage)
|
||||||
|
{
|
||||||
|
$this->aWarnings[] = $sWarningMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function ResetWarnings()
|
||||||
|
{
|
||||||
|
$this->aWarnings = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function HasWarnings()
|
||||||
|
{
|
||||||
|
return (count($this->aWarnings) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function RecordWarnings()
|
||||||
|
{
|
||||||
|
$sWarningMessage = '';
|
||||||
|
$MAX_WARNING_LENGTH = 255;
|
||||||
|
switch(count($this->aWarnings))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
$sWarningMessage = '';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
$sWarningMessage = $this->aWarnings[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$sWarningMessage = count($this->aWarnings)." warnings: ".implode(' ', $this->aWarnings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($sWarningMessage) > $MAX_WARNING_LENGTH)
|
||||||
|
{
|
||||||
|
$sWarningMessage = substr($sWarningMessage, 0, $MAX_WARNING_LENGTH - 3).'...';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Set('status_last_warning', $sWarningMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function DBInsert()
|
||||||
{
|
{
|
||||||
throw new CoreException('A synchronization replica must be created only by the mean of triggers');
|
throw new CoreException('A synchronization replica must be created only by the mean of triggers');
|
||||||
}
|
}
|
||||||
@@ -1688,6 +1787,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
|
|
||||||
public function Synchro($oDataSource, $aReconciliationKeys, $aAttributes, $oChange, &$oStatLog)
|
public function Synchro($oDataSource, $aReconciliationKeys, $aAttributes, $oChange, &$oStatLog)
|
||||||
{
|
{
|
||||||
|
$this->ResetWarnings();
|
||||||
switch($this->Get('status'))
|
switch($this->Get('status'))
|
||||||
{
|
{
|
||||||
case 'new':
|
case 'new':
|
||||||
@@ -1714,6 +1814,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TO DO: can we retry this ??
|
||||||
// Reconciliation could not be performed - log and EXIT
|
// Reconciliation could not be performed - log and EXIT
|
||||||
$oStatLog->AddTrace("Could not reconcile on null value for attribute '$sFilterCode'", $this);
|
$oStatLog->AddTrace("Could not reconcile on null value for attribute '$sFilterCode'", $this);
|
||||||
$this->SetLastError("Could not reconcile on null value for attribute '$sFilterCode'");
|
$this->SetLastError("Could not reconcile on null value for attribute '$sFilterCode'");
|
||||||
@@ -1736,7 +1837,19 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
$oStatLog->AddTrace("Nothing found on: $sConditionDesc", $this);
|
$oStatLog->AddTrace("Nothing found on: $sConditionDesc", $this);
|
||||||
if ($oDataSource->Get('action_on_zero') == 'create')
|
if ($oDataSource->Get('action_on_zero') == 'create')
|
||||||
{
|
{
|
||||||
$this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog);
|
$bCreated = $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog);
|
||||||
|
if ($bCreated)
|
||||||
|
{
|
||||||
|
if ($this->HasWarnings())
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_created_warnings');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Creation error has precedence over any warning
|
||||||
|
$this->ResetWarnings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else // assumed to be 'error'
|
else // assumed to be 'error'
|
||||||
{
|
{
|
||||||
@@ -1751,9 +1864,20 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
if ($oDataSource->Get('action_on_one') == 'update')
|
if ($oDataSource->Get('action_on_one') == 'update')
|
||||||
{
|
{
|
||||||
$oDestObj = $oDestSet->Fetch();
|
$oDestObj = $oDestSet->Fetch();
|
||||||
$this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors');
|
$bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors');
|
||||||
$this->Set('dest_id', $oDestObj->GetKey());
|
$this->Set('dest_id', $oDestObj->GetKey());
|
||||||
$this->Set('dest_class', get_class($oDestObj));
|
$this->Set('dest_class', get_class($oDestObj));
|
||||||
|
if ($this->HasWarnings())
|
||||||
|
{
|
||||||
|
if ($bModified)
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_new_updated_warnings');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_new_unchanged_warnings');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1774,21 +1898,46 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
elseif ($oDataSource->Get('action_on_multiple') == 'create')
|
elseif ($oDataSource->Get('action_on_multiple') == 'create')
|
||||||
{
|
{
|
||||||
$this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog);
|
$bCreated = $this->CreateObjectFromReplica($oDataSource->GetTargetClass(), $aAttributes, $oChange, $oStatLog);
|
||||||
|
if ($bCreated)
|
||||||
|
{
|
||||||
|
if ($this->HasWarnings())
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_created_warnings');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Creation error has precedence over any warning
|
||||||
|
$this->ResetWarnings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// assumed to be 'take_first'
|
// assumed to be 'take_first'
|
||||||
$oDestObj = $oDestSet->Fetch();
|
$oDestObj = $oDestSet->Fetch();
|
||||||
$this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors');
|
$bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj_new', 'stats_nb_replica_reconciled_errors');
|
||||||
$this->Set('dest_id', $oDestObj->GetKey());
|
$this->Set('dest_id', $oDestObj->GetKey());
|
||||||
$this->Set('dest_class', get_class($oDestObj));
|
$this->Set('dest_class', get_class($oDestObj));
|
||||||
|
if ($this->HasWarnings())
|
||||||
|
{
|
||||||
|
if ($bModified)
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_new_updated_warnings');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_new_unchanged_warnings');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->RecordWarnings();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'synchronized': // try to recover synchronized replicas with warnings
|
||||||
case 'modified':
|
case 'modified':
|
||||||
$oDestObj = MetaModel::GetObject($oDataSource->GetTargetClass(), $this->Get('dest_id'));
|
$oDestObj = MetaModel::GetObject($oDataSource->GetTargetClass(), $this->Get('dest_id'));
|
||||||
if ($oDestObj == null)
|
if ($oDestObj == null)
|
||||||
{
|
{
|
||||||
$this->Set('status', 'orphan'); // The destination object has been deleted !
|
$this->Set('status', 'orphan'); // The destination object has been deleted !
|
||||||
@@ -1797,8 +1946,20 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj', 'stats_nb_obj_updated_errors');
|
$bModified = $this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj', 'stats_nb_obj_updated_errors');
|
||||||
|
if ($this->HasWarnings())
|
||||||
|
{
|
||||||
|
if ($bModified)
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_updated_warnings');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$oStatLog->Inc('stats_nb_obj_unchanged_warnings');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
$this->RecordWarnings();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // Do nothing in all other cases
|
default: // Do nothing in all other cases
|
||||||
@@ -1811,6 +1972,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
protected function UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, &$oStatLog, $sStatsCode, $sStatsCodeError)
|
protected function UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, &$oStatLog, $sStatsCode, $sStatsCodeError)
|
||||||
{
|
{
|
||||||
$aValueTrace = array();
|
$aValueTrace = array();
|
||||||
|
$bModified = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach($aAttributes as $sAttCode => $oSyncAtt)
|
foreach($aAttributes as $sAttCode => $oSyncAtt)
|
||||||
@@ -1826,6 +1988,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
if ($oDestObj->IsModified())
|
if ($oDestObj->IsModified())
|
||||||
{
|
{
|
||||||
$oDestObj->DBUpdateTracked($oChange);
|
$oDestObj->DBUpdateTracked($oChange);
|
||||||
|
$bModified = true;
|
||||||
$oStatLog->AddTrace('Updated object - Values: {'.implode(', ', $aValueTrace).'}', $this);
|
$oStatLog->AddTrace('Updated object - Values: {'.implode(', ', $aValueTrace).'}', $this);
|
||||||
if (($sStatsCode != '') &&(MetaModel::IsValidAttCode(get_class($oStatLog), $sStatsCode.'_updated')))
|
if (($sStatsCode != '') &&(MetaModel::IsValidAttCode(get_class($oStatLog), $sStatsCode.'_updated')))
|
||||||
{
|
{
|
||||||
@@ -1851,13 +2014,16 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
$this->SetLastError('Unable to update destination object: ', $e);
|
$this->SetLastError('Unable to update destination object: ', $e);
|
||||||
$oStatLog->Inc($sStatsCodeError);
|
$oStatLog->Inc($sStatsCodeError);
|
||||||
}
|
}
|
||||||
|
return $bModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the destination object populating it with the Extended data found in the synchro_data_XXXX table
|
* Creates the destination object populating it with the Extended data found in the synchro_data_XXXX table
|
||||||
|
* @return bool Whether or not the object was created
|
||||||
*/
|
*/
|
||||||
protected function CreateObjectFromReplica($sClass, $aAttributes, $oChange, &$oStatLog)
|
protected function CreateObjectFromReplica($sClass, $aAttributes, $oChange, &$oStatLog)
|
||||||
{
|
{
|
||||||
|
$bCreated = false;
|
||||||
$oDestObj = MetaModel::NewObject($sClass);
|
$oDestObj = MetaModel::NewObject($sClass);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1879,6 +2045,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
$this->Set('status_last_error', '');
|
$this->Set('status_last_error', '');
|
||||||
$this->Set('status', 'synchronized');
|
$this->Set('status', 'synchronized');
|
||||||
$this->Set('info_creation_date', date('Y-m-d H:i:s'));
|
$this->Set('info_creation_date', date('Y-m-d H:i:s'));
|
||||||
|
$bCreated = true;
|
||||||
|
|
||||||
$oStatLog->AddTrace("Created (".implode(', ', $aValueTrace).")", $this);
|
$oStatLog->AddTrace("Created (".implode(', ', $aValueTrace).")", $this);
|
||||||
$oStatLog->Inc('stats_nb_obj_created');
|
$oStatLog->Inc('stats_nb_obj_created');
|
||||||
@@ -1889,6 +2056,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
$this->SetLastError('Unable to create destination object: ', $e);
|
$this->SetLastError('Unable to create destination object: ', $e);
|
||||||
$oStatLog->Inc('stats_nb_obj_created_errors');
|
$oStatLog->Inc('stats_nb_obj_created_errors');
|
||||||
}
|
}
|
||||||
|
return $bCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1983,6 +2151,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
// $sExtAttCode is a valid attribute code
|
// $sExtAttCode is a valid attribute code
|
||||||
//
|
//
|
||||||
$sClass = $this->Get('base_class');
|
$sClass = $this->Get('base_class');
|
||||||
|
|
||||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sExtAttCode);
|
$oAttDef = MetaModel::GetAttributeDef($sClass, $sExtAttCode);
|
||||||
|
|
||||||
if (!is_null($oSyncAtt) && ($oSyncAtt instanceof SynchroAttExtKey))
|
if (!is_null($oSyncAtt) && ($oSyncAtt instanceof SynchroAttExtKey))
|
||||||
@@ -2005,8 +2174,12 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Note: differs from null (in which case the value would be left unchanged)
|
if ($rawValue != '')
|
||||||
$oStatLog->AddTrace("Could not find [unique] object for '$sExtAttCode': searched on $sReconcAttCode = '$rawValue'", $this);
|
{
|
||||||
|
// Note: differs from null (in which case the value would be left unchanged)
|
||||||
|
$oStatLog->AddTrace("Could not find [unique] object for '$sExtAttCode': searched on $sReconcAttCode = '$rawValue'", $this);
|
||||||
|
$this->AddWarning("Could not find [unique] object for '$sExtAttCode': searched on $sReconcAttCode = '$rawValue'");
|
||||||
|
}
|
||||||
$retValue = 0;
|
$retValue = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2108,6 +2281,14 @@ class SynchroReplica extends DBObject implements iDisplay
|
|||||||
}
|
}
|
||||||
$oPage->Details($aDetails);
|
$oPage->Details($aDetails);
|
||||||
$oPage->add('</fieldset>');
|
$oPage->add('</fieldset>');
|
||||||
|
$oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'), false);
|
||||||
|
if (is_object($oDestObj))
|
||||||
|
{
|
||||||
|
$oPage->add('<fieldset>');
|
||||||
|
$oPage->add('<legend>'.Dict::Format('Core:SynchroReplica:TargetObject', $oDestObj->GetHyperlink()).'</legend>');
|
||||||
|
$oDestObj->DisplayBareProperties($oPage, false, $aExtraParams);
|
||||||
|
$oPage->add('<fieldset>');
|
||||||
|
}
|
||||||
$oPage->add('</td><td>');
|
$oPage->add('</td><td>');
|
||||||
$oPage->add('<fieldset>');
|
$oPage->add('<fieldset>');
|
||||||
$oPage->add('<legend>'.Dict::S('Core:SynchroReplica:PublicData').'</legend>');
|
$oPage->add('<legend>'.Dict::S('Core:SynchroReplica:PublicData').'</legend>');
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
<!-- Added the following import tag to pass the Eclipse validation -->
|
<!-- Added the following import tag to pass the Eclipse validation -->
|
||||||
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
|
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
|
||||||
<xsd:complexType name="SearchCondition">
|
<xsd:complexType name="SearchCondition">
|
||||||
<wsdl:documentation>
|
<!--wsdl:documentation>
|
||||||
A criteria to restrict a search (strict search is performed)
|
A criteria to restrict a search (strict search is performed)
|
||||||
Example: name = 'myserver.combodo.fr'
|
Example: name = 'myserver.combodo.fr'
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="attcode" type="xsd:string"/>
|
<xsd:element name="attcode" type="xsd:string"/>
|
||||||
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
|
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
|
||||||
@@ -25,20 +25,20 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="ExternalKeySearch">
|
<xsd:complexType name="ExternalKeySearch">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Specifies [how to find] a value for an external key.
|
Specifies [how to find] a value for an external key.
|
||||||
the class of object to search for will depend on the usage that is being made, therefore the search conditions that may be used will vary depending on the parameter that is concerned.
|
the class of object to search for will depend on the usage that is being made, therefore the search conditions that may be used will vary depending on the parameter that is concerned.
|
||||||
If one criteria is not relevant, then the match will not be attempted and warning will be logged (or an error if the target external key is mandatory)
|
If one criteria is not relevant, then the match will not be attempted and warning will be logged (or an error if the target external key is mandatory)
|
||||||
Example: match on customer = 'Demo' and type = 'Router'
|
Example: match on customer = 'Demo' and type = 'Router'
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
|
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
|
||||||
</xsd:all>
|
</xsd:all>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="AttributeValue">
|
<xsd:complexType name="AttributeValue">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Specifies a value to set
|
Specifies a value to set
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="attcode" type="xsd:string"/>
|
<xsd:element name="attcode" type="xsd:string"/>
|
||||||
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
|
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
|
||||||
@@ -52,9 +52,9 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="LinkCreationSpec">
|
<xsd:complexType name="LinkCreationSpec">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Specifies [how to match] one item to attach and what values should be set on the newly created link.
|
Specifies [how to match] one item to attach and what values should be set on the newly created link.
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="class" type="xsd:string"/>
|
<xsd:element name="class" type="xsd:string"/>
|
||||||
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
|
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
|
||||||
@@ -69,9 +69,9 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="LogMessage">
|
<xsd:complexType name="LogMessage">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
An event that happened during the execution of the web service
|
An event that happened during the execution of the web service
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="text" type="xsd:string"/>
|
<xsd:element name="text" type="xsd:string"/>
|
||||||
</xsd:all>
|
</xsd:all>
|
||||||
@@ -84,9 +84,9 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="ResultLog">
|
<xsd:complexType name="ResultLog">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
A Log of events of the same category
|
A Log of events of the same category
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="messages" type="typens:ArrayOfLogMessage"/>
|
<xsd:element name="messages" type="typens:ArrayOfLogMessage"/>
|
||||||
</xsd:all>
|
</xsd:all>
|
||||||
@@ -105,10 +105,10 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="ResultMessage">
|
<xsd:complexType name="ResultMessage">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Output expected, depending on the operation invoked.
|
Output expected, depending on the operation invoked.
|
||||||
Example: CreateIncidentTicket will return 'created' => basic information on the created ticket
|
Example: CreateIncidentTicket will return 'created' => basic information on the created ticket
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="label" type="xsd:string"/>
|
<xsd:element name="label" type="xsd:string"/>
|
||||||
<xsd:element name="values" type="typens:ArrayOfResultData"/>
|
<xsd:element name="values" type="typens:ArrayOfResultData"/>
|
||||||
@@ -122,12 +122,12 @@
|
|||||||
</xsd:complexContent>
|
</xsd:complexContent>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
<xsd:complexType name="Result">
|
<xsd:complexType name="Result">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Standard result structure returned by all of the operations, excepted GetVersion (returning a string)
|
Standard result structure returned by all of the operations, excepted GetVersion (returning a string)
|
||||||
result holds returned data if the status is set to true
|
result holds returned data if the status is set to true
|
||||||
errors, warnings and infos will help in understanding what happened (unknown identifiers, object matching issues/results)
|
errors, warnings and infos will help in understanding what happened (unknown identifiers, object matching issues/results)
|
||||||
This resulting structure is being tracked into the application log as well.
|
This resulting structure is being tracked into the application log as well.
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<xsd:all>
|
<xsd:all>
|
||||||
<xsd:element name="status" type="xsd:boolean"/>
|
<xsd:element name="status" type="xsd:boolean"/>
|
||||||
<xsd:element name="result" type="typens:ArrayOfResultMessage"/>
|
<xsd:element name="result" type="typens:ArrayOfResultMessage"/>
|
||||||
@@ -189,31 +189,31 @@
|
|||||||
</message>
|
</message>
|
||||||
<portType name="WebServicePortType">
|
<portType name="WebServicePortType">
|
||||||
<operation name="GetVersion">
|
<operation name="GetVersion">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Get the current version of Itop
|
Get the current version of Itop
|
||||||
As this service is very simple, it is a test to get trained for more complex operations
|
As this service is very simple, it is a test to get trained for more complex operations
|
||||||
</wsdl:documentation> -->
|
</wsdl:documentation --> -->
|
||||||
<input message="typens:GetVersion"/>
|
<input message="typens:GetVersion"/>
|
||||||
<output message="typens:GetVersionResponse"/>
|
<output message="typens:GetVersionResponse"/>
|
||||||
</operation>
|
</operation>
|
||||||
<operation name="CreateRequestTicket">
|
<operation name="CreateRequestTicket">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Create a ticket, return information about reconciliation on external keys and the created ticket
|
Create a ticket, return information about reconciliation on external keys and the created ticket
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<input message="typens:CreateRequestTicket"/>
|
<input message="typens:CreateRequestTicket"/>
|
||||||
<output message="typens:CreateRequestTicketResponse"/>
|
<output message="typens:CreateRequestTicketResponse"/>
|
||||||
</operation>
|
</operation>
|
||||||
<operation name="CreateIncidentTicket">
|
<operation name="CreateIncidentTicket">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Create a ticket, return information about reconciliation on external keys and the created ticket
|
Create a ticket, return information about reconciliation on external keys and the created ticket
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<input message="typens:CreateIncidentTicket"/>
|
<input message="typens:CreateIncidentTicket"/>
|
||||||
<output message="typens:CreateIncidentTicketResponse"/>
|
<output message="typens:CreateIncidentTicketResponse"/>
|
||||||
</operation>
|
</operation>
|
||||||
<operation name="SearchObjects">
|
<operation name="SearchObjects">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
Create a ticket, return information about reconciliation on external keys and the created ticket
|
Create a ticket, return information about reconciliation on external keys and the created ticket
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<input message="typens:SearchObjects"/>
|
<input message="typens:SearchObjects"/>
|
||||||
<output message="typens:SearchObjectsResponse"/>
|
<output message="typens:SearchObjectsResponse"/>
|
||||||
</operation>
|
</operation>
|
||||||
@@ -258,9 +258,9 @@
|
|||||||
</operation>
|
</operation>
|
||||||
</binding>
|
</binding>
|
||||||
<service name="ITopService">
|
<service name="ITopService">
|
||||||
<wsdl:documentation>
|
<!-- wsdl:documentation>
|
||||||
ITop is the central solution for managing your IT infrastructure
|
ITop is the central solution for managing your IT infrastructure
|
||||||
</wsdl:documentation>
|
</wsdl:documentation -->
|
||||||
<port name="WebServicePort" binding="typens:WebServiceBinding">
|
<port name="WebServicePort" binding="typens:WebServiceBinding">
|
||||||
<soap:address location="___SOAP_SERVER_URI___"/>
|
<soap:address location="___SOAP_SERVER_URI___"/>
|
||||||
</port>
|
</port>
|
||||||
|
|||||||
Reference in New Issue
Block a user