/** * Helper to link objects * * @param string sLinkAttCode * @param string sLinkedClass * @param array $aLinkList * @param DBObject oTargetObj * @param WebServiceResult oRes * * @return array List of objects that could not be found */ protected function AddLinkedObjects($sLinkAttCode, $sParamName, $sLinkedClass, $aLinkList, &$oTargetObj, &$oRes) { $oLinkAtt = MetaModel::GetAttributeDef(get_class($oTargetObj), $sLinkAttCode); $sLinkClass = $oLinkAtt->GetLinkedClass(); $sExtKeyToItem = $oLinkAtt->GetExtKeyToRemote(); $aItemsFound = array(); $aItemsNotFound = array(); if (is_null($aLinkList)) { return $aItemsNotFound; } foreach ($aLinkList as $aItemData) { if (!array_key_exists('class', $aItemData)) { $oRes->LogWarning("Parameter {$sParamName}: missing 'class' specification"); continue; // skip } $sTargetClass = $aItemData['class']; if (!MetaModel::IsValidClass($sTargetClass)) { $oRes->LogError("Parameter {$sParamName}: invalid class '{$sTargetClass}'"); continue; // skip } if (!MetaModel::IsParentClass($sLinkedClass, $sTargetClass)) { $oRes->LogError("Parameter {$sParamName}: '{$sTargetClass}' is not a child class of '{$sLinkedClass}'"); continue; // skip } $oReconFilter = new CMDBSearchFilter($sTargetClass); $aCIStringDesc = array(); foreach ($aItemData['search'] as $sAttCode => $value) { if (!MetaModel::IsValidFilterCode($sTargetClass, $sAttCode)) { $aCodes = array_keys(MetaModel::GetClassFilterDefs($sTargetClass)); $oRes->LogError("Parameter {$sParamName}: '{$sAttCode}' is not a valid filter code for class '{$sTargetClass}', expecting a value in {" . implode(', ', $aCodes) . "}"); continue 2; // skip the entire item } $aCIStringDesc[] = "{$sAttCode}: {$value}"; // The attribute is one of our reconciliation key $oReconFilter->AddCondition($sAttCode, $value, '='); } if (count($aCIStringDesc) == 1) { // take the last and unique value to describe the object $sItemDesc = $value; } else { // describe the object by the given keys $sItemDesc = $sTargetClass . '(' . implode('/', $aCIStringDesc) . ')'; } $oExtObjects = new CMDBObjectSet($oReconFilter); switch ($oExtObjects->Count()) { case 0: $oRes->LogWarning("Parameter {$sParamName}: object to link {$sLinkedClass} / {$sItemDesc} could not be found (searched: '" . $oReconFilter->ToOQL(true) . "')"); $aItemsNotFound[] = $sItemDesc; break; case 1: $aItemsFound[] = array('object' => $oExtObjects->Fetch(), 'link_values' => @$aItemData['link_values'], 'desc' => $sItemDesc); break; default: $oRes->LogWarning("Parameter {$sParamName}: Found " . $oExtObjects->Count() . " matches for item '{$sItemDesc}' (searched: '" . $oReconFilter->ToOQL(true) . "')"); $aItemsNotFound[] = $sItemDesc; } } if (count($aItemsFound) > 0) { $aLinks = array(); foreach ($aItemsFound as $aItemData) { $oLink = MetaModel::NewObject($sLinkClass); $oLink->Set($sExtKeyToItem, $aItemData['object']->GetKey()); foreach ($aItemData['link_values'] as $sKey => $value) { if (!MetaModel::IsValidAttCode($sLinkClass, $sKey)) { $oRes->LogWarning("Parameter {$sParamName}: Attaching item '" . $aItemData['desc'] . "', the attribute code '{$sKey}' is not valid ; check the class '{$sLinkClass}'"); } else { $oLink->Set($sKey, $value); } } $aLinks[] = $oLink; } $oImpactedInfraSet = DBObjectSet::FromArray($sLinkClass, $aLinks); $oTargetObj->Set($sLinkAttCode, $oImpactedInfraSet); } return $aItemsNotFound; }
public function GetSiloSelectionForm() { // List of visible Organizations $iCount = 0; $oSet = null; if (MetaModel::IsValidClass('Organization')) { // Display the list of *favorite* organizations... but keeping in mind what is the real number of organizations $aFavoriteOrgs = appUserPreferences::GetPref('favorite_orgs', null); $oSearchFilter = new DBObjectSearch('Organization'); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); $oSet = new CMDBObjectSet($oSearchFilter); $iCount = $oSet->Count(); // total number of existing Orgs // Now get the list of Orgs to be displayed in the menu $oSearchFilter = DBObjectSearch::FromOQL(ApplicationMenu::GetFavoriteSiloQuery()); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); if (!empty($aFavoriteOrgs)) { $oSearchFilter->AddCondition('id', $aFavoriteOrgs, 'IN'); } $oSet = new CMDBObjectSet($oSearchFilter); // List of favorite orgs } switch ($iCount) { case 0: // No such dimension/silo => nothing to select $sHtml = '<div id="SiloSelection"><!-- nothing to select --></div>'; break; case 1: // Only one possible choice... no selection, but display the value $oOrg = $oSet->Fetch(); $sHtml = '<div id="SiloSelection">' . $oOrg->GetName() . '</div>'; $sHtml .= ''; break; default: $sHtml = ''; $oAppContext = new ApplicationContext(); $iCurrentOrganization = $oAppContext->GetCurrentValue('org_id'); $sHtml = '<div id="SiloSelection">'; $sHtml .= '<form style="display:inline" action="' . utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php">'; //<select class="org_combo" name="c[org_id]" title="Pick an organization" onChange="this.form.submit();">'; $sFavoriteOrgs = ''; $oWidget = new UIExtKeyWidget('Organization', 'org_id', '', true); $sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '', array('iFieldSize' => 20, 'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'), 'sDefaultValue' => Dict::S('UI:AllOrganizations')), null, 'select', false); $this->add_ready_script('$("#org_id").bind("extkeychange", function() { $("#SiloSelection form").submit(); } )'); $this->add_ready_script("\$('#label_org_id').click( function() { \$(this).val(''); \$('#org_id').val(''); return true; } );\n"); // Add other dimensions/context information to this form $oAppContext->Reset('org_id'); // org_id is handled above and we want to be able to change it here ! $oAppContext->Reset('menu'); // don't pass the menu, since a menu may expect more parameters $sHtml .= $oAppContext->GetForForm(); // Pass what remains, if anything... $sHtml .= '</form>'; $sHtml .= '</div>'; } return $sHtml; }
/** * Renders the "Actions" popup menu for the given set of objects * * Note that the menu links containing (or ending) with a hash (#) will have their fragment * part (whatever is after the hash) dynamically replaced (by javascript) when the menu is * displayed, to correspond to the current hash/fragment in the page. This allows modifying * an object in with the same tab active by default as the tab that was active when selecting * the "Modify..." action. */ public function GetRenderContent(WebPage $oPage, $aExtraParams = array(), $sId) { if ($this->m_sStyle == 'popup') { $this->m_sStyle = 'list'; } $sHtml = ''; $oAppContext = new ApplicationContext(); $sContext = $oAppContext->GetForLink(); if (!empty($sContext)) { $sContext = '&' . $sContext; } $sClass = $this->m_oFilter->GetClass(); $oReflectionClass = new ReflectionClass($sClass); $oSet = new CMDBObjectSet($this->m_oFilter); $sFilter = $this->m_oFilter->serialize(); $sFilterDesc = $this->m_oFilter->ToOql(true); $aActions = array(); $sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass); $sRootUrl = utils::GetAbsoluteUrlAppRoot(); // 1:n links, populate the target object as a default value when creating a new linked object if (isset($aExtraParams['target_attr'])) { $aExtraParams['default'][$aExtraParams['target_attr']] = $aExtraParams['object_id']; } $sDefault = ''; if (!empty($aExtraParams['default'])) { foreach ($aExtraParams['default'] as $sKey => $sValue) { $sDefault .= "&default[{$sKey}]={$sValue}"; } } $bIsCreationAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_CREATE) == UR_ALLOWED_YES && $oReflectionClass->IsSubclassOf('cmdbAbstractObject'); switch ($oSet->Count()) { case 0: // No object in the set, the only possible action is "new" if ($bIsCreationAllowed) { $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}"); } break; case 1: $oObj = $oSet->Fetch(); $id = $oObj->GetKey(); $bLocked = false; if (MetaModel::GetConfig()->Get('concurrent_lock_enabled')) { $aLockInfo = iTopOwnershipLock::IsLocked(get_class($oObj), $id); if ($aLockInfo['locked']) { $bLocked = true; //$this->AddMenuSeparator($aActions); //$aActions['concurrent_lock_unlock'] = array ('label' => Dict::S('UI:Menu:ReleaseConcurrentLock'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=kill_lock&class=$sClass&id=$id{$sContext}"); } } $bRawModifiedAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) == UR_ALLOWED_YES && $oReflectionClass->IsSubclassOf('cmdbAbstractObject'); $bIsModifyAllowed = !$bLocked && $bRawModifiedAllowed; $bIsDeleteAllowed = !$bLocked && UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); // Just one object in the set, possible actions are "new / clone / modify and delete" if (!isset($aExtraParams['link_attr'])) { if ($bIsModifyAllowed) { $aActions['UI:Menu:Modify'] = array('label' => Dict::S('UI:Menu:Modify'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify&class={$sClass}&id={$id}{$sContext}#"); } if ($bIsCreationAllowed) { $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}"); } if ($bIsDeleteAllowed) { $aActions['UI:Menu:Delete'] = array('label' => Dict::S('UI:Menu:Delete'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=delete&class={$sClass}&id={$id}{$sContext}"); } // Transitions / Stimuli if (!$bLocked) { $aTransitions = $oObj->EnumTransitions(); if (count($aTransitions)) { $this->AddMenuSeparator($aActions); $aStimuli = Metamodel::EnumStimuli(get_class($oObj)); foreach ($aTransitions as $sStimulusCode => $aTransitionDef) { $iActionAllowed = get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction' ? UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet) : UR_ALLOWED_NO; switch ($iActionAllowed) { case UR_ALLOWED_YES: $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=stimulus&stimulus={$sStimulusCode}&class={$sClass}&id={$id}{$sContext}"); break; default: // Do nothing } } } } // Relations... $aRelations = MetaModel::EnumRelationsEx($sClass); if (count($aRelations)) { $this->AddMenuSeparator($aActions); foreach ($aRelations as $sRelationCode => $aRelationInfo) { if (array_key_exists('down', $aRelationInfo)) { $aActions[$sRelationCode . '_down'] = array('label' => $aRelationInfo['down'], 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=swf_navigator&relation={$sRelationCode}&direction=down&class={$sClass}&id={$id}{$sContext}"); } if (array_key_exists('up', $aRelationInfo)) { $aActions[$sRelationCode . '_up'] = array('label' => $aRelationInfo['up'], 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=swf_navigator&relation={$sRelationCode}&direction=up&class={$sClass}&id={$id}{$sContext}"); } } } if ($bLocked && $bRawModifiedAllowed) { // Add a special menu to kill the lock, but only to allowed users who can also modify this object $aAllowedProfiles = MetaModel::GetConfig()->Get('concurrent_lock_override_profiles'); $bCanKill = false; $oUser = UserRights::GetUserObject(); $aUserProfiles = array(); if (!is_null($oUser)) { $oProfileSet = $oUser->Get('profile_list'); while ($oProfile = $oProfileSet->Fetch()) { $aUserProfiles[$oProfile->Get('profile')] = true; } } foreach ($aAllowedProfiles as $sProfile) { if (array_key_exists($sProfile, $aUserProfiles)) { $bCanKill = true; break; } } if ($bCanKill) { $this->AddMenuSeparator($aActions); $aActions['concurrent_lock_unlock'] = array('label' => Dict::S('UI:Menu:KillConcurrentLock'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=kill_lock&class={$sClass}&id={$id}{$sContext}"); } } /* $this->AddMenuSeparator($aActions); // Static menus: Email this page & CSV Export $sUrl = ApplicationContext::MakeObjectUrl($sClass, $id); $aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl)); $aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}"); // The style tells us whether the menu is displayed on a list of one object, or on the details of the given object if ($this->m_sStyle == 'list') { // Actions specific to the list $sOQL = addslashes($sFilterDesc); $aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')"); } */ } $this->AddMenuSeparator($aActions); foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { $oSet->Rewind(); foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $sUrl) { $aActions[$sLabel] = array('label' => $sLabel, 'url' => $sUrl); } } break; default: // Check rights // New / Modify $bIsModifyAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY, $oSet) && $oReflectionClass->IsSubclassOf('cmdbAbstractObject'); $bIsBulkModifyAllowed = !MetaModel::IsAbstract($sClass) && UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_MODIFY, $oSet) && $oReflectionClass->IsSubclassOf('cmdbAbstractObject'); $bIsBulkDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_BULK_DELETE, $oSet); if (isset($aExtraParams['link_attr'])) { $id = $aExtraParams['object_id']; $sTargetAttr = $aExtraParams['target_attr']; $oAttDef = MetaModel::GetAttributeDef($sClass, $sTargetAttr); $sTargetClass = $oAttDef->GetTargetClass(); $bIsDeleteAllowed = UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE, $oSet); if ($bIsModifyAllowed) { $aActions['UI:Menu:Add'] = array('label' => Dict::S('UI:Menu:Add'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify_links&class={$sClass}&link_attr=" . $aExtraParams['link_attr'] . "&target_class={$sTargetClass}&id={$id}&addObjects=true{$sContext}"); } if ($bIsBulkModifyAllowed) { $aActions['UI:Menu:Manage'] = array('label' => Dict::S('UI:Menu:Manage'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=modify_links&class={$sClass}&link_attr=" . $aExtraParams['link_attr'] . "&target_class={$sTargetClass}&id={$id}{$sContext}"); } //if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => 'Remove All...', 'url' => "#"); } } else { // many objects in the set, possible actions are: new / modify all / delete all if ($bIsCreationAllowed) { $aActions['UI:Menu:New'] = array('label' => Dict::S('UI:Menu:New'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=new&class={$sClass}{$sContext}{$sDefault}"); } if ($bIsBulkModifyAllowed) { $aActions['UI:Menu:ModifyAll'] = array('label' => Dict::S('UI:Menu:ModifyAll'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=select_for_modify_all&class={$sClass}&filter=" . urlencode($sFilter) . "{$sContext}"); } if ($bIsBulkDeleteAllowed) { $aActions['UI:Menu:BulkDelete'] = array('label' => Dict::S('UI:Menu:BulkDelete'), 'url' => "{$sRootUrl}pages/{$sUIPage}?operation=select_for_deletion&filter=" . urlencode($sFilter) . "{$sContext}"); } // Stimuli $aStates = MetaModel::EnumStates($sClass); // Do not perform time consuming computations if there are too may objects in the list $iLimit = MetaModel::GetConfig()->Get('complex_actions_limit'); if (count($aStates) > 0 && ($iLimit == 0 || $oSet->Count() < $iLimit)) { // Life cycle actions may be available... if all objects are in the same state // // Group by <state> $oGroupByExp = new FieldExpression(MetaModel::GetStateAttributeCode($sClass), $this->m_oFilter->GetClassAlias()); $aGroupBy = array('__state__' => $oGroupByExp); $aQueryParams = array(); if (isset($aExtraParams['query_params'])) { $aQueryParams = $aExtraParams['query_params']; } $sSql = $this->m_oFilter->MakeGroupByQuery($aQueryParams, $aGroupBy); $aRes = CMDBSource::QueryToArray($sSql); if (count($aRes) == 1) { // All objects are in the same state... $sState = $aRes[0]['__state__']; $aTransitions = Metamodel::EnumTransitions($sClass, $sState); if (count($aTransitions)) { $this->AddMenuSeparator($aActions); $aStimuli = Metamodel::EnumStimuli($sClass); foreach ($aTransitions as $sStimulusCode => $aTransitionDef) { $oSet->Rewind(); // As soon as the user rights implementation will browse the object set, // then we might consider using OptimizeColumnLoad() here $iActionAllowed = UserRights::IsStimulusAllowed($sClass, $sStimulusCode, $oSet); $iActionAllowed = get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction' ? $iActionAllowed : UR_ALLOWED_NO; switch ($iActionAllowed) { case UR_ALLOWED_YES: case UR_ALLOWED_DEPENDS: $aActions[$sStimulusCode] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "{$sRootUrl}pages/UI.php?operation=select_bulk_stimulus&stimulus={$sStimulusCode}&state={$sState}&class={$sClass}&filter=" . urlencode($sFilter) . "{$sContext}"); break; default: // Do nothing } } } } } /* $this->AddMenuSeparator($aActions); $sUrl = utils::GetAbsoluteUrlAppRoot(); $aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=$sFilterDesc&body=".urlencode("{$sUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."{$sContext}")); $aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=".urlencode($sFilter)."&format=csv{$sContext}"); $sOQL = addslashes($sFilterDesc); $aActions['UI:Menu:AddToDashboard'] = array ('label' => Dict::S('UI:Menu:AddToDashboard'), 'url' => "#", 'onclick' => "return DashletCreationDlg('$sOQL')"); */ } } $this->AddMenuSeparator($aActions); foreach (MetaModel::EnumPlugins('iApplicationUIExtension') as $oExtensionInstance) { $oSet->Rewind(); foreach ($oExtensionInstance->EnumAllowedActions($oSet) as $sLabel => $data) { if (is_array($data)) { // New plugins can provide javascript handlers via the 'onclick' property //TODO: enable extension of different menus by checking the 'target' property ?? $aActions[$sLabel] = array('label' => $sLabel, 'url' => isset($data['url']) ? $data['url'] : '#', 'onclick' => isset($data['onclick']) ? $data['onclick'] : ''); } else { // Backward compatibility with old plugins $aActions[$sLabel] = array('label' => $sLabel, 'url' => $data); } } } // New extensions based on iPopupMenuItem interface switch ($this->m_sStyle) { case 'list': $oSet->Rewind(); $param = $oSet; $iMenuId = iPopupMenuExtension::MENU_OBJLIST_ACTIONS; break; case 'details': $oSet->Rewind(); $param = $oSet->Fetch(); $iMenuId = iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS; break; } utils::GetPopupMenuItems($oPage, $iMenuId, $param, $aActions); $aFavoriteActions = array(); $aCallSpec = array($sClass, 'GetShortcutActions'); if (is_callable($aCallSpec)) { $aShortcutActions = call_user_func($aCallSpec, $sClass); foreach ($aActions as $key => $aAction) { if (in_array($key, $aShortcutActions)) { $aFavoriteActions[] = $aAction; unset($aActions[$key]); } } } else { $aShortcutActions = array(); } if (count($aFavoriteActions) > 0) { $sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>" . Dict::S('UI:Menu:OtherActions') . "\n<ul>\n"; } else { $sHtml .= "<div class=\"itop_popup actions_menu\"><ul>\n<li>" . Dict::S('UI:Menu:Actions') . "\n<ul>\n"; } $sHtml .= $oPage->RenderPopupMenuItems($aActions, $aFavoriteActions); static $bPopupScript = false; if (!$bPopupScript) { // Output this once per page... $oPage->add_ready_script("\$(\"div.itop_popup>ul\").popupmenu();\n"); $bPopupScript = true; } return $sHtml; }
function DisplayBareRelations(WebPage $oPage, $bEditMode = false) { parent::DisplayBareRelations($oPage, $bEditMode); if (!$bEditMode) { $oPage->SetCurrentTab(Dict::S('Class:Subnet/Tab:IPUsage')); $bit_ip = ip2long($this->Get('ip')); $bit_mask = ip2long($this->Get('ip_mask')); $iIPMin = sprintf('%u', $bit_ip & $bit_mask | 1); // exclude the first one: identifies the subnet itself $iIPMax = sprintf('%u', ($bit_ip | ~$bit_mask) & 0xfffffffe); // exclude the last one : broadcast address $sIPMin = long2ip($iIPMin); $sIPMax = long2ip($iIPMax); $oPage->p(Dict::Format('Class:Subnet/Tab:IPUsage-explain', $sIPMin, $sIPMax)); $oIfFilter = DBObjectSearch::FromOQL("SELECT IPInterface AS if WHERE INET_ATON(if.ipaddress) >= INET_ATON('{$sIPMin}') AND INET_ATON(if.ipaddress) <= INET_ATON('{$sIPMax}')"); $oIfSet = new CMDBObjectSet($oIfFilter); $oBlock = new DisplayBlock($oIfFilter, 'list', false); $oBlock->Display($oPage, 'nwif', array('menu' => false)); $iCountUsed = $oIfSet->Count(); $iCountRange = $iIPMax - $iIPMin; // On 32-bit systems the substraction will be computed using floats for values greater than PHP_MAX_INT; $iFreeCount = $iCountRange - $iCountUsed; $oPage->SetCurrentTab(Dict::S('Class:Subnet/Tab:FreeIPs')); $oPage->p(Dict::Format('Class:Subnet/Tab:FreeIPs-count', $iFreeCount)); $oPage->p(Dict::S('Class:Subnet/Tab:FreeIPs-explain')); $aUsedIPs = $oIfSet->GetColumnAsArray('ipaddress', false); $iAnIP = $iIPMin; $iFound = 0; while ($iFound < min($iFreeCount, 10) && $iAnIP <= $iIPMax) { $sAnIP = long2ip($iAnIP); if (!in_array($sAnIP, $aUsedIPs)) { $iFound++; $oPage->p($sAnIP); } else { } $iAnIP++; } } }
/** * Displays the status (SynchroLog) of the datasource in a graphical manner * @param $oPage WebPage * @return void */ protected function DisplayStatusTab(WebPage $oPage) { $oPage->SetCurrentTab(Dict::S('Core:SynchroStatus')); $sSelectSynchroLog = 'SELECT SynchroLog WHERE sync_source_id = :source_id'; $oSetSynchroLog = new CMDBObjectSet(DBObjectSearch::FromOQL($sSelectSynchroLog), array('start_date' => false), array('source_id' => $this->GetKey())); $oSetSynchroLog->SetLimit(100); // Display only the 100 latest runs if ($oSetSynchroLog->Count() > 0) { $oLastLog = $oSetSynchroLog->Fetch(); $sStartDate = $oLastLog->Get('start_date'); $oLastLog->Get('stats_nb_replica_seen'); $iLastLog = 0; $iDSid = $this->GetKey(); if ($oLastLog->Get('status') == 'running') { // Still running ! $oPage->p('<h2>' . Dict::Format('Core:Synchro:SynchroRunningStartedOn_Date', $sStartDate) . '</h2>'); } else { $sEndDate = $oLastLog->Get('end_date'); $iLastLog = $oLastLog->GetKey(); $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">'); // List all the log entries for the user to select $oPage->add('<h2 style="line-height:55px;">' . Dict::S('Core:Synchro:History') . '</h2>'); $oSetSynchroLog->Rewind(); $oPage->add('<select size="25" onChange="UpdateSynoptics(this.value);">'); $sSelected = ' selected'; // First log is selected by default $sScript = "var aSynchroLog = {\n"; while ($oLog = $oSetSynchroLog->Fetch()) { $sLogTitle = Dict::Format('Core:SynchroLogTitle', $oLog->Get('status'), $oLog->Get('start_date')); $oPage->add('<option value="' . $oLog->GetKey() . '"' . $sSelected . '>' . $sLogTitle . '</option>'); $sSelected = ''; // only the first log is selected by default $aData = $this->ProcessLog($oLog); $sScript .= '"' . $oLog->GetKey() . '": ' . json_encode($aData) . ",\n"; } $sScript .= "end: 'Done'"; $sScript .= "};\n"; $sScript .= <<<EOF \t\t\tvar sLastLog = '{$iLastLog}'; \tfunction ToggleSynoptics(sId, bShow) \t{ \t\tif (bShow) \t\t{ \t\t\t\$(sId).show(); \t\t} \t\telse \t\t{ \t\t\t\$(sId).hide(); \t\t} \t} \t \tfunction UpdateSynoptics(id) \t{ \t\tvar aValues = aSynchroLog[id]; \t\tif (aValues == undefined) return; \t\t \t\tfor (var sKey in aValues) \t\t{ \t\t\t\$('#c_'+sKey).html(aValues[sKey]); \t\t\tvar fOpacity = (aValues[sKey] == 0) ? 0.3 : 1; \t\t\t\$('#'+sKey).fadeTo("slow", fOpacity); \t\t} \t\t//alert('id = '+id+', lastLog='+sLastLog+', id==sLastLog: '+(id==sLastLog)+' obj_updated_errors: '+aValues['obj_updated_errors']); \t\tif ( (id == sLastLog) && (aValues['obj_new_errors'] > 0) ) \t\t{ \t\t\t\$('#new_errors_link').show(); \t\t} \t\telse \t\t{ \t\t\t\$('#new_errors_link').hide(); \t\t} \t\t \t\tif ( (id == sLastLog) && (aValues['obj_updated_errors'] > 0) ) \t\t{ \t\t\t\$('#updated_errors_link').show(); \t\t} \t\telse \t\t{ \t\t\t\$('#updated_errors_link').hide(); \t\t} \t\t \t\tif ( (id == sLastLog) && (aValues['obj_disappeared_errors'] > 0) ) \t\t{ \t\t\t\$('#disappeared_errors_link').show(); \t\t} \t\telse \t\t{ \t\t\t\$('#disappeared_errors_link').hide(); \t\t} \t\t \t\tToggleSynoptics('#cw_obj_created_warnings', aValues['obj_created_warnings'] > 0); \t\tToggleSynoptics('#cw_obj_new_updated_warnings', aValues['obj_new_updated_warnings'] > 0); \t\tToggleSynoptics('#cw_obj_new_unchanged_warnings', aValues['obj_new_unchanged_warnings'] > 0); \t\tToggleSynoptics('#cw_obj_updated_warnings', aValues['obj_updated_warnings'] > 0); \t\tToggleSynoptics('#cw_obj_unchanged_warnings', aValues['obj_unchanged_warnings'] > 0); \t} EOF; $oPage->add_script($sScript); $oPage->add('</select>'); $oPage->add('</td><td style="vertical-align:top;">'); // Now build the big "synoptics" view $aData = $this->ProcessLog($oLastLog); $sNbReplica = $this->GetIcon() . " " . Dict::Format('Core:Synchro:Nb_Replica', "<span id=\"c_nb_replica_total\">{$aData['nb_replica_total']}</span>"); $sNbObjects = MetaModel::GetClassIcon($this->GetTargetClass()) . " " . Dict::Format('Core:Synchro:Nb_Class:Objects', $this->GetTargetClass(), "<span id=\"c_nb_obj_total\">{$aData['nb_obj_total']}</span>"); $oPage->add(<<<EOF \t<table class="synoptics"> \t<tr class="synoptics_header"> \t<td>{$sNbReplica}</td><td> </td><td>{$sNbObjects}</td> \t</tr> \t<tr> EOF ); $sBaseOQL = "SELECT SynchroReplica WHERE sync_source_id=" . $this->GetKey() . " AND status_last_error!=''"; $oPage->add($this->HtmlBox('repl_ignored', $aData, '#999') . '<td colspan="2"> </td>'); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('repl_disappeared', $aData, '#630', 'rowspan="4"') . '<td rowspan="4" class="arrow">=></td>' . $this->HtmlBox('obj_disappeared_no_action', $aData, '#333')); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('obj_deleted', $aData, '#000')); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('obj_obsoleted', $aData, '#630')); $oPage->add("</tr>\n<tr>"); $sOQL = urlencode($sBaseOQL . " AND status='obsolete'"); $oPage->add($this->HtmlBox('obj_disappeared_errors', $aData, '#C00', '', " <a style=\"color:#fff\" href=\"../synchro/replica.php?operation=oql&datasource={$iDSid}&oql={$sOQL}\" id=\"disappeared_errors_link\">Show</a>")); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('repl_existing', $aData, '#093', 'rowspan="3"') . '<td rowspan="3" class="arrow">=></td>' . $this->HtmlBox('obj_unchanged', $aData, '#393')); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('obj_updated', $aData, '#3C3')); $oPage->add("</tr>\n<tr>"); $sOQL = urlencode($sBaseOQL . " AND status='modified'"); $oPage->add($this->HtmlBox('obj_updated_errors', $aData, '#C00', '', " <a style=\"color:#fff\" href=\"../synchro/replica.php?operation=oql&datasource={$iDSid}&oql={$sOQL}\" id=\"updated_errors_link\">Show</a>")); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('repl_new', $aData, '#339', 'rowspan="4"') . '<td rowspan="4" class="arrow">=></td>' . $this->HtmlBox('obj_new_unchanged', $aData, '#393')); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('obj_new_updated', $aData, '#3C3')); $oPage->add("</tr>\n<tr>"); $oPage->add($this->HtmlBox('obj_created', $aData, '#339')); $oPage->add("</tr>\n<tr>"); $sOQL = urlencode($sBaseOQL . " AND status='new'"); $oPage->add($this->HtmlBox('obj_new_errors', $aData, '#C00', '', " <a style=\"color:#fff\" href=\"../synchro/replica.php?operation=oql&datasource={$iDSid}&oql={$sOQL}\" id=\"new_errors_link\">Show</a>")); $oPage->add("</tr>\n</table>\n"); $oPage->add('</td></tr></table>'); $oPage->add_ready_script("UpdateSynoptics('{$iLastLog}')"); } else { $oPage->p('<h2>' . Dict::S('Core:Synchro:NeverRun') . '</h2>'); } }
/** * Validate the parameters and create the ticket object (based on the page's POSTed parameters) * @param WebPage $oP The current web page for the output * @param Organization $oUserOrg The organization of the current user * @return void */ function DoCreateRequest($oP, $oUserOrg) { $aParameters = $oP->ReadAllParams(PORTAL_ALL_PARAMS . ',template_id'); $sTransactionId = utils::ReadPostedParam('transaction_id', ''); if (!utils::IsTransactionValid($sTransactionId)) { $oP->add("<h1>" . Dict::S('UI:Error:ObjectAlreadyCreated') . "</h1>\n"); //ShowOngoingTickets($oP); return; } // Validate the parameters // 1) ServiceCategory $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICECATEGORY_QUERY); $oSearch->AllowAllData(); // In case the user has the rights on his org only $oSet = new CMDBObjectSet($oSearch, array(), array('id' => $aParameters['service_id'], 'org_id' => $oUserOrg->GetKey())); if ($oSet->Count() != 1) { // Invalid service for the current user ! throw new Exception("Invalid Service Category: id={$aParameters['service_id']} - count: " . $oSet->Count()); } $oServiceCategory = $oSet->Fetch(); // 2) Service Subcategory $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY); RestrictSubcategories($oSearch); $oSearch->AllowAllData(); // In case the user has the rights on his org only $oSet = new CMDBObjectSet($oSearch, array(), array('service_id' => $aParameters['service_id'], 'id' => $aParameters['servicesubcategory_id'], 'org_id' => $oUserOrg->GetKey())); if ($oSet->Count() != 1) { // Invalid subcategory throw new Exception("Invalid ServiceSubcategory: id={$aParameters['servicesubcategory_id']} for service category " . $oServiceCategory->GetName() . "({$aParameters['service_id']}) - count: " . $oSet->Count()); } $oServiceSubCategory = $oSet->Fetch(); $sClass = ComputeClass($oServiceSubCategory->GetKey()); $oRequest = MetaModel::NewObject($sClass); $aAttList = array_merge(explode(',', GetConstant($sClass, 'FORM_ATTRIBUTES')), array('service_id', 'servicesubcategory_id')); $oRequest->UpdateObjectFromPostedForm('', $aAttList); $oRequest->Set('org_id', $oUserOrg->GetKey()); $oRequest->Set('caller_id', UserRights::GetContactId()); if (isset($aParameters['moreinfo'])) { // There is a template, insert it into the description $sLogAttCode = GetConstant($sClass, 'PUBLIC_LOG'); $oRequest->Set($sLogAttCode, $aParameters['moreinfo']); } $sTypeAttCode = GetConstant($sClass, 'TYPE'); if ($sTypeAttCode != '' && PORTAL_SET_TYPE_FROM != '') { $oRequest->Set($sTypeAttCode, $oServiceSubCategory->Get(PORTAL_SET_TYPE_FROM)); } if (MetaModel::IsValidAttCode($sClass, 'origin')) { $oRequest->Set('origin', 'portal'); } $oAttPlugin = new AttachmentPlugIn(); $oAttPlugin->OnFormSubmit($oRequest); list($bRes, $aIssues) = $oRequest->CheckToWrite(); if ($bRes) { if (isset($aParameters['template_id'])) { $oTemplate = MetaModel::GetObject('Template', $aParameters['template_id']); $sLogAttCode = GetConstant($sClass, 'PUBLIC_LOG'); $oRequest->Set($sLogAttCode, $oTemplate->GetPostedValuesAsText($oRequest) . "\n"); $oRequest->DBInsertNoReload(); $oTemplate->RecordExtraDataFromPostedForm($oRequest); } else { $oRequest->DBInsertNoReload(); } $oP->add("<h1>" . Dict::Format('UI:Title:Object_Of_Class_Created', $oRequest->GetName(), MetaModel::GetName($sClass)) . "</h1>\n"); //DisplayObject($oP, $oRequest, $oUserOrg); ShowOngoingTickets($oP); } else { RequestCreationForm($oP, $oUserOrg); $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues)); $oP->add_ready_script("alert('" . addslashes($sIssueDesc) . "');"); } }
public function MakeValueFromString($sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null) { if (is_null($sSepItem) || empty($sSepItem)) { $sSepItem = MetaModel::GetConfig()->Get('link_set_item_separator'); } if (is_null($sSepAttribute) || empty($sSepAttribute)) { $sSepAttribute = MetaModel::GetConfig()->Get('link_set_attribute_separator'); } if (is_null($sSepValue) || empty($sSepValue)) { $sSepValue = MetaModel::GetConfig()->Get('link_set_value_separator'); } if (is_null($sAttributeQualifier) || empty($sAttributeQualifier)) { $sAttributeQualifier = MetaModel::GetConfig()->Get('link_set_attribute_qualifier'); } $sTargetClass = $this->Get('linked_class'); $sInput = str_replace($sSepItem, "\n", $sProposedValue); $oCSVParser = new CSVParser($sInput, $sSepAttribute, $sAttributeQualifier); $aInput = $oCSVParser->ToArray(0); $aLinks = array(); foreach ($aInput as $aRow) { // 1st - get the values, split the extkey->searchkey specs, and eventually get the finalclass value $aExtKeys = array(); $aValues = array(); foreach ($aRow as $sCell) { $iSepPos = strpos($sCell, $sSepValue); if ($iSepPos === false) { // Houston... throw new CoreException('Wrong format for link attribute specification', array('value' => $sCell)); } $sAttCode = trim(substr($sCell, 0, $iSepPos)); $sValue = substr($sCell, $iSepPos + strlen($sSepValue)); if (preg_match('/^(.+)->(.+)$/', $sAttCode, $aMatches)) { $sKeyAttCode = $aMatches[1]; $sRemoteAttCode = $aMatches[2]; $aExtKeys[$sKeyAttCode][$sRemoteAttCode] = $sValue; if (!MetaModel::IsValidAttCode($sTargetClass, $sKeyAttCode)) { throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sTargetClass, 'attcode' => $sKeyAttCode)); } $oKeyAttDef = MetaModel::GetAttributeDef($sTargetClass, $sKeyAttCode); $sRemoteClass = $oKeyAttDef->GetTargetClass(); if (!MetaModel::IsValidAttCode($sRemoteClass, $sRemoteAttCode)) { throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sRemoteClass, 'attcode' => $sRemoteAttCode)); } } else { if (!MetaModel::IsValidAttCode($sTargetClass, $sAttCode)) { throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sTargetClass, 'attcode' => $sAttCode)); } $oAttDef = MetaModel::GetAttributeDef($sTargetClass, $sAttCode); $aValues[$sAttCode] = $oAttDef->MakeValueFromString($sValue, $bLocalizedValue, $sSepItem, $sSepAttribute, $sSepValue, $sAttributeQualifier); } } // 2nd - Instanciate the object and set the value if (isset($aValues['finalclass'])) { $sLinkClass = $aValues['finalclass']; if (!is_subclass_of($sLinkClass, $sTargetClass)) { throw new CoreException('Wrong class for link attribute specification', array('requested_class' => $sLinkClass, 'expected_class' => $sTargetClass)); } } elseif (MetaModel::IsAbstract($sTargetClass)) { throw new CoreException('Missing finalclass for link attribute specification'); } else { $sLinkClass = $sTargetClass; } $oLink = MetaModel::NewObject($sLinkClass); foreach ($aValues as $sAttCode => $sValue) { $oLink->Set($sAttCode, $sValue); } // 3rd - Set external keys from search conditions foreach ($aExtKeys as $sKeyAttCode => $aReconciliation) { $oKeyAttDef = MetaModel::GetAttributeDef($sTargetClass, $sKeyAttCode); $sKeyClass = $oKeyAttDef->GetTargetClass(); $oExtKeyFilter = new DBObjectSearch($sKeyClass); $aReconciliationDesc = array(); foreach ($aReconciliation as $sRemoteAttCode => $sValue) { $oExtKeyFilter->AddCondition($sRemoteAttCode, $sValue, '='); $aReconciliationDesc[] = "{$sRemoteAttCode}={$sValue}"; } $oExtKeySet = new CMDBObjectSet($oExtKeyFilter); switch ($oExtKeySet->Count()) { case 0: $sReconciliationDesc = implode(', ', $aReconciliationDesc); throw new CoreException("Found no match", array('ext_key' => $sKeyAttCode, 'reconciliation' => $sReconciliationDesc)); break; case 1: $oRemoteObj = $oExtKeySet->Fetch(); $oLink->Set($sKeyAttCode, $oRemoteObj->GetKey()); break; default: $sReconciliationDesc = implode(', ', $aReconciliationDesc); throw new CoreException("Found several matches", array('ext_key' => $sKeyAttCode, 'reconciliation' => $sReconciliationDesc)); // Found several matches, ambiguous } } // Check (roughly) if such a link is valid $aErrors = array(); foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sAttCode => $oAttDef) { if ($oAttDef->IsExternalKey()) { if ($oAttDef->GetTargetClass() == $this->GetHostClass() || is_subclass_of($this->GetHostClass(), $oAttDef->GetTargetClass())) { continue; // Don't check the key to self } } if ($oAttDef->IsWritable() && $oAttDef->IsNull($oLink->Get($sAttCode)) && !$oAttDef->IsNullAllowed()) { $aErrors[] = $sAttCode; } } if (count($aErrors) > 0) { throw new CoreException("Missing value for mandatory attribute(s): " . implode(', ', $aErrors)); } $aLinks[] = $oLink; } $oSet = DBObjectSet::FromArray($sTargetClass, $aLinks); return $oSet; }
public function GetReferencingObjects($bAllowAllData = false) { $aDependentObjects = array(); $aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this)); foreach ($aRererencingMe as $sRemoteClass => $aExtKeys) { foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) { // skip if this external key is behind an external field if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) { continue; } $oSearch = new DBObjectSearch($sRemoteClass); $oSearch->AddCondition($sExtKeyAttCode, $this->GetKey(), '='); if ($bAllowAllData) { $oSearch->AllowAllData(); } $oSet = new CMDBObjectSet($oSearch); if ($oSet->Count() > 0) { $aDependentObjects[$sRemoteClass][$sExtKeyAttCode] = array('attribute' => $oExtKeyAttDef, 'objects' => $oSet); } } } return $aDependentObjects; }
$oP->add("<tr>\n"); $oP->add("<th><img src=\"../images/minus.gif\"></th><th class=\"alignLeft\">" . Dict::S('UI:Audit:HeaderAuditRule') . "</th><th>" . Dict::S('UI:Audit:HeaderNbObjects') . "</th><th>" . Dict::S('UI:Audit:HeaderNbErrors') . "</th><th>" . Dict::S('UI:Audit:PercentageOk') . "</th>\n"); $oP->add("</tr>\n"); while ($oAuditCategory = $oCategoriesSet->fetch()) { try { $oDefinitionFilter = DBObjectSearch::FromOQL($oAuditCategory->Get('definition_set')); FilterByContext($oDefinitionFilter, $oAppContext); $aObjectsWithErrors = array(); if (!empty($currentOrganization)) { if (MetaModel::IsValidFilterCode($oDefinitionFilter->GetClass(), 'org_id')) { $oDefinitionFilter->AddCondition('org_id', $currentOrganization, '='); } } $aResults = array(); $oDefinitionSet = new CMDBObjectSet($oDefinitionFilter); $iCount = $oDefinitionSet->Count(); $oRulesFilter = new DBObjectSearch('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=\"audit.php?operation=errors&category=" . $oAuditCategory->GetKey() . "&rule=" . $oAuditRule->GetKey() . "\">0</a>"; $aRow['percent_ok'] = '100.00'; $aRow['class'] = GetReportColor($iCount, 0); } else { try { $oFilter = GetRuleResultFilter($oAuditRule->GetKey(), $oDefinitionFilter, $oAppContext); $aErrors = $oFilter->ToDataArray(array('id'));
/** * Read the context directly in the PHP parameters (either POST or GET) * return nothing */ protected function ReadContext() { if (!isset(self::$aDefaultValues)) { self::$aDefaultValues = array(); $aContext = utils::ReadParam('c', array(), false, 'context_param'); foreach ($this->aNames as $sName) { $sValue = isset($aContext[$sName]) ? $aContext[$sName] : ''; // TO DO: check if some of the context parameters are mandatory (or have default values) if (!empty($sValue)) { self::$aDefaultValues[$sName] = $sValue; } // Hmm, there must be a better (more generic) way to handle the case below: // When there is only one possible (allowed) organization, the context must be // fixed to this org if ($sName == 'org_id') { if (MetaModel::IsValidClass('Organization')) { $oSearchFilter = new DBObjectSearch('Organization'); $oSearchFilter->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', true); $oSet = new CMDBObjectSet($oSearchFilter); $iCount = $oSet->Count(); if ($iCount == 1) { // Only one possible value for org_id, set it in the context $oOrg = $oSet->Fetch(); self::$aDefaultValues[$sName] = $oOrg->GetKey(); } } } } } $this->aValues = self::$aDefaultValues; }
/** * Search for an organization with the given code in the database * * @param string $Id The organization Id to look for * @return cmdbOrganization the organization if it exists, null otherwise */ protected function GetOrganization($sId) { $oOrg = null; $oFilter = new CMDBSearchFilter('bizOrganization'); $oFilter->AddCondition('id', $sId, '='); $oSet = new CMDBObjectSet($oFilter); if ($oSet->Count() > 0) { $oOrg = $oSet->Fetch(); // Let's take the first one found } return $oOrg; }
function test_pkey() { echo "<h4>Test search on pkey</h4>"; $sExpr1 = "SELECT cmdbContact WHERE id IN (40, 42)"; $sExpr2 = "SELECT cmdbContact WHERE IN NOT IN (40, 42)"; $this->search_and_show_list_from_oql($sExpr1); $this->search_and_show_list_from_oql($sExpr2); echo "Et maintenant, on fusionne....</br>\n"; $oSet1 = new CMDBObjectSet(DBObjectSearch::FromOQL($sExpr1)); $oSet2 = new CMDBObjectSet(DBObjectSearch::FromOQL($sExpr2)); $oIntersect = $oSet1->CreateIntersect($oSet2); $oDelta = $oSet1->CreateDelta($oSet2); $oMerge = clone $oSet1; $oAppend->Append($oSet2); $oAppend->Append($oSet2); echo "Set1 - Found " . $oSet1->Count() . " items.</br>\n"; echo "Set2 - Found " . $oSet2->Count() . " items.</br>\n"; echo "Intersect - Found " . $oIntersect->Count() . " items.</br>\n"; echo "Delta - Found " . $oDelta->Count() . " items.</br>\n"; echo "Append - Found " . $oAppend->Count() . " items.</br>\n"; //$this->show_list($oObjSet); }
public function Process(CMDBChange $oChange = null) { // Note: $oChange can be null, in which case the aim is to check what would be done // Debug... // if (false) { echo "<pre>\n"; echo "Attributes:\n"; print_r($this->m_aAttList); echo "ExtKeys:\n"; print_r($this->m_aExtKeys); echo "Reconciliation:\n"; print_r($this->m_aReconcilKeys); echo "Synchro scope:\n"; print_r($this->m_sSynchroScope); echo "Synchro changes:\n"; print_r($this->m_aOnDisappear); //echo "Data:\n"; //print_r($this->m_aData); echo "</pre>\n"; exit; } $aResult = array(); if (!is_null($this->m_sDateFormat) && strlen($this->m_sDateFormat) > 0) { // Translate dates from the source data // foreach ($this->m_aAttList as $sAttCode => $iCol) { $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); if ($oAttDef instanceof AttributeDateTime) { foreach ($this->m_aData as $iRow => $aRowData) { $sNewDate = utils::StringToTime($this->m_aData[$iRow][$iCol], $this->m_sDateFormat); if ($sNewDate !== false) { // Todo - improve the reporting $this->m_aData[$iRow][$iCol] = $sNewDate; } else { // Leave the cell unchanged $aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat')); $aResult[$iRow][$sAttCode] = new CellStatus_Issue(null, $this->m_aData[$iRow][$iCol], Dict::S('UI:CSVReport-Row-Issue-DateFormat')); } } } } } // Compute the results // if (!is_null($this->m_sSynchroScope)) { $aVisited = array(); } $iPreviousTimeLimit = ini_get('max_execution_time'); $iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop'); foreach ($this->m_aData as $iRow => $aRowData) { set_time_limit($iLoopTimeLimit); if (isset($aResult[$iRow]["__STATUS__"])) { // An issue at the earlier steps - skip the rest continue; } try { $oReconciliationFilter = new DBObjectSearch($this->m_sClass); $bSkipQuery = false; foreach ($this->m_aReconcilKeys as $sAttCode) { $valuecondition = null; if (array_key_exists($sAttCode, $this->m_aExtKeys)) { if ($this->IsNullExternalKeySpec($aRowData, $sAttCode)) { $oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); if ($oExtKey->IsNullAllowed()) { $valuecondition = $oExtKey->GetNullValue(); $aResult[$iRow][$sAttCode] = new CellStatus_Void($oExtKey->GetNullValue()); } else { $aResult[$iRow][$sAttCode] = new CellStatus_NullIssue(); } } else { // The value has to be found or verified list($sQuery, $aMatches) = $this->ResolveExternalKey($aRowData, $sAttCode, $aResult[$iRow]); if (count($aMatches) == 1) { $oRemoteObj = reset($aMatches); // first item $valuecondition = $oRemoteObj->GetKey(); $aResult[$iRow][$sAttCode] = new CellStatus_Void($oRemoteObj->GetKey()); } elseif (count($aMatches) == 0) { $aResult[$iRow][$sAttCode] = new CellStatus_SearchIssue(); } else { $aResult[$iRow][$sAttCode] = new CellStatus_Ambiguous(null, count($aMatches), $sQuery); } } } else { // The value is given in the data row $iCol = $this->m_aAttList[$sAttCode]; if ($sAttCode == 'id') { $valuecondition = $aRowData[$iCol]; } else { $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); $valuecondition = $oAttDef->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues); } } if (is_null($valuecondition)) { $bSkipQuery = true; } else { $oReconciliationFilter->AddCondition($sAttCode, $valuecondition, '='); } } if ($bSkipQuery) { $aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Reconciliation')); } else { $oReconciliationSet = new CMDBObjectSet($oReconciliationFilter); switch ($oReconciliationSet->Count()) { case 0: $oTargetObj = $this->CreateObject($aResult, $iRow, $aRowData, $oChange); // $aResult[$iRow]["__STATUS__"]=> set in CreateObject $aVisited[] = $oTargetObj->GetKey(); break; case 1: $oTargetObj = $oReconciliationSet->Fetch(); $this->UpdateObject($aResult, $iRow, $oTargetObj, $aRowData, $oChange); // $aResult[$iRow]["__STATUS__"]=> set in UpdateObject if (!is_null($this->m_sSynchroScope)) { $aVisited[] = $oTargetObj->GetKey(); } break; default: // Found several matches, ambiguous $aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-Ambiguous')); $aResult[$iRow]["id"] = new CellStatus_Ambiguous(0, $oReconciliationSet->Count(), $oReconciliationFilter->ToOql()); $aResult[$iRow]["finalclass"] = 'n/a'; } } } catch (Exception $e) { $aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::Format('UI:CSVReport-Row-Issue-Internal', get_class($e), $e->getMessage())); } } if (!is_null($this->m_sSynchroScope)) { // Compute the delta between the scope and visited objects $oScopeSearch = DBObjectSearch::FromOQL($this->m_sSynchroScope); $oScopeSet = new DBObjectSet($oScopeSearch); while ($oObj = $oScopeSet->Fetch()) { $iObj = $oObj->GetKey(); if (!in_array($iObj, $aVisited)) { set_time_limit($iLoopTimeLimit); $iRow++; $this->UpdateMissingObject($aResult, $iRow, $oObj, $oChange); } } } set_time_limit($iPreviousTimeLimit); // Fill in the blanks - the result matrix is expected to be 100% complete // foreach ($this->m_aData as $iRow => $aRowData) { foreach ($this->m_aAttList as $iCol) { if (!array_key_exists($iCol, $aResult[$iRow])) { $aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]); } } foreach ($this->m_aExtKeys as $sAttCode => $aForeignAtts) { if (!array_key_exists($sAttCode, $aResult[$iRow])) { $aResult[$iRow][$sAttCode] = new CellStatus_Void('n/a'); } foreach ($aForeignAtts as $sForeignAttCode => $iCol) { if (!array_key_exists($iCol, $aResult[$iRow])) { // The foreign attribute is one of our reconciliation key $aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]); } } } } return $aResult; }
protected function DoExecute() { foreach (MetaModel::GetClasses() as $sClassName) { if (MetaModel::HasTable($sClassName)) { continue; } $oNobody = MetaModel::GetObject($sClassName, 123); $oBaby = new $sClassName(); $oFilter = new DBObjectSearch($sClassName); // Challenge reversibility of OQL / filter object // $sExpr1 = $oFilter->ToOQL(); $oNewFilter = DBObjectSearch::FromOQL($sExpr1); $sExpr2 = $oNewFilter->ToOQL(); if ($sExpr1 != $sExpr2) { $this->ReportError("Found two different OQL expression out of the (same?) filter: <em>{$sExpr1}</em> != <em>{$sExpr2}</em>"); } // Use the filter (perform the query) // $oSet = new CMDBObjectSet($oFilter); $this->ReportSuccess('Found ' . $oSet->Count() . " objects of class {$sClassName}"); } return true; }