mirror of
https://github.com/Combodo/iTop.git
synced 2026-09-29 21:09:10 +02:00
Implemented the capability to modify queries by the mean of a plugin (beta)
SVN:1.2[1840]
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 "<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)
|
||||
//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)
|
||||
// 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 "<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);
|
||||
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 "<p>Parent class: $sParentClass... let's call MakeQuerySingleTable()</p>";
|
||||
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): <pre>".print_r($aExtKeys, true)."</pre><br/>\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<br/>\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 "<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";
|
||||
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();
|
||||
$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: <pre>".print_r($oJoinExpr, true)."</pre><br/>\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 "<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());
|
||||
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"));
|
||||
|
||||
|
||||
?>
|
||||
?>
|
||||
59
core/querybuildercontext.class.inc.php
Normal file
59
core/querybuildercontext.class.inc.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Associated with the metamodel -> MakeQuery/MakeQuerySingleTable
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
33
core/querymodifier.class.inc.php
Normal file
33
core/querymodifier.class.inc.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
// Copyright (C) 2010 Combodo SARL
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 3 of the License.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
/**
|
||||
* Interface iQueryModifier
|
||||
* Defines the API to tweak queries (e.g. translate data on the fly)
|
||||
*
|
||||
* @author Erwan Taloc <erwan.taloc@combodo.com>
|
||||
* @author Romain Quetiez <romain.quetiez@combodo.com>
|
||||
* @author Denis Flaven <denis.flaven@combodo.com>
|
||||
* @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);
|
||||
}
|
||||
?>
|
||||
@@ -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 "<li>Join '$sJoinType', $sLeftField, $sRightTableAlias.$sRightField".$oSQLQuery->DisplayHtml()."</li>\n";
|
||||
echo "<li>Join '$sJoinType', ON ($sOnCondition)".$oSQLQuery->DisplayHtml()."</li>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sLeftField = $aJoinInfo["leftfield"];
|
||||
$sRightField = $aJoinInfo["rightfield"];
|
||||
$sRightTableAlias = $aJoinInfo["righttablealias"];
|
||||
|
||||
echo "<li>Join '$sJoinType', $sLeftField, $sRightTableAlias.$sRightField".$oSQLQuery->DisplayHtml()."</li>\n";
|
||||
}
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 "<pre>\n";
|
||||
///print_r($oFilter->GetModifierProperties('QueryLocalizerPlugin'));
|
||||
///echo "</pre>\n";
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user