|
@@ -15,6 +15,8 @@
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
require_once(APPROOT.'core/modulehandler.class.inc.php');
|
|
require_once(APPROOT.'core/modulehandler.class.inc.php');
|
|
|
|
+require_once(APPROOT.'core/querybuildercontext.class.inc.php');
|
|
|
|
+require_once(APPROOT.'core/querymodifier.class.inc.php');
|
|
|
|
|
|
/**
|
|
/**
|
|
* Metamodel
|
|
* Metamodel
|
|
@@ -25,8 +27,6 @@ require_once(APPROOT.'core/modulehandler.class.inc.php');
|
|
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
|
* @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
|
|
*/
|
|
*/
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
// #@# todo: change into class const (see Doctrine)
|
|
// #@# todo: change into class const (see Doctrine)
|
|
// Doctrine example
|
|
// Doctrine example
|
|
// class toto
|
|
// class toto
|
|
@@ -1404,7 +1404,7 @@ abstract class MetaModel
|
|
|
|
|
|
// Build the list of available extensions
|
|
// Build the list of available extensions
|
|
//
|
|
//
|
|
- $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension');
|
|
|
|
|
|
+ $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier');
|
|
foreach($aInterfaces as $sInterface)
|
|
foreach($aInterfaces as $sInterface)
|
|
{
|
|
{
|
|
self::$m_aExtensionClasses[$sInterface] = array();
|
|
self::$m_aExtensionClasses[$sInterface] = array();
|
|
@@ -1924,12 +1924,26 @@ abstract class MetaModel
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Compute query modifiers properties (can be set in the search itself, by the context, etc.)
|
|
|
|
+ //
|
|
|
|
+ $aModifierProperties = self::MakeModifierProperties($oFilter);
|
|
|
|
+
|
|
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
|
if (self::$m_bQueryCacheEnabled || self::$m_bTraceQueries)
|
|
{
|
|
{
|
|
// Need to identify the query
|
|
// Need to identify the query
|
|
$sOqlQuery = $oFilter->ToOql();
|
|
$sOqlQuery = $oFilter->ToOql();
|
|
|
|
|
|
- $sRawId = $sOqlQuery;
|
|
|
|
|
|
+ if (count($aModifierProperties))
|
|
|
|
+ {
|
|
|
|
+ array_multisort($aModifierProperties);
|
|
|
|
+ $sModifierProperties = json_encode($aModifierProperties);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ $sModifierProperties = '';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ $sRawId = $sOqlQuery.$sModifierProperties;
|
|
if (!is_null($aAttToLoad))
|
|
if (!is_null($aAttToLoad))
|
|
{
|
|
{
|
|
foreach($aAttToLoad as $sAlias => $aAttributes)
|
|
foreach($aAttToLoad as $sAlias => $aAttributes)
|
|
@@ -2024,12 +2038,10 @@ abstract class MetaModel
|
|
|
|
|
|
if (!isset($oSelect))
|
|
if (!isset($oSelect))
|
|
{
|
|
{
|
|
- $aClassAliases = array();
|
|
|
|
- $aTableAliases = array();
|
|
|
|
- $oQBExpr = new QueryBuilderExpressions(array(), $oFilter->GetCriteria());
|
|
|
|
|
|
+ $oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
|
|
|
|
|
$oKPI = new ExecutionKPI();
|
|
$oKPI = new ExecutionKPI();
|
|
- $oSelect = self::MakeQuery($oFilter->GetSelectedClasses(), $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, $aAttToLoad, array(), true /* main query */);
|
|
|
|
|
|
+ $oSelect = self::MakeQuery($oBuild, $oFilter, $aAttToLoad, array(), true /* main query */);
|
|
$oSelect->SetSourceOQL($sOqlQuery);
|
|
$oSelect->SetSourceOQL($sOqlQuery);
|
|
$oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery);
|
|
$oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery);
|
|
|
|
|
|
@@ -2138,12 +2150,33 @@ abstract class MetaModel
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ protected static function MakeModifierProperties($oFilter)
|
|
|
|
+ {
|
|
|
|
+ // Compute query modifiers properties (can be set in the search itself, by the context, etc.)
|
|
|
|
+ //
|
|
|
|
+ $aModifierProperties = array();
|
|
|
|
+ foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier)
|
|
|
|
+ {
|
|
|
|
+ // Lowest precedence: the application context
|
|
|
|
+ $aPluginProps = ApplicationContext::GetPluginProperties($sPluginClass);
|
|
|
|
+ // Highest precedence: programmatically specified (or OQL)
|
|
|
|
+ foreach($oFilter->GetModifierProperties($sPluginClass) as $sProp => $value)
|
|
|
|
+ {
|
|
|
|
+ $aPluginProps[$sProp] = $value;
|
|
|
|
+ }
|
|
|
|
+ if (count($aPluginProps) > 0)
|
|
|
|
+ {
|
|
|
|
+ $aModifierProperties[$sPluginClass] = $aPluginProps;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return $aModifierProperties;
|
|
|
|
+ }
|
|
|
|
+
|
|
public static function MakeDeleteQuery(DBObjectSearch $oFilter, $aArgs = array())
|
|
public static function MakeDeleteQuery(DBObjectSearch $oFilter, $aArgs = array())
|
|
{
|
|
{
|
|
- $aClassAliases = array();
|
|
|
|
- $aTableAliases = array();
|
|
|
|
- $oQBExpr = new QueryBuilderExpressions(array(), $oFilter->GetCriteria());
|
|
|
|
- $oSelect = self::MakeQuery($oFilter->GetSelectedClasses(), $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, null, array(), true /* main query */);
|
|
|
|
|
|
+ $aModifierProperties = self::MakeModifierProperties($oFilter);
|
|
|
|
+ $oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
|
|
|
+ $oSelect = self::MakeQuery($oBuild, $oFilter, null, array(), true /* main query */);
|
|
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
|
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
|
return $oSelect->RenderDelete($aScalarArgs);
|
|
return $oSelect->RenderDelete($aScalarArgs);
|
|
}
|
|
}
|
|
@@ -2151,26 +2184,21 @@ abstract class MetaModel
|
|
public static function MakeUpdateQuery(DBObjectSearch $oFilter, $aValues, $aArgs = array())
|
|
public static function MakeUpdateQuery(DBObjectSearch $oFilter, $aValues, $aArgs = array())
|
|
{
|
|
{
|
|
// $aValues is an array of $sAttCode => $value
|
|
// $aValues is an array of $sAttCode => $value
|
|
- $aClassAliases = array();
|
|
|
|
- $aTableAliases = array();
|
|
|
|
- $oQBExpr = new QueryBuilderExpressions(array(), $oFilter->GetCriteria());
|
|
|
|
- $oSelect = self::MakeQuery($oFilter->GetSelectedClasses(), $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, null, $aValues, true /* main query */);
|
|
|
|
|
|
+ $aModifierProperties = self::MakeModifierProperties($oFilter);
|
|
|
|
+ $oBuild = new QueryBuilderContext($oFilter, $aModifierProperties);
|
|
|
|
+ $oSelect = self::MakeQuery($oBuild, $oFilter, null, $aValues, true /* main query */);
|
|
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
|
$aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams());
|
|
return $oSelect->RenderUpdate($aScalarArgs);
|
|
return $oSelect->RenderUpdate($aScalarArgs);
|
|
}
|
|
}
|
|
|
|
|
|
- private static function MakeQuery($aSelectedClasses, &$oQBExpr, &$aClassAliases, &$aTableAliases, DBObjectSearch $oFilter, $aAttToLoad = null, $aValues = array(), $bIsMainQuery = false)
|
|
|
|
|
|
+ private static function MakeQuery(&$oBuild, DBObjectSearch $oFilter, $aAttToLoad = null, $aValues = array(), $bIsMainQuery = false)
|
|
{
|
|
{
|
|
// Note: query class might be different than the class of the filter
|
|
// Note: query class might be different than the class of the filter
|
|
// -> this occurs when we are linking our class to an external class (referenced by, or pointing to)
|
|
// -> this occurs when we are linking our class to an external class (referenced by, or pointing to)
|
|
$sClass = $oFilter->GetFirstJoinedClass();
|
|
$sClass = $oFilter->GetFirstJoinedClass();
|
|
$sClassAlias = $oFilter->GetFirstJoinedClassAlias();
|
|
$sClassAlias = $oFilter->GetFirstJoinedClassAlias();
|
|
|
|
|
|
- $bIsOnQueriedClass = array_key_exists($sClassAlias, $aSelectedClasses);
|
|
|
|
- if ($bIsOnQueriedClass)
|
|
|
|
- {
|
|
|
|
- $aClassAliases = array_merge($aClassAliases, $oFilter->GetJoinedClasses());
|
|
|
|
- }
|
|
|
|
|
|
+ $bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
|
|
|
|
|
|
self::DbgTrace("Entering: ".$oFilter->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
|
self::DbgTrace("Entering: ".$oFilter->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
|
|
|
|
|
@@ -2180,7 +2208,7 @@ abstract class MetaModel
|
|
if ($bIsOnQueriedClass)
|
|
if ($bIsOnQueriedClass)
|
|
{
|
|
{
|
|
// default to the whole list of attributes + the very std id/finalclass
|
|
// default to the whole list of attributes + the very std id/finalclass
|
|
- $oQBExpr->AddSelect($sClassAlias.'id', new FieldExpression('id', $sClassAlias));
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->AddSelect($sClassAlias.'id', new FieldExpression('id', $sClassAlias));
|
|
|
|
|
|
if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad))
|
|
if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad))
|
|
{
|
|
{
|
|
@@ -2196,7 +2224,7 @@ abstract class MetaModel
|
|
|
|
|
|
foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
|
|
foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
|
|
{
|
|
{
|
|
- $oQBExpr->AddSelect($sClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->AddSelect($sClassAlias.$sAttCode.$sColId, new FieldExpression($sAttCode.$sColId, $sClassAlias));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2216,14 +2244,14 @@ abstract class MetaModel
|
|
foreach($aFullText as $sFTNeedle)
|
|
foreach($aFullText as $sFTNeedle)
|
|
{
|
|
{
|
|
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%$sFTNeedle%"));
|
|
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%$sFTNeedle%"));
|
|
- $oQBExpr->AddCondition($oNewCond);
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->AddCondition($oNewCond);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
|
|
+//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n";
|
|
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
|
|
$aExpectedAtts = array(); // array of (attcode => fieldexpression)
|
|
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
|
|
//echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n";
|
|
- $oQBExpr->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts);
|
|
|
|
|
|
// Compute a clear view of required joins (from the current class)
|
|
// Compute a clear view of required joins (from the current class)
|
|
// Build the list of external keys:
|
|
// Build the list of external keys:
|
|
@@ -2260,9 +2288,9 @@ abstract class MetaModel
|
|
{
|
|
{
|
|
$aTranslateNow = array();
|
|
$aTranslateNow = array();
|
|
$aTranslateNow[$sClassAlias]['friendlyname'] = self::GetNameExpression($sClass, $sClassAlias);
|
|
$aTranslateNow[$sClassAlias]['friendlyname'] = self::GetNameExpression($sClass, $sClassAlias);
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
- $oQBExpr->Translate($aTranslateNow, false);
|
|
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
|
|
+//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, 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";
|
|
|
|
|
|
$aNameSpec = self::GetNameSpec($sClass);
|
|
$aNameSpec = self::GetNameSpec($sClass);
|
|
foreach($aNameSpec[1] as $i => $sAttCode)
|
|
foreach($aNameSpec[1] as $i => $sAttCode)
|
|
@@ -2304,7 +2332,7 @@ abstract class MetaModel
|
|
self::DbgTrace("Main (=leaf) class, call MakeQuerySingleTable()");
|
|
self::DbgTrace("Main (=leaf) class, call MakeQuerySingleTable()");
|
|
if (self::HasTable($sClass))
|
|
if (self::HasTable($sClass))
|
|
{
|
|
{
|
|
- $oSelectBase = self::MakeQuerySingleTable($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, $sClass, $aExtKeys, $aValues);
|
|
|
|
|
|
+ $oSelectBase = self::MakeQuerySingleTable($oBuild, $oFilter, $sClass, $aExtKeys, $aValues);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
@@ -2313,7 +2341,7 @@ abstract class MetaModel
|
|
// As the join will not filter on the expected classes, we have to specify it explicitely
|
|
// As the join will not filter on the expected classes, we have to specify it explicitely
|
|
$sExpectedClasses = implode("', '", self::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
|
|
$sExpectedClasses = implode("', '", self::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL));
|
|
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
|
|
$oFinalClassRestriction = Expression::FromOQL("`$sClassAlias`.finalclass IN ('$sExpectedClasses')");
|
|
- $oQBExpr->AddCondition($oFinalClassRestriction);
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction);
|
|
}
|
|
}
|
|
|
|
|
|
// Then we join the queries of the eventual parent classes (compound model)
|
|
// Then we join the queries of the eventual parent classes (compound model)
|
|
@@ -2322,7 +2350,7 @@ abstract class MetaModel
|
|
if (!self::HasTable($sParentClass)) continue;
|
|
if (!self::HasTable($sParentClass)) continue;
|
|
//echo "<p>Parent class: $sParentClass... let's call MakeQuerySingleTable()</p>";
|
|
//echo "<p>Parent class: $sParentClass... let's call MakeQuerySingleTable()</p>";
|
|
self::DbgTrace("Parent class: $sParentClass... let's call MakeQuerySingleTable()");
|
|
self::DbgTrace("Parent class: $sParentClass... let's call MakeQuerySingleTable()");
|
|
- $oSelectParentTable = self::MakeQuerySingleTable($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, $sParentClass, $aExtKeys, $aValues);
|
|
|
|
|
|
+ $oSelectParentTable = self::MakeQuerySingleTable($oBuild, $oFilter, $sParentClass, $aExtKeys, $aValues);
|
|
if (is_null($oSelectBase))
|
|
if (is_null($oSelectBase))
|
|
{
|
|
{
|
|
$oSelectBase = $oSelectParentTable;
|
|
$oSelectBase = $oSelectParentTable;
|
|
@@ -2347,11 +2375,11 @@ abstract class MetaModel
|
|
//self::DbgTrace($oSelectForeign->RenderSelect(array()));
|
|
//self::DbgTrace($oSelectForeign->RenderSelect(array()));
|
|
|
|
|
|
$sForeignClassAlias = $oForeignFilter->GetFirstJoinedClassAlias();
|
|
$sForeignClassAlias = $oForeignFilter->GetFirstJoinedClassAlias();
|
|
- $oQBExpr->PushJoinField(new FieldExpression($sForeignKeyAttCode, $sForeignClassAlias));
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sForeignKeyAttCode, $sForeignClassAlias));
|
|
|
|
|
|
- $oSelectForeign = self::MakeQuery($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oForeignFilter, $aAttToLoad);
|
|
|
|
|
|
+ $oSelectForeign = self::MakeQuery($oBuild, $oForeignFilter, $aAttToLoad);
|
|
|
|
|
|
- $oJoinExpr = $oQBExpr->PopJoinField();
|
|
|
|
|
|
+ $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
|
|
$sForeignKeyTable = $oJoinExpr->GetParent();
|
|
$sForeignKeyTable = $oJoinExpr->GetParent();
|
|
$sForeignKeyColumn = $oJoinExpr->GetName();
|
|
$sForeignKeyColumn = $oJoinExpr->GetName();
|
|
$oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable);
|
|
$oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable);
|
|
@@ -2390,8 +2418,8 @@ abstract class MetaModel
|
|
//
|
|
//
|
|
if ($bIsMainQuery)
|
|
if ($bIsMainQuery)
|
|
{
|
|
{
|
|
- $oSelectBase->SetCondition($oQBExpr->GetCondition());
|
|
|
|
- $oSelectBase->SetSelect($oQBExpr->GetSelect());
|
|
|
|
|
|
+ $oSelectBase->SetCondition($oBuild->m_oQBExpressions->GetCondition());
|
|
|
|
+ $oSelectBase->SetSelect($oBuild->m_oQBExpressions->GetSelect());
|
|
}
|
|
}
|
|
|
|
|
|
// That's all... cross fingers and we'll get some working query
|
|
// That's all... cross fingers and we'll get some working query
|
|
@@ -2402,7 +2430,7 @@ abstract class MetaModel
|
|
return $oSelectBase;
|
|
return $oSelectBase;
|
|
}
|
|
}
|
|
|
|
|
|
- protected static function MakeQuerySingleTable($aSelectedClasses, &$oQBExpr, &$aClassAliases, &$aTableAliases, $oFilter, $sTableClass, $aExtKeys, $aValues)
|
|
|
|
|
|
+ protected static function MakeQuerySingleTable(&$oBuild, $oFilter, $sTableClass, $aExtKeys, $aValues)
|
|
{
|
|
{
|
|
// $aExtKeys is an array of sTableClass => array of (sAttCode (keys) => array of sAttCode (fields))
|
|
// $aExtKeys is an array of sTableClass => array of (sAttCode (keys) => array of sAttCode (fields))
|
|
//echo "MAKEQUERY($sTableClass)-liste des clefs externes($sTableClass): <pre>".print_r($aExtKeys, true)."</pre><br/>\n";
|
|
//echo "MAKEQUERY($sTableClass)-liste des clefs externes($sTableClass): <pre>".print_r($aExtKeys, true)."</pre><br/>\n";
|
|
@@ -2416,13 +2444,13 @@ abstract class MetaModel
|
|
$sTargetClass = $oFilter->GetFirstJoinedClass();
|
|
$sTargetClass = $oFilter->GetFirstJoinedClass();
|
|
$sTargetAlias = $oFilter->GetFirstJoinedClassAlias();
|
|
$sTargetAlias = $oFilter->GetFirstJoinedClassAlias();
|
|
$sTable = self::DBGetTable($sTableClass);
|
|
$sTable = self::DBGetTable($sTableClass);
|
|
- $sTableAlias = self::GenerateUniqueAlias($aTableAliases, $sTargetAlias.'_'.$sTable, $sTable);
|
|
|
|
|
|
+ $sTableAlias = $oBuild->GenerateTableAlias($sTargetAlias.'_'.$sTable, $sTable);
|
|
|
|
|
|
$aTranslation = array();
|
|
$aTranslation = array();
|
|
$aExpectedAtts = array();
|
|
$aExpectedAtts = array();
|
|
- $oQBExpr->GetUnresolvedFields($sTargetAlias, $aExpectedAtts);
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->GetUnresolvedFields($sTargetAlias, $aExpectedAtts);
|
|
|
|
|
|
- $bIsOnQueriedClass = array_key_exists($sTargetAlias, $aSelectedClasses);
|
|
|
|
|
|
+ $bIsOnQueriedClass = array_key_exists($sTargetAlias, $oBuild->GetRootFilter()->GetSelectedClasses());
|
|
|
|
|
|
self::DbgTrace("Entering: tableclass=$sTableClass, filter=".$oFilter->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
|
self::DbgTrace("Entering: tableclass=$sTableClass, filter=".$oFilter->ToOQL().", ".($bIsOnQueriedClass ? "MAIN" : "SECONDARY"));
|
|
|
|
|
|
@@ -2471,6 +2499,18 @@ abstract class MetaModel
|
|
$aUpdateValues[$sColumn] = $sValue;
|
|
$aUpdateValues[$sColumn] = $sValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 2 - The SQL query, for this table only
|
|
|
|
+ //
|
|
|
|
+ $oSelectBase = new SQLQuery($sTable, $sTableAlias, array(), $bIsOnQueriedClass, $aUpdateValues, $oSelectedIdField);
|
|
|
|
+
|
|
|
|
+ // 3 - Resolve expected expressions (translation table: alias.attcode => table.column)
|
|
|
|
+ //
|
|
|
|
+ foreach(self::ListAttributeDefs($sTableClass) as $sAttCode=>$oAttDef)
|
|
|
|
+ {
|
|
|
|
+ // Skip this attribute if not defined in this table
|
|
|
|
+ if (self::$m_aAttribOrigins[$sTargetClass][$sAttCode] != $sTableClass) continue;
|
|
|
|
|
|
// Select...
|
|
// Select...
|
|
//
|
|
//
|
|
@@ -2487,16 +2527,17 @@ abstract class MetaModel
|
|
{
|
|
{
|
|
if (array_key_exists($sAttCode, $aExpectedAtts))
|
|
if (array_key_exists($sAttCode, $aExpectedAtts))
|
|
{
|
|
{
|
|
- $aTranslation[$sTargetAlias][$sAttCode.$sColId] = new FieldExpressionResolved($sSQLExpr, $sTableAlias);
|
|
|
|
|
|
+ $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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // 3 - The whole stuff, for this table only
|
|
|
|
- //
|
|
|
|
- $oSelectBase = new SQLQuery($sTable, $sTableAlias, array(), $bIsOnQueriedClass, $aUpdateValues, $oSelectedIdField);
|
|
|
|
-
|
|
|
|
//echo "MAKEQUERY- Classe $sTableClass<br/>\n";
|
|
//echo "MAKEQUERY- Classe $sTableClass<br/>\n";
|
|
// 4 - The external keys -> joins...
|
|
// 4 - The external keys -> joins...
|
|
//
|
|
//
|
|
@@ -2516,7 +2557,7 @@ abstract class MetaModel
|
|
// The join was not explicitely defined in the filter,
|
|
// The join was not explicitely defined in the filter,
|
|
// we need to do it now
|
|
// we need to do it now
|
|
$sKeyClass = $oKeyAttDef->GetTargetClass();
|
|
$sKeyClass = $oKeyAttDef->GetTargetClass();
|
|
- $sKeyClassAlias = self::GenerateUniqueAlias($aClassAliases, $sKeyClass.'_'.$sKeyAttCode, $sKeyClass);
|
|
|
|
|
|
+ $sKeyClassAlias = $oBuild->GenerateClassAlias($sKeyClass.'_'.$sKeyAttCode, $sKeyClass);
|
|
$oExtFilter = new DBObjectSearch($sKeyClass, $sKeyClassAlias);
|
|
$oExtFilter = new DBObjectSearch($sKeyClass, $sKeyClassAlias);
|
|
|
|
|
|
$aAllPointingTo[$sKeyAttCode][TREE_OPERATOR_EQUALS][$sKeyClassAlias] = $oExtFilter;
|
|
$aAllPointingTo[$sKeyAttCode][TREE_OPERATOR_EQUALS][$sKeyClassAlias] = $oExtFilter;
|
|
@@ -2573,18 +2614,18 @@ abstract class MetaModel
|
|
}
|
|
}
|
|
// Translate prior to recursing
|
|
// Translate prior to recursing
|
|
//
|
|
//
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."\n".print_r($aTranslateNow, true)."</pre></p>\n";
|
|
|
|
- $oQBExpr->Translate($aTranslateNow, false);
|
|
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
|
|
+//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 MakeQuery()/p>\n";
|
|
//echo "<p>External key $sKeyAttCode (class: $sKeyClass), call MakeQuery()/p>\n";
|
|
self::DbgTrace("External key $sKeyAttCode (class: $sKeyClass), call MakeQuery()");
|
|
self::DbgTrace("External key $sKeyAttCode (class: $sKeyClass), call MakeQuery()");
|
|
- $oQBExpr->PushJoinField(new FieldExpression('id', $sKeyClassAlias));
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression('id', $sKeyClassAlias));
|
|
|
|
|
|
-//echo "<p>Recursive MakeQuery ".__LINE__.": <pre>\n".print_r($aSelectedClasses, true)."</pre></p>\n";
|
|
|
|
- $oSelectExtKey = self::MakeQuery($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oExtFilter);
|
|
|
|
|
|
+//echo "<p>Recursive MakeQuery ".__LINE__.": <pre>\n".print_r($oBuild->GetRootFilter()->GetSelectedClasses(), true)."</pre></p>\n";
|
|
|
|
+ $oSelectExtKey = self::MakeQuery($oBuild, $oExtFilter);
|
|
|
|
|
|
- $oJoinExpr = $oQBExpr->PopJoinField();
|
|
|
|
|
|
+ $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
|
|
$sExternalKeyTable = $oJoinExpr->GetParent();
|
|
$sExternalKeyTable = $oJoinExpr->GetParent();
|
|
$sExternalKeyField = $oJoinExpr->GetName();
|
|
$sExternalKeyField = $oJoinExpr->GetName();
|
|
|
|
|
|
@@ -2604,9 +2645,9 @@ abstract class MetaModel
|
|
}
|
|
}
|
|
elseif(self::$m_aAttribOrigins[$sKeyClass][$sKeyAttCode] == $sTableClass)
|
|
elseif(self::$m_aAttribOrigins[$sKeyClass][$sKeyAttCode] == $sTableClass)
|
|
{
|
|
{
|
|
- $oQBExpr->PushJoinField(new FieldExpression($sKeyAttCode, $sKeyClassAlias));
|
|
|
|
- $oSelectExtKey = self::MakeQuery($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oExtFilter);
|
|
|
|
- $oJoinExpr = $oQBExpr->PopJoinField();
|
|
|
|
|
|
+ $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sKeyAttCode, $sKeyClassAlias));
|
|
|
|
+ $oSelectExtKey = self::MakeQuery($oBuild, $oExtFilter);
|
|
|
|
+ $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
|
|
//echo "MAKEQUERY-PopJoinField pour $sKeyAttCode, $sKeyClassAlias: <pre>".print_r($oJoinExpr, true)."</pre><br/>\n";
|
|
//echo "MAKEQUERY-PopJoinField pour $sKeyAttCode, $sKeyClassAlias: <pre>".print_r($oJoinExpr, true)."</pre><br/>\n";
|
|
$sExternalKeyTable = $oJoinExpr->GetParent();
|
|
$sExternalKeyTable = $oJoinExpr->GetParent();
|
|
$sExternalKeyField = $oJoinExpr->GetName();
|
|
$sExternalKeyField = $oJoinExpr->GetName();
|
|
@@ -2625,9 +2666,9 @@ abstract class MetaModel
|
|
|
|
|
|
// Translate the selected columns
|
|
// Translate the selected columns
|
|
//
|
|
//
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
- $oQBExpr->Translate($aTranslation, false);
|
|
|
|
-//echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oQBExpr, true)."</pre></p>\n";
|
|
|
|
|
|
+//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());
|
|
//MyHelpers::var_dump_html($oSelectBase->RenderSelect());
|
|
return $oSelectBase;
|
|
return $oSelectBase;
|
|
@@ -4660,7 +4701,7 @@ abstract class MetaModel
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns an array of classes implementing the given interface
|
|
|
|
|
|
+ * Returns an array of classes=>instance implementing the given interface
|
|
*/
|
|
*/
|
|
public static function EnumPlugins($sInterface)
|
|
public static function EnumPlugins($sInterface)
|
|
{
|
|
{
|
|
@@ -4743,5 +4784,4 @@ MetaModel::RegisterZList("preview", array("description"=>"All attributes visible
|
|
MetaModel::RegisterZList("standard_search", array("description"=>"List of criteria for the standard search", "type"=>"filters"));
|
|
MetaModel::RegisterZList("standard_search", array("description"=>"List of criteria for the standard search", "type"=>"filters"));
|
|
MetaModel::RegisterZList("advanced_search", array("description"=>"List of criteria for the advanced search", "type"=>"filters"));
|
|
MetaModel::RegisterZList("advanced_search", array("description"=>"List of criteria for the advanced search", "type"=>"filters"));
|
|
|
|
|
|
-
|
|
|
|
-?>
|
|
|
|
|
|
+?>
|