diff --git a/core/dbsearch.class.php b/core/dbsearch.class.php index 0fe45b240..468d4b7fe 100644 --- a/core/dbsearch.class.php +++ b/core/dbsearch.class.php @@ -979,7 +979,7 @@ abstract class DBSearch $aAttToLoad = array(); $oSQLQuery = $oQueryFilter->GetSQLQuery(array(), $aArgs, $aAttToLoad, null, 0, 0, false, $aGroupByExpr, $aSelectExpr); - $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams()); + $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments()); try { $bBeautifulSQL = self::$m_bTraceQueries || self::$m_bDebugQuery || self::$m_bIndentQueries; @@ -997,6 +997,10 @@ abstract class DBSearch return $sRes; } + function GetExpectedArguments() + { + return $this->GetCriteria()->ListParameters(); + } /** * Generate a SQL query from the current search @@ -1076,7 +1080,7 @@ abstract class DBSearch else { // The complete list of arguments will include magic arguments (e.g. current_user->attcode) - $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams()); + $aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments()); } try { diff --git a/core/dbunionsearch.class.php b/core/dbunionsearch.class.php index ff5abe83e..adcd76c51 100644 --- a/core/dbunionsearch.class.php +++ b/core/dbunionsearch.class.php @@ -667,6 +667,16 @@ class DBUnionSearch extends DBSearch return $oSQLQuery; } + function GetExpectedArguments() + { + $aVariableCriteria = array(); + foreach ($this->aSearches as $oSearch) + { + $aVariableCriteria = array_merge($aVariableCriteria, $oSearch->GetExpectedArguments()); + } + + return $aVariableCriteria; + } /** * @return \Expression */ diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 3ea6ea84d..d63cb6d14 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -4127,44 +4127,52 @@ abstract class MetaModel * * @param array $aArgs Context arguments (some can be persistent objects) * @param array $aMoreArgs Other query parameters + * @param array $aExpectedArgs variables present in the query + * * @return array */ - public static function PrepareQueryArguments($aArgs, $aMoreArgs = array()) + public static function PrepareQueryArguments($aArgs, $aMoreArgs = array(), $aExpectedArgs = null) { $aScalarArgs = array(); - foreach(array_merge($aArgs, $aMoreArgs) as $sArgName => $value) + if (is_null($aExpectedArgs) || count($aExpectedArgs) > 0 || count($aMoreArgs)>0) { - if (self::IsValidObject($value)) + foreach (array_merge($aArgs, $aMoreArgs) as $sArgName => $value) { - if (strpos($sArgName, '->object()') === false) + if (self::IsValidObject($value)) { - // Normalize object arguments - $aScalarArgs[$sArgName.'->object()'] = $value; + if (strpos($sArgName, '->object()') === false) + { + // Normalize object arguments + $aScalarArgs[$sArgName.'->object()'] = $value; + } + else + { + // Leave as is + $aScalarArgs[$sArgName] = $value; + } } else { - // Leave as is - $aScalarArgs[$sArgName] = $value; - } - } - else - { - if (is_scalar($value)) - { - $aScalarArgs[$sArgName] = (string)$value; - } - elseif (is_null($value)) - { - $aScalarArgs[$sArgName] = null; - } - elseif (is_array($value)) - { - $aScalarArgs[$sArgName] = $value; + if (is_scalar($value)) + { + $aScalarArgs[$sArgName] = (string)$value; + } + elseif (is_null($value)) + { + $aScalarArgs[$sArgName] = null; + } + elseif (is_array($value)) + { + $aScalarArgs[$sArgName] = $value; + } } } + return static::AddMagicPlaceholders($aScalarArgs, $aExpectedArgs); + } + else + { + return array(); } - - return static::AddMagicPlaceholders($aScalarArgs); } /** @@ -4172,21 +4180,68 @@ abstract class MetaModel * * @return array of placeholder (or name->object()) => value (or object) */ - public static function AddMagicPlaceholders($aPlaceholders) + public static function AddMagicPlaceholders($aPlaceholders, $aExpectedArgs = null) { // Add standard magic arguments // - $aPlaceholders['current_contact_id'] = UserRights::GetContactId(); // legacy - - $oUser = UserRights::GetUserObject(); - if (!is_null($oUser)) + if (is_null($aExpectedArgs)) { - $aPlaceholders['current_user->object()'] = $oUser; + $aPlaceholders['current_contact_id'] = UserRights::GetContactId(); // legacy - $oContact = UserRights::GetContactObject(); - if (!is_null($oContact)) + $oUser = UserRights::GetUserObject(); + if (!is_null($oUser)) { - $aPlaceholders['current_contact->object()'] = $oContact; + $aPlaceholders['current_user->object()'] = $oUser; + + $oContact = UserRights::GetContactObject(); + if (!is_null($oContact)) + { + $aPlaceholders['current_contact->object()'] = $oContact; + } + } + } + else + { + $aCurrentUser = array(); + $aCurrentContact = array(); + foreach ($aExpectedArgs as $expression) + { + $aName = explode('->', $expression->GetName()); + if ($aName[0] == 'current_contact_id') + { + $aPlaceholders['current_contact_id'] = UserRights::GetContactId(); + } + if ($aName[0] == 'current_user') + { + array_push($aCurrentUser, $aName[1]); + } + if ($aName[0] == 'current_contact') + { + array_push($aCurrentContact, $aName[1]); + } + } + if (count($aCurrentUser) > 0) + { + $oSearch = DBObjectSearch::FromOQL("SELECT User WHERE id = :id"); + $oSet = new DBObjectSet($oSearch, array(), array('id' => UserRights::GetUserId())); + $oSet->OptimizeColumnLoad($aCurrentUser); + $oUser = $oSet->fetch(); + $aPlaceholders['current_user->object()'] = $oUser; + foreach ($aCurrentUser as $sField) + { + $aPlaceholders['current_user->'.$sField] = $oUser->Get($sField); + } + } + if (count($aCurrentContact) > 0) + { + $oSearch = DBObjectSearch::FromOQL("SELECT Contact WHERE id = :id"); + $oSet = new DBObjectSet($oSearch, array(), array('id' => UserRights::GetContactId())); + $oSet->OptimizeColumnLoad($aCurrentContact); + $oUser = $oSet->fetch(); + foreach ($aCurrentContact as $sField) + { + $aPlaceholders['current_contact->'.$sField] = $oUser->Get($sField); + } } } diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php index 90335f9ed..28b456c0a 100644 --- a/core/oql/expression.class.inc.php +++ b/core/oql/expression.class.inc.php @@ -158,6 +158,9 @@ abstract class Expression // recursively builds an array of [classAlias][fieldName] => value abstract public function ListConstantFields(); + // recursively builds an array of parameters to give to current request + abstract public function ListParameters(); + public function RequiresField($sClass, $sFieldName) { // #@# todo - optimize : this is called quite often when building a single query ! @@ -354,6 +357,11 @@ class SQLExpression extends Expression return array(); } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { // Do nothing, since there is nothing to rename @@ -593,6 +601,13 @@ class BinaryExpression extends Expression return $aResult; } + public function ListParameters() + { + $aLeft = $this->GetLeftExpr()->ListParameters(); + $aRight = $this->GetRightExpr()->ListParameters(); + return array_merge($aLeft, $aRight); + } + public function RenameParam($sOldName, $sNewName) { $this->GetLeftExpr()->RenameParam($sOldName, $sNewName); @@ -934,6 +949,11 @@ class UnaryExpression extends Expression return array(); } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { // Do nothing @@ -1848,6 +1868,12 @@ class VariableExpression extends UnaryExpression } return $oRet; } + + public function ListParameters() + { + return array($this); + } + } // Temporary, until we implement functions and expression casting! @@ -2001,6 +2027,16 @@ class ListExpression extends Expression return $aRes; } + public function ListParameters() + { + $aRes = array(); + foreach ($this->m_aExpressions as $oExpr) + { + $aRes = array_merge($aRes, $oExpr->ListParameters()); + } + return $aRes; + } + public function RenameParam($sOldName, $sNewName) { foreach ($this->m_aExpressions as $key => $oExpr) @@ -2142,6 +2178,11 @@ class NestedQueryExpression extends Expression return $this->m_oNestedQuery->ListConstantFields(); } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { $this->m_oNestedQuery->RenameParam($sOldName, $sNewName); @@ -2289,6 +2330,11 @@ class FunctionExpression extends Expression return $aRes; } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { foreach ($this->m_aArgs as $key => $oExpr) @@ -2570,6 +2616,11 @@ class IntervalExpression extends Expression return array(); } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { $this->m_oValue->RenameParam($sOldName, $sNewName); @@ -2716,6 +2767,11 @@ class CharConcatExpression extends Expression return $aRes; } + public function ListParameters() + { + return array(); + } + public function RenameParam($sOldName, $sNewName) { foreach ($this->m_aExpressions as $key => $oExpr)