Files
iTop/core/oqlclasstreeoptimizer.class.inc.php
Pierre Goiffon d8e2a1cc7c Merge branch 'support/2.7' into develop
# Conflicts:
#	README.md
#	composer.json
#	composer.lock
#	core/cmdbsource.class.inc.php
#	core/dbobject.class.php
#	datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php
#	datamodels/2.x/combodo-db-tools/dbtools.php
#	datamodels/2.x/combodo-db-tools/dictionaries/zh_cn.dict.combodo-db-tools.php
#	datamodels/2.x/itop-attachments/dictionaries/zh_cn.dict.itop-attachments.php
#	datamodels/2.x/itop-core-update/dictionaries/zh_cn.dict.itop-core-update.php
#	dictionaries/zh_cn.dictionary.itop.core.php
#	dictionaries/zh_cn.dictionary.itop.ui.php
#	lib/composer/InstalledVersions.php
#	lib/composer/autoload_classmap.php
#	lib/composer/autoload_static.php
#	lib/composer/installed.php
#	lib/composer/platform_check.php
#	pages/ajax.render.php
#	pages/csvimport.php
#	setup/ajax.dataloader.php
#	setup/index.php
#	setup/setuputils.class.inc.php
#	test/application/UtilsTest.php
2021-06-14 16:19:56 +02:00

78 lines
2.0 KiB
PHP

<?php
/**
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class OQLClassTreeOptimizer
{
/** @var OQLClassNode */
private $oOQLClassNode;
/** @var QueryBuilderContext */
private $oBuild;
/**
* OQLClassTreeOptimizer constructor.
*
* @param OQLClassNode $oOQLClassNode
* @param QueryBuilderContext $oBuild
*/
public function __construct($oOQLClassNode, $oBuild)
{
$this->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;
}
}