oOQLClassNode = $oOQLClassNode; $this->oBuild = $oBuild; } /** * Prune the unnecessary joins */ public function OptimizeClassTree() { $this->PruneJoins($this->oOQLClassNode); } /** * @param OQLClassNode $oCurrentClassNode * * @return bool */ private function PruneJoins($oCurrentClassNode) { $aExpectedAttributes = $this->oBuild->m_oQBExpressions->GetExpectedFields($oCurrentClassNode->GetNodeClassAlias()); $bCanBeRemoved = empty($aExpectedAttributes); foreach ($oCurrentClassNode->GetJoins() as $sLeftKey => $aJoins) { foreach ($aJoins as $index => $oJoin) { if ($this->PruneJoins($oJoin->GetOOQLClassNode())) { if ($oJoin->IsOutbound()) { // If joined class in not the same class than the external key target class // then the join cannot be removed because it is used to filter the request $sJoinedClass = $oJoin->GetOOQLClassNode()->GetNodeClass(); $sExtKeyAttCode = $oJoin->GetLeftField(); $oExtKeyAttDef = MetaModel::GetAttributeDef($oCurrentClassNode->GetNodeClass(), $sExtKeyAttCode); if (($oExtKeyAttDef instanceof AttributeExternalKey) && ($sJoinedClass == $oExtKeyAttDef->GetTargetClass())) { // The join is not used, remove from tree $oCurrentClassNode->RemoveJoin($sLeftKey, $index); } } else { // Inbound joins cannot be removed $bCanBeRemoved = false; } } else { // This join is used, so the current node cannot be removed $bCanBeRemoved = false; } } } return $bCanBeRemoved; } }