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)."
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)."
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
\n";
+///print_r($oFilter->GetModifierProperties('QueryLocalizerPlugin'));
+///echo "\n";
?>