Пример #1
0
 /**
  * Helper to make an output value for a given attribute
  * 	 
  * @param DBObject $oObject The object being reported
  * @param string $sAttCode The attribute code (must be valid)
  * @param boolean $bExtendedOutput Output all of the link set attributes ?
  * @return string A scalar representation of the value
  */
 protected function MakeResultValue(DBObject $oObject, $sAttCode, $bExtendedOutput = false)
 {
     if ($sAttCode == 'id') {
         $value = $oObject->GetKey();
     } else {
         $sClass = get_class($oObject);
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
         if ($oAttDef instanceof AttributeLinkedSet) {
             // Iterate on the set and build an array of array of attcode=>value
             $oSet = $oObject->Get($sAttCode);
             $value = array();
             while ($oLnk = $oSet->Fetch()) {
                 $sLnkRefClass = $bExtendedOutput ? get_class($oLnk) : $oAttDef->GetLinkedClass();
                 $aLnkValues = array();
                 foreach (MetaModel::ListAttributeDefs($sLnkRefClass) as $sLnkAttCode => $oLnkAttDef) {
                     // Skip attributes pointing to the current object (redundant data)
                     if ($sLnkAttCode == $oAttDef->GetExtKeyToMe()) {
                         continue;
                     }
                     // Skip any attribute of the link that points to the current object
                     $oLnkAttDef = MetaModel::GetAttributeDef($sLnkRefClass, $sLnkAttCode);
                     if (method_exists($oLnkAttDef, 'GetKeyAttCode')) {
                         if ($oLnkAttDef->GetKeyAttCode() == $oAttDef->GetExtKeyToMe()) {
                             continue;
                         }
                     }
                     $aLnkValues[$sLnkAttCode] = $this->MakeResultValue($oLnk, $sLnkAttCode, $bExtendedOutput);
                 }
                 $value[] = $aLnkValues;
             }
         } else {
             $value = $oAttDef->GetForJSON($oObject->Get($sAttCode));
         }
     }
     return $value;
 }
Пример #2
0
 /**
  * Computes a text-like fingerprint identifying the content of the object
  * but excluding the specified columns
  * @param $aExcludedColumns array The list of columns to exclude
  * @return string
  */
 public function Fingerprint($aExcludedColumns = array())
 {
     $sFingerprint = '';
     foreach (MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef) {
         if (!in_array($sAttCode, $aExcludedColumns)) {
             if ($oAttDef->IsPartOfFingerprint()) {
                 $sFingerprint .= chr(0) . $oAttDef->Fingerprint($this->Get($sAttCode));
             }
         }
     }
     return $sFingerprint;
 }
 /**
  * Find redundancy settings that can be viewed and modified in a tab
  * Settings are distributed to the corresponding link set attribute so as to be shown in the relevant tab	 
  */
 protected function FindVisibleRedundancySettings()
 {
     $aRet = array();
     foreach (MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef) {
         if ($oAttDef instanceof AttributeRedundancySettings) {
             if ($oAttDef->IsVisible()) {
                 $aQueryInfo = $oAttDef->GetRelationQueryData();
                 if (isset($aQueryInfo['sAttribute'])) {
                     $oUpperAttDef = MetaModel::GetAttributeDef($aQueryInfo['sFromClass'], $aQueryInfo['sAttribute']);
                     $oHostAttDef = $oUpperAttDef->GetMirrorLinkAttribute();
                     if ($oHostAttDef) {
                         $sHostAttCode = $oHostAttDef->GetCode();
                         $aRet[$sHostAttCode][] = $oAttDef;
                     }
                 }
             }
         }
     }
     return $aRet;
 }
 public function ListAttributes($sClass, $sScope = null)
 {
     $aScope = null;
     if ($sScope != null) {
         $aScope = array();
         foreach (explode(',', $sScope) as $sScopeClass) {
             $aScope[] = trim($sScopeClass);
         }
     }
     $aAttributes = array();
     foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
         $sAttributeClass = get_class($oAttDef);
         if ($aScope != null) {
             foreach ($aScope as $sScopeClass) {
                 if ($sAttributeClass == $sScopeClass || is_subclass_of($sAttributeClass, $sScopeClass)) {
                     $aAttributes[$sAttCode] = $sAttributeClass;
                     break;
                 }
             }
         } else {
             $aAttributes[$sAttCode] = $sAttributeClass;
         }
     }
     return $aAttributes;
 }
Пример #5
0
 /**
  * @param hash $aOrderBy Array of '[<classalias>.]attcode' => bAscending
  */
 public function ToDataArray($aColumns = array(), $aOrderBy = array(), $aArgs = array())
 {
     $sSQL = $this->MakeSelectQuery($aOrderBy, $aArgs);
     $resQuery = CMDBSource::Query($sSQL);
     if (!$resQuery) {
         return;
     }
     if (count($aColumns) == 0) {
         $aColumns = array_keys(MetaModel::ListAttributeDefs($this->GetClass()));
         // Add the standard id (as first column)
         array_unshift($aColumns, 'id');
     }
     $aQueryCols = CMDBSource::GetColumns($resQuery);
     $sClassAlias = $this->GetClassAlias();
     $aColMap = array();
     foreach ($aColumns as $sAttCode) {
         $sColName = $sClassAlias . $sAttCode;
         if (in_array($sColName, $aQueryCols)) {
             $aColMap[$sAttCode] = $sColName;
         }
     }
     $aRes = array();
     while ($aRow = CMDBSource::FetchArray($resQuery)) {
         $aMappedRow = array();
         foreach ($aColMap as $sAttCode => $sColName) {
             $aMappedRow[$sAttCode] = $aRow[$sColName];
         }
         $aRes[] = $aMappedRow;
     }
     CMDBSource::FreeResult($resQuery);
     return $aRes;
 }
Пример #6
0
 /**
  * Compute the order of the fields & pages in the wizard
  * @param $oPage iTopWebPage The current page (used to display error messages) 
  * @param $sClass string Name of the class
  * @param $sStateCode string Code of the target state of the object
  * @return hash Two dimensional array: each element represents the list of fields for a given page   
  */
 protected function ComputeWizardStructure()
 {
     $aWizardSteps = array('mandatory' => array(), 'optional' => array());
     $aFieldsDone = array();
     // Store all the fields that are already covered by a previous step of the wizard
     $aStates = MetaModel::EnumStates($this->m_sClass);
     $sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
     $aMandatoryAttributes = array();
     // Some attributes are always mandatory independently of the state machine (if any)
     foreach (MetaModel::GetAttributesList($this->m_sClass) as $sAttCode) {
         $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
         if (!$oAttDef->IsExternalField() && !$oAttDef->IsNullAllowed() && $oAttDef->IsWritable() && $sAttCode != $sStateAttCode) {
             $aMandatoryAttributes[$sAttCode] = OPT_ATT_MANDATORY;
         }
     }
     // Now check the attributes that are mandatory in the specified state
     if (!empty($this->m_sTargetState) && count($aStates[$this->m_sTargetState]['attribute_list']) > 0) {
         // Check all the fields that *must* be included in the wizard for this
         // particular target state
         $aFields = array();
         foreach ($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions) {
             if (isset($aMandatoryAttributes[$sAttCode]) && $aMandatoryAttributes[$sAttCode] & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) {
                 $aMandatoryAttributes[$sAttCode] |= $iOptions;
             } else {
                 $aMandatoryAttributes[$sAttCode] = $iOptions;
             }
         }
     }
     // Check all the fields that *must* be included in the wizard
     // i.e. all mandatory, must-change or must-prompt fields that are
     // not also read-only or hidden.
     // Some fields may be required (null not allowed) from the database
     // perspective, but hidden or read-only from the user interface perspective
     $aFields = array();
     foreach ($aMandatoryAttributes as $sAttCode => $iOptions) {
         if ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT) && !($iOptions & (OPT_ATT_READONLY | OPT_ATT_HIDDEN))) {
             $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
             $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
             $aFields[$sAttCode] = array();
             foreach ($aPrerequisites as $sCode) {
                 $aFields[$sAttCode][$sCode] = '';
             }
         }
     }
     // Now use the dependencies between the fields to order them
     // Start from the order of the 'details'
     $aList = MetaModel::FlattenZlist(MetaModel::GetZListItems($this->m_sClass, 'details'));
     $index = 0;
     $aOrder = array();
     foreach ($aFields as $sAttCode => $void) {
         $aOrder[$sAttCode] = 999;
         // At the end of the list...
     }
     foreach ($aList as $sAttCode) {
         if (array_key_exists($sAttCode, $aFields)) {
             $aOrder[$sAttCode] = $index;
         }
         $index++;
     }
     foreach ($aFields as $sAttCode => $aDependencies) {
         // All fields with no remaining dependencies can be entered at this
         // step of the wizard
         if (count($aDependencies) > 0) {
             $iMaxPos = 0;
             // Remove this field from the dependencies of the other fields
             foreach ($aDependencies as $sDependentAttCode => $void) {
                 // position the current field after the ones it depends on
                 $iMaxPos = max($iMaxPos, 1 + $aOrder[$sDependentAttCode]);
             }
         }
     }
     asort($aOrder);
     $aCurrentStep = array();
     foreach ($aOrder as $sAttCode => $rank) {
         $aCurrentStep[] = $sAttCode;
         $aFieldsDone[$sAttCode] = '';
     }
     $aWizardSteps['mandatory'][] = $aCurrentStep;
     // Now computes the steps to fill the optional fields
     $aFields = array();
     // reset
     foreach (MetaModel::ListAttributeDefs($this->m_sClass) as $sAttCode => $oAttDef) {
         $iOptions = isset($aStates[$this->m_sTargetState]['attribute_list'][$sAttCode]) ? $aStates[$this->m_sTargetState]['attribute_list'][$sAttCode] : 0;
         if ($sStateAttCode != $sAttCode && !$oAttDef->IsExternalField() && ($iOptions & (OPT_ATT_HIDDEN | OPT_ATT_READONLY)) == 0 && !isset($aFieldsDone[$sAttCode])) {
             // 'State', external fields, read-only and hidden fields
             // and fields that are already listed in the wizard
             // are removed from the 'optional' part of the wizard
             $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
             $aPrerequisites = $oAttDef->GetPrerequisiteAttributes();
             $aFields[$sAttCode] = array();
             foreach ($aPrerequisites as $sCode) {
                 if (!isset($aFieldsDone[$sCode])) {
                     // retain only the dependencies that were not covered
                     // in the 'mandatory' part of the wizard
                     $aFields[$sAttCode][$sCode] = '';
                 }
             }
         }
     }
     // Now use the dependencies between the fields to order them
     while (count($aFields) > 0) {
         $aCurrentStep = array();
         foreach ($aFields as $sAttCode => $aDependencies) {
             // All fields with no remaining dependencies can be entered at this
             // step of the wizard
             if (count($aDependencies) == 0) {
                 $aCurrentStep[] = $sAttCode;
                 $aFieldsDone[$sAttCode] = '';
                 unset($aFields[$sAttCode]);
                 // Remove this field from the dependencies of the other fields
                 foreach ($aFields as $sUpdatedCode => $aDummy) {
                     // remove the dependency
                     unset($aFields[$sUpdatedCode][$sAttCode]);
                 }
             }
         }
         if (count($aCurrentStep) == 0) {
             // This step of the wizard would contain NO field !
             $this->m_oPage->add(Dict::S('UI:Error:WizardCircularReferenceInDependencies'));
             print_r($aFields);
             break;
         }
         $aWizardSteps['optional'][] = $aCurrentStep;
     }
     return $aWizardSteps;
 }
 public function GetReconciliationFormElement($sTargetClass, $sFieldName)
 {
     $sHtml = "<select name=\"{$sFieldName}\">\n";
     $sSelected = '' == $this->Get('reconciliation_attcode') ? ' selected' : '';
     $sHtml .= "<option value=\"\" {$sSelected}>" . Dict::S('Core:SynchroAttExtKey:ReconciliationById') . "</option>\n";
     foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sAttCode => $oAttDef) {
         if ($oAttDef->IsScalar()) {
             $sSelected = $sAttCode == $this->Get('reconciliation_attcode') ? ' selected' : '';
             $sHtml .= "<option value=\"{$sAttCode}\" {$sSelected}>" . MetaModel::GetLabel($sTargetClass, $sAttCode) . "</option>\n";
         }
     }
     $sHtml .= "</select>\n";
     return $sHtml;
 }
 protected function GetObjectActionGrant($oUser, $sClass, $iActionCode, $oObject = null)
 {
     if (is_null($oObject)) {
         $iObjectRef = -999;
     } else {
         $iObjectRef = $oObject->GetKey();
     }
     // load and cache permissions for the current user on the given object
     //
     $aTest = @$this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iObjectRef][$iActionCode];
     if (is_array($aTest)) {
         return $aTest;
     }
     $sAction = self::$m_aActionCodes[$iActionCode];
     $iInstancePermission = UR_ALLOWED_NO;
     $aAttributes = array();
     foreach ($this->GetMatchingProfiles($oUser, $sClass, $oObject) as $iProfile) {
         $oGrantRecord = $this->GetClassActionGrant($iProfile, $sClass, $sAction);
         if (is_null($oGrantRecord)) {
             continue;
             // loop to the next profile
         } else {
             $iInstancePermission = UR_ALLOWED_YES;
             // update the list of attributes with those allowed for this profile
             //
             $oSearch = DBObjectSearch::FromOQL_AllData("SELECT URP_AttributeGrant WHERE actiongrantid = :actiongrantid");
             $oSet = new DBObjectSet($oSearch, array(), array('actiongrantid' => $oGrantRecord->GetKey()));
             $aProfileAttributes = $oSet->GetColumnAsArray('attcode', false);
             if (count($aProfileAttributes) == 0) {
                 $aAllAttributes = array_keys(MetaModel::ListAttributeDefs($sClass));
                 $aAttributes = array_merge($aAttributes, $aAllAttributes);
             } else {
                 $aAttributes = array_merge($aAttributes, $aProfileAttributes);
             }
         }
     }
     $aRes = array('permission' => $iInstancePermission, 'attributes' => $aAttributes);
     $this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iObjectRef][$iActionCode] = $aRes;
     return $aRes;
 }
Пример #9
0
 /**
  * List external keys for which there is a LinkSet (direct or indirect) on the other end
  * For those external keys, a change will have a special meaning on the other end
  * in term of change tracking	 	 	 
  */
 public static final function GetTrackForwardExternalKeys($sClass)
 {
     if (!isset(self::$m_aTrackForwardCache[$sClass])) {
         $aRes = array();
         foreach (MetaModel::GetExternalKeys($sClass) as $sAttCode => $oAttDef) {
             $sRemoteClass = $oAttDef->GetTargetClass();
             foreach (MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) {
                 if (!$oRemoteAttDef->IsLinkSet()) {
                     continue;
                 }
                 if (!is_subclass_of($sClass, $oRemoteAttDef->GetLinkedClass()) && $oRemoteAttDef->GetLinkedClass() != $sClass) {
                     continue;
                 }
                 if ($oRemoteAttDef->GetExtKeyToMe() != $sAttCode) {
                     continue;
                 }
                 $aRes[$sAttCode] = $oRemoteAttDef;
             }
         }
         self::$m_aTrackForwardCache[$sClass] = $aRes;
     }
     return self::$m_aTrackForwardCache[$sClass];
 }
Пример #10
0
 protected function FindRecipients($sRecipAttCode, $aArgs)
 {
     $sOQL = $this->Get($sRecipAttCode);
     if (strlen($sOQL) == '') {
         return '';
     }
     try {
         $oSearch = DBObjectSearch::FromOQL($sOQL);
         $oSearch->AllowAllData();
     } catch (OQLException $e) {
         $this->m_aMailErrors[] = "query syntax error for recipient '{$sRecipAttCode}'";
         return $e->getMessage();
     }
     $sClass = $oSearch->GetClass();
     // Determine the email attribute (the first one will be our choice)
     foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
         if ($oAttDef instanceof AttributeEmailAddress) {
             $sEmailAttCode = $sAttCode;
             // we've got one, exit the loop
             break;
         }
     }
     if (!isset($sEmailAttCode)) {
         $this->m_aMailErrors[] = "wrong target for recipient '{$sRecipAttCode}'";
         return "The objects of the class '{$sClass}' do not have any email attribute";
     }
     $oSet = new DBObjectSet($oSearch, array(), $aArgs);
     $aRecipients = array();
     while ($oObj = $oSet->Fetch()) {
         $sAddress = trim($oObj->Get($sEmailAttCode));
         if (strlen($sAddress) > 0) {
             $aRecipients[] = $sAddress;
             $this->m_iRecipients++;
         }
     }
     return implode(', ', $aRecipients);
 }
Пример #11
0
/**
 * Display the details of a given class of objects
 */
function DisplayClassDetails($oPage, $sClass, $sContext)
{
    $oPage->add("<h2>" . MetaModel::GetName($sClass) . " ({$sClass}) - " . MetaModel::GetClassDescription($sClass) . "</h2>\n");
    if (MetaModel::IsAbstract($sClass)) {
        $oPage->p(Dict::S('UI:Schema:AbstractClass'));
    } else {
        $oPage->p(Dict::S('UI:Schema:NonAbstractClass'));
    }
    //	$oPage->p("<h3>".Dict::S('UI:Schema:ClassHierarchyTitle')."</h3>");
    $aParentClasses = array();
    foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) {
        $aParentClasses[] = MakeClassHLink($sParentClass, $sContext);
    }
    if (count($aParentClasses) > 0) {
        $sParents = implode(' &gt;&gt; ', $aParentClasses) . " &gt;&gt; <b>{$sClass}</b>";
    } else {
        $sParents = '';
    }
    $oPage->p("[<a href=\"schema.php?operation=list{$sContext}\">" . Dict::S('UI:Schema:AllClasses') . "</a>] {$sParents}");
    if (MetaModel::HasChildrenClasses($sClass)) {
        $oPage->add("<ul id=\"ClassHierarchy\">");
        $oPage->add("<li class=\"closed\">" . $sClass . "\n");
        DisplaySubclasses($oPage, $sClass, $sContext);
        $oPage->add("</li>\n");
        $oPage->add("</ul>\n");
        $oPage->add_ready_script('$("#ClassHierarchy").treeview();');
    }
    $oPage->p('');
    $oPage->AddTabContainer('details');
    $oPage->SetCurrentTabContainer('details');
    // List the attributes of the object
    $aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys($sClass);
    $aDetails = array();
    foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
        if ($oAttDef->IsExternalKey()) {
            $sValue = Dict::Format('UI:Schema:ExternalKey_To', MakeClassHLink($oAttDef->GetTargetClass(), $sContext));
            if (array_key_exists($sAttCode, $aForwardChangeTracking)) {
                $oLinkSet = $aForwardChangeTracking[$sAttCode];
                $sRemoteClass = $oLinkSet->GetHostClass();
                $sValue = $sValue . "<span title=\"Forward changes to {$sRemoteClass}\">*</span>";
            }
        } elseif ($oAttDef->IsLinkSet()) {
            $sValue = MakeClassHLink($oAttDef->GetLinkedClass(), $sContext);
        } else {
            $sValue = $oAttDef->GetDescription();
        }
        $sType = $oAttDef->GetType() . ' (' . $oAttDef->GetTypeDesc() . ')';
        $sOrigin = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
        $sAllowedValues = "";
        $sMoreInfo = "";
        $aCols = array();
        foreach ($oAttDef->GetSQLColumns() as $sCol => $sFieldDesc) {
            $aCols[] = "{$sCol}: {$sFieldDesc}";
        }
        if (count($aCols) > 0) {
            $sCols = implode(', ', $aCols);
            $aMoreInfo = array();
            $aMoreInfo[] = Dict::Format('UI:Schema:Columns_Description', $sCols);
            $aMoreInfo[] = Dict::Format('UI:Schema:Default_Description', $oAttDef->GetDefaultValue());
            $aMoreInfo[] = $oAttDef->IsNullAllowed() ? Dict::S('UI:Schema:NullAllowed') : Dict::S('UI:Schema:NullNotAllowed');
            $sMoreInfo .= implode(', ', $aMoreInfo);
        }
        if ($oAttDef instanceof AttributeEnum) {
            // Display localized values for the enum (which depend on the localization provided by the class)
            $aLocalizedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array());
            $aDescription = array();
            foreach ($aLocalizedValues as $val => $sDisplay) {
                $aDescription[] = htmlentities("{$val} => ", ENT_QUOTES, 'UTF-8') . $sDisplay;
            }
            $sAllowedValues = implode(', ', $aDescription);
        } else {
            $sAllowedValues = '';
        }
        $aDetails[] = array('code' => $oAttDef->GetCode(), 'type' => $sType, 'origin' => $sOrigin, 'label' => $oAttDef->GetLabel(), 'description' => $sValue, 'values' => $sAllowedValues, 'moreinfo' => $sMoreInfo);
    }
    $oPage->SetCurrentTab(Dict::S('UI:Schema:Attributes'));
    $aConfig = array('code' => array('label' => Dict::S('UI:Schema:AttributeCode'), 'description' => Dict::S('UI:Schema:AttributeCode+')), 'label' => array('label' => Dict::S('UI:Schema:Label'), 'description' => Dict::S('UI:Schema:Label+')), 'type' => array('label' => Dict::S('UI:Schema:Type'), 'description' => Dict::S('UI:Schema:Type+')), 'origin' => array('label' => Dict::S('UI:Schema:Origin'), 'description' => Dict::S('UI:Schema:Origin+')), 'description' => array('label' => Dict::S('UI:Schema:Description'), 'description' => Dict::S('UI:Schema:Description+')), 'values' => array('label' => Dict::S('UI:Schema:AllowedValues'), 'description' => Dict::S('UI:Schema:AllowedValues+')), 'moreinfo' => array('label' => Dict::S('UI:Schema:MoreInfo'), 'description' => Dict::S('UI:Schema:MoreInfo+')));
    $oPage->table($aConfig, $aDetails);
    // List the search criteria for this object
    $aDetails = array();
    foreach (MetaModel::GetClassFilterDefs($sClass) as $sFilterCode => $oFilterDef) {
        $aOpDescs = array();
        foreach ($oFilterDef->GetOperators() as $sOpCode => $sOpDescription) {
            $sIsTheLooser = $sOpCode == $oFilterDef->GetLooseOperator() ? " (loose search)" : "";
            $aOpDescs[] = "{$sOpCode} ({$sOpDescription}){$sIsTheLooser}";
        }
        $aDetails[] = array('code' => $sFilterCode, 'description' => $oFilterDef->GetLabel(), 'operators' => implode(" / ", $aOpDescs));
    }
    $oPage->SetCurrentTab(Dict::S('UI:Schema:SearchCriteria'));
    $aConfig = array('code' => array('label' => Dict::S('UI:Schema:FilterCode'), 'description' => Dict::S('UI:Schema:FilterCode+')), 'description' => array('label' => Dict::S('UI:Schema:FilterDescription'), 'description' => Dict::S('UI:Schema:FilterDescription+')), 'operators' => array('label' => Dict::S('UI:Schema:AvailOperators'), 'description' => Dict::S('UI:Schema:AvailOperators+')));
    $oPage->table($aConfig, $aDetails);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:ChildClasses'));
    DisplaySubclasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:ReferencingClasses'));
    DisplayReferencingClasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:RelatedClasses'));
    DisplayRelatedClasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:LifeCycle'));
    DisplayLifecycle($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:Triggers'));
    DisplayTriggers($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab();
    $oPage->SetCurrentTabContainer();
}
 /**
  * Maps an external key to its (newly created) value
  */
 protected function ResolveExternalKeys()
 {
     foreach ($this->m_aObjectsCache as $sClass => $oObjList) {
         foreach ($oObjList as $oTargetObj) {
             $bChanged = false;
             $sClass = get_class($oTargetObj);
             foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
                 if ($oAttDef->IsExternalKey() && $oTargetObj->Get($sAttCode) < 0) {
                     $sTargetClass = $oAttDef->GetTargetClass();
                     $iTempKey = $oTargetObj->Get($sAttCode);
                     $iExtKey = $this->GetObjectKey($sTargetClass, -$iTempKey);
                     if ($iExtKey == 0) {
                         $sMsg = "unresolved extkey in {$sClass}::" . $oTargetObj->GetKey() . "(" . $oTargetObj->GetName() . ")::{$sAttCode}={$sTargetClass}::{$iTempKey}";
                         SetupPage::log_warning($sMsg);
                         $this->m_aWarnings[] = $sMsg;
                         //echo "<pre>aKeys[".$sTargetClass."]:\n";
                         //print_r($this->m_aKeys[$sTargetClass]);
                         //echo "</pre>\n";
                     } else {
                         $bChanged = true;
                         $oTargetObj->Set($sAttCode, $iExtKey);
                     }
                 }
             }
             if ($bChanged) {
                 try {
                     if (is_subclass_of($oTargetObj, 'CMDBObject')) {
                         $oTargetObj->DBUpdateTracked($this->m_oChange);
                     } else {
                         $oTargetObj->DBUpdate();
                     }
                 } catch (Exception $e) {
                     $this->m_aErrors[] = "The object changes could not be tracked - {$sClass}/{$iExtKey} - " . $e->getMessage();
                 }
             }
         }
     }
     return true;
 }
Пример #13
0
 /**
  * The email recipient is the person who is allowed to regain control when the password gets lost	
  * Throws an exception if the feature cannot be available
  */
 public function GetResetPasswordEmail()
 {
     if (!MetaModel::IsValidAttCode(get_class($this), 'contactid')) {
         throw new Exception(Dict::S('UI:ResetPwd-Error-NoContact'));
     }
     $iContactId = $this->Get('contactid');
     if ($iContactId == 0) {
         throw new Exception(Dict::S('UI:ResetPwd-Error-NoContact'));
     }
     $oContact = MetaModel::GetObject('Contact', $iContactId);
     // Determine the email attribute (the first one will be our choice)
     foreach (MetaModel::ListAttributeDefs(get_class($oContact)) as $sAttCode => $oAttDef) {
         if ($oAttDef instanceof AttributeEmailAddress) {
             $sEmailAttCode = $sAttCode;
             // we've got one, exit the loop
             break;
         }
     }
     if (!isset($sEmailAttCode)) {
         throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmailAtt'));
     }
     $sRes = trim($oContact->Get($sEmailAttCode));
     return $sRes;
 }
Пример #14
0
function MakeDictionaryTemplate($sModules = '', $sLanguage = 'EN US')
{
    $sRes = '';
    Dict::SetDefaultLanguage($sLanguage);
    $aAvailableLanguages = Dict::GetLanguages();
    $sDesc = $aAvailableLanguages[$sLanguage]['description'];
    $sLocalizedDesc = $aAvailableLanguages[$sLanguage]['localized_description'];
    $sRes .= "// Dictionary conventions\n";
    $sRes .= htmlentities("// Class:<class_name>\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>+\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>+\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>/Value:<value>\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Stimulus:<stimulus_code>\n", ENT_QUOTES, 'UTF-8');
    $sRes .= htmlentities("// Class:<class_name>/Stimulus:<stimulus_code>+\n", ENT_QUOTES, 'UTF-8');
    $sRes .= "\n";
    // Note: I did not use EnumCategories(), because a given class maybe found in several categories
    // Need to invent the "module", to characterize the origins of a class
    if (strlen($sModules) == 0) {
        $aModules = array('bizmodel', 'core/cmdb', 'gui', 'application', 'addon/userrights', 'monitoring');
    } else {
        $aModules = explode(', ', $sModules);
    }
    $sRes .= "//////////////////////////////////////////////////////////////////////\n";
    $sRes .= "// Note: The classes have been grouped by categories: " . implode(', ', $aModules) . "\n";
    $sRes .= "//////////////////////////////////////////////////////////////////////\n";
    foreach ($aModules as $sCategory) {
        $sRes .= "//////////////////////////////////////////////////////////////////////\n";
        $sRes .= "// Classes in '{$sCategory}'\n";
        $sRes .= "//////////////////////////////////////////////////////////////////////\n";
        $sRes .= "//\n";
        $sRes .= "\n";
        foreach (MetaModel::GetClasses($sCategory) as $sClass) {
            if (!MetaModel::HasTable($sClass)) {
                continue;
            }
            $bNotInDico = false;
            $bNotImportant = true;
            $sClassRes = "//\n";
            $sClassRes .= "// Class: {$sClass}\n";
            $sClassRes .= "//\n";
            $sClassRes .= "\n";
            $sClassRes .= "Dict::Add('{$sLanguage}', '{$sDesc}', '{$sLocalizedDesc}', array(\n";
            $sClassRes .= MakeDictEntry("Class:{$sClass}", MetaModel::GetName_Obsolete($sClass), $sClass, $bNotInDico);
            $sClassRes .= MakeDictEntry("Class:{$sClass}+", MetaModel::GetClassDescription_Obsolete($sClass), '', $bNotImportant);
            foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
                if ($sAttCode == 'friendlyname') {
                    continue;
                }
                // Skip this attribute if not originaly defined in this class
                if (MetaModel::GetAttributeOrigin($sClass, $sAttCode) != $sClass) {
                    continue;
                }
                $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}", $oAttDef->GetLabel_Obsolete(), $sAttCode, $bNotInDico);
                $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}+", $oAttDef->GetDescription_Obsolete(), '', $bNotImportant);
                if ($oAttDef instanceof AttributeEnum) {
                    if (MetaModel::GetStateAttributeCode($sClass) == $sAttCode) {
                        foreach (MetaModel::EnumStates($sClass) as $sStateCode => $aStateData) {
                            if (array_key_exists('label', $aStateData)) {
                                $sValue = $aStateData['label'];
                            } else {
                                $sValue = MetaModel::GetStateLabel($sClass, $sStateCode);
                            }
                            if (array_key_exists('description', $aStateData)) {
                                $sValuePlus = $aStateData['description'];
                            } else {
                                $sValuePlus = MetaModel::GetStateDescription($sClass, $sStateCode);
                            }
                            $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sStateCode}", $sValue, '', $bNotInDico);
                            $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sStateCode}+", $sValuePlus, '', $bNotImportant);
                        }
                    } else {
                        foreach ($oAttDef->GetAllowedValues() as $sKey => $value) {
                            $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sKey}", $value, '', $bNotInDico);
                            $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sKey}+", $value, '', $bNotImportant);
                        }
                    }
                }
            }
            foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) {
                $sClassRes .= MakeDictEntry("Class:{$sClass}/Stimulus:{$sStimulusCode}", $oStimulus->GetLabel_Obsolete(), '', $bNotInDico);
                $sClassRes .= MakeDictEntry("Class:{$sClass}/Stimulus:{$sStimulusCode}+", $oStimulus->GetDescription_Obsolete(), '', $bNotImportant);
            }
            $sClassRes .= "));\n";
            $sClassRes .= "\n";
            $sRes .= $sClassRes;
        }
    }
    return $sRes;
}
Пример #15
0
 /**
  * Helpr to clone (in memory) an object and to apply to it the values taken from a second object
  * @param DBObject $oObjToClone
  * @param DBObject $oObjWithValues
  * @return DBObject The modified clone
  */
 protected function CopyFrom($oObjToClone, $oObjWithValues)
 {
     $oObj = MetaModel::GetObject(get_class($oObjToClone), $oObjToClone->GetKey());
     foreach (MetaModel::ListAttributeDefs(get_class($oObj)) as $sAttCode => $oAttDef) {
         if (!in_array($sAttCode, $this->aExcludedColumns) && $oAttDef->IsWritable()) {
             $oObj->Set($sAttCode, $oObjWithValues->Get($sAttCode));
         }
     }
     return $oObj;
 }
Пример #16
0
 $aValues = array();
 $aObjects = array();
 foreach ($aSelectObject as $iId) {
     $aObjects[] = MetaModel::GetObject($sClass, $iId);
 }
 $oSet = DBObjectSet::FromArray($sClass, $aObjects);
 $oObj = $oSet->ComputeCommonObject($aValues);
 $sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
 $oObj->Set($sStateAttCode, $sTargetState);
 $sReadyScript = '';
 foreach ($aExpectedAttributes as $sAttCode => $iExpectCode) {
     // Prompt for an attribute if
     // - the attribute must be changed or must be displayed to the user for confirmation
     // - or the field is mandatory and currently empty
     if ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT) || $iExpectCode & OPT_ATT_MANDATORY && $oObj->Get($sAttCode) == '') {
         $aAttributesDef = MetaModel::ListAttributeDefs($sClass);
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
         $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
         // List of attributes that are needed for the current one
         if (count($aPrerequisites) > 0) {
             // When 'enabling' a field, all its prerequisites must be enabled too
             $sFieldList = "['" . implode("','", $aPrerequisites) . "']";
             $oP->add_ready_script("\$('#enable_{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, true); } );\n");
         }
         $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode);
         // List of attributes that are needed for the current one
         if (count($aDependents) > 0) {
             // When 'disabling' a field, all its dependent fields must be disabled too
             $sFieldList = "['" . implode("','", $aDependents) . "']";
             $oP->add_ready_script("\$('#enable_{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, false); } );\n");
         }
 /**
  * Read a list of attribute codes from a Rest/Json structure.
  * 	 
  * @param string $sClass Name of the class
  * @param StdClass $oData Structured input data.
  * @param string $sParamName Name of the parameter to fetch from the input data
  * @return An array of class => list of attributes (see RestResultWithObjects::AddObject that uses it)
  * @throws Exception
  * @api
  */
 public static function GetFieldList($sClass, $oData, $sParamName)
 {
     $sFields = self::GetOptionalParam($oData, $sParamName, '*');
     $aShowFields = array();
     if ($sFields == '*') {
         foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
             $aShowFields[$sClass][] = $sAttCode;
         }
     } elseif ($sFields == '*+') {
         foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sRefClass) {
             foreach (MetaModel::ListAttributeDefs($sRefClass) as $sAttCode => $oAttDef) {
                 $aShowFields[$sRefClass][] = $sAttCode;
             }
         }
     } else {
         foreach (explode(',', $sFields) as $sAttCode) {
             $sAttCode = trim($sAttCode);
             if ($sAttCode != 'id' && !MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                 throw new Exception("{$sParamName}: invalid attribute code '{$sAttCode}'");
             }
             $aShowFields[$sClass][] = $sAttCode;
         }
     }
     return $aShowFields;
 }
    /**
     * Display a form for modifying several objects at once
     * The form will be submitted to the current page, with the specified additional values	 
     */
    public static function DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, $sCustomOperation, $sCancelUrl, $aExcludeAttributes = array(), $aContextData = array())
    {
        if (count($aSelectedObj) > 0) {
            $iAllowedCount = count($aSelectedObj);
            $sSelectedObj = implode(',', $aSelectedObj);
            $sOQL = "SELECT {$sClass} WHERE id IN (" . $sSelectedObj . ")";
            $oSet = new CMDBObjectSet(DBObjectSearch::FromOQL($sOQL));
            // Compute the distribution of the values for each field to determine which of the "scalar" fields are homogenous
            $aList = MetaModel::ListAttributeDefs($sClass);
            $aValues = array();
            foreach ($aList as $sAttCode => $oAttDef) {
                if ($oAttDef->IsScalar()) {
                    $aValues[$sAttCode] = array();
                }
            }
            while ($oObj = $oSet->Fetch()) {
                foreach ($aList as $sAttCode => $oAttDef) {
                    if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
                        $currValue = $oObj->Get($sAttCode);
                        if ($oAttDef instanceof AttributeCaseLog) {
                            $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 (!array_key_exists($currValue, $aValues[$sAttCode])) {
                            $aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
                        } else {
                            $aValues[$sAttCode][$currValue]['count']++;
                        }
                    }
                }
            }
            // Now create an object that has values for the homogenous values only
            $oDummyObj = new $sClass();
            // @@ What if the class is abstract ?
            $aComments = array();
            function MyComparison($a, $b)
            {
                if ($a['count'] == $b['count']) {
                    return 0;
                }
                return $a['count'] > $b['count'] ? -1 : 1;
            }
            $iFormId = cmdbAbstractObject::GetNextFormId();
            // Identifier that prefixes all the form fields
            $sReadyScript = '';
            $aDependsOn = array();
            $sFormPrefix = '2_';
            foreach ($aList as $sAttCode => $oAttDef) {
                $aPrerequisites = MetaModel::GetPrequisiteAttributes($sClass, $sAttCode);
                // List of attributes that are needed for the current one
                if (count($aPrerequisites) > 0) {
                    // When 'enabling' a field, all its prerequisites must be enabled too
                    $sFieldList = "['{$sFormPrefix}" . implode("','{$sFormPrefix}", $aPrerequisites) . "']";
                    $oP->add_ready_script("\$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, true); } );\n");
                }
                $aDependents = MetaModel::GetDependentAttributes($sClass, $sAttCode);
                // List of attributes that are needed for the current one
                if (count($aDependents) > 0) {
                    // When 'disabling' a field, all its dependent fields must be disabled too
                    $sFieldList = "['{$sFormPrefix}" . implode("','{$sFormPrefix}", $aDependents) . "']";
                    $oP->add_ready_script("\$('#enable_{$sFormPrefix}{$sAttCode}').bind('change', function(evt, sFormId) { return PropagateCheckBox( this.checked, {$sFieldList}, false); } );\n");
                }
                if ($oAttDef->IsScalar() && $oAttDef->IsWritable()) {
                    if ($oAttDef->GetEditClass() == 'One Way Password') {
                        $sTip = "Unknown values";
                        $sReadyScript .= "\$('#multi_values_{$sAttCode}').qtip( { content: '{$sTip}', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );";
                        $oDummyObj->Set($sAttCode, null);
                        $aComments[$sAttCode] = '<input type="checkbox" id="enable_' . $iFormId . '_' . $sAttCode . '" onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                        $aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_' . $sAttCode . '"> ? </div>';
                        $sReadyScript .= 'ToogleField(false, \'' . $iFormId . '_' . $sAttCode . '\');' . "\n";
                    } else {
                        $iCount = count($aValues[$sAttCode]);
                        if ($iCount == 1) {
                            // Homogenous value
                            reset($aValues[$sAttCode]);
                            $aKeys = array_keys($aValues[$sAttCode]);
                            $currValue = $aKeys[0];
                            // The only value is the first key
                            //echo "<p>current value for $sAttCode : $currValue</p>";
                            $oDummyObj->Set($sAttCode, $currValue);
                            $aComments[$sAttCode] = '<input type="checkbox" checked id="enable_' . $iFormId . '_' . $sAttCode . '"  onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                            $aComments[$sAttCode] .= '<div class="mono_value">1</div>';
                        } else {
                            // Non-homogenous value
                            $aMultiValues = $aValues[$sAttCode];
                            uasort($aMultiValues, 'MyComparison');
                            $iMaxCount = 5;
                            $sTip = "<p><b>" . Dict::Format('UI:BulkModify_Count_DistinctValues', $iCount) . "</b><ul>";
                            $index = 0;
                            foreach ($aMultiValues as $sCurrValue => $aVal) {
                                $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>";
                                $index++;
                                if ($iMaxCount == $index) {
                                    $sTip .= "<li>" . Dict::Format('UI:BulkModify:N_MoreValues', count($aMultiValues) - $iMaxCount) . "</li>";
                                    break;
                                }
                            }
                            $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' }} } );";
                            $oDummyObj->Set($sAttCode, null);
                            $aComments[$sAttCode] = '<input type="checkbox" id="enable_' . $iFormId . '_' . $sAttCode . '" onClick="ToogleField(this.checked, \'' . $iFormId . '_' . $sAttCode . '\')"/>';
                            $aComments[$sAttCode] .= '<div class="multi_values" id="multi_values_' . $sAttCode . '">' . $iCount . '</div>';
                        }
                        $sReadyScript .= 'ToogleField(' . ($iCount == 1 ? 'true' : 'false') . ', \'' . $iFormId . '_' . $sAttCode . '\');' . "\n";
                    }
                }
            }
            $sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
            if ($sStateAttCode != '' && $oDummyObj->GetState() == '') {
                // Hmmm, it's not gonna work like this ! Set a default value for the "state"
                // Maybe we should use the "state" that is the most common among the objects...
                $aMultiValues = $aValues[$sStateAttCode];
                uasort($aMultiValues, 'MyComparison');
                foreach ($aMultiValues as $sCurrValue => $aVal) {
                    $oDummyObj->Set($sStateAttCode, $sCurrValue);
                    break;
                }
                //$oStateAtt = MetaModel::GetAttributeDef($sClass, $sStateAttCode);
                //$oDummyObj->Set($sStateAttCode, $oStateAtt->GetDefaultValue());
            }
            $oP->add("<div class=\"page_header\">\n");
            $oP->add("<h1>" . $oDummyObj->GetIcon() . "&nbsp;" . Dict::Format('UI:Modify_M_ObjectsOf_Class_OutOf_N', $iAllowedCount, $sClass, $iAllowedCount) . "</h1>\n");
            $oP->add("</div>\n");
            $oP->add("<div class=\"wizContainer\">\n");
            $sDisableFields = json_encode($aExcludeAttributes);
            $aParams = array('fieldsComments' => $aComments, 'noRelations' => true, 'custom_operation' => $sCustomOperation, 'custom_button' => Dict::S('UI:Button:PreviewModifications'), 'selectObj' => $sSelectedObj, 'preview_mode' => true, 'disabled_fields' => $sDisableFields, 'disable_plugins' => true);
            $aParams = $aParams + $aContextData;
            // merge keeping associations
            $oDummyObj->DisplayModifyForm($oP, $aParams);
            $oP->add("</div>\n");
            $oP->add_ready_script($sReadyScript);
            $oP->add_ready_script(<<<EOF
\$('.wizContainer button.cancel').unbind('click');
\$('.wizContainer button.cancel').click( function() { window.location.href = '{$sCancelUrl}'; } );
EOF
);
        } else {
            $oP->p("No object selected !, nothing to do");
        }
    }
 /**
  * Find the corresponding "link" attribute on the target class
  * 	 
  * @return string The attribute code on the target class, or null if none has been found
  */
 public function GetMirrorLinkAttribute()
 {
     $oRet = null;
     $sRemoteClass = $this->GetTargetClass();
     foreach (MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) {
         if (!$oRemoteAttDef->IsLinkSet()) {
             continue;
         }
         if (!is_subclass_of($this->GetHostClass(), $oRemoteAttDef->GetLinkedClass()) && $oRemoteAttDef->GetLinkedClass() != $this->GetHostClass()) {
             continue;
         }
         if ($oRemoteAttDef->GetExtKeyToMe() != $this->GetCode()) {
             continue;
         }
         $oRet = $oRemoteAttDef;
         break;
     }
     return $oRet;
 }
 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));
                 }
                 $aValues[$sAttCode] = $sValue;
             }
         }
         // 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 CMDBSearchFilter($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;
 }
Пример #21
0
 /**
  * Helper to search for the redundancy attribute	
  */
 protected function FindRedundancyAttribute($sRelCode, $aQueryInfo, $sClass)
 {
     $oRet = null;
     foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
         if ($oAttDef instanceof AttributeRedundancySettings) {
             if ($oAttDef->Get('relation_code') == $sRelCode) {
                 if ($oAttDef->Get('neighbour_id') == $aQueryInfo['sNeighbour']) {
                     $oRet = $oAttDef;
                     break;
                 }
             }
         }
     }
     return $oRet;
 }
 /**
  * Prepare the given object set with the list of fields as read into $this->aStatusInfo['fields']
  */
 protected function OptimizeColumnLoad(DBObjectSet $oSet)
 {
     $aColumnsToLoad = array();
     foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
         $sClass = $aFieldSpec['sClass'];
         $sAlias = $aFieldSpec['sAlias'];
         $sAttCode = $aFieldSpec['sAttCode'];
         if (!array_key_exists($sAlias, $aColumnsToLoad)) {
             $aColumnsToLoad[$sAlias] = array();
         }
         // id is not a real attribute code and, moreover, is always loaded
         if ($sAttCode != 'id') {
             // Extended attributes are not recognized by DBObjectSet::OptimizeColumnLoad
             if (($iPos = strpos($sAttCode, '->')) === false) {
                 $aColumnsToLoad[$sAlias][] = $sAttCode;
                 $sClass = '???';
             } else {
                 $sExtKeyAttCode = substr($sAttCode, 0, $iPos);
                 $sRemoteAttCode = substr($sAttCode, $iPos + 2);
                 // Load the external key to avoid an object reload!
                 $aColumnsToLoad[$sAlias][] = $sExtKeyAttCode;
                 // Load the external field (if any) to avoid getting the remote object (see DBObject::Get that does the same)
                 $oExtFieldAtt = MetaModel::FindExternalField($sClass, $sExtKeyAttCode, $sRemoteAttCode);
                 if (!is_null($oExtFieldAtt)) {
                     $aColumnsToLoad[$sAlias][] = $oExtFieldAtt->GetCode();
                 }
             }
         }
     }
     // Add "always loaded attributes"
     //
     $aSelectedClasses = $this->oSearch->GetSelectedClasses();
     foreach ($aSelectedClasses as $sAlias => $sClass) {
         foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
             if ($oAttDef->AlwaysLoadInTables()) {
                 $aColumnsToLoad[$sAlias][] = $sAttCode;
             }
         }
     }
     $oSet->OptimizeColumnLoad($aColumnsToLoad);
 }
Пример #23
0
/**
 * Helper function to build the mapping drop-down list for a field
 * Spec: Possible choices are "writable" fields in this class plus external fields that are listed as reconciliation keys
 *       for any class pointed to by an external key in the current class.
 *       If not in advanced mode, all "id" fields (id and external keys) must be mapped to ":none:" (i.e -- ignore this field --)
 *       External fields that do not correspond to a reconciliation key must be mapped to ":none:"
 *       Otherwise, if a field equals either the 'code' or the 'label' (translated) of a field, then it's mapped automatically
 * @param string $sClassName Name of the class used for the mapping
 * @param string $sFieldName Name of the field, as it comes from the data file (header line)
 * @param integer $iFieldIndex Number of the field in the sequence
 * @param bool $bAdvancedMode Whether or not advanced mode was chosen
 * @param string $sDefaultChoice If set, this will be the item selected by default
 * @return string The HTML code corresponding to the drop-down list for this field
 */
function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode, $sDefaultChoice)
{
    $aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
    $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
    $sFieldCode = '';
    // Code of the attribute, if there is a match
    $aMatches = array();
    if (preg_match('/^(.+)\\*$/', $sFieldName, $aMatches)) {
        // Remove any trailing "star" character.
        // A star character at the end can be used to indicate a mandatory field
        $sFieldName = $aMatches[1];
    } else {
        if (preg_match('/^(.+)\\*->(.+)$/', $sFieldName, $aMatches)) {
            // Remove any trailing "star" character before the arrow (->)
            // A star character at the end can be used to indicate a mandatory field
            $sFieldName = $aMatches[1] . '->' . $aMatches[2];
        }
    }
    if ($sFieldName == 'id') {
        $sFieldCode = 'id';
    }
    if ($bAdvancedMode) {
        $aChoices['id'] = Dict::S('UI:CSVImport:idField');
    }
    foreach (MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef) {
        $sStar = '';
        if ($oAttDef->IsExternalKey()) {
            if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                $sFieldCode = $sAttCode;
            }
            if ($bAdvancedMode) {
                $aChoices[$sAttCode] = $oAttDef->GetLabel();
            }
            $oExtKeyAttDef = MetaModel::GetAttributeDef($sClassName, $oAttDef->GetKeyAttCode());
            if (!$oExtKeyAttDef->IsNullAllowed()) {
                $sStar = '*';
            }
            // Get fields of the external class that are considered as reconciliation keys
            $sTargetClass = $oAttDef->GetTargetClass();
            foreach (MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef) {
                if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode)) {
                    $bExtKey = $oTargetAttDef->IsExternalKey();
                    $sSuffix = '';
                    if ($bExtKey) {
                        $sSuffix = '->id';
                    }
                    if ($bAdvancedMode || !$bExtKey) {
                        // When not in advanced mode do not allow to use reconciliation keys (on external keys) if they are themselves external keys !
                        $aChoices[$sAttCode . '->' . $sTargetAttCode] = MetaModel::GetLabel($sClassName, $sAttCode . '->' . $sTargetAttCode, true);
                        if (strcasecmp($sFieldName, $oAttDef->GetLabel() . '->' . $oTargetAttDef->GetLabel() . $sSuffix) == 0 || strcasecmp($sFieldName, $sAttCode . '->' . $sTargetAttCode . $sSuffix) == 0) {
                            $sFieldCode = $sAttCode . '->' . $sTargetAttCode;
                        }
                    }
                }
            }
        } else {
            if ($oAttDef->IsWritable() && (!$oAttDef->IsLinkset() || $bAdvancedMode && $oAttDef->IsIndirect())) {
                $aChoices[$sAttCode] = MetaModel::GetLabel($sClassName, $sAttCode, true);
                if ($sFieldName == $oAttDef->GetLabel() || $sFieldName == $sAttCode) {
                    $sFieldCode = $sAttCode;
                }
            }
        }
    }
    asort($aChoices);
    $sHtml = "<select id=\"mapping_{$iFieldIndex}\" name=\"field[{$iFieldIndex}]\">\n";
    $bIsIdField = IsIdField($sClassName, $sFieldCode);
    foreach ($aChoices as $sAttCode => $sLabel) {
        $sSelected = '';
        if ($bIsIdField && !$bAdvancedMode) {
            if ($sAttCode == ':none:') {
                $sSelected = ' selected';
            }
        } else {
            if (empty($sFieldCode) && strpos($sFieldName, '->') !== false) {
                if ($sAttCode == ':none:') {
                    $sSelected = ' selected';
                }
            } else {
                if (is_null($sDefaultChoice) && $sFieldCode == $sAttCode) {
                    $sSelected = ' selected';
                } else {
                    if (!is_null($sDefaultChoice) && $sDefaultChoice == $sAttCode) {
                        $sSelected = ' selected';
                    }
                }
            }
        }
        $sHtml .= "<option value=\"{$sAttCode}\"{$sSelected}>{$sLabel}</option>\n";
    }
    $sHtml .= "</select>\n";
    return $sHtml;
}
    protected function GetInteractiveFieldsWidget(WebPage $oP, $sWidgetId)
    {
        $oSet = new DBObjectSet($this->oSearch);
        $aSelectedClasses = $this->oSearch->GetSelectedClasses();
        $aAuthorizedClasses = array();
        foreach ($aSelectedClasses as $sAlias => $sClassName) {
            if (UserRights::IsActionAllowed($sClassName, UR_ACTION_BULK_READ, $oSet) && (UR_ALLOWED_YES || UR_ALLOWED_DEPENDS)) {
                $aAuthorizedClasses[$sAlias] = $sClassName;
            }
        }
        $aAllFieldsByAlias = array();
        foreach ($aAuthorizedClasses as $sAlias => $sClass) {
            $aAllFields = array();
            if (count($aAuthorizedClasses) > 1) {
                $sShortAlias = $sAlias . '.';
            } else {
                $sShortAlias = '';
            }
            if ($this->IsValidField($sClass, 'id')) {
                $aAllFields[] = array('code' => $sShortAlias . 'id', 'unique_label' => $sShortAlias . Dict::S('Core:BulkExport:Identifier'), 'label' => $sShortAlias . 'id', 'subattr' => array(array('code' => $sShortAlias . 'id', 'unique_label' => $sShortAlias . Dict::S('Core:BulkExport:Identifier'), 'label' => $sShortAlias . 'id'), array('code' => $sShortAlias . 'friendlyname', 'unique_label' => $sShortAlias . Dict::S('Core:BulkExport:Friendlyname'), 'label' => $sShortAlias . Dict::S('Core:BulkExport:Friendlyname'))));
            }
            foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
                if ($this->IsSubAttribute($sClass, $sAttCode, $oAttDef)) {
                    continue;
                }
                if ($this->IsValidField($sClass, $sAttCode, $oAttDef)) {
                    $sShortLabel = $oAttDef->GetLabel();
                    $sLabel = $sShortAlias . $oAttDef->GetLabel();
                    $aSubAttr = $this->GetSubAttributes($sClass, $sAttCode, $oAttDef);
                    $aValidSubAttr = array();
                    foreach ($aSubAttr as $aSubAttDef) {
                        if ($this->IsValidField($sClass, $aSubAttDef['code'], $aSubAttDef['attdef'])) {
                            $aValidSubAttr[] = array('code' => $sShortAlias . $aSubAttDef['code'], 'label' => $aSubAttDef['label'], 'unique_label' => $aSubAttDef['unique_label']);
                        }
                    }
                    $aAllFields[] = array('code' => $sShortAlias . $sAttCode, 'label' => $sShortLabel, 'unique_label' => $sLabel, 'subattr' => $aValidSubAttr);
                }
            }
            usort($aAllFields, array(get_class($this), 'SortOnLabel'));
            if (count($aAuthorizedClasses) > 1) {
                $sKey = MetaModel::GetName($sClass) . ' (' . $sAlias . ')';
            } else {
                $sKey = MetaModel::GetName($sClass);
            }
            $aAllFieldsByAlias[$sKey] = $aAllFields;
        }
        $oP->add('<div id="' . $sWidgetId . '"></div>');
        $JSAllFields = json_encode($aAllFieldsByAlias);
        $oSet = new DBObjectSet($this->oSearch);
        $iCount = $oSet->Count();
        $iPreviewLimit = 3;
        $oSet->SetLimit($iPreviewLimit);
        $aSampleData = array();
        while ($aRow = $oSet->FetchAssoc()) {
            $aSampleRow = array();
            foreach ($aAuthorizedClasses as $sAlias => $sClass) {
                if (count($aAuthorizedClasses) > 1) {
                    $sShortAlias = $sAlias . '.';
                } else {
                    $sShortAlias = '';
                }
                if ($this->IsValidField($sClass, 'id')) {
                    $aSampleRow[$sShortAlias . 'id'] = $this->GetSampleKey($aRow[$sAlias]);
                }
                foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
                    if ($this->IsValidField($sClass, $sAttCode, $oAttDef)) {
                        $aSampleRow[$sShortAlias . $sAttCode] = $this->GetSampleData($aRow[$sAlias], $sAttCode);
                    }
                }
            }
            $aSampleData[] = $aSampleRow;
        }
        $sJSSampleData = json_encode($aSampleData);
        $aLabels = array('preview_header' => Dict::S('Core:BulkExport:DragAndDropHelp'), 'empty_preview' => Dict::S('Core:BulkExport:EmptyPreview'), 'columns_order' => Dict::S('Core:BulkExport:ColumnsOrder'), 'columns_selection' => Dict::S('Core:BulkExport:AvailableColumnsFrom_Class'), 'check_all' => Dict::S('Core:BulkExport:CheckAll'), 'uncheck_all' => Dict::S('Core:BulkExport:UncheckAll'), 'no_field_selected' => Dict::S('Core:BulkExport:NoFieldSelected'));
        $sJSLabels = json_encode($aLabels);
        $oP->add_ready_script(<<<EOF
\$('#{$sWidgetId}').tabularfieldsselector({fields: {$JSAllFields}, value_holder: '#tabular_fields', advanced_holder: '#tabular_advanced', sample_data: {$sJSSampleData}, total_count: {$iCount}, preview_limit: {$iPreviewLimit}, labels: {$sJSLabels} });
EOF
);
    }
Пример #25
0
 protected function FixVisibleColumns()
 {
     foreach ($this->aClassAliases as $sAlias => $sClass) {
         foreach ($this->aColumns[$sAlias] as $sAttCode => $aData) {
             // Remove non-existent columns
             // TODO: check if the existing ones are still valid (in case their type changed)
             if ($sAttCode != '_key_' && !MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                 unset($this->aColumns[$sAlias][$sAttCode]);
             }
         }
         $aList = MetaModel::ListAttributeDefs($sClass);
         // Add the other (non visible ones), sorted in alphabetical order
         $aTempData = array();
         foreach ($aList as $sAttCode => $oAttDef) {
             if (!array_key_exists($sAttCode, $this->aColumns[$sAlias]) && !$oAttDef instanceof AttributeLinkSet) {
                 $aFieldData = $this->GetFieldData($sAlias, $sAttCode, $oAttDef, false, 'none');
                 if ($aFieldData) {
                     $aTempData[$aFieldData['label']] = $aFieldData;
                 }
             }
         }
         ksort($aTempData);
         foreach ($aTempData as $sLabel => $aFieldData) {
             $this->aColumns[$sAlias][$aFieldData['code']] = $aFieldData;
         }
     }
 }
Пример #26
0
 public function DisplayDetails(WebPage $oPage, $bEditMode = false)
 {
     $oPage->add('<h1>' . MetaModel::GetName(get_class($this)) . ': ' . $this->GetName() . '</h1>');
     $aValues = array();
     $aList = MetaModel::FlattenZList(MetaModel::GetZListItems(get_class($this), 'details'));
     if (empty($aList)) {
         $aList = array_keys(MetaModel::ListAttributeDefs(get_class($this)));
     }
     foreach ($aList as $sAttCode) {
         $aValues[$sAttCode] = array('label' => MetaModel::GetLabel(get_class($this), $sAttCode), 'value' => $this->GetAsHTML($sAttCode));
     }
     $oPage->details($aValues);
 }
Пример #27
0
 public function Render(WebPage $oPage, $aParams = array(), $bEditMode = false)
 {
     $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this->m_oObj));
     $aTemplateFields = array();
     preg_match_all('/\\$this->([a-z0-9_]+)\\$/', $this->m_sTemplate, $aMatches);
     foreach ($aMatches[1] as $sAttCode) {
         if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode)) {
             $aTemplateFields[] = $sAttCode;
         } else {
             $aParams['this->' . $sAttCode] = "<!--Unknown attribute: {$sAttCode}-->";
         }
     }
     preg_match_all('/\\$this->field\\(([a-z0-9_]+)\\)\\$/', $this->m_sTemplate, $aMatches);
     foreach ($aMatches[1] as $sAttCode) {
         if (MetaModel::IsValidAttCode(get_class($this->m_oObj), $sAttCode)) {
             $aTemplateFields[] = $sAttCode;
         } else {
             $aParams['this->field(' . $sAttCode . ')'] = "<!--Unknown attribute: {$sAttCode}-->";
         }
     }
     $aFieldsComments = isset($aParams['fieldsComments']) ? $aParams['fieldsComments'] : array();
     $aFieldsMap = array();
     $sClass = get_class($this->m_oObj);
     // Renders the fields used in the template
     foreach (MetaModel::ListAttributeDefs(get_class($this->m_oObj)) as $sAttCode => $oAttDef) {
         $aParams['this->label(' . $sAttCode . ')'] = $oAttDef->GetLabel();
         $aParams['this->comments(' . $sAttCode . ')'] = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '';
         $iInputId = '2_' . $sAttCode;
         // TODO: generate a real/unique prefix...
         if (in_array($sAttCode, $aTemplateFields)) {
             if ($this->m_oObj->IsNew()) {
                 $iFlags = $this->m_oObj->GetInitialStateAttributeFlags($sAttCode);
             } else {
                 $iFlags = $this->m_oObj->GetAttributeFlags($sAttCode);
             }
             if ($iFlags & OPT_ATT_MANDATORY && $this->m_oObj->IsNew()) {
                 $iFlags = $iFlags & ~OPT_ATT_READONLY;
                 // Mandatory fields cannot be read-only when creating an object
             }
             if (!$oAttDef->IsWritable() || $sStateAttCode == $sAttCode) {
                 $iFlags = $iFlags | OPT_ATT_READONLY;
             }
             if ($iFlags & OPT_ATT_HIDDEN) {
                 $aParams['this->label(' . $sAttCode . ')'] = '';
                 $aParams['this->field(' . $sAttCode . ')'] = '';
                 $aParams['this->comments(' . $sAttCode . ')'] = '';
                 $aParams['this->' . $sAttCode] = '';
             } else {
                 if ($bEditMode && $iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE)) {
                     // Check if the attribute is not read-only because of a synchro...
                     $aReasons = array();
                     $sSynchroIcon = '';
                     if ($iFlags & OPT_ATT_SLAVE) {
                         $iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
                         $sSynchroIcon = "&nbsp;<img id=\"synchro_{$sInputId}\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>";
                         $sTip = '';
                         foreach ($aReasons as $aRow) {
                             $sTip .= "<p>Synchronized with {$aRow['name']} - {$aRow['description']}</p>";
                         }
                         $oPage->add_ready_script("\$('#synchro_{$iInputId}').qtip( { content: '{$sTip}', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
                     }
                     // Attribute is read-only
                     $sHTMLValue = "<span id=\"field_{$iInputId}\">" . $this->m_oObj->GetAsHTML($sAttCode);
                     $sHTMLValue .= '<input type="hidden" id="' . $iInputId . '" name="attr_' . $sAttCode . '" value="' . htmlentities($this->m_oObj->Get($sAttCode), ENT_QUOTES, 'UTF-8') . '"/></span>';
                     $aFieldsMap[$sAttCode] = $iInputId;
                     $aParams['this->comments(' . $sAttCode . ')'] = $sSynchroIcon;
                 }
                 if ($bEditMode && !($iFlags & OPT_ATT_READONLY)) {
                     $aParams['this->field(' . $sAttCode . ')'] = "<span id=\"field_{$iInputId}\">" . $this->m_oObj->GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $this->m_oObj->Get($sAttCode), $this->m_oObj->GetEditValue($sAttCode), $iInputId, '', $iFlags, array('this' => $this->m_oObj)) . '</span>';
                     $aFieldsMap[$sAttCode] = $iInputId;
                 } else {
                     $aParams['this->field(' . $sAttCode . ')'] = $this->m_oObj->GetAsHTML($sAttCode);
                 }
                 $aParams['this->' . $sAttCode] = "<table class=\"field\"><tr><td class=\"label\">" . $aParams['this->label(' . $sAttCode . ')'] . ":</td><td>" . $aParams['this->field(' . $sAttCode . ')'] . "</td><td>" . $aParams['this->comments(' . $sAttCode . ')'] . "</td></tr></table>";
             }
         }
     }
     // Renders the PlugIns used in the template
     preg_match_all('/\\$PlugIn:([A-Za-z0-9_]+)->properties\\(\\)\\$/', $this->m_sTemplate, $aMatches);
     $aPlugInProperties = $aMatches[1];
     foreach ($aPlugInProperties as $sPlugInClass) {
         $oInstance = MetaModel::GetPlugins('iApplicationUIExtension', $sPlugInClass);
         if ($oInstance != null) {
             $offset = $oPage->start_capture();
             $oInstance->OnDisplayProperties($this->m_oObj, $oPage, $bEditMode);
             $sContent = $oPage->end_capture($offset);
             $aParams["PlugIn:{$sPlugInClass}->properties()"] = $sContent;
         } else {
             $aParams["PlugIn:{$sPlugInClass}->properties()"] = "Missing PlugIn: {$sPlugInClass}";
         }
     }
     $offset = $oPage->start_capture();
     parent::Render($oPage, $aParams);
     $sContent = $oPage->end_capture($offset);
     // Remove empty table rows in case some attributes are hidden...
     $sContent = preg_replace('/<tr[^>]*>\\s*(<td[^>]*>\\s*<\\/td>)+\\s*<\\/tr>/im', '', $sContent);
     $oPage->add($sContent);
     return $aFieldsMap;
 }
Пример #28
0
 protected function MakeSQLObjectQuerySingleTable(&$oBuild, $aAttToLoad, $sTableClass, $aExtKeys, $aValues)
 {
     // $aExtKeys is an array of sTableClass => array of (sAttCode (keys) => array of sAttCode (fields))
     //echo "MakeSQLObjectQuery($sTableClass)-liste des clefs externes($sTableClass): <pre>".print_r($aExtKeys, true)."</pre><br/>\n";
     // Prepare the query for a single table (compound objects)
     // Ignores the items (attributes/filters) that are not on the target table
     // Perform an (inner or left) join for every external key (and specify the expected fields)
     //
     // Returns an SQLQuery
     //
     $sTargetClass = $this->GetFirstJoinedClass();
     $sTargetAlias = $this->GetFirstJoinedClassAlias();
     $sTable = MetaModel::DBGetTable($sTableClass);
     $sTableAlias = $oBuild->GenerateTableAlias($sTargetAlias . '_' . $sTable, $sTable);
     $aTranslation = array();
     $aExpectedAtts = array();
     $oBuild->m_oQBExpressions->GetUnresolvedFields($sTargetAlias, $aExpectedAtts);
     $bIsOnQueriedClass = array_key_exists($sTargetAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
     self::DbgTrace("Entering: tableclass={$sTableClass}, filter=" . $this->ToOQL() . ", " . ($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
     // 1 - SELECT and UPDATE
     //
     // Note: no need for any values nor fields for foreign Classes (ie not the queried Class)
     //
     $aUpdateValues = array();
     // 1/a - Get the key and friendly name
     //
     // We need one pkey to be the key, let's take the first one available
     $oSelectedIdField = null;
     $oIdField = new FieldExpressionResolved(MetaModel::DBGetKey($sTableClass), $sTableAlias);
     $aTranslation[$sTargetAlias]['id'] = $oIdField;
     if ($bIsOnQueriedClass) {
         // Add this field to the list of queried fields (required for the COUNT to work fine)
         $oSelectedIdField = $oIdField;
     }
     // 1/b - Get the other attributes
     //
     foreach (MetaModel::ListAttributeDefs($sTableClass) as $sAttCode => $oAttDef) {
         // Skip this attribute if not defined in this table
         if (MetaModel::GetAttributeOrigin($sTargetClass, $sAttCode) != $sTableClass) {
             continue;
         }
         // Skip this attribute if not made of SQL columns
         if (count($oAttDef->GetSQLExpressions()) == 0) {
             continue;
         }
         // Update...
         //
         if ($bIsOnQueriedClass && array_key_exists($sAttCode, $aValues)) {
             assert($oAttDef->IsDirectField());
             foreach ($oAttDef->GetSQLValues($aValues[$sAttCode]) as $sColumn => $sValue) {
                 $aUpdateValues[$sColumn] = $sValue;
             }
         }
     }
     // 2 - The SQL query, for this table only
     //
     $oSelectBase = new SQLObjectQuery($sTable, $sTableAlias, array(), $bIsOnQueriedClass, $aUpdateValues, $oSelectedIdField);
     // 3 - Resolve expected expressions (translation table: alias.attcode => table.column)
     //
     foreach (MetaModel::ListAttributeDefs($sTableClass) as $sAttCode => $oAttDef) {
         // Skip this attribute if not defined in this table
         if (MetaModel::GetAttributeOrigin($sTargetClass, $sAttCode) != $sTableClass) {
             continue;
         }
         // Select...
         //
         if ($oAttDef->IsExternalField()) {
             // skip, this will be handled in the joined tables (done hereabove)
         } else {
             //echo "<p>MakeSQLObjectQuerySingleTable: Field $sAttCode is part of the table $sTable (named: $sTableAlias)</p>";
             // standard field, or external key
             // add it to the output
             foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) {
                 if (array_key_exists($sAttCode . $sColId, $aExpectedAtts)) {
                     $oFieldSQLExp = new FieldExpressionResolved($sSQLExpr, $sTableAlias);
                     foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier) {
                         $oFieldSQLExp = $oQueryModifier->GetFieldExpression($oBuild, $sTargetClass, $sAttCode, $sColId, $oFieldSQLExp, $oSelectBase);
                     }
                     $aTranslation[$sTargetAlias][$sAttCode . $sColId] = $oFieldSQLExp;
                 }
             }
         }
     }
     //echo "MakeSQLObjectQuery- Classe $sTableClass<br/>\n";
     // 4 - The external keys -> joins...
     //
     $aAllPointingTo = $this->GetCriteria_PointingTo();
     if (array_key_exists($sTableClass, $aExtKeys)) {
         foreach ($aExtKeys[$sTableClass] as $sKeyAttCode => $aExtFields) {
             $oKeyAttDef = MetaModel::GetAttributeDef($sTableClass, $sKeyAttCode);
             $aPointingTo = $this->GetCriteria_PointingTo($sKeyAttCode);
             //echo "MakeSQLObjectQuery-Cle '$sKeyAttCode'<br/>\n";
             if (!array_key_exists(TREE_OPERATOR_EQUALS, $aPointingTo)) {
                 //echo "MakeSQLObjectQuery-Ajoutons l'operateur TREE_OPERATOR_EQUALS pour $sKeyAttCode<br/>\n";
                 // The join was not explicitely defined in the filter,
                 // we need to do it now
                 $sKeyClass = $oKeyAttDef->GetTargetClass();
                 $sKeyClassAlias = $oBuild->GenerateClassAlias($sKeyClass . '_' . $sKeyAttCode, $sKeyClass);
                 $oExtFilter = new DBObjectSearch($sKeyClass, $sKeyClassAlias);
                 $aAllPointingTo[$sKeyAttCode][TREE_OPERATOR_EQUALS][$sKeyClassAlias] = $oExtFilter;
             }
         }
     }
     //echo "MakeSQLObjectQuery-liste des clefs de jointure: <pre>".print_r(array_keys($aAllPointingTo), true)."</pre><br/>\n";
     foreach ($aAllPointingTo as $sKeyAttCode => $aPointingTo) {
         foreach ($aPointingTo as $iOperatorCode => $aFilter) {
             foreach ($aFilter as $oExtFilter) {
                 if (!MetaModel::IsValidAttCode($sTableClass, $sKeyAttCode)) {
                     continue;
                 }
                 // Not defined in the class, skip it
                 // The aliases should not conflict because normalization occured while building the filter
                 $oKeyAttDef = MetaModel::GetAttributeDef($sTableClass, $sKeyAttCode);
                 $sKeyClass = $oExtFilter->GetFirstJoinedClass();
                 $sKeyClassAlias = $oExtFilter->GetFirstJoinedClassAlias();
                 //echo "MakeSQLObjectQuery-$sTableClass::$sKeyAttCode Foreach PointingTo($iOperatorCode) <span style=\"color:red\">$sKeyClass (alias:$sKeyClassAlias)</span><br/>\n";
                 // Note: there is no search condition in $oExtFilter, because normalization did merge the condition onto the top of the filter tree
                 //echo "MakeSQLObjectQuery-array_key_exists($sTableClass, \$aExtKeys)<br/>\n";
                 if ($iOperatorCode == TREE_OPERATOR_EQUALS) {
                     if (array_key_exists($sTableClass, $aExtKeys) && array_key_exists($sKeyAttCode, $aExtKeys[$sTableClass])) {
                         // Specify expected attributes for the target class query
                         // ... and use the current alias !
                         $aTranslateNow = array();
                         // Translation for external fields - must be performed before the join is done (recursion...)
                         foreach ($aExtKeys[$sTableClass][$sKeyAttCode] as $sAttCode => $oAtt) {
                             //echo "MakeSQLObjectQuery aExtKeys[$sTableClass][$sKeyAttCode] => $sAttCode-oAtt: <pre>".print_r($oAtt, true)."</pre><br/>\n";
                             if ($oAtt instanceof AttributeFriendlyName) {
                                 // Note: for a given ext key, there is one single attribute "friendly name"
                                 $aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression('friendlyname', $sKeyClassAlias);
                                 //echo "<p><b>aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression('friendlyname', $sKeyClassAlias);</b></p>\n";
                             } else {
                                 $sExtAttCode = $oAtt->GetExtAttCode();
                                 // Translate mainclass.extfield => remoteclassalias.remotefieldcode
                                 $oRemoteAttDef = MetaModel::GetAttributeDef($sKeyClass, $sExtAttCode);
                                 foreach ($oRemoteAttDef->GetSQLExpressions() as $sColId => $sRemoteAttExpr) {
                                     $aTranslateNow[$sTargetAlias][$sAttCode . $sColId] = new FieldExpression($sExtAttCode, $sKeyClassAlias);
                                     //echo "<p><b>aTranslateNow[$sTargetAlias][$sAttCode.$sColId] = new FieldExpression($sExtAttCode, $sKeyClassAlias);</b></p>\n";
                                 }
                                 //echo "<p><b>ExtAttr2: $sTargetAlias.$sAttCode to $sKeyClassAlias.$sRemoteAttExpr (class: $sKeyClass)</b></p>\n";
                             }
                         }
                         if ($oKeyAttDef instanceof AttributeObjectKey) {
                             // Add the condition: `$sTargetAlias`.$sClassAttCode IN (subclasses of $sKeyClass')
                             $sClassAttCode = $oKeyAttDef->Get('class_attcode');
                             $oClassAttDef = MetaModel::GetAttributeDef($sTargetClass, $sClassAttCode);
                             foreach ($oClassAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) {
                                 $aTranslateNow[$sTargetAlias][$sClassAttCode . $sColId] = new FieldExpressionResolved($sSQLExpr, $sTableAlias);
                             }
                             $oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sKeyClass, ENUM_CHILD_CLASSES_ALL));
                             $oClassExpr = new FieldExpression($sClassAttCode, $sTargetAlias);
                             $oClassRestriction = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
                             $oBuild->m_oQBExpressions->AddCondition($oClassRestriction);
                         }
                         // Translate prior to recursing
                         //
                         //echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."\n".print_r($aTranslateNow, true)."</pre></p>\n";
                         $oBuild->m_oQBExpressions->Translate($aTranslateNow, false);
                         //echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
                         //echo "<p>External key $sKeyAttCode (class: $sKeyClass), call MakeSQLObjectQuery()/p>\n";
                         self::DbgTrace("External key {$sKeyAttCode} (class: {$sKeyClass}), call MakeSQLObjectQuery()");
                         $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression('id', $sKeyClassAlias));
                         //echo "<p>Recursive MakeSQLObjectQuery ".__LINE__.": <pre>\n".print_r($oBuild->GetRootFilter()->GetSelectedClasses(), true)."</pre></p>\n";
                         $oSelectExtKey = $oExtFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad);
                         $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
                         $sExternalKeyTable = $oJoinExpr->GetParent();
                         $sExternalKeyField = $oJoinExpr->GetName();
                         $aCols = $oKeyAttDef->GetSQLExpressions();
                         // Workaround a PHP bug: sometimes issuing a Notice if invoking current(somefunc())
                         $sLocalKeyField = current($aCols);
                         // get the first column for an external key
                         self::DbgTrace("External key {$sKeyAttCode}, Join on {$sLocalKeyField} = {$sExternalKeyField}");
                         if ($oKeyAttDef->IsNullAllowed()) {
                             $oSelectBase->AddLeftJoin($oSelectExtKey, $sLocalKeyField, $sExternalKeyField, $sExternalKeyTable);
                         } else {
                             $oSelectBase->AddInnerJoin($oSelectExtKey, $sLocalKeyField, $sExternalKeyField, $sExternalKeyTable);
                         }
                     }
                 } elseif (MetaModel::GetAttributeOrigin($sKeyClass, $sKeyAttCode) == $sTableClass) {
                     $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sKeyAttCode, $sKeyClassAlias));
                     $oSelectExtKey = $oExtFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad);
                     $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
                     $sExternalKeyTable = $oJoinExpr->GetParent();
                     $sExternalKeyField = $oJoinExpr->GetName();
                     $sLeftIndex = $sExternalKeyField . '_left';
                     // TODO use GetSQLLeft()
                     $sRightIndex = $sExternalKeyField . '_right';
                     // TODO use GetSQLRight()
                     $LocalKeyLeft = $oKeyAttDef->GetSQLLeft();
                     $LocalKeyRight = $oKeyAttDef->GetSQLRight();
                     $oSelectBase->AddInnerJoinTree($oSelectExtKey, $LocalKeyLeft, $LocalKeyRight, $sLeftIndex, $sRightIndex, $sExternalKeyTable, $iOperatorCode);
                 }
             }
         }
     }
     // Translate the selected columns
     //
     //echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
     $oBuild->m_oQBExpressions->Translate($aTranslation, false);
     //echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
     //MyHelpers::var_dump_html($oSelectBase->RenderSelect());
     return $oSelectBase;
 }
 public function Process($iTimeLimit)
 {
     $aList = array();
     foreach (MetaModel::GetClasses() as $sClass) {
         foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
             if ($oAttDef instanceof AttributeStopWatch) {
                 foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData) {
                     $iPercent = $aThresholdData['percent'];
                     // could be different than the index !
                     $sNow = date('Y-m-d H:i:s');
                     $sExpression = "SELECT {$sClass} WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '{$sNow}'";
                     $oFilter = DBObjectSearch::FromOQL($sExpression);
                     $oSet = new DBObjectSet($oFilter);
                     while (time() < $iTimeLimit && ($oObj = $oSet->Fetch())) {
                         $sClass = get_class($oObj);
                         $aList[] = $sClass . '::' . $oObj->GetKey() . ' ' . $sAttCode . ' ' . $iThreshold;
                         // Execute planned actions
                         //
                         foreach ($aThresholdData['actions'] as $aActionData) {
                             $sVerb = $aActionData['verb'];
                             $aParams = $aActionData['params'];
                             $aValues = array();
                             foreach ($aParams as $def) {
                                 if (is_string($def)) {
                                     // Old method (pre-2.1.0) non typed parameters
                                     $aValues[] = $def;
                                 } else {
                                     $sParamType = array_key_exists('type', $def) ? $def['type'] : 'string';
                                     switch ($sParamType) {
                                         case 'int':
                                             $value = (int) $def['value'];
                                             break;
                                         case 'float':
                                             $value = (double) $def['value'];
                                             break;
                                         case 'bool':
                                             $value = (bool) $def['value'];
                                             break;
                                         case 'reference':
                                             $value = ${$def['value']};
                                             break;
                                         case 'string':
                                         default:
                                             $value = (string) $def['value'];
                                     }
                                     $aValues[] = $value;
                                 }
                             }
                             $aCallSpec = array($oObj, $sVerb);
                             call_user_func_array($aCallSpec, $aValues);
                         }
                         // Mark the threshold as "triggered"
                         //
                         $oSW = $oObj->Get($sAttCode);
                         $oSW->MarkThresholdAsTriggered($iThreshold);
                         $oObj->Set($sAttCode, $oSW);
                         if ($oObj->IsModified()) {
                             CMDBObject::SetTrackInfo("Automatic - threshold triggered");
                             $oMyChange = CMDBObject::GetCurrentChange();
                             $oObj->DBUpdateTracked($oMyChange, true);
                         }
                         // Activate any existing trigger
                         //
                         $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
                         $oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('{$sClassList}') AND stop_watch_code=:stop_watch_code AND threshold_index = :threshold_index"), array(), array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold));
                         while ($oTrigger = $oTriggerSet->Fetch()) {
                             $oTrigger->DoActivate($oObj->ToArgs('this'));
                         }
                     }
                 }
             }
         }
     }
     $iProcessed = count($aList);
     return "Triggered {$iProcessed} threshold(s):" . implode(", ", $aList);
 }
Пример #30
0
 // Note: it may happen that an external field has the same label as the external key
 //       in that case, we consider that the external key has precedence
 //
 $aKnownColumnNames = array();
 foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
     if ($bLocalize) {
         $sColName = strtolower(MetaModel::GetLabel($sClass, $sAttCode));
     } else {
         $sColName = strtolower($sAttCode);
     }
     if (!$oAttDef->IsExternalField() || !array_key_exists($sColName, $aKnownColumnNames)) {
         $aKnownColumnNames[$sColName][] = $sAttCode;
     }
     if ($oAttDef->IsExternalKey(EXTKEY_RELATIVE)) {
         $sRemoteClass = $oAttDef->GetTargetClass();
         foreach (MetaModel::ListAttributeDefs($sRemoteClass) as $sRemoteAttCode => $oRemoteAttDef) {
             $sAttCodeEx = $sAttCode . '->' . $sRemoteAttCode;
             if ($bLocalize) {
                 $sColName = strtolower(MetaModel::GetLabel($sClass, $sAttCodeEx));
             } else {
                 $sColName = strtolower($sAttCodeEx);
             }
             if (!array_key_exists($sColName, $aKnownColumnNames)) {
                 $aKnownColumnNames[$sColName][] = $sAttCodeEx;
             }
         }
     }
 }
 //print_r($aKnownColumnNames);
 //print_r(array_keys($aKnownColumnNames));
 //exit;