/**
  * Split the string into placholders
  * @param Hash $aParamTypes Class of the expected parameters: hash array of '<param_id>' => '<class_name>'
  * @return void
  */
 protected function Analyze($aParamTypes = array())
 {
     if (!is_null($this->m_aPlaceholders)) {
         return;
     }
     $this->m_aPlaceholders = array();
     if (preg_match_all('/\\$([a-z0-9_]+(->[a-z0-9_]+)*)\\$/', $this->m_sRaw, $aMatches)) {
         foreach ($aMatches[1] as $sPlaceholder) {
             $oPlaceholder = new TemplateStringPlaceholder($sPlaceholder);
             $oPlaceholder->bIsValid = false;
             foreach ($aParamTypes as $sParamName => $sClass) {
                 $sParamPrefix = $sParamName . '->';
                 if (substr($sPlaceholder, 0, strlen($sParamPrefix)) == $sParamPrefix) {
                     // Todo - detect functions (label...)
                     $oPlaceholder->sFunction = '';
                     $oPlaceholder->sParamName = $sParamName;
                     $sAttcode = substr($sPlaceholder, strlen($sParamPrefix));
                     $oPlaceholder->sAttcode = $sAttcode;
                     $oPlaceholder->bIsValid = MetaModel::IsValidAttCode($sClass, $sAttcode, true);
                 }
             }
             $this->m_aPlaceholders[] = $oPlaceholder;
         }
     }
 }
Пример #2
0
/**
 * Adds the context parameters to the audit query
 */
function FilterByContext(DBSearch &$oFilter, ApplicationContext $oAppContext)
{
    $sObjClass = $oFilter->GetClass();
    $aContextParams = $oAppContext->GetNames();
    $aCallSpec = array($sObjClass, 'MapContextParam');
    if (is_callable($aCallSpec)) {
        foreach ($aContextParams as $sParamName) {
            $sValue = $oAppContext->GetCurrentValue($sParamName, null);
            if ($sValue != null) {
                $sAttCode = call_user_func($aCallSpec, $sParamName);
                // Returns null when there is no mapping for this parameter
                if ($sAttCode != null && MetaModel::IsValidAttCode($sObjClass, $sAttCode)) {
                    // Check if the condition points to a hierarchical key
                    if ($sAttCode == 'id') {
                        // Filtering on the objects themselves
                        $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($sObjClass);
                        if ($sHierarchicalKeyCode !== false) {
                            $oRootFilter = new DBObjectSearch($sObjClass);
                            $oRootFilter->AddCondition($sAttCode, $sValue);
                            $oFilter->AddCondition_PointingTo($oRootFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
                            // Use the 'below' operator by default
                            $bConditionAdded = true;
                        }
                    } else {
                        $oAttDef = MetaModel::GetAttributeDef($sObjClass, $sAttCode);
                        $bConditionAdded = false;
                        if ($oAttDef->IsExternalKey()) {
                            $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
                            if ($sHierarchicalKeyCode !== false) {
                                $oRootFilter = new DBObjectSearch($oAttDef->GetTargetClass());
                                $oRootFilter->AddCondition('id', $sValue);
                                $oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
                                $oHKFilter->AddCondition_PointingTo($oRootFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
                                // Use the 'below' operator by default
                                $oFilter->AddCondition_PointingTo($oHKFilter, $sAttCode);
                                $bConditionAdded = true;
                            }
                        }
                    }
                    if (!$bConditionAdded) {
                        $oFilter->AddCondition($sAttCode, $sValue);
                    }
                }
            }
        }
    }
}
 function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
 {
     parent::DisplayBareRelations($oPage, $bEditMode);
     $sTicketListAttCode = 'tickets_list';
     if (MetaModel::IsValidAttCode(get_class($this), $sTicketListAttCode)) {
         // Display one list per leaf class (the only way to display the status as of now)
         $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sTicketListAttCode);
         $sLnkClass = $oAttDef->GetLinkedClass();
         $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
         $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
         $iTotal = 0;
         $aSearches = array();
         foreach (MetaModel::EnumChildClasses('Ticket') as $sSubClass) {
             if (!MetaModel::HasChildrenClasses($sSubClass)) {
                 $sStateAttCode = MetaModel::GetStateAttributeCode($sSubClass);
                 if ($sStateAttCode != '') {
                     $oSearch = DBSearch::FromOQL("SELECT {$sSubClass} AS t JOIN {$sLnkClass} AS lnk ON lnk.{$sExtKeyToRemote} = t.id WHERE {$sExtKeyToMe} = :myself AND {$sStateAttCode} NOT IN ('rejected', 'resolved', 'closed')", array('myself' => $this->GetKey()));
                     $aSearches[$sSubClass] = $oSearch;
                     $oSet = new DBObjectSet($oSearch);
                     $iTotal += $oSet->Count();
                 }
             }
         }
         $sCount = $iTotal > 0 ? ' (' . $iTotal . ')' : '';
         $oPage->SetCurrentTab(Dict::S('Class:FunctionalCI/Tab:OpenedTickets') . $sCount);
         foreach ($aSearches as $sSubClass => $oSearch) {
             $sBlockId = __CLASS__ . '_opened_' . $sSubClass;
             $oPage->add('<fieldset>');
             $oPage->add('<legend>' . MetaModel::GetName($sSubClass) . '</legend>');
             $oBlock = new DisplayBlock($oSearch, 'list', false);
             $oBlock->Display($oPage, $sBlockId, array('menu' => false));
             $oPage->add('</fieldset>');
         }
     }
 }
 /**
  * Specify a condition on external keys or link sets
  * @param sAttSpec Can be either an attribute code or extkey->[sAttSpec] or linkset->[sAttSpec] and so on, recursively
  *                 Example: infra_list->ci_id->location_id->country	 
  * @param value The value to match (can be an array => IN(val1, val2...)
  * @return void
  */
 public function AddConditionAdvanced($sAttSpec, $value)
 {
     $sClass = $this->GetClass();
     $iPos = strpos($sAttSpec, '->');
     if ($iPos !== false) {
         $sAttCode = substr($sAttSpec, 0, $iPos);
         $sSubSpec = substr($sAttSpec, $iPos + 2);
         if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             throw new Exception("Invalid attribute code '{$sClass}/{$sAttCode}' in condition specification '{$sAttSpec}'");
         }
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
         if ($oAttDef->IsLinkSet()) {
             $sTargetClass = $oAttDef->GetLinkedClass();
             $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
             $oNewFilter = new DBObjectSearch($sTargetClass);
             $oNewFilter->AddConditionAdvanced($sSubSpec, $value);
             $this->AddCondition_ReferencedBy($oNewFilter, $sExtKeyToMe);
         } elseif ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
             $sTargetClass = $oAttDef->GetTargetClass(EXTKEY_ABSOLUTE);
             $oNewFilter = new DBObjectSearch($sTargetClass);
             $oNewFilter->AddConditionAdvanced($sSubSpec, $value);
             $this->AddCondition_PointingTo($oNewFilter, $sAttCode);
         } else {
             throw new Exception("Attribute specification '{$sAttSpec}', '{$sAttCode}' should be either a link set or an external key");
         }
     } else {
         // $sAttSpec is an attribute code
         //
         if (is_array($value)) {
             $oField = new FieldExpression($sAttSpec, $this->GetClass());
             $oListExpr = ListExpression::FromScalars($value);
             $oInValues = new BinaryExpression($oField, 'IN', $oListExpr);
             $this->AddConditionExpression($oInValues);
         } else {
             $this->AddCondition($sAttSpec, $value);
         }
     }
 }
 public function GetValueDescription($sValue)
 {
     if (is_null($sValue)) {
         // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label
         $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', Dict::S('Enum:Undefined'));
     } else {
         $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', '', true);
         if (strlen($sDescription) == 0) {
             $sParentClass = MetaModel::GetParentClass($this->m_sHostClass);
             if ($sParentClass) {
                 if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) {
                     $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode);
                     $sDescription = $oAttDef->GetValueDescription($sValue);
                 }
             }
         }
     }
     return $sDescription;
 }
 protected function ForgotPwdGo()
 {
     $sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
     try {
         UserRights::Login($sAuthUser);
         // Set the user's language (if possible!)
         $oUser = UserRights::GetUserObject();
         if ($oUser == null) {
             throw new Exception(Dict::Format('UI:ResetPwd-Error-WrongLogin', $sAuthUser));
         }
         if (!MetaModel::IsValidAttCode(get_class($oUser), 'reset_pwd_token')) {
             throw new Exception(Dict::S('UI:ResetPwd-Error-NotPossible'));
         }
         if (!$oUser->CanChangePassword()) {
             throw new Exception(Dict::S('UI:ResetPwd-Error-FixedPwd'));
         }
         $sTo = $oUser->GetResetPasswordEmail();
         // throws Exceptions if not allowed
         if ($sTo == '') {
             throw new Exception(Dict::S('UI:ResetPwd-Error-NoEmail'));
         }
         // This token allows the user to change the password without knowing the previous one
         $sToken = substr(md5(APPROOT . uniqid()), 0, 16);
         $oUser->Set('reset_pwd_token', $sToken);
         CMDBObject::SetTrackInfo('Reset password');
         $oUser->DBUpdate();
         $oEmail = new Email();
         $oEmail->SetRecipientTO($sTo);
         $sFrom = MetaModel::GetConfig()->Get('forgot_password_from');
         if ($sFrom == '') {
             $sFrom = $sTo;
         }
         $oEmail->SetRecipientFrom($sFrom);
         $oEmail->SetSubject(Dict::S('UI:ResetPwd-EmailSubject'));
         $sResetUrl = utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?loginop=reset_pwd&auth_user='******'login')) . '&token=' . urlencode($sToken);
         $oEmail->SetBody(Dict::Format('UI:ResetPwd-EmailBody', $sResetUrl));
         $iRes = $oEmail->Send($aIssues, true);
         switch ($iRes) {
             //case EMAIL_SEND_PENDING:
             case EMAIL_SEND_OK:
                 break;
             case EMAIL_SEND_ERROR:
             default:
                 IssueLog::Error('Failed to send the email with the NEW password for ' . $oUser->Get('friendlyname') . ': ' . implode(', ', $aIssues));
                 throw new Exception(Dict::S('UI:ResetPwd-Error-Send'));
         }
         $this->DisplayLoginHeader();
         $this->add("<div id=\"login\">\n");
         $this->add("<h1>" . Dict::S('UI:Login:ForgotPwdForm') . "</h1>\n");
         $this->add("<p>" . Dict::S('UI:ResetPwd-EmailSent') . "</p>");
         $this->add("<form method=\"post\">\n");
         $this->add("<table>\n");
         $this->add("<tr><td colspan=\"2\" class=\"center v-spacer\"><input type=\"button\" onClick=\"window.close();\" value=\"" . Dict::S('UI:Button:Done') . "\" /></td></tr>\n");
         $this->add("</table>\n");
         $this->add("</form>\n");
         $this->add("</div\n");
     } catch (Exception $e) {
         $this->DisplayForgotPwdForm(true, $e->getMessage());
     }
 }
 /**
  * Updates the object from a flat array of values
  * @param string $aValues array of attcode => scalar or array (N-N links)
  * @return void
  */
 public function UpdateObjectFromArray($aValues)
 {
     foreach ($aValues as $sAttCode => $value) {
         $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
         if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect()) {
             $aLinks = $value;
             $sLinkedClass = $oAttDef->GetLinkedClass();
             $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
             $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
             $oLinkedSet = DBObjectSet::FromScratch($sLinkedClass);
             if (is_array($aLinks)) {
                 foreach ($aLinks as $id => $aData) {
                     if (is_numeric($id)) {
                         if ($id < 0) {
                             // New link to be created, the opposite of the id (-$id) is the ID of the remote object
                             $oLink = MetaModel::NewObject($sLinkedClass);
                             $oLink->Set($sExtKeyToRemote, -$id);
                             $oLink->Set($sExtKeyToMe, $this->GetKey());
                         } else {
                             // Existing link, potentially to be updated...
                             $oLink = MetaModel::GetObject($sLinkedClass, $id);
                         }
                         // Now populate the attributes
                         foreach ($aData as $sName => $value) {
                             if (MetaModel::IsValidAttCode($sLinkedClass, $sName)) {
                                 $oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName);
                                 if ($oLinkAttDef->IsWritable()) {
                                     $oLink->Set($sName, $value);
                                 }
                             }
                         }
                         $oLinkedSet->AddObject($oLink);
                     }
                 }
             }
             $this->Set($sAttCode, $oLinkedSet);
         } elseif ($oAttDef->GetEditClass() == 'Document') {
             // There should be an uploaded file with the named attr_<attCode>
             $oDocument = $value['fcontents'];
             if (!$oDocument->IsEmpty()) {
                 // A new file has been uploaded
                 $this->Set($sAttCode, $oDocument);
             }
         } elseif ($oAttDef->GetEditClass() == 'One Way Password') {
             // Check if the password was typed/changed
             $aPwdData = $value;
             if (!is_null($aPwdData) && $aPwdData['changed']) {
                 // The password has been changed or set
                 $this->Set($sAttCode, $aPwdData['value']);
             }
         } elseif ($oAttDef->GetEditClass() == 'Duration') {
             $aDurationData = $value;
             if (!is_array($aDurationData)) {
                 continue;
             }
             $iValue = ((24 * $aDurationData['d'] + $aDurationData['h']) * 60 + $aDurationData['m']) * 60 + $aDurationData['s'];
             $this->Set($sAttCode, $iValue);
             $previousValue = $this->Get($sAttCode);
             if ($previousValue !== $iValue) {
                 $this->Set($sAttCode, $iValue);
             }
         } else {
             if ($oAttDef->GetEditClass() == 'LinkedSet' && !$oAttDef->IsIndirect() && ($oAttDef->GetEditMode() == LINKSET_EDITMODE_INPLACE || $oAttDef->GetEditMode() == LINKSET_EDITMODE_ADDREMOVE)) {
                 $oLinkset = $this->Get($sAttCode);
                 $sLinkedClass = $oLinkset->GetClass();
                 $aObjSet = array();
                 $oLinkset->Rewind();
                 $bModified = false;
                 while ($oLink = $oLinkset->Fetch()) {
                     if (in_array($oLink->GetKey(), $value['to_be_deleted'])) {
                         // The link is to be deleted, don't copy it in the array
                         $bModified = true;
                     } else {
                         if (!array_key_exists('to_be_removed', $value) || !in_array($oLink->GetKey(), $value['to_be_removed'])) {
                             $aObjSet[] = $oLink;
                         }
                     }
                 }
                 if (array_key_exists('to_be_created', $value) && count($value['to_be_created']) > 0) {
                     // Now handle the links to be created
                     foreach ($value['to_be_created'] as $aData) {
                         $sSubClass = $aData['class'];
                         if ($sLinkedClass == $sSubClass || is_subclass_of($sSubClass, $sLinkedClass)) {
                             $aObjData = $aData['data'];
                             $oLink = new $sSubClass();
                             $oLink->UpdateObjectFromArray($aObjData);
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if (array_key_exists('to_be_added', $value) && count($value['to_be_added']) > 0) {
                     // Now handle the links to be added by making the remote object point to self
                     foreach ($value['to_be_added'] as $iObjKey) {
                         $oLink = MetaModel::GetObject($sLinkedClass, $iObjKey, false);
                         if ($oLink) {
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if (array_key_exists('to_be_removed', $value) && count($value['to_be_removed']) > 0) {
                     // Now handle the links to be removed by making the remote object point to nothing
                     // Keep them in the set (modified), DBWriteLinks will handle them
                     foreach ($value['to_be_removed'] as $iObjKey) {
                         $oLink = MetaModel::GetObject($sLinkedClass, $iObjKey, false);
                         if ($oLink) {
                             $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
                             $oLink->Set($sExtKeyToMe, null);
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if ($bModified) {
                     $oNewSet = DBObjectSet::FromArray($oLinkset->GetClass(), $aObjSet);
                     $this->Set($sAttCode, $oNewSet);
                 }
             } else {
                 if (!is_null($value)) {
                     $aAttributes[$sAttCode] = trim($value);
                     $previousValue = $this->Get($sAttCode);
                     if ($previousValue !== $aAttributes[$sAttCode]) {
                         $this->Set($sAttCode, $aAttributes[$sAttCode]);
                     }
                 }
             }
         }
     }
 }
Пример #8
0
 /**
  * Create an ResponseTicket (Incident or UserRequest) from an external system
  * Some CIs might be specified (by their name/IP)
  *	 
  * @param string sClass The class of the ticket: Incident or UserRequest
  * @param string sTitle
  * @param string sDescription
  * @param array aCallerDesc
  * @param array aCustomerDesc
  * @param array aServiceDesc
  * @param array aServiceSubcategoryDesc
  * @param string sProduct
  * @param array aWorkgroupDesc
  * @param array aImpactedCIs
  * @param string sImpact
  * @param string sUrgency
  *
  * @return WebServiceResult
  */
 protected function _CreateResponseTicket($sClass, $sTitle, $sDescription, $aCallerDesc, $aCustomerDesc, $aServiceDesc, $aServiceSubcategoryDesc, $sProduct, $aWorkgroupDesc, $aImpactedCIs, $sImpact, $sUrgency)
 {
     $oRes = new WebServiceResult();
     try {
         $oMyChange = MetaModel::NewObject("CMDBChange");
         $oMyChange->Set("date", time());
         $oMyChange->Set("userinfo", "Administrator");
         $iChangeId = $oMyChange->DBInsertNoReload();
         $oNewTicket = MetaModel::NewObject($sClass);
         $this->MyObjectSetScalar('title', 'title', $sTitle, $oNewTicket, $oRes);
         $this->MyObjectSetScalar('description', 'description', $sDescription, $oNewTicket, $oRes);
         $this->MyObjectSetExternalKey('org_id', 'customer', $aCustomerDesc, $oNewTicket, $oRes);
         $this->MyObjectSetExternalKey('caller_id', 'caller', $aCallerDesc, $oNewTicket, $oRes);
         $this->MyObjectSetExternalKey('service_id', 'service', $aServiceDesc, $oNewTicket, $oRes);
         if (!array_key_exists('service_id', $aServiceSubcategoryDesc)) {
             $aServiceSubcategoryDesc['service_id'] = $oNewTicket->Get('service_id');
         }
         $this->MyObjectSetExternalKey('servicesubcategory_id', 'servicesubcategory', $aServiceSubcategoryDesc, $oNewTicket, $oRes);
         if (MetaModel::IsValidAttCode($sClass, 'product')) {
             // 1.x data models
             $this->MyObjectSetScalar('product', 'product', $sProduct, $oNewTicket, $oRes);
         }
         if (MetaModel::IsValidAttCode($sClass, 'workgroup_id')) {
             // 1.x data models
             $this->MyObjectSetExternalKey('workgroup_id', 'workgroup', $aWorkgroupDesc, $oNewTicket, $oRes);
         } else {
             if (MetaModel::IsValidAttCode($sClass, 'team_id')) {
                 // 2.x data models
                 $this->MyObjectSetExternalKey('team_id', 'workgroup', $aWorkgroupDesc, $oNewTicket, $oRes);
             }
         }
         if (MetaModel::IsValidAttCode($sClass, 'ci_list')) {
             // 1.x data models
             $aDevicesNotFound = $this->AddLinkedObjects('ci_list', 'impacted_cis', 'FunctionalCI', $aImpactedCIs, $oNewTicket, $oRes);
         } else {
             if (MetaModel::IsValidAttCode($sClass, 'functionalcis_list')) {
                 // 2.x data models
                 $aDevicesNotFound = $this->AddLinkedObjects('functionalcis_list', 'impacted_cis', 'FunctionalCI', $aImpactedCIs, $oNewTicket, $oRes);
             }
         }
         if (count($aDevicesNotFound) > 0) {
             $this->MyObjectSetScalar('description', 'n/a', $sDescription . ' - Related CIs: ' . implode(', ', $aDevicesNotFound), $oNewTicket, $oRes);
         } else {
             $this->MyObjectSetScalar('description', 'n/a', $sDescription, $oNewTicket, $oRes);
         }
         $this->MyObjectSetScalar('impact', 'impact', $sImpact, $oNewTicket, $oRes);
         $this->MyObjectSetScalar('urgency', 'urgency', $sUrgency, $oNewTicket, $oRes);
         $this->MyObjectInsert($oNewTicket, 'created', $oMyChange, $oRes);
     } catch (CoreException $e) {
         $oRes->LogError($e->getMessage());
     } catch (Exception $e) {
         $oRes->LogError($e->getMessage());
     }
     $this->LogUsage(__FUNCTION__, $oRes);
     return $oRes;
 }
 public static function GetContactId($sName = '')
 {
     if (empty($sName)) {
         $oUser = self::$m_oUser;
     } else {
         $oUser = FindUser($sName);
     }
     if (is_null($oUser)) {
         return '';
     }
     if (!MetaModel::IsValidAttCode(get_class($oUser), 'contactid')) {
         return '';
     }
     return $oUser->Get('contactid');
 }
Пример #10
0
 public function Get($sAttCode)
 {
     if (($iPos = strpos($sAttCode, '->')) === false) {
         return $this->GetStrict($sAttCode);
     } else {
         $sExtKeyAttCode = substr($sAttCode, 0, $iPos);
         $sRemoteAttCode = substr($sAttCode, $iPos + 2);
         if (!MetaModel::IsValidAttCode(get_class($this), $sExtKeyAttCode)) {
             throw new CoreException("Unknown external key '{$sExtKeyAttCode}' for the class " . get_class($this));
         }
         $oExtFieldAtt = MetaModel::FindExternalField(get_class($this), $sExtKeyAttCode, $sRemoteAttCode);
         if (!is_null($oExtFieldAtt)) {
             return $this->GetStrict($oExtFieldAtt->GetCode());
         } else {
             $oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
             $sRemoteClass = $oKeyAttDef->GetTargetClass();
             $oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
             if (is_null($oRemoteObj)) {
                 return '';
             } else {
                 return $oRemoteObj->Get($sRemoteAttCode);
             }
         }
     }
 }
 /**
  * Find out which attribute is corresponding the the dimension 'owner org'
  * returns null if no such attribute has been found (no filtering should occur)	 
  */
 public static function GetOwnerOrganizationAttCode($sClass)
 {
     $sAttCode = null;
     $aCallSpec = array($sClass, 'MapContextParam');
     if ($sClass == 'Organization' || is_subclass_of($sClass, 'Organization')) {
         $sAttCode = 'id';
     } elseif (is_callable($aCallSpec)) {
         $sAttCode = call_user_func($aCallSpec, 'org_id');
         // Returns null when there is no mapping for this parameter
         if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             // Skip silently. The data model checker will tell you something about this...
             $sAttCode = null;
         }
     } elseif (MetaModel::IsValidAttCode($sClass, 'org_id')) {
         $sAttCode = 'org_id';
     }
     return $sAttCode;
 }
Пример #12
0
 public static final function IsValidAttCode($sClass, $sAttCode, $bExtended = false)
 {
     if (!array_key_exists($sClass, self::$m_aAttribDefs)) {
         return false;
     }
     if ($bExtended) {
         if (($iPos = strpos($sAttCode, '->')) === false) {
             $bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
         } else {
             $sExtKeyAttCode = substr($sAttCode, 0, $iPos);
             $sRemoteAttCode = substr($sAttCode, $iPos + 2);
             if (MetaModel::IsValidAttCode($sClass, $sExtKeyAttCode)) {
                 $oKeyAttDef = MetaModel::GetAttributeDef($sClass, $sExtKeyAttCode);
                 $sRemoteClass = $oKeyAttDef->GetTargetClass();
                 $bRes = MetaModel::IsValidAttCode($sRemoteClass, $sRemoteAttCode, true);
             } else {
                 $bRes = false;
             }
         }
     } else {
         $bRes = array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass]);
     }
     return $bRes;
 }
 /**
  * Give a default value for item_org_id (if relevant...)
  * @return void
  */
 public function SetDefaultOrgId()
 {
     // First check that the organization CAN be fetched from the target class
     //
     $sClass = $this->Get('item_class');
     $aCallSpec = array($sClass, 'MapContextParam');
     if (is_callable($aCallSpec)) {
         $sAttCode = call_user_func($aCallSpec, 'org_id');
         // Returns null when there is no mapping for this parameter
         if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             // Second: check that the organization CAN be fetched from the current user
             //
             if (MetaModel::IsValidClass('Person')) {
                 $aCallSpec = array($sClass, 'MapContextParam');
                 if (is_callable($aCallSpec)) {
                     $sAttCode = call_user_func($aCallSpec, 'org_id');
                     // Returns null when there is no mapping for this parameter
                     if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                         // OK - try it
                         //
                         $oCurrentPerson = MetaModel::GetObject('Person', UserRights::GetContactId(), false);
                         if ($oCurrentPerson) {
                             $this->Set('item_org_id', $oCurrentPerson->Get($sAttCode));
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * Initializes the given object with the default values provided by the context
  */
 public function InitObjectFromContext(DBObject &$oObj)
 {
     $sClass = get_class($oObj);
     foreach ($this->GetNames() as $key) {
         $aCallSpec = array($sClass, 'MapContextParam');
         if (is_callable($aCallSpec)) {
             $sAttCode = call_user_func($aCallSpec, $key);
             // Returns null when there is no mapping for this parameter
             if (MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                 $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
                 if ($oAttDef->IsWritable()) {
                     $value = $this->GetCurrentValue($key, null);
                     if (!is_null($value)) {
                         $oObj->Set($sAttCode, $value);
                     }
                 }
             }
         }
     }
 }
 /**
  * Helper function to load the objects from a standard XML file into the database
  * @param $sFilePath string The full path to the XML file to load
  * @param $bUpdateKeyCacheOnly bool Set to true to *just* update the keys cache but not reload the objects
  */
 function LoadFile($sFilePath, $bUpdateKeyCacheOnly = false)
 {
     global $aKeys;
     $oXml = simplexml_load_file($sFilePath);
     $aReplicas = array();
     foreach ($oXml as $sClass => $oXmlObj) {
         if (!MetaModel::IsValidClass($sClass)) {
             SetupPage::log_error("Unknown class - {$sClass}");
             throw new Exception("Unknown class - {$sClass}");
         }
         $iSrcId = (int) $oXmlObj['id'];
         // Mandatory to cast
         // Import algorithm
         // Here enumerate all the attributes of the object
         // for all attribute that is neither an external field
         // not an external key, assign it
         // Store all external keys for further reference
         // Create the object an store the correspondance between its newly created Id
         // and its original Id
         // Once all the objects have been created re-assign all the external keys to
         // their actual Ids
         $iExistingId = $this->GetObjectKey($sClass, $iSrcId);
         if ($iExistingId != 0) {
             $oTargetObj = MetaModel::GetObject($sClass, $iExistingId);
         } else {
             $oTargetObj = MetaModel::NewObject($sClass);
         }
         foreach ($oXmlObj as $sAttCode => $oSubNode) {
             if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
                 $sMsg = "Unknown attribute code - {$sClass}/{$sAttCode}";
                 continue;
                 // ignore silently...
                 //SetupPage::log_error($sMsg);
                 //throw(new Exception($sMsg));
             }
             $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
             if ($oAttDef->IsWritable() && $oAttDef->IsScalar()) {
                 if ($oAttDef->IsExternalKey()) {
                     if (substr(trim($oSubNode), 0, 6) == 'SELECT') {
                         $sQuery = trim($oSubNode);
                         $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sQuery));
                         $iMatches = $oSet->Count();
                         if ($iMatches == 1) {
                             $oFoundObject = $oSet->Fetch();
                             $iExtKey = $oFoundObject->GetKey();
                         } else {
                             $sMsg = "Ext key not reconcilied - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $sQuery . "' - found {$iMatches} matche(s)";
                             SetupPage::log_error($sMsg);
                             $this->m_aErrors[] = $sMsg;
                             $iExtKey = 0;
                         }
                     } else {
                         $iDstObj = (int) $oSubNode;
                         // Attempt to find the object in the list of loaded objects
                         $iExtKey = $this->GetObjectKey($oAttDef->GetTargetClass(), $iDstObj);
                         if ($iExtKey == 0) {
                             $iExtKey = -$iDstObj;
                             // Convention: Unresolved keys are stored as negative !
                             $oTargetObj->RegisterAsDirty();
                         }
                         // here we allow external keys to be invalid because we will resolve them later on...
                     }
                     //$oTargetObj->CheckValue($sAttCode, $iExtKey);
                     $oTargetObj->Set($sAttCode, $iExtKey);
                 } elseif ($oAttDef instanceof AttributeBlob) {
                     $sMimeType = (string) $oSubNode->mimetype;
                     $sFileName = (string) $oSubNode->filename;
                     $data = base64_decode((string) $oSubNode->data);
                     $oDoc = new ormDocument($data, $sMimeType, $sFileName);
                     $oTargetObj->Set($sAttCode, $oDoc);
                 } else {
                     $value = (string) $oSubNode;
                     if ($value == '') {
                         $value = $oAttDef->GetNullValue();
                     }
                     $res = $oTargetObj->CheckValue($sAttCode, $value);
                     if ($res !== true) {
                         // $res contains the error description
                         $sMsg = "Value not allowed - {$sClass}/{$iSrcId} - {$sAttCode}: '" . $oSubNode . "' ; {$res}";
                         SetupPage::log_error($sMsg);
                         $this->m_aErrors[] = $sMsg;
                     }
                     $oTargetObj->Set($sAttCode, $value);
                 }
             }
         }
         $this->StoreObject($sClass, $oTargetObj, $iSrcId, $bUpdateKeyCacheOnly, $bUpdateKeyCacheOnly);
     }
     return true;
 }
 /**
  * Initializes the default search parameters based on 1) a 'current' object and 2) the silos defined by the context
  * @param DBObject $oSourceObj
  * @param DBObjectSearch $oSearch
  */
 protected function SetSearchDefaultFromContext($oSourceObj, &$oSearch)
 {
     $oAppContext = new ApplicationContext();
     $sSrcClass = get_class($oSourceObj);
     $sDestClass = $oSearch->GetClass();
     foreach ($oAppContext->GetNames() as $key) {
         // Find the value of the object corresponding to each 'context' parameter
         $aCallSpec = array($sSrcClass, 'MapContextParam');
         $sAttCode = '';
         if (is_callable($aCallSpec)) {
             $sAttCode = call_user_func($aCallSpec, $key);
             // Returns null when there is no mapping for this parameter
         }
         if (MetaModel::IsValidAttCode($sSrcClass, $sAttCode)) {
             $oAttDef = MetaModel::GetAttributeDef($sSrcClass, $sAttCode);
             $defaultValue = $oSourceObj->Get($sAttCode);
             // Find the attcode for the same 'context' parameter in the destination class
             // and sets its value as the default value for the search condition
             $aCallSpec = array($sDestClass, 'MapContextParam');
             $sAttCode = '';
             if (is_callable($aCallSpec)) {
                 $sAttCode = call_user_func($aCallSpec, $key);
                 // Returns null when there is no mapping for this parameter
             }
             if (MetaModel::IsValidAttCode($sDestClass, $sAttCode) && !empty($defaultValue)) {
                 $oSearch->AddCondition($sAttCode, $defaultValue);
             }
         }
     }
 }
 /**
  * Update the destination object with given values
  */
 public function UpdateDestObject($aValues, $oChange, &$oStatLog)
 {
     try {
         if ($this->Get('dest_class') == '') {
             $this->SetLastError('No destination object to update');
             $oStatLog->Inc('stats_nb_obj_obsoleted_errors');
         } else {
             $oDestObj = MetaModel::GetObject($this->Get('dest_class'), $this->Get('dest_id'));
             foreach ($aValues as $sAttCode => $value) {
                 if (!MetaModel::IsValidAttCode(get_class($oDestObj), $sAttCode)) {
                     throw new Exception("Unknown attribute code '{$sAttCode}'");
                 }
                 $oDestObj->Set($sAttCode, $value);
             }
             $this->Set('info_last_modified', date('Y-m-d H:i:s'));
             $oDestObj->DBUpdateTracked($oChange);
             $oStatLog->AddTrace("Replica marked as obsolete", $this);
             $oStatLog->Inc('stats_nb_obj_obsoleted');
         }
     } catch (Exception $e) {
         $this->SetLastError('Unable to update the destination object: ', $e);
         $oStatLog->Inc('stats_nb_obj_obsoleted_errors');
     }
 }
Пример #18
0
 /**
  * Add a condition (restriction) to the current DBSearch on which the display block is based
  * taking into account the hierarchical keys for which the condition is based on the 'below' operator
  */
 protected function AddCondition($sFilterCode, $condition, $sOpCode = null)
 {
     // Workaround to an issue revealed whenever a condition on org_id is applied twice (with a hierarchy of organizations)
     // Moreover, it keeps the query as simple as possible
     if (isset($this->m_aConditions[$sFilterCode]) && $condition == $this->m_aConditions[$sFilterCode]) {
         // Skip
         return;
     }
     $this->m_aConditions[$sFilterCode] = $condition;
     $sClass = $this->m_oFilter->GetClass();
     $bConditionAdded = false;
     // If the condition is an external key with a class having a hierarchy, use a "below" criteria
     if (MetaModel::IsValidAttCode($sClass, $sFilterCode)) {
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sFilterCode);
         if ($oAttDef->IsExternalKey()) {
             $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass($oAttDef->GetTargetClass());
             if ($sHierarchicalKeyCode !== false) {
                 $oFilter = new DBObjectSearch($oAttDef->GetTargetClass());
                 if ($sOpCode == 'IN' && is_array($condition)) {
                     $oFilter->AddConditionExpression(self::GetConditionIN($oFilter, 'id', $condition));
                 } else {
                     $oFilter->AddCondition('id', $condition);
                 }
                 $oHKFilter = new DBObjectSearch($oAttDef->GetTargetClass());
                 $oHKFilter->AddCondition_PointingTo($oFilter, $sHierarchicalKeyCode, TREE_OPERATOR_BELOW);
                 // Use the 'below' operator by default
                 $this->m_oFilter->AddCondition_PointingTo($oHKFilter, $sFilterCode);
                 $bConditionAdded = true;
             } else {
                 if ($sOpCode == 'IN' && is_array($condition)) {
                     $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
                     $bConditionAdded = true;
                 }
             }
         } else {
             if ($sOpCode == 'IN' && is_array($condition)) {
                 $this->m_oFilter->AddConditionExpression(self::GetConditionIN($this->m_oFilter, $sFilterCode, $condition));
                 $bConditionAdded = true;
             }
         }
     }
     // In all other cases, just add the condition directly
     if (!$bConditionAdded) {
         $this->m_oFilter->AddCondition($sFilterCode, $condition);
         // Use the default 'loose' operator
     }
 }
Пример #19
0
     $oPage->add('<td>&nbsp;</td>');
     $oPage->add('<td><input id="search_' . $index . '" type="checkbox" name="search_field[' . $index . ']" value="1" /></td>');
     $oPage->add('<td>' . (isset($aData[$iStartLine][$index - 1]) ? htmlentities($aData[$iStartLine][$index - 1], ENT_QUOTES, 'UTF-8') : '&nbsp;') . '</td>');
     $oPage->add('<td>' . (isset($aData[$iStartLine + 1][$index - 1]) ? htmlentities($aData[$iStartLine + 1][$index - 1], ENT_QUOTES, 'UTF-8') : '&nbsp;') . '</td>');
     $oPage->add('</tr>');
     $index++;
 }
 $oPage->add("</table>\n");
 if (empty($sInitSearchField)) {
     // Propose a reconciliation scheme
     //
     $aReconciliationKeys = MetaModel::GetReconcKeys($sClassName);
     $aMoreReconciliationKeys = array();
     // Store: key => void to automatically remove duplicates
     foreach ($aReconciliationKeys as $sAttCode) {
         if (!MetaModel::IsValidAttCode($sClassName, $sAttCode)) {
             continue;
         }
         $oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
         if ($oAttDef->IsExternalKey()) {
             // An external key is specified as a reconciliation key: this means that all the reconciliation
             // keys of this class are proposed to identify the target object
             $aMoreReconciliationKeys = array_merge($aMoreReconciliationKeys, GetMappingsForExtKey($sAttCode, $oAttDef, $bAdvanced));
         } elseif ($oAttDef->IsExternalField()) {
             // An external field is specified as a reconciliation key, translate the field into a field on the target class
             // since external fields are not writable, and thus never appears in the mapping form
             $sKeyAttCode = $oAttDef->GetKeyAttCode();
             $sTargetAttCode = $oAttDef->GetExtAttCode();
             $aMoreReconciliationKeys[$sKeyAttCode . '->' . $sTargetAttCode] = '';
         }
     }
 public function IsValidAttCode($sClass, $sAttCode)
 {
     return MetaModel::IsValidAttCode($sClass, $sAttCode);
 }
Пример #21
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;
         }
     }
 }
Пример #22
0
 public function GetForTemplate($sPlaceholderAttCode)
 {
     $ret = null;
     if (($iPos = strpos($sPlaceholderAttCode, '->')) !== false) {
         $sExtKeyAttCode = substr($sPlaceholderAttCode, 0, $iPos);
         $sRemoteAttCode = substr($sPlaceholderAttCode, $iPos + 2);
         if (!MetaModel::IsValidAttCode(get_class($this), $sExtKeyAttCode)) {
             throw new CoreException("Unknown attribute '{$sExtKeyAttCode}' for the class " . get_class($this));
         }
         $oKeyAttDef = MetaModel::GetAttributeDef(get_class($this), $sExtKeyAttCode);
         if (!$oKeyAttDef instanceof AttributeExternalKey) {
             throw new CoreException("'{$sExtKeyAttCode}' is not an external key of the class " . get_class($this));
         }
         $sRemoteClass = $oKeyAttDef->GetTargetClass();
         $oRemoteObj = MetaModel::GetObject($sRemoteClass, $this->GetStrict($sExtKeyAttCode), false);
         if (is_null($oRemoteObj)) {
             $ret = Dict::S('UI:UndefinedObject');
         } else {
             // Recurse
             $ret = $oRemoteObj->GetForTemplate($sRemoteAttCode);
         }
     } else {
         switch ($sPlaceholderAttCode) {
             case 'id':
                 $ret = $this->GetKey();
                 break;
             case 'hyperlink()':
                 $ret = $this->GetHyperlink('iTopStandardURLMaker', false);
                 break;
             case 'hyperlink(portal)':
                 $ret = $this->GetHyperlink('PortalURLMaker', false);
                 break;
             case 'name()':
                 $ret = $this->GetName();
                 break;
             default:
                 if (preg_match('/^([^(]+)\\((.+)\\)$/', $sPlaceholderAttCode, $aMatches)) {
                     $sVerb = $aMatches[1];
                     $sAttCode = $aMatches[2];
                 } else {
                     $sVerb = '';
                     $sAttCode = $sPlaceholderAttCode;
                 }
                 $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
                 $ret = $oAttDef->GetForTemplate($this->Get($sAttCode), $sVerb, $this);
         }
     }
     return $ret;
 }
 /**
  * Describe (as a text string) the modifications corresponding to this change
  */
 public function GetDescription()
 {
     $sResult = '';
     $oTargetObjectClass = $this->Get('objclass');
     $oTargetObjectKey = $this->Get('objkey');
     $oTargetSearch = new DBObjectSearch($oTargetObjectClass);
     $oTargetSearch->AddCondition('id', $oTargetObjectKey, '=');
     $oMonoObjectSet = new DBObjectSet($oTargetSearch);
     if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES) {
         if (!MetaModel::IsValidAttCode($this->Get('objclass'), $this->Get('attcode'))) {
             return '';
         }
         // Protects against renamed attributes...
         $oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
         $sAttName = $oAttDef->GetLabel();
         $sLinkClass = $oAttDef->GetLinkedClass();
         $aLinkClasses = MetaModel::EnumChildClasses($sLinkClass, ENUM_CHILD_CLASSES_ALL);
         // Search for changes on the corresponding link
         //
         $oSearch = new DBObjectSearch('CMDBChangeOpSetAttribute');
         $oSearch->AddCondition('change', $this->Get('change'), '=');
         $oSearch->AddCondition('objkey', $this->Get('link_id'), '=');
         if (count($aLinkClasses) == 1) {
             // Faster than the whole building of the expression below for just one value ??
             $oSearch->AddCondition('objclass', $sLinkClass, '=');
         } else {
             $oField = new FieldExpression('objclass', $oSearch->GetClassAlias());
             $sListExpr = '(' . implode(', ', CMDBSource::Quote($aLinkClasses)) . ')';
             $sOQLCondition = $oField->Render() . " IN {$sListExpr}";
             $oNewCondition = Expression::FromOQL($sOQLCondition);
             $oSearch->AddConditionExpression($oNewCondition);
         }
         $oSet = new DBObjectSet($oSearch);
         $aChanges = array();
         while ($oChangeOp = $oSet->Fetch()) {
             $aChanges[] = $oChangeOp->GetDescription();
         }
         if (count($aChanges) == 0) {
             return '';
         }
         $sItemDesc = MetaModel::GetHyperLink($this->Get('item_class'), $this->Get('item_id'));
         $sResult = $sAttName . ' - ';
         $sResult .= Dict::Format('Change:LinkSet:Modified', $sItemDesc);
         $sResult .= ' : ' . implode(', ', $aChanges);
     }
     return $sResult;
 }
Пример #24
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;
 }
 /**
  * Helper to link objects
  *
  * @param string sLinkAttCode
  * @param string sLinkedClass
  * @param array $aLinkList
  * @param DBObject oTargetObj
  * @param WebServiceResult oRes
  *
  * @return array List of objects that could not be found
  */
 protected function AddLinkedObjects($sLinkAttCode, $sParamName, $sLinkedClass, $aLinkList, &$oTargetObj, &$oRes)
 {
     $oLinkAtt = MetaModel::GetAttributeDef(get_class($oTargetObj), $sLinkAttCode);
     $sLinkClass = $oLinkAtt->GetLinkedClass();
     $sExtKeyToItem = $oLinkAtt->GetExtKeyToRemote();
     $aItemsFound = array();
     $aItemsNotFound = array();
     if (is_null($aLinkList)) {
         return $aItemsNotFound;
     }
     foreach ($aLinkList as $aItemData) {
         if (!array_key_exists('class', $aItemData)) {
             $oRes->LogWarning("Parameter {$sParamName}: missing 'class' specification");
             continue;
             // skip
         }
         $sTargetClass = $aItemData['class'];
         if (!MetaModel::IsValidClass($sTargetClass)) {
             $oRes->LogError("Parameter {$sParamName}: invalid class '{$sTargetClass}'");
             continue;
             // skip
         }
         if (!MetaModel::IsParentClass($sLinkedClass, $sTargetClass)) {
             $oRes->LogError("Parameter {$sParamName}: '{$sTargetClass}' is not a child class of '{$sLinkedClass}'");
             continue;
             // skip
         }
         $oReconFilter = new CMDBSearchFilter($sTargetClass);
         $aCIStringDesc = array();
         foreach ($aItemData['search'] as $sAttCode => $value) {
             if (!MetaModel::IsValidFilterCode($sTargetClass, $sAttCode)) {
                 $aCodes = array_keys(MetaModel::GetClassFilterDefs($sTargetClass));
                 $oRes->LogError("Parameter {$sParamName}: '{$sAttCode}' is not a valid filter code for class '{$sTargetClass}', expecting a value in {" . implode(', ', $aCodes) . "}");
                 continue 2;
                 // skip the entire item
             }
             $aCIStringDesc[] = "{$sAttCode}: {$value}";
             // The attribute is one of our reconciliation key
             $oReconFilter->AddCondition($sAttCode, $value, '=');
         }
         if (count($aCIStringDesc) == 1) {
             // take the last and unique value to describe the object
             $sItemDesc = $value;
         } else {
             // describe the object by the given keys
             $sItemDesc = $sTargetClass . '(' . implode('/', $aCIStringDesc) . ')';
         }
         $oExtObjects = new CMDBObjectSet($oReconFilter);
         switch ($oExtObjects->Count()) {
             case 0:
                 $oRes->LogWarning("Parameter {$sParamName}: object to link {$sLinkedClass} / {$sItemDesc} could not be found (searched: '" . $oReconFilter->ToOQL(true) . "')");
                 $aItemsNotFound[] = $sItemDesc;
                 break;
             case 1:
                 $aItemsFound[] = array('object' => $oExtObjects->Fetch(), 'link_values' => @$aItemData['link_values'], 'desc' => $sItemDesc);
                 break;
             default:
                 $oRes->LogWarning("Parameter {$sParamName}: Found " . $oExtObjects->Count() . " matches for item '{$sItemDesc}' (searched: '" . $oReconFilter->ToOQL(true) . "')");
                 $aItemsNotFound[] = $sItemDesc;
         }
     }
     if (count($aItemsFound) > 0) {
         $aLinks = array();
         foreach ($aItemsFound as $aItemData) {
             $oLink = MetaModel::NewObject($sLinkClass);
             $oLink->Set($sExtKeyToItem, $aItemData['object']->GetKey());
             foreach ($aItemData['link_values'] as $sKey => $value) {
                 if (!MetaModel::IsValidAttCode($sLinkClass, $sKey)) {
                     $oRes->LogWarning("Parameter {$sParamName}: Attaching item '" . $aItemData['desc'] . "', the attribute code '{$sKey}' is not valid ; check the class '{$sLinkClass}'");
                 } else {
                     $oLink->Set($sKey, $value);
                 }
             }
             $aLinks[] = $oLink;
         }
         $oImpactedInfraSet = DBObjectSet::FromArray($sLinkClass, $aLinks);
         $oTargetObj->Set($sLinkAttCode, $oImpactedInfraSet);
     }
     return $aItemsNotFound;
 }
 /**
  * Interpret the Rest/Json value and get a valid attribute value
  * 	 
  * @param string $sClass Name of the class
  * @param string $sAttCode Attribute code
  * @param mixed $value Depending on the type of attribute (a scalar, or search criteria, or list of related objects...)
  * @return mixed The value that can be used with DBObject::Set()
  * @throws Exception If the specification of the value is not valid.
  * @api
  */
 public static function MakeValue($sClass, $sAttCode, $value)
 {
     try {
         if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             throw new Exception("Unknown attribute");
         }
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
         if ($oAttDef instanceof AttributeExternalKey) {
             $oExtKeyObject = static::FindObjectFromKey($oAttDef->GetTargetClass(), $value, true);
             $value = $oExtKeyObject != null ? $oExtKeyObject->GetKey() : 0;
         } elseif ($oAttDef instanceof AttributeLinkedSet) {
             if (!is_array($value)) {
                 throw new Exception("A link set must be defined by an array of objects");
             }
             $sLnkClass = $oAttDef->GetLinkedClass();
             $aLinks = array();
             foreach ($value as $oValues) {
                 $oLnk = static::MakeObjectFromFields($sLnkClass, $oValues);
                 $aLinks[] = $oLnk;
             }
             $value = DBObjectSet::FromArray($sLnkClass, $aLinks);
         } else {
             $value = $oAttDef->FromJSONToValue($value);
         }
     } catch (Exception $e) {
         throw new Exception("{$sAttCode}: " . $e->getMessage(), $e->getCode());
     }
     return $value;
 }
Пример #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
/**
 * Validate the parameters and create the ticket object (based on the page's POSTed parameters)
 * @param WebPage $oP The current web page for the  output
 * @param Organization $oUserOrg The organization of the current user
 * @return void
 */
function DoCreateRequest($oP, $oUserOrg)
{
    $aParameters = $oP->ReadAllParams(PORTAL_ALL_PARAMS . ',template_id');
    $sTransactionId = utils::ReadPostedParam('transaction_id', '');
    if (!utils::IsTransactionValid($sTransactionId)) {
        $oP->add("<h1>" . Dict::S('UI:Error:ObjectAlreadyCreated') . "</h1>\n");
        //ShowOngoingTickets($oP);
        return;
    }
    // Validate the parameters
    // 1) ServiceCategory
    $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICECATEGORY_QUERY);
    $oSearch->AllowAllData();
    // In case the user has the rights on his org only
    $oSet = new CMDBObjectSet($oSearch, array(), array('id' => $aParameters['service_id'], 'org_id' => $oUserOrg->GetKey()));
    if ($oSet->Count() != 1) {
        // Invalid service for the current user !
        throw new Exception("Invalid Service Category: id={$aParameters['service_id']} - count: " . $oSet->Count());
    }
    $oServiceCategory = $oSet->Fetch();
    // 2) Service Subcategory
    $oSearch = DBObjectSearch::FromOQL(PORTAL_VALIDATE_SERVICESUBCATEGORY_QUERY);
    RestrictSubcategories($oSearch);
    $oSearch->AllowAllData();
    // In case the user has the rights on his org only
    $oSet = new CMDBObjectSet($oSearch, array(), array('service_id' => $aParameters['service_id'], 'id' => $aParameters['servicesubcategory_id'], 'org_id' => $oUserOrg->GetKey()));
    if ($oSet->Count() != 1) {
        // Invalid subcategory
        throw new Exception("Invalid ServiceSubcategory: id={$aParameters['servicesubcategory_id']} for service category " . $oServiceCategory->GetName() . "({$aParameters['service_id']}) - count: " . $oSet->Count());
    }
    $oServiceSubCategory = $oSet->Fetch();
    $sClass = ComputeClass($oServiceSubCategory->GetKey());
    $oRequest = MetaModel::NewObject($sClass);
    $aAttList = array_merge(explode(',', GetConstant($sClass, 'FORM_ATTRIBUTES')), array('service_id', 'servicesubcategory_id'));
    $oRequest->UpdateObjectFromPostedForm('', $aAttList);
    $oRequest->Set('org_id', $oUserOrg->GetKey());
    $oRequest->Set('caller_id', UserRights::GetContactId());
    if (isset($aParameters['moreinfo'])) {
        // There is a template, insert it into the description
        $sLogAttCode = GetConstant($sClass, 'PUBLIC_LOG');
        $oRequest->Set($sLogAttCode, $aParameters['moreinfo']);
    }
    $sTypeAttCode = GetConstant($sClass, 'TYPE');
    if ($sTypeAttCode != '' && PORTAL_SET_TYPE_FROM != '') {
        $oRequest->Set($sTypeAttCode, $oServiceSubCategory->Get(PORTAL_SET_TYPE_FROM));
    }
    if (MetaModel::IsValidAttCode($sClass, 'origin')) {
        $oRequest->Set('origin', 'portal');
    }
    $oAttPlugin = new AttachmentPlugIn();
    $oAttPlugin->OnFormSubmit($oRequest);
    list($bRes, $aIssues) = $oRequest->CheckToWrite();
    if ($bRes) {
        if (isset($aParameters['template_id'])) {
            $oTemplate = MetaModel::GetObject('Template', $aParameters['template_id']);
            $sLogAttCode = GetConstant($sClass, 'PUBLIC_LOG');
            $oRequest->Set($sLogAttCode, $oTemplate->GetPostedValuesAsText($oRequest) . "\n");
            $oRequest->DBInsertNoReload();
            $oTemplate->RecordExtraDataFromPostedForm($oRequest);
        } else {
            $oRequest->DBInsertNoReload();
        }
        $oP->add("<h1>" . Dict::Format('UI:Title:Object_Of_Class_Created', $oRequest->GetName(), MetaModel::GetName($sClass)) . "</h1>\n");
        //DisplayObject($oP, $oRequest, $oUserOrg);
        ShowOngoingTickets($oP);
    } else {
        RequestCreationForm($oP, $oUserOrg);
        $sIssueDesc = Dict::Format('UI:ObjectCouldNotBeWritten', implode(', ', $aIssues));
        $oP->add_ready_script("alert('" . addslashes($sIssueDesc) . "');");
    }
}
 protected function DisplaySearchField($sClass, $sAttSpec, $aExtraParams, $sPrefix, $sFieldName = null, $aFilterParams = array())
 {
     if (is_null($sFieldName)) {
         $sFieldName = str_replace('->', PARAM_ARROW_SEP, $sAttSpec);
     }
     $iPos = strpos($sAttSpec, '->');
     if ($iPos !== false) {
         $sAttCode = substr($sAttSpec, 0, $iPos);
         $sSubSpec = substr($sAttSpec, $iPos + 2);
         if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) {
             throw new Exception("Invalid attribute code '{$sClass}/{$sAttCode}' in search specification '{$sAttSpec}'");
         }
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
         if ($oAttDef->IsLinkSet()) {
             $sTargetClass = $oAttDef->GetLinkedClass();
         } elseif ($oAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
             $sTargetClass = $oAttDef->GetTargetClass(EXTKEY_ABSOLUTE);
         } else {
             throw new Exception("Attribute specification '{$sAttSpec}', '{$sAttCode}' should be either a link set or an external key");
         }
         $this->DisplaySearchField($sTargetClass, $sSubSpec, $aExtraParams, $sPrefix, $sFieldName, $aFilterParams);
     } else {
         // $sAttSpec is an attribute code
         //
         $this->add('<span style="white-space: nowrap;padding:5px;display:inline-block;">');
         $sFilterValue = '';
         $sFilterValue = utils::ReadParam($sPrefix . $sFieldName, '', false, 'raw_data');
         $sFilterOpCode = null;
         // Use the default 'loose' OpCode
         $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttSpec);
         if ($oAttDef->IsExternalKey()) {
             $sTargetClass = $oAttDef->GetTargetClass();
             $sFilterDefName = 'PORTAL_TICKETS_SEARCH_FILTER_' . $sAttSpec;
             if (defined($sFilterDefName)) {
                 try {
                     $oFitlerWithParams = DBObjectSearch::FromOQL(constant($sFilterDefName));
                     $sFilterOQL = $oFitlerWithParams->ToOQL(true, $aFilterParams);
                     $oAllowedValues = new DBObjectSet(DBObjectSearch::FromOQL($sFilterOQL), array(), $aFilterParams);
                 } catch (OQLException $e) {
                     throw new Exception("Incorrect filter '{$sFilterDefName}' for attribute '{$sAttcode}': " . $e->getMessage());
                 }
             } else {
                 $oAllowedValues = new DBObjectSet(new DBObjectSearch($sTargetClass));
             }
             $iFieldSize = $oAttDef->GetMaxSize();
             $iMaxComboLength = $oAttDef->GetMaximumComboLength();
             $this->add("<label>" . MetaModel::GetFilterLabel($sClass, $sAttSpec) . ":</label>&nbsp;");
             //$oWidget = UIExtKeyWidget::DIsplayFromAttCode($sAttSpec, $sClass, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sPrefix.$sFieldName, false, '', $sPrefix, '');
             //$this->add($oWidget->Display($this, $aExtraParams, true /* bSearchMode */));
             $aExtKeyParams = $aExtraParams;
             $aExtKeyParams['iFieldSize'] = $oAttDef->GetMaxSize();
             $aExtKeyParams['iMinChars'] = $oAttDef->GetMinAutoCompleteChars();
             //	                      DisplayFromAttCode($this, $sAttCode, $sClass, $sTitle,              $oAllowedValues, $value,        $iInputId,            $bMandatory, $sFieldName = '', $sFormPrefix = '', $aArgs, $bSearchMode = false)
             $sHtml = UIExtKeyWidget::DisplayFromAttCode($this, $sAttSpec, $sClass, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, $sPrefix . $sFieldName, false, $sPrefix . $sFieldName, $sPrefix, $aExtKeyParams, true);
             $this->add($sHtml);
         } else {
             $aAllowedValues = MetaModel::GetAllowedValues_flt($sClass, $sAttSpec, $aExtraParams);
             if (is_null($aAllowedValues)) {
                 // Any value is possible, display an input box
                 $sSanitizedValue = htmlentities($sFilterValue, ENT_QUOTES, 'UTF-8');
                 $this->add("<label>" . MetaModel::GetFilterLabel($sClass, $sAttSpec) . ":</label>&nbsp;<input class=\"textSearch\" name=\"{$sPrefix}{$sFieldName}\" value=\"{$sSanitizedValue}\"/>\n");
             } else {
                 //Enum field or external key, display a combo
                 $sValue = "<select name=\"{$sPrefix}{$sFieldName}\">\n";
                 $sValue .= "<option value=\"\">" . Dict::S('UI:SearchValue:Any') . "</option>\n";
                 foreach ($aAllowedValues as $key => $value) {
                     if ($sFilterValue == $key) {
                         $sSelected = ' selected';
                     } else {
                         $sSelected = '';
                     }
                     $sValue .= "<option value=\"{$key}\"{$sSelected}>{$value}</option>\n";
                 }
                 $sValue .= "</select>\n";
                 $this->add("<label>" . MetaModel::GetFilterLabel($sClass, $sAttSpec) . ":</label>&nbsp;{$sValue}\n");
             }
         }
         unset($aExtraParams[$sFieldName]);
         $this->add('</span> ');
         $sTip = $oAttDef->GetHelpOnSmartSearch();
         if (strlen($sTip) > 0) {
             $sTip = addslashes($sTip);
             $sTip = str_replace(array("\n", "\r"), " ", $sTip);
             // :input does represent in form visible input (INPUT, SELECT, TEXTAREA)
             $this->add_ready_script("\$(':input[name={$sPrefix}{$sFieldName}]').qtip( { content: '{$sTip}', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
         }
     }
 }
 public function CheckProjectionSpec($oProjectionSpec, $sProjectedClass)
 {
     $sExpression = $oProjectionSpec->Get('value');
     $sAttribute = $oProjectionSpec->Get('attribute');
     // Shortcut: "any value" or "no value" means no projection
     if (empty($sExpression)) {
         return;
     }
     if ($sExpression == '<any>') {
         return;
     }
     // 1st - compute the data type for the dimension
     //
     $sType = $this->Get('type');
     if (MetaModel::IsValidClass($sType)) {
         $sExpectedType = $sType;
     } else {
         $sExpectedType = '_scalar_';
     }
     // 2nd - compute the data type for the projection
     //
     $sTargetClass = '';
     if ($sExpression == '<this>' || $sExpression == '<user>') {
         $sTargetClass = $sProjectedClass;
     } elseif ($sExpression == '<any>') {
         $sTargetClass = '';
     } else {
         // Evaluate wether it is a constant or not
         try {
             $oObjectSearch = DBObjectSearch::FromOQL_AllData($sExpression);
             $sTargetClass = $oObjectSearch->GetClass();
         } catch (OqlException $e) {
         }
     }
     if (empty($sTargetClass)) {
         $sFoundType = '_void_';
     } else {
         if (empty($sAttribute)) {
             $sFoundType = $sTargetClass;
         } else {
             if (!MetaModel::IsValidAttCode($sTargetClass, $sAttribute)) {
                 throw new CoreException('Unkown attribute code in projection specification', array('found' => $sAttribute, 'expecting' => MetaModel::GetAttributesList($sTargetClass), 'class' => $sTargetClass, 'projection' => $oProjectionSpec));
             }
             $oAttDef = MetaModel::GetAttributeDef($sTargetClass, $sAttribute);
             if ($oAttDef->IsExternalKey()) {
                 $sFoundType = $oAttDef->GetTargetClass();
             } else {
                 $sFoundType = '_scalar_';
             }
         }
     }
     // Compare the dimension type and projection type
     if ($sFoundType != '_void_' && $sFoundType != $sExpectedType) {
         throw new CoreException('Wrong type in projection specification', array('found' => $sFoundType, 'expecting' => $sExpectedType, 'expression' => $sExpression, 'attribute' => $sAttribute, 'projection' => $oProjectionSpec));
     }
 }