public function GetSelectFilter($oUser, $sClass, $aSettings = array()) { $aConditions = array(); foreach ($this->m_aDimensions as $iDimension => $oDimension) { $oClassProj = @$this->m_aClassProjs[$sClass][$iDimension]; if (is_null($oClassProj)) { // Authorize any for this dimension, then no additional criteria is required continue; } // 1 - Get class projection info // $oExpression = null; $sExpr = $oClassProj->Get('value'); if ($sExpr == '<this>') { $sColumn = $oClassProj->Get('attribute'); if (empty($sColumn)) { $oExpression = new FieldExpression('id', $sClass); } else { $oExpression = new FieldExpression($sColumn, $sClass); } } elseif ($sExpr == '<any>' || $sExpr == '') { // Authorize any for this dimension, then no additional criteria is required continue; } elseif (strtolower(substr($sExpr, 0, 6)) == 'select') { throw new CoreException('Sorry, projections by the mean of OQL are not supported currently, please specify an attribute instead', array('class' => $sClass, 'expression' => $sExpr)); } else { // Constant value(s) // unsupported throw new CoreException('Sorry, constant projections are not supported currently, please specify an attribute instead', array('class' => $sClass, 'expression' => $sExpr)); // $aRes = explode(';', trim($sExpr)); } // 2 - Get profile projection info and use it if needed // $aProjections = self::GetReadableProjectionsByDim($oUser, $sClass, $oDimension); if (is_null($aProjections)) { // Authorize any for this dimension, then no additional criteria is required continue; } elseif (count($aProjections) == 0) { // Authorize none, then exit as quickly as possible return false; } else { // Authorize the given set of values $oListExpr = ListExpression::FromScalars($aProjections); $oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr); $aConditions[] = $oCondition; } } if (count($aConditions) == 0) { // allow all return true; } else { $oFilter = new DBObjectSearch($sClass); foreach ($aConditions as $oCondition) { $oFilter->AddConditionExpression($oCondition); } //return true; return $oFilter; } }
/** * Retrieve the DBSearch corresponding to the objects present in this set * * Limitation: * This method will NOT work for sets with several columns (i.e. several objects per row) * * @return DBObjectSearch */ public function GetFilter() { // Make sure that we carry on the parameters of the set with the filter $oFilter = $this->m_oFilter->DeepClone(); // Note: the arguments found within a set can be object (but not in a filter) // That's why PrepareQueryArguments must be invoked there $oFilter->SetInternalParams(array_merge($oFilter->GetInternalParams(), MetaModel::PrepareQueryArguments($this->m_aArgs))); if (count($this->m_aAddedIds) == 0) { return $oFilter; } else { $oIdListExpr = ListExpression::FromScalars(array_keys($this->m_aAddedIds)); $oIdExpr = new FieldExpression('id', $oFilter->GetClassAlias()); $oIdInList = new BinaryExpression($oIdExpr, 'IN', $oIdListExpr); $oFilter->MergeConditionExpression($oIdInList); return $oFilter; } }
/** * ... */ public function MakeSelectFilter($sClass, $aAllowedOrgs, $aSettings = array(), $sAttCode = null) { if ($sAttCode == null) { $sAttCode = $this->GetOwnerOrganizationAttCode($sClass); } if (empty($sAttCode)) { return $oFilter = new DBObjectSearch($sClass); } $oExpression = new FieldExpression($sAttCode, $sClass); $oFilter = new DBObjectSearch($sClass); $oListExpr = ListExpression::FromScalars($aAllowedOrgs); $oCondition = new BinaryExpression($oExpression, 'IN', $oListExpr); $oFilter->AddConditionExpression($oCondition); if ($this->HasSharing()) { if ($sAttCode == 'id' && isset($aSettings['bSearchMode']) && $aSettings['bSearchMode']) { // Querying organizations (or derived) // and the expected list of organizations will be used as a search criteria // Therefore the query can also return organization having objects shared with the allowed organizations // // 1) build the list of organizations sharing something with the allowed organizations // Organization <== sharing_org_id == SharedObject having org_id IN {user orgs} $oShareSearch = new DBObjectSearch('SharedObject'); $oOrgField = new FieldExpression('org_id', 'SharedObject'); $oShareSearch->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr)); $oSearchSharers = new DBObjectSearch('Organization'); $oSearchSharers->AllowAllData(); $oSearchSharers->AddCondition_ReferencedBy($oShareSearch, 'sharing_org_id'); $aSharers = array(); foreach ($oSearchSharers->ToDataArray(array('id')) as $aRow) { $aSharers[] = $aRow['id']; } // 2) Enlarge the overall results: ... OR id IN(id1, id2, id3) if (count($aSharers) > 0) { $oSharersList = ListExpression::FromScalars($aSharers); $oFilter->MergeConditionExpression(new BinaryExpression($oExpression, 'IN', $oSharersList)); } } $aShareProperties = SharedObject::GetSharedClassProperties($sClass); if ($aShareProperties) { $sShareClass = $aShareProperties['share_class']; $sShareAttCode = $aShareProperties['attcode']; $oSearchShares = new DBObjectSearch($sShareClass); $oSearchShares->AllowAllData(); $sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization'); $oOrgField = new FieldExpression('org_id', $sShareClass); $oSearchShares->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr)); $aShared = array(); foreach ($oSearchShares->ToDataArray(array($sShareAttCode)) as $aRow) { $aShared[] = $aRow[$sShareAttCode]; } if (count($aShared) > 0) { $oObjId = new FieldExpression('id', $sClass); $oSharedIdList = ListExpression::FromScalars($aShared); $oFilter->MergeConditionExpression(new BinaryExpression($oObjId, 'IN', $oSharedIdList)); } } } // if HasSharing return $oFilter; }
/** * Get the friendly name for the class and its subclasses (if finalclass = 'subclass' ...) * Simplifies the final expression by grouping classes having the same name expression * Used when querying a parent class */ protected static function GetExtendedNameExpression($sClass) { // 1st step - get all of the required expressions (instantiable classes) // and group them using their OQL representation // $aFNExpressions = array(); // signature => array('expression' => oExp, 'classes' => array of classes) foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass) { if ($sSubClass != $sClass && MetaModel::IsAbstract($sSubClass)) { continue; } $oSubClassName = MetaModel::GetNameExpression($sSubClass); $sSignature = $oSubClassName->Render(); if (!array_key_exists($sSignature, $aFNExpressions)) { $aFNExpressions[$sSignature] = array('expression' => $oSubClassName, 'classes' => array()); } $aFNExpressions[$sSignature]['classes'][] = $sSubClass; } // 2nd step - build the final name expression depending on the finalclass // if (count($aFNExpressions) == 1) { $aExpData = reset($aFNExpressions); $oNameExpression = $aExpData['expression']; } else { $oNameExpression = null; foreach ($aFNExpressions as $sSignature => $aExpData) { $oClassListExpr = ListExpression::FromScalars($aExpData['classes']); $oClassExpr = new FieldExpression('finalclass', $sClass); $oClassInList = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); if (is_null($oNameExpression)) { $oNameExpression = $aExpData['expression']; } else { $oNameExpression = new FunctionExpression('IF', array($oClassInList, $aExpData['expression'], $oNameExpression)); } } } return $oNameExpression; }
/** * 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); } } }