diff --git a/application/applicationcontext.class.inc.php b/application/applicationcontext.class.inc.php index 374b6ceb0..0d5f27f4d 100644 --- a/application/applicationcontext.class.inc.php +++ b/application/applicationcontext.class.inc.php @@ -303,5 +303,58 @@ class ApplicationContext return ''; } } + + protected static $m_aPluginProperties = null; + + /** + * Load plugin properties for the current session + * @return void + */ + protected static function LoadPluginProperties() + { + if (isset($_SESSION['PluginProperties'])) + { + self::$m_aPluginProperties = $_SESSION['PluginProperties']; + } + else + { + self::$m_aPluginProperties = array(); + } + } + + /** + * Set plugin properties + * @param sPluginClass string Class implementing any plugin interface + * @param sProperty string Name of the property + * @param value scalar Value (numeric or string) + * @return void + */ + public static function SetPluginProperty($sPluginClass, $sProperty, $value) + { + if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties(); + + self::$m_aPluginProperties[$sPluginClass][$sProperty] = $value; + $_SESSION['PluginProperties'][$sPluginClass][$sProperty] = $value; + } + + /** + * Get plugin properties + * @param sPluginClass string Class implementing any plugin interface + * @return array of sProperty=>value pairs + */ + public static function GetPluginProperties($sPluginClass) + { + if (is_null(self::$m_aPluginProperties)) self::LoadPluginProperties(); + + if (array_key_exists($sPluginClass, self::$m_aPluginProperties)) + { + return self::$m_aPluginProperties[$sPluginClass]; + } + else + { + return array(); + } + } + } ?> diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index 0d6c54247..927e49226 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -66,6 +66,12 @@ class DBObjectSearch $this->m_aRelatedTo = array(); $this->m_bDataFiltered = false; $this->m_aParentConditions = array(); + + $this->m_aModifierProperties = array(); + foreach (MetaModel::EnumPlugins('iQueryModifier') as $sPluginClass => $oQueryModifier) + { + $this->m_aModifierProperties[$sPluginClass] = ApplicationContext::GetPluginProperties($sPluginClass); + } } public function AllowAllData() {$this->m_bAllowAllData = true;} @@ -126,6 +132,23 @@ class DBObjectSearch } + public function SetModifierProperty($sPluginClass, $sProperty, $value) + { + $this->m_aModifierProperties[$sPluginClass][$sProperty] = $value; + } + + public function GetModifierProperties($sPluginClass) + { + if (array_key_exists($sPluginClass, $this->m_aModifierProperties)) + { + return $this->m_aModifierProperties[$sPluginClass]; + } + else + { + return array(); + } + } + public function IsAny() { // #@# todo - if (!$this->m_oSearchCondition->IsTrue()) return false; diff --git a/core/expression.class.inc.php b/core/expression.class.inc.php index ad2590ca9..75f6184fa 100644 --- a/core/expression.class.inc.php +++ b/core/expression.class.inc.php @@ -953,10 +953,10 @@ class QueryBuilderExpressions protected $m_aSelectExpr; protected $m_aJoinFields; - public function __construct($aSelect, $oCondition) + public function __construct($oCondition) { $this->m_oConditionExpr = $oCondition; - $this->m_aSelectExpr = $aSelect; + $this->m_aSelectExpr = array(); $this->m_aJoinFields = array(); } diff --git a/core/metamodel.class.php b/core/metamodel.class.php index c0e840489..ba03b8767 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -15,6 +15,8 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 @@ -25,8 +27,6 @@ require_once(APPROOT.'core/modulehandler.class.inc.php'); * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL */ - - // #@# todo: change into class const (see Doctrine) // Doctrine example // class toto @@ -1404,7 +1404,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) // Build the list of available extensions // - $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension'); + $aInterfaces = array('iApplicationUIExtension', 'iApplicationObjectExtension', 'iQueryModifier'); foreach($aInterfaces as $sInterface) { self::$m_aExtensionClasses[$sInterface] = array(); @@ -2035,12 +2035,10 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) if (!isset($oSelect)) { - $aClassAliases = array(); - $aTableAliases = array(); - $oQBExpr = new QueryBuilderExpressions(array(), $oFilter->GetCriteria()); + $oBuild = new QueryBuilderContext($oFilter); $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); $oKPI->ComputeStats('MakeQuery (select)', $sOqlQuery); @@ -2151,10 +2149,8 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) 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 */); + $oBuild = new QueryBuilderContext($oFilter); + $oSelect = self::MakeQuery($oBuild, $oFilter, null, array(), true /* main query */); $aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams()); return $oSelect->RenderDelete($aScalarArgs); } @@ -2162,26 +2158,20 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) public static function MakeUpdateQuery(DBObjectSearch $oFilter, $aValues, $aArgs = array()) { // $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 */); + $oBuild = new QueryBuilderContext($oFilter); + $oSelect = self::MakeQuery($oBuild, $oFilter, null, $aValues, true /* main query */); $aScalarArgs = array_merge(self::PrepareQueryArguments($aArgs), $oFilter->GetInternalParams()); 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 // -> this occurs when we are linking our class to an external class (referenced by, or pointing to) $sClass = $oFilter->GetFirstJoinedClass(); $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")); @@ -2191,7 +2181,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) if ($bIsOnQueriedClass) { // 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)) { @@ -2207,7 +2197,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) 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)); } } @@ -2227,14 +2217,14 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) foreach($aFullText as $sFTNeedle) { $oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%$sFTNeedle%")); - $oQBExpr->AddCondition($oNewCond); + $oBuild->m_oQBExpressions->AddCondition($oNewCond); } } } -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; $aExpectedAtts = array(); // array of (attcode => fieldexpression) //echo "

".__LINE__.": GetUnresolvedFields($sClassAlias, ...)

\n"; - $oQBExpr->GetUnresolvedFields($sClassAlias, $aExpectedAtts); + $oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts); // Compute a clear view of required joins (from the current class) // Build the list of external keys: @@ -2271,9 +2261,9 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) { $aTranslateNow = array(); $aTranslateNow[$sClassAlias]['friendlyname'] = self::GetNameExpression($sClass, $sClassAlias); -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; - $oQBExpr->Translate($aTranslateNow, false); -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; + $oBuild->m_oQBExpressions->Translate($aTranslateNow, false); +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; $aNameSpec = self::GetNameSpec($sClass); foreach($aNameSpec[1] as $i => $sAttCode) @@ -2315,7 +2305,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) self::DbgTrace("Main (=leaf) class, call MakeQuerySingleTable()"); if (self::HasTable($sClass)) { - $oSelectBase = self::MakeQuerySingleTable($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oFilter, $sClass, $aExtKeys, $aValues); + $oSelectBase = self::MakeQuerySingleTable($oBuild, $oFilter, $sClass, $aExtKeys, $aValues); } else { @@ -2324,7 +2314,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) // 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)); $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) @@ -2333,7 +2323,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) if (!self::HasTable($sParentClass)) continue; //echo "

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)) { $oSelectBase = $oSelectParentTable; @@ -2358,11 +2348,11 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) //self::DbgTrace($oSelectForeign->RenderSelect(array())); $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(); $sForeignKeyColumn = $oJoinExpr->GetName(); $oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable); @@ -2401,8 +2391,8 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) // 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 @@ -2413,7 +2403,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) 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)) //echo "MAKEQUERY($sTableClass)-liste des clefs externes($sTableClass):
".print_r($aExtKeys, true)."

\n"; @@ -2427,13 +2417,13 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) $sTargetClass = $oFilter->GetFirstJoinedClass(); $sTargetAlias = $oFilter->GetFirstJoinedClassAlias(); $sTable = self::DBGetTable($sTableClass); - $sTableAlias = self::GenerateUniqueAlias($aTableAliases, $sTargetAlias.'_'.$sTable, $sTable); + $sTableAlias = $oBuild->GenerateTableAlias($sTargetAlias.'_'.$sTable, $sTable); $aTranslation = 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")); @@ -2482,6 +2472,18 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) $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... // @@ -2498,16 +2500,17 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) { 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
\n"; // 4 - The external keys -> joins... // @@ -2527,7 +2530,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) // The join was not explicitely defined in the filter, // we need to do it now $sKeyClass = $oKeyAttDef->GetTargetClass(); - $sKeyClassAlias = self::GenerateUniqueAlias($aClassAliases, $sKeyClass.'_'.$sKeyAttCode, $sKeyClass); + $sKeyClassAlias = $oBuild->GenerateClassAlias($sKeyClass.'_'.$sKeyAttCode, $sKeyClass); $oExtFilter = new DBObjectSearch($sKeyClass, $sKeyClassAlias); $aAllPointingTo[$sKeyAttCode][TREE_OPERATOR_EQUALS][$sKeyClassAlias] = $oExtFilter; @@ -2584,18 +2587,18 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) } // Translate prior to recursing // -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."\n".print_r($aTranslateNow, true)."

\n"; - $oQBExpr->Translate($aTranslateNow, false); -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."\n".print_r($aTranslateNow, true)."

\n"; + $oBuild->m_oQBExpressions->Translate($aTranslateNow, false); +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; //echo "

External key $sKeyAttCode (class: $sKeyClass), call MakeQuery()/p>\n"; self::DbgTrace("External key $sKeyAttCode (class: $sKeyClass), call MakeQuery()"); - $oQBExpr->PushJoinField(new FieldExpression('id', $sKeyClassAlias)); + $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression('id', $sKeyClassAlias)); -//echo "

Recursive MakeQuery ".__LINE__.":

\n".print_r($aSelectedClasses, true)."

\n"; - $oSelectExtKey = self::MakeQuery($aSelectedClasses, $oQBExpr, $aClassAliases, $aTableAliases, $oExtFilter); +//echo "

Recursive MakeQuery ".__LINE__.":

\n".print_r($oBuild->GetRootFilter()->GetSelectedClasses(), true)."

\n"; + $oSelectExtKey = self::MakeQuery($oBuild, $oExtFilter); - $oJoinExpr = $oQBExpr->PopJoinField(); + $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField(); $sExternalKeyTable = $oJoinExpr->GetParent(); $sExternalKeyField = $oJoinExpr->GetName(); @@ -2615,9 +2618,9 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) } 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:
".print_r($oJoinExpr, true)."

\n"; $sExternalKeyTable = $oJoinExpr->GetParent(); $sExternalKeyField = $oJoinExpr->GetName(); @@ -2636,9 +2639,9 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) // Translate the selected columns // -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; - $oQBExpr->Translate($aTranslation, false); -//echo "

oQBExpr ".__LINE__.":

\n".print_r($oQBExpr, true)."

\n"; +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; + $oBuild->m_oQBExpressions->Translate($aTranslation, false); +//echo "

oQBExpr ".__LINE__.":

\n".print_r($oBuild->m_oQBExpressions, true)."

\n"; //MyHelpers::var_dump_html($oSelectBase->RenderSelect()); return $oSelectBase; @@ -4646,7 +4649,7 @@ if (!array_key_exists($sAttCode, self::$m_aAttribDefs[$sClass])) } /** - * Returns an array of classes implementing the given interface + * Returns an array of classes=>instance implementing the given interface */ public static function EnumPlugins($sInterface) { @@ -4731,5 +4734,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("advanced_search", array("description"=>"List of criteria for the advanced search", "type"=>"filters")); - -?> +?> \ No newline at end of file diff --git a/core/querybuildercontext.class.inc.php b/core/querybuildercontext.class.inc.php new file mode 100644 index 000000000..ffca08712 --- /dev/null +++ b/core/querybuildercontext.class.inc.php @@ -0,0 +1,59 @@ + MakeQuery/MakeQuerySingleTable + * + * @author Erwan Taloc + * @author Romain Quetiez + * @author Denis Flaven + * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL + */ + +class QueryBuilderContext +{ + protected $m_oRootFilter; + protected $m_aClassAliases; + protected $m_aTableAliases; + + public $m_oQBExpressions; + + public function __construct($oFilter) + { + $this->m_oRootFilter = $oFilter; + $this->m_oQBExpressions = new QueryBuilderExpressions($oFilter->GetCriteria()); + + $this->m_aClassAliases = $oFilter->GetJoinedClasses(); + $this->m_aTableAliases = array(); + } + + public function GetRootFilter() + { + return $this->m_oRootFilter; + } + + public function GenerateTableAlias($sNewName, $sRealName) + { + return MetaModel::GenerateUniqueAlias($this->m_aTableAliases, $sNewName, $sRealName); + } + + public function GenerateClassAlias($sNewName, $sRealName) + { + return MetaModel::GenerateUniqueAlias($this->m_aClassAliases, $sNewName, $sRealName); + } +} + +?> \ No newline at end of file diff --git a/core/querymodifier.class.inc.php b/core/querymodifier.class.inc.php new file mode 100644 index 000000000..8fdfcf6cc --- /dev/null +++ b/core/querymodifier.class.inc.php @@ -0,0 +1,33 @@ + + * @author Romain Quetiez + * @author Denis Flaven + * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL + */ + +interface iQueryModifier +{ + public function __construct(); + + public function GetFieldExpression(QueryBuilderContext &$oBuild, $sClass, $sAttCode, $sColId, Expression $oFieldSQLExp, SQLQuery &$oSelect); +} +?> diff --git a/core/sqlquery.class.inc.php b/core/sqlquery.class.inc.php index e39c89b81..582206573 100644 --- a/core/sqlquery.class.inc.php +++ b/core/sqlquery.class.inc.php @@ -68,6 +68,11 @@ class SQLQuery $this->m_oSelectedIdField = $oSelectedIdField; } + public function GetTableAlias() + { + return $this->m_sTableAlias; + } + public function SetSourceOQL($sOQL) { $this->m_SourceOQL = $sOQL; @@ -101,11 +106,20 @@ class SQLQuery { $sJoinType = $aJoinInfo["jointype"]; $oSQLQuery = $aJoinInfo["select"]; - $sLeftField = $aJoinInfo["leftfield"]; - $sRightField = $aJoinInfo["rightfield"]; - $sRightTableAlias = $aJoinInfo["righttablealias"]; + if (isset($aJoinInfo["on_expression"])) + { + $sOnCondition = $aJoinInfo["on_expression"]->Render(); - echo "
  • Join '$sJoinType', $sLeftField, $sRightTableAlias.$sRightField".$oSQLQuery->DisplayHtml()."
  • \n"; + echo "
  • Join '$sJoinType', ON ($sOnCondition)".$oSQLQuery->DisplayHtml()."
  • \n"; + } + else + { + $sLeftField = $aJoinInfo["leftfield"]; + $sRightField = $aJoinInfo["rightfield"]; + $sRightTableAlias = $aJoinInfo["righttablealias"]; + + echo "
  • Join '$sJoinType', $sLeftField, $sRightTableAlias.$sRightField".$oSQLQuery->DisplayHtml()."
  • \n"; + } } echo ""; } @@ -196,6 +210,24 @@ class SQLQuery { return $this->AddJoin("left", $oSQLQuery, $sLeftField, $sRightField); } + + public function AddInnerJoinEx(SQLQuery $oSQLQuery, Expression $oOnExpression) + { + $this->m_aJoinSelects[] = array( + "jointype" => 'inner', + "select" => $oSQLQuery, + "on_expression" => $oOnExpression + ); + } + + public function AddLeftJoinEx(SQLQuery $oSQLQuery, Expression $oOnExpression) + { + $this->m_aJoinSelects[] = array( + "jointype" => 'left', + "select" => $oSQLQuery, + "on_expression" => $oOnExpression + ); + } // Interface, build the SQL query public function RenderDelete($aArgs = array()) @@ -412,8 +444,14 @@ class SQLQuery break; case "inner": case "left": - // table or tablealias ??? - $sJoinCond = "`$sCallerAlias`.`{$aJoinData['leftfield']}` = `$sRightTableAlias`.`{$aJoinData['rightfield']}`"; + if (isset($aJoinData["on_expression"])) + { + $sJoinCond = $aJoinData["on_expression"]->Render(); + } + else + { + $sJoinCond = "`$sCallerAlias`.`{$aJoinData['leftfield']}` = `$sRightTableAlias`.`{$aJoinData['rightfield']}`"; + } $aFrom[$this->m_sTableAlias] = array("jointype"=>$aJoinData['jointype'], "tablename"=>$this->m_sTable, "joincondition"=>"$sJoinCond"); break; case "inner_tree": @@ -488,10 +526,6 @@ class SQLQuery foreach ($this->m_aJoinSelects as $aJoinData) { $oRightSelect = $aJoinData["select"]; -// $sJoinType = $aJoinData["jointype"]; -// $sLeftField = $aJoinData["leftfield"]; -// $sRightField = $aJoinData["rightfield"]; -// $sRightTableAlias = $aJoinData["righttablealias"]; $sJoinTableAlias = $oRightSelect->privRenderSingleTable($aTempFrom, $aFields, $aDelTables, $aSetValues, $aSelectedIdFields, $this->m_sTableAlias, $aJoinData); } diff --git a/pages/run_query.php b/pages/run_query.php index e52edcc1c..db83b533c 100644 --- a/pages/run_query.php +++ b/pages/run_query.php @@ -97,6 +97,9 @@ function ShowExamples($oP, $sExpression) $sOperation = utils::ReadParam('operation', 'menu'); $oAppContext = new ApplicationContext(); +ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', UserRights::GetUserLanguage()); +ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', 'FR FR'); + $oP = new iTopWebPage(Dict::S('UI:RunQuery:Title')); // Main program @@ -201,4 +204,8 @@ catch(Exception $e) } $oP->output(); +///$oFilter = new DBObjectSearch('Server'); +///echo "
    \n";
    +///print_r($oFilter->GetModifierProperties('QueryLocalizerPlugin'));
    +///echo "
    \n"; ?>