mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Obsolescence: introduction of this new concept (wording could change later). The obsolescence of an object is computed after other attributes, by the mean of an OQL expression. The code has been refactored (again) so as to factorize between the computation of friendly names and the computation of obsolescence flags. The refactoring involved a significant AND RISKY change: external key friendly names (magic attributes) have been changed from AttributeFriendlyName to AttributeExternalField, which simplifies the SQL query build logic.
SVN:trunk[4732]
This commit is contained in:
@@ -1381,15 +1381,12 @@ EOF
|
||||
$rawValue = $oObj->Get($sAttCodeEx);
|
||||
// Due to custom formatting rules, empty friendlynames may be rendered as non-empty strings
|
||||
// let's fix this and make sure we render an empty string if the key == 0
|
||||
if ($oAttDef instanceof AttributeFriendlyName)
|
||||
if ($oAttDef instanceof AttributeExternalField && $oAttDef->IsFriendlyName())
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
if ($sKeyAttCode != 'id')
|
||||
if ($oObj->Get($sKeyAttCode) == 0)
|
||||
{
|
||||
if ($oObj->Get($sKeyAttCode) == 0)
|
||||
{
|
||||
$rawValue = '';
|
||||
}
|
||||
$rawValue = '';
|
||||
}
|
||||
}
|
||||
if ($bLocalize)
|
||||
|
||||
@@ -928,8 +928,15 @@ class DataTableSettings implements Serializable
|
||||
}
|
||||
else if ($oAttDef->IsExternalField())
|
||||
{
|
||||
$oExtAttDef = $oAttDef->GetExtAttDef();
|
||||
$sLabel = Dict::Format('UI:ExtField_AsRemoteField', $oAttDef->GetLabel(), $oExtAttDef->GetLabel());
|
||||
if ($oAttDef->IsFriendlyName())
|
||||
{
|
||||
$sLabel = Dict::Format('UI:ExtKey_AsFriendlyName', $oAttDef->GetLabel());
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExtAttDef = $oAttDef->GetExtAttDef();
|
||||
$sLabel = Dict::Format('UI:ExtField_AsRemoteField', $oAttDef->GetLabel(), $oExtAttDef->GetLabel());
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef instanceof AttributeFriendlyName)
|
||||
{
|
||||
|
||||
@@ -239,7 +239,7 @@ abstract class AttributeDefinition
|
||||
*/
|
||||
static public function IsBasedOnDBColumns() {return false;}
|
||||
/**
|
||||
* Returns true if the attribute value is built after other attributes by the mean of an expression
|
||||
* Returns true if the attribute value is built after other attributes by the mean of an expression (obtained via GetOQLExpression)
|
||||
* @return bool
|
||||
*/
|
||||
static public function IsBasedOnOQLExpression() {return false;}
|
||||
@@ -926,9 +926,12 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
}
|
||||
}
|
||||
if ($sAttCode == $this->GetExtKeyToMe()) continue;
|
||||
if ($oAttDef->IsExternalField() && ($oAttDef->GetKeyAttCode() == $this->GetExtKeyToMe())) continue;
|
||||
if (($oAttDef instanceof AttributeFriendlyName) && ($oAttDef->GetKeyAttCode() == $this->GetExtKeyToMe())) continue;
|
||||
if (($oAttDef instanceof AttributeFriendlyName) && ($oAttDef->GetKeyAttCode() == 'id')) continue;
|
||||
if ($oAttDef->IsExternalField())
|
||||
{
|
||||
if ($oAttDef->GetKeyAttCode() == $this->GetExtKeyToMe()) continue;
|
||||
if ($oAttDef->IsFriendlyName()) continue;
|
||||
}
|
||||
if ($oAttDef instanceof AttributeFriendlyName) continue;
|
||||
if (!$oAttDef->IsScalar()) continue;
|
||||
$sAttValue = $oObj->GetAsXML($sAttCode, $bLocalize);
|
||||
$sRes .= "<$sAttCode>$sAttValue</$sAttCode>\n";
|
||||
@@ -4826,11 +4829,20 @@ class AttributeExternalField extends AttributeDefinition
|
||||
|
||||
public function GetLabel($sDefault = null)
|
||||
{
|
||||
$sLabel = parent::GetLabel('');
|
||||
if (strlen($sLabel) == 0)
|
||||
if ($this->IsFriendlyName())
|
||||
{
|
||||
$oRemoteAtt = $this->GetExtAttDef();
|
||||
$sLabel = $oRemoteAtt->GetLabel($this->m_sCode);
|
||||
$sKeyAttCode = $this->Get("extkey_attcode");
|
||||
$oExtKeyAttDef = MetaModel::GetAttributeDef($this->GetHostClass(), $sKeyAttCode);
|
||||
$sLabel = $oExtKeyAttDef->GetLabel($this->m_sCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sLabel = parent::GetLabel('');
|
||||
if (strlen($sLabel) == 0)
|
||||
{
|
||||
$oRemoteAtt = $this->GetExtAttDef();
|
||||
$sLabel = $oRemoteAtt->GetLabel($this->m_sCode);
|
||||
}
|
||||
}
|
||||
return $sLabel;
|
||||
}
|
||||
@@ -4872,6 +4884,27 @@ class AttributeExternalField extends AttributeDefinition
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsFriendlyName()
|
||||
{
|
||||
$oRemoteAtt = $this->GetExtAttDef();
|
||||
if ($oRemoteAtt instanceof AttributeExternalField)
|
||||
{
|
||||
$bRet = $oRemoteAtt->IsFriendlyName();
|
||||
}
|
||||
elseif ($oRemoteAtt instanceof AttributeFriendlyName)
|
||||
{
|
||||
$bRet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$bRet = false;
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
public function GetTargetClass($iType = EXTKEY_RELATIVE)
|
||||
{
|
||||
return $this->GetKeyAttDef($iType)->GetTargetClass();
|
||||
@@ -6700,12 +6733,11 @@ class AttributePropertySet extends AttributeTable
|
||||
*/
|
||||
class AttributeFriendlyName extends AttributeDefinition
|
||||
{
|
||||
public function __construct($sCode, $sExtKeyAttCode)
|
||||
public function __construct($sCode)
|
||||
{
|
||||
$this->m_sCode = $sCode;
|
||||
$aParams = array();
|
||||
$aParams["default_value"] = '';
|
||||
$aParams["extkey_attcode"] = $sExtKeyAttCode;
|
||||
parent::__construct($sCode, $aParams);
|
||||
|
||||
$this->m_sValue = $this->Get("default_value");
|
||||
@@ -6732,84 +6764,15 @@ class AttributeFriendlyName extends AttributeDefinition
|
||||
static public function IsBasedOnOQLExpression() {return true;}
|
||||
public function GetOQLExpression()
|
||||
{
|
||||
return static::GetExtendedNameExpression($this->GetHostClass());
|
||||
return MetaModel::GetNameExpression($this->GetHostClass());
|
||||
}
|
||||
/**
|
||||
* Get the friendly name for the class and its subclasses (if finalclass = 'subclass' ...)
|
||||
* Simplifies the final expression by grouping classes having the same name expression
|
||||
* Used when querying a parent class
|
||||
*/
|
||||
static protected function GetExtendedNameExpression($sClass)
|
||||
{
|
||||
// 1st step - get all of the required expressions (instantiable classes)
|
||||
// and group them using their OQL representation
|
||||
//
|
||||
$aFNExpressions = array(); // signature => array('expression' => oExp, 'classes' => array of classes)
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass)
|
||||
{
|
||||
if (($sSubClass != $sClass) && MetaModel::IsAbstract($sSubClass)) continue;
|
||||
|
||||
$oSubClassName = MetaModel::GetNameExpression($sSubClass);
|
||||
$sSignature = $oSubClassName->Render();
|
||||
if (!array_key_exists($sSignature, $aFNExpressions))
|
||||
{
|
||||
$aFNExpressions[$sSignature] = array(
|
||||
'expression' => $oSubClassName,
|
||||
'classes' => array(),
|
||||
);
|
||||
}
|
||||
$aFNExpressions[$sSignature]['classes'][] = $sSubClass;
|
||||
}
|
||||
|
||||
// 2nd step - build the final name expression depending on the finalclass
|
||||
//
|
||||
if (count($aFNExpressions) == 1)
|
||||
{
|
||||
$aExpData = reset($aFNExpressions);
|
||||
$oNameExpression = $aExpData['expression'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNameExpression = null;
|
||||
foreach ($aFNExpressions as $sSignature => $aExpData)
|
||||
{
|
||||
$oClassListExpr = ListExpression::FromScalars($aExpData['classes']);
|
||||
$oClassExpr = new FieldExpression('finalclass', $sClass);
|
||||
$oClassInList = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
|
||||
|
||||
if (is_null($oNameExpression))
|
||||
{
|
||||
$oNameExpression = $aExpData['expression'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNameExpression = new FunctionExpression('IF', array($oClassInList, $aExpData['expression'], $oNameExpression));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $oNameExpression;
|
||||
}
|
||||
|
||||
|
||||
public function GetKeyAttCode() {return $this->Get("extkey_attcode");}
|
||||
|
||||
public function GetExtAttCode() {return 'friendlyname';}
|
||||
|
||||
public function GetLabel($sDefault = null)
|
||||
{
|
||||
$sLabel = parent::GetLabel('');
|
||||
if (strlen($sLabel) == 0)
|
||||
{
|
||||
$sKeyAttCode = $this->Get("extkey_attcode");
|
||||
if ($sKeyAttCode == 'id')
|
||||
{
|
||||
return Dict::S('Core:FriendlyName-Label');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExtKeyAttDef = MetaModel::GetAttributeDef($this->GetHostClass(), $sKeyAttCode);
|
||||
$sLabel = $oExtKeyAttDef->GetLabel($this->m_sCode);
|
||||
}
|
||||
$sLabel = Dict::S('Core:FriendlyName-Label');
|
||||
}
|
||||
return $sLabel;
|
||||
}
|
||||
@@ -6818,16 +6781,7 @@ class AttributeFriendlyName extends AttributeDefinition
|
||||
$sLabel = parent::GetDescription('');
|
||||
if (strlen($sLabel) == 0)
|
||||
{
|
||||
$sKeyAttCode = $this->Get("extkey_attcode");
|
||||
if ($sKeyAttCode == 'id')
|
||||
{
|
||||
return Dict::S('Core:FriendlyName-Description');
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExtKeyAttDef = MetaModel::GetAttributeDef($this->GetHostClass(), $sKeyAttCode);
|
||||
$sLabel = $oExtKeyAttDef->GetDescription('');
|
||||
}
|
||||
$sLabel = Dict::S('Core:FriendlyName-Description');
|
||||
}
|
||||
return $sLabel;
|
||||
}
|
||||
@@ -7712,3 +7666,58 @@ class AttributeArchiveDate extends AttributeDate
|
||||
return parent::GetDescription($sDefault);
|
||||
}
|
||||
}
|
||||
|
||||
class AttributeObsolescenceFlag extends AttributeBoolean
|
||||
{
|
||||
public function __construct($sCode)
|
||||
{
|
||||
parent::__construct($sCode, array("allowed_values"=>null, "sql"=>$sCode, "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array()));
|
||||
}
|
||||
public function IsWritable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public function IsMagic()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function IsBasedOnDBColumns() {return false;}
|
||||
/**
|
||||
* Returns true if the attribute value is built after other attributes by the mean of an expression (obtained via GetOQLExpression)
|
||||
* @return bool
|
||||
*/
|
||||
static public function IsBasedOnOQLExpression() {return true;}
|
||||
public function GetOQLExpression()
|
||||
{
|
||||
return MetaModel::GetObsolescenceExpression($this->GetHostClass());
|
||||
}
|
||||
|
||||
public function GetSQLExpressions($sPrefix = '')
|
||||
{
|
||||
return array();
|
||||
if ($sPrefix == '')
|
||||
{
|
||||
$sPrefix = $this->GetCode(); // Warning AttributeComputedFieldVoid does not have any sql property
|
||||
}
|
||||
return array('' => $sPrefix);
|
||||
}
|
||||
public function GetSQLColumns($bFullSpec = false) {return array();} // returns column/spec pairs (1 in most of the cases), for STRUCTURING (DB creation)
|
||||
public function GetSQLValues($value) {return array();} // returns column/value pairs (1 in most of the cases), for WRITING (Insert, Update)
|
||||
|
||||
public function GetEditClass() {return "";}
|
||||
|
||||
public function GetValuesDef() {return null;}
|
||||
public function GetPrerequisiteAttributes($sClass = null) {return $this->GetOptional("depends_on", array());}
|
||||
|
||||
public function IsDirectField() {return true;}
|
||||
static public function IsScalar() {return true;}
|
||||
public function GetSQLExpr()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function GetDefaultValue(DBObject $oHostObject = null) {return $this->MakeRealValue("", $oHostObject);}
|
||||
public function IsNullAllowed() {return false;}
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
|
||||
{
|
||||
if (($oDef->IsExternalField() || ($oDef instanceof AttributeFriendlyName)) && ($oDef->GetKeyAttCode() == $sAttCode))
|
||||
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
|
||||
{
|
||||
$this->m_aCurrValues[$sCode] = $value->Get($oDef->GetExtAttCode());
|
||||
$this->m_aLoadedAtt[$sCode] = true;
|
||||
@@ -423,7 +423,7 @@ abstract class DBObject implements iDisplay
|
||||
// Invalidate the corresponding fields so that they get reloaded in case they are needed (See Get())
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
|
||||
{
|
||||
if (($oDef->IsExternalField() || ($oDef instanceof AttributeFriendlyName)) && ($oDef->GetKeyAttCode() == $sAttCode))
|
||||
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
|
||||
{
|
||||
$this->m_aCurrValues[$sCode] = $oDef->GetDefaultValue($this);
|
||||
unset($this->m_aLoadedAtt[$sCode]);
|
||||
@@ -566,7 +566,7 @@ abstract class DBObject implements iDisplay
|
||||
else
|
||||
{
|
||||
// Not loaded... is it related to an external key?
|
||||
if ($oAttDef->IsExternalField() || ($oAttDef instanceof AttributeFriendlyName))
|
||||
if ($oAttDef->IsExternalField())
|
||||
{
|
||||
// Let's get the object and compute all of the corresponding attributes
|
||||
// (i.e not only the requested attribute)
|
||||
@@ -588,7 +588,7 @@ abstract class DBObject implements iDisplay
|
||||
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
|
||||
{
|
||||
if (($oDef->IsExternalField() || ($oDef instanceof AttributeFriendlyName)) && ($oDef->GetKeyAttCode() == $sExtKeyAttCode))
|
||||
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sExtKeyAttCode))
|
||||
{
|
||||
if ($oRemote)
|
||||
{
|
||||
@@ -3614,6 +3614,16 @@ abstract class DBObject implements iDisplay
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
public function IsObsolete()
|
||||
{
|
||||
$bRet = false;
|
||||
if (MetaModel::IsValidAttCode(get_class($this), 'obsolescence_flag') && $this->Get('obsolescence_flag'))
|
||||
{
|
||||
$bRet = true;
|
||||
}
|
||||
return $bRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $bArchive
|
||||
* @throws Exception
|
||||
|
||||
@@ -1677,15 +1677,15 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
|
||||
$aFNJoinAlias = array(); // array of (subclass => alias)
|
||||
foreach ($aExpectedAtts as $sAttCode => $oExpression)
|
||||
foreach ($aExpectedAtts as $sExpectedAttCode => $oExpression)
|
||||
{
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sAttCode)) continue;
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if (!MetaModel::IsValidAttCode($sClass, $sExpectedAttCode)) continue;
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sExpectedAttCode);
|
||||
if ($oAttDef->IsBasedOnOQLExpression())
|
||||
{
|
||||
// To optimize: detect a restriction on child classes in the condition expression
|
||||
// e.g. SELECT FunctionalCI WHERE finalclass IN ('Server', 'VirtualMachine')
|
||||
$oExpression = $oAttDef->GetOQLExpression($sClass);
|
||||
$oExpression = static::GetPolymorphicExpression($sClass, $sExpectedAttCode);
|
||||
|
||||
$aRequiredFields = array();
|
||||
$oExpression->GetUnresolvedFields('', $aRequiredFields);
|
||||
@@ -1700,7 +1700,7 @@ class DBObjectSearch extends DBSearch
|
||||
$sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode);
|
||||
$aExtKeys[$sClassOfAttribute][$sAttCode] = array();
|
||||
}
|
||||
elseif ($oAttDef->IsExternalField() || ($oAttDef instanceof AttributeFriendlyName))
|
||||
elseif ($oAttDef->IsExternalField())
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
$sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sKeyAttCode);
|
||||
@@ -1739,7 +1739,7 @@ class DBObjectSearch extends DBSearch
|
||||
$oExpression = $oExpression->Translate($aTranslateFields, false);
|
||||
|
||||
$aTranslateNow = array();
|
||||
$aTranslateNow[$sClassAlias]['friendlyname'] = $oExpression;
|
||||
$aTranslateNow[$sClassAlias][$sExpectedAttCode] = $oExpression;
|
||||
$oBuild->m_oQBExpressions->Translate($aTranslateNow, false);
|
||||
}
|
||||
}
|
||||
@@ -1747,17 +1747,14 @@ class DBObjectSearch extends DBSearch
|
||||
// Add the ext fields used in the select (eventually adds an external key)
|
||||
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
|
||||
{
|
||||
if ($oAttDef->IsExternalField() || ($oAttDef instanceof AttributeFriendlyName))
|
||||
if ($oAttDef->IsExternalField())
|
||||
{
|
||||
if (array_key_exists($sAttCode, $aExpectedAtts))
|
||||
{
|
||||
// Add the external attribute
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
if ($sKeyAttCode != 'id')
|
||||
{
|
||||
// Add the external attribute
|
||||
$sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode);
|
||||
$aExtKeys[$sKeyTableClass][$sKeyAttCode][$sAttCode] = $oAttDef;
|
||||
}
|
||||
$sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode);
|
||||
$aExtKeys[$sKeyTableClass][$sKeyAttCode][$sAttCode] = $oAttDef;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1871,7 +1868,6 @@ class DBObjectSearch extends DBSearch
|
||||
protected function MakeSQLObjectQuerySingleTable(&$oBuild, $aAttToLoad, $sTableClass, $aExtKeys, $aValues)
|
||||
{
|
||||
// $aExtKeys is an array of sTableClass => array of (sAttCode (keys) => array of sAttCode (fields))
|
||||
//echo "MakeSQLObjectQuery($sTableClass)-liste des clefs externes($sTableClass): <pre>".print_r($aExtKeys, true)."</pre><br/>\n";
|
||||
|
||||
// Prepare the query for a single table (compound objects)
|
||||
// Ignores the items (attributes/filters) that are not on the target table
|
||||
@@ -1953,7 +1949,6 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
else
|
||||
{
|
||||
//echo "<p>MakeSQLObjectQuerySingleTable: Field $sAttCode is part of the table $sTable (named: $sTableAlias)</p>";
|
||||
// standard field, or external key
|
||||
// add it to the output
|
||||
foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr)
|
||||
@@ -1971,7 +1966,6 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
}
|
||||
|
||||
//echo "MakeSQLObjectQuery- Classe $sTableClass<br/>\n";
|
||||
// 4 - The external keys -> joins...
|
||||
//
|
||||
$aAllPointingTo = $this->GetCriteria_PointingTo();
|
||||
@@ -1983,10 +1977,8 @@ class DBObjectSearch extends DBSearch
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef($sTableClass, $sKeyAttCode);
|
||||
|
||||
$aPointingTo = $this->GetCriteria_PointingTo($sKeyAttCode);
|
||||
//echo "MakeSQLObjectQuery-Cle '$sKeyAttCode'<br/>\n";
|
||||
if (!array_key_exists(TREE_OPERATOR_EQUALS, $aPointingTo))
|
||||
{
|
||||
//echo "MakeSQLObjectQuery-Ajoutons l'operateur TREE_OPERATOR_EQUALS pour $sKeyAttCode<br/>\n";
|
||||
// The join was not explicitely defined in the filter,
|
||||
// we need to do it now
|
||||
$sKeyClass = $oKeyAttDef->GetTargetClass();
|
||||
@@ -1997,8 +1989,7 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
//echo "MakeSQLObjectQuery-liste des clefs de jointure: <pre>".print_r(array_keys($aAllPointingTo), true)."</pre><br/>\n";
|
||||
|
||||
|
||||
foreach ($aAllPointingTo as $sKeyAttCode => $aPointingTo)
|
||||
{
|
||||
foreach($aPointingTo as $iOperatorCode => $aFilter)
|
||||
@@ -2011,11 +2002,8 @@ class DBObjectSearch extends DBSearch
|
||||
$sKeyClass = $oExtFilter->GetFirstJoinedClass();
|
||||
$sKeyClassAlias = $oExtFilter->GetFirstJoinedClassAlias();
|
||||
|
||||
//echo "MakeSQLObjectQuery-$sTableClass::$sKeyAttCode Foreach PointingTo($iOperatorCode) <span style=\"color:red\">$sKeyClass (alias:$sKeyClassAlias)</span><br/>\n";
|
||||
|
||||
// Note: there is no search condition in $oExtFilter, because normalization did merge the condition onto the top of the filter tree
|
||||
// Note: there is no search condition in $oExtFilter, because normalization did merge the condition onto the top of the filter tree
|
||||
|
||||
//echo "MakeSQLObjectQuery-array_key_exists($sTableClass, \$aExtKeys)<br/>\n";
|
||||
if ($iOperatorCode == TREE_OPERATOR_EQUALS)
|
||||
{
|
||||
if (array_key_exists($sTableClass, $aExtKeys) && array_key_exists($sKeyAttCode, $aExtKeys[$sTableClass]))
|
||||
@@ -2025,12 +2013,10 @@ class DBObjectSearch extends DBSearch
|
||||
$aTranslateNow = array(); // Translation for external fields - must be performed before the join is done (recursion...)
|
||||
foreach($aExtKeys[$sTableClass][$sKeyAttCode] as $sAttCode => $oAtt)
|
||||
{
|
||||
//echo "MakeSQLObjectQuery aExtKeys[$sTableClass][$sKeyAttCode] => $sAttCode-oAtt: <pre>".print_r($oAtt, true)."</pre><br/>\n";
|
||||
if ($oAtt instanceof AttributeFriendlyName)
|
||||
if ($oAtt->IsFriendlyName())
|
||||
{
|
||||
// Note: for a given ext key, there is one single attribute "friendly name"
|
||||
$aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression('friendlyname', $sKeyClassAlias);
|
||||
//echo "<p><b>aTranslateNow[$sTargetAlias][$sAttCode] = new FieldExpression('friendlyname', $sKeyClassAlias);</b></p>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2040,9 +2026,7 @@ class DBObjectSearch extends DBSearch
|
||||
foreach ($oRemoteAttDef->GetSQLExpressions() as $sColId => $sRemoteAttExpr)
|
||||
{
|
||||
$aTranslateNow[$sTargetAlias][$sAttCode.$sColId] = new FieldExpression($sExtAttCode, $sKeyClassAlias);
|
||||
//echo "<p><b>aTranslateNow[$sTargetAlias][$sAttCode.$sColId] = new FieldExpression($sExtAttCode, $sKeyClassAlias);</b></p>\n";
|
||||
}
|
||||
//echo "<p><b>ExtAttr2: $sTargetAlias.$sAttCode to $sKeyClassAlias.$sRemoteAttExpr (class: $sKeyClass)</b></p>\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2064,15 +2048,11 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
// Translate prior to recursing
|
||||
//
|
||||
//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 MakeSQLObjectQuery()/p>\n";
|
||||
|
||||
self::DbgTrace("External key $sKeyAttCode (class: $sKeyClass), call MakeSQLObjectQuery()");
|
||||
$oBuild->m_oQBExpressions->PushJoinField(new FieldExpression('id', $sKeyClassAlias));
|
||||
|
||||
//echo "<p>Recursive MakeSQLObjectQuery ".__LINE__.": <pre>\n".print_r($oBuild->GetRootFilter()->GetSelectedClasses(), true)."</pre></p>\n";
|
||||
$oSelectExtKey = $oExtFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad);
|
||||
|
||||
$oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField();
|
||||
@@ -2114,9 +2094,7 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
// Translate the selected columns
|
||||
//
|
||||
//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";
|
||||
|
||||
// Filter out archived records
|
||||
//
|
||||
@@ -2125,7 +2103,6 @@ class DBObjectSearch extends DBSearch
|
||||
if (!$oBuild->GetRootFilter()->GetArchiveMode())
|
||||
{
|
||||
$bIsOnJoinedClass = array_key_exists($sTargetAlias, $oBuild->GetRootFilter()->GetJoinedClasses());
|
||||
//$bIsOnJoinedClass = true;
|
||||
if ($bIsOnJoinedClass)
|
||||
{
|
||||
if (MetaModel::IsParentClass($sTableClass, $sTargetClass))
|
||||
@@ -2136,7 +2113,84 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
//MyHelpers::var_dump_html($oSelectBase->RenderSelect());
|
||||
return $oSelectBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expression for the class and its subclasses (if finalclass = 'subclass' ...)
|
||||
* Simplifies the final expression by grouping classes having the same expression
|
||||
*/
|
||||
static protected function GetPolymorphicExpression($sClass, $sAttCode)
|
||||
{
|
||||
// 1st step - get all of the required expressions (instantiable classes)
|
||||
// and group them using their OQL representation
|
||||
//
|
||||
$aExpressions = array(); // signature => array('expression' => oExp, 'classes' => array of classes)
|
||||
foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sSubClass)
|
||||
{
|
||||
if (($sSubClass != $sClass) && MetaModel::IsAbstract($sSubClass)) continue;
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode);
|
||||
$oSubClassExp = $oAttDef->GetOQLExpression($sSubClass);
|
||||
|
||||
// 3rd step - position the attributes in the hierarchy of classes
|
||||
//
|
||||
$oSubClassExp->Browse(function($oNode) use ($sSubClass) {
|
||||
if ($oNode instanceof FieldExpression)
|
||||
{
|
||||
$sAttCode = $oNode->GetName();
|
||||
$oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode);
|
||||
if ($oAttDef->IsExternalField())
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
$sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sKeyAttCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode);
|
||||
}
|
||||
$sParent = MetaModel::GetAttributeOrigin($sClassOfAttribute, $oNode->GetName());
|
||||
$oNode->SetParent($sParent);
|
||||
}
|
||||
});
|
||||
|
||||
$sSignature = $oSubClassExp->Render();
|
||||
if (!array_key_exists($sSignature, $aExpressions))
|
||||
{
|
||||
$aExpressions[$sSignature] = array(
|
||||
'expression' => $oSubClassExp,
|
||||
'classes' => array(),
|
||||
);
|
||||
}
|
||||
$aExpressions[$sSignature]['classes'][] = $sSubClass;
|
||||
}
|
||||
|
||||
// 2nd step - build the final name expression depending on the finalclass
|
||||
//
|
||||
if (count($aExpressions) == 1)
|
||||
{
|
||||
$aExpData = reset($aExpressions);
|
||||
$oExpression = $aExpData['expression'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExpression = null;
|
||||
foreach ($aExpressions as $sSignature => $aExpData)
|
||||
{
|
||||
$oClassListExpr = ListExpression::FromScalars($aExpData['classes']);
|
||||
$oClassExpr = new FieldExpression('finalclass', $sClass);
|
||||
$oClassInList = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr);
|
||||
|
||||
if (is_null($oExpression))
|
||||
{
|
||||
$oExpression = $aExpData['expression'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$oExpression = new FunctionExpression('IF', array($oClassInList, $aExpData['expression'], $oExpression));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $oExpression;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,6 +324,18 @@ abstract class MetaModel
|
||||
self::_check_subclass($sClass);
|
||||
return self::$m_aClassParams[$sClass]["archive"];
|
||||
}
|
||||
final static public function IsObsoletable($sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
return (!is_null(self::$m_aClassParams[$sClass]['obsolescence_expression']));
|
||||
}
|
||||
final static public function GetObsolescenceExpression($sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
$sOql = self::$m_aClassParams[$sClass]['obsolescence_expression'];
|
||||
$oRet = Expression::FromOQL($sOql);
|
||||
return $oRet;
|
||||
}
|
||||
final static public function GetNameSpec($sClass)
|
||||
{
|
||||
self::_check_subclass($sClass);
|
||||
@@ -379,20 +391,10 @@ abstract class MetaModel
|
||||
//
|
||||
$iReplacement = (int)$sPiece - 1;
|
||||
|
||||
if (isset($aAttributes[$iReplacement]))
|
||||
{
|
||||
$sAttCode = $aAttributes[$iReplacement];
|
||||
$oAttDef = self::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef->IsExternalField() || ($oAttDef instanceof AttributeFriendlyName))
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
$sClassOfAttribute = self::GetAttributeOrigin($sClass, $sKeyAttCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sClassOfAttribute = self::GetAttributeOrigin($sClass, $sAttCode);
|
||||
}
|
||||
$aExpressions[] = new FieldExpression($sAttCode, $sClassOfAttribute);
|
||||
if (isset($aAttributes[$iReplacement]))
|
||||
{
|
||||
$sAttCode = $aAttributes[$iReplacement];
|
||||
$aExpressions[] = new FieldExpression($sAttCode);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1758,6 +1760,31 @@ abstract class MetaModel
|
||||
self::$m_aClassParams[$sPHPClass]['archive_root_class'] = $bArchiveRoot ? $sPHPClass : self::$m_aClassParams[$sParent]['archive_root_class'];
|
||||
}
|
||||
|
||||
// Inherit obsolescence expression
|
||||
$sObsolescence = null;
|
||||
if (isset(self::$m_aClassParams[$sPHPClass]['obsolescence_expression']))
|
||||
{
|
||||
// Defined or overloaded
|
||||
$sObsolescence = self::$m_aClassParams[$sPHPClass]['obsolescence_expression'];
|
||||
}
|
||||
elseif (@self::$m_aClassParams[$sParent]['obsolescence_expression'])
|
||||
{
|
||||
// Inherited
|
||||
$sObsolescence = self::$m_aClassParams[$sParent]['obsolescence_expression'];
|
||||
}
|
||||
self::$m_aClassParams[$sPHPClass]['obsolescence_expression'] = $sObsolescence;
|
||||
|
||||
if (@self::$m_aClassParams[$sParent]['obsolescence_expression'])
|
||||
{
|
||||
// Inherited or overloaded
|
||||
self::$m_aClassParams[$sPHPClass]['obsolescence_root_class'] = self::$m_aClassParams[$sParent]['obsolescence_root_class'];
|
||||
}
|
||||
elseif ($sObsolescence)
|
||||
{
|
||||
// Defined
|
||||
self::$m_aClassParams[$sPHPClass]['obsolescence_root_class'] = $sPHPClass;
|
||||
}
|
||||
|
||||
foreach (MetaModel::EnumPlugins('iOnClassInitialization') as $sPluginClass => $oClassInit)
|
||||
{
|
||||
$oClassInit->OnAfterClassInitialization($sPHPClass);
|
||||
@@ -1814,7 +1841,7 @@ abstract class MetaModel
|
||||
{
|
||||
// Create the friendly name attribute
|
||||
$sFriendlyNameAttCode = 'friendlyname';
|
||||
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode, 'id');
|
||||
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode);
|
||||
self::AddMagicAttribute($oFriendlyName, $sClass);
|
||||
|
||||
if (self::$m_aClassParams[$sClass]["archive_root"])
|
||||
@@ -1831,14 +1858,33 @@ abstract class MetaModel
|
||||
$sArchiveRoot = self::$m_aClassParams[$sClass]['archive_root_class'];
|
||||
// Inherit archive attributes
|
||||
$oArchiveFlag = clone self::$m_aAttribDefs[$sArchiveRoot]['archive_flag'];
|
||||
$oArchiveFlag->SetHostClass($sArchiveRoot);
|
||||
$oArchiveFlag->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass]['archive_flag'] = $oArchiveFlag;
|
||||
self::$m_aAttribOrigins[$sClass]['archive_flag'] = $sArchiveRoot;
|
||||
$oArchiveDate = clone self::$m_aAttribDefs[$sArchiveRoot]['archive_date'];
|
||||
$oArchiveDate->SetHostClass($sArchiveRoot);
|
||||
$oArchiveDate->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass]['archive_date'] = $oArchiveDate;
|
||||
self::$m_aAttribOrigins[$sClass]['archive_date'] = $sArchiveRoot;
|
||||
}
|
||||
if (!is_null(self::$m_aClassParams[$sClass]['obsolescence_expression']))
|
||||
{
|
||||
$oObsolescenceFlag = new AttributeObsolescenceFlag('obsolescence_flag');
|
||||
self::AddMagicAttribute($oObsolescenceFlag, $sClass);
|
||||
|
||||
$sObsolescenceRoot = self::$m_aClassParams[$sClass]['obsolescence_root_class'];
|
||||
if ($sClass == $sObsolescenceRoot)
|
||||
{
|
||||
$oObsolescenceDate = new AttributeDate('obsolescence_date', array('magic' => true, "allowed_values" => null, "sql" => 'obsolescence_date', "default_value" => '', "is_null_allowed" => true, "depends_on" => array()));
|
||||
self::AddMagicAttribute($oObsolescenceDate, $sClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObsolescenceDate = clone self::$m_aAttribDefs[$sObsolescenceRoot]['archive_date'];
|
||||
$oObsolescenceDate->SetHostClass($sClass);
|
||||
self::$m_aAttribDefs[$sClass]['obsolescence_date'] = $oObsolescenceDate;
|
||||
self::$m_aAttribOrigins[$sClass]['obsolescence_date'] = $sObsolescenceRoot;
|
||||
}
|
||||
}
|
||||
foreach (self::$m_aAttribDefs[$sClass] as $sAttCode => $oAttDef)
|
||||
{
|
||||
// Compute the filter codes
|
||||
@@ -1882,8 +1928,8 @@ abstract class MetaModel
|
||||
else
|
||||
{
|
||||
// Create the friendly name attribute
|
||||
$sFriendlyNameAttCode = $sAttCode.'_friendlyname';
|
||||
$oFriendlyName = new AttributeFriendlyName($sFriendlyNameAttCode, $sAttCode);
|
||||
$sFriendlyNameAttCode = $sAttCode.'_friendlyname';
|
||||
$oFriendlyName = new AttributeExternalField($sFriendlyNameAttCode, array('magic' => true, 'allowed_values'=>null, 'extkey_attcode'=>$sAttCode, "target_attcode"=>'friendlyname', 'depends_on'=>array()));
|
||||
self::AddMagicAttribute($oFriendlyName, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]);
|
||||
|
||||
if (self::HasChildrenClasses($sRemoteClass))
|
||||
@@ -1936,6 +1982,12 @@ abstract class MetaModel
|
||||
$oArchiveRemote = new AttributeExternalField($sArchiveRemote, array("allowed_values"=>null, "extkey_attcode"=>$sAttCode, "target_attcode"=>'archive_flag', "depends_on"=>array()));
|
||||
self::AddMagicAttribute($oArchiveRemote, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]);
|
||||
}
|
||||
if (self::IsObsoletable($sRemoteClass))
|
||||
{
|
||||
$sObsoleteRemote = $sAttCode.'_obsolescence_flag';
|
||||
$oObsoleteRemote = new AttributeExternalField($sObsoleteRemote, array("allowed_values"=>null, "extkey_attcode"=>$sAttCode, "target_attcode"=>'archive_flag', "depends_on"=>array()));
|
||||
self::AddMagicAttribute($oObsoleteRemote, $sClass, self::$m_aAttribOrigins[$sClass][$sAttCode]);
|
||||
}
|
||||
}
|
||||
if ($oAttDef instanceof AttributeMetaEnum)
|
||||
{
|
||||
@@ -2490,6 +2542,18 @@ abstract class MetaModel
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
public static function EnumObsoletableClasses()
|
||||
{
|
||||
$aRes = array();
|
||||
foreach (self::GetClasses() as $sClass)
|
||||
{
|
||||
if (self::IsObsoletable($sClass))
|
||||
{
|
||||
$aRes[] = $sClass;
|
||||
}
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
public static function HasChildrenClasses($sClass)
|
||||
{
|
||||
@@ -5157,26 +5221,29 @@ abstract class MetaModel
|
||||
else
|
||||
{
|
||||
$oAttDef = static::GetAttributeDef($sClass, $sField);
|
||||
if ($oAttDef instanceof AttributeFriendlyName)
|
||||
if ($oAttDef->IsExternalField())
|
||||
{
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef($sClass, $oAttDef->GetKeyAttCode());
|
||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||
$sFriendlyNameAttCode = static::GetFriendlyNameAttributeCode($sRemoteClass);
|
||||
if (is_null($sFriendlyNameAttCode))
|
||||
if ($oAttDef->IsFriendlyName())
|
||||
{
|
||||
// The friendly name is made of several attributes
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->friendlyname';
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef($sClass, $oAttDef->GetKeyAttCode());
|
||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||
$sFriendlyNameAttCode = static::GetFriendlyNameAttributeCode($sRemoteClass);
|
||||
if (is_null($sFriendlyNameAttCode))
|
||||
{
|
||||
// The friendly name is made of several attributes
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->friendlyname';
|
||||
}
|
||||
else
|
||||
{
|
||||
// The friendly name is made of a single attribute
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->'.$sFriendlyNameAttCode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The friendly name is made of a single attribute
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->'.$sFriendlyNameAttCode;
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode();
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->IsExternalField())
|
||||
{
|
||||
$sRet = $oAttDef->GetKeyAttCode().'->'.$oAttDef->GetExtAttCode();
|
||||
}
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,13 @@ abstract class Expression
|
||||
// recursive rendering (aArgs used as input by default, or used as output if bRetrofitParams set to True
|
||||
abstract public function Render(&$aArgs = null, $bRetrofitParams = false);
|
||||
|
||||
/**
|
||||
* Recursively browse the expression tree
|
||||
* @param Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function Browse(Closure $callback);
|
||||
|
||||
abstract public function ApplyParameters($aArgs);
|
||||
|
||||
// recursively builds an array of class => fieldname
|
||||
@@ -76,6 +83,10 @@ abstract class Expression
|
||||
return self::FromOQL(base64_decode($sValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sConditionExpr
|
||||
* @return Expression
|
||||
*/
|
||||
static public function FromOQL($sConditionExpr)
|
||||
{
|
||||
$oOql = new OqlInterpreter($sConditionExpr);
|
||||
@@ -139,6 +150,11 @@ class SQLExpression extends Expression
|
||||
return $this->m_sSQL;
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
}
|
||||
@@ -245,7 +261,14 @@ class BinaryExpression extends Expression
|
||||
$sRight = $this->GetRightExpr()->Render($aArgs, $bRetrofitParams);
|
||||
return "($sLeft $sOperator $sRight)";
|
||||
}
|
||||
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
$this->m_oLeftExpr->Browse($callback);
|
||||
$this->m_oRightExpr->Browse($callback);
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
if ($this->m_oLeftExpr instanceof VariableExpression)
|
||||
@@ -358,7 +381,7 @@ class UnaryExpression extends Expression
|
||||
public function GetValue()
|
||||
{
|
||||
return $this->m_value;
|
||||
}
|
||||
}
|
||||
|
||||
// recursive rendering
|
||||
public function Render(&$aArgs = null, $bRetrofitParams = false)
|
||||
@@ -366,6 +389,11 @@ class UnaryExpression extends Expression
|
||||
return CMDBSource::Quote($this->m_value);
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
}
|
||||
@@ -484,6 +512,12 @@ class FieldExpression extends UnaryExpression
|
||||
public function GetParent() {return $this->m_sParent;}
|
||||
public function GetName() {return $this->m_sName;}
|
||||
|
||||
public function SetParent($sParent)
|
||||
{
|
||||
$this->m_sParent = $sParent;
|
||||
$this->m_value = $sParent.'.'.$this->m_sName;
|
||||
}
|
||||
|
||||
// recursive rendering
|
||||
public function Render(&$aArgs = null, $bRetrofitParams = false)
|
||||
{
|
||||
@@ -680,7 +714,7 @@ class VariableExpression extends UnaryExpression
|
||||
throw new MissingQueryArgument('Missing query argument', array('expecting'=>$this->m_sName, 'available'=>array_keys($aArgs)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function RenameParam($sOldName, $sNewName)
|
||||
{
|
||||
if ($this->m_sName == $sOldName)
|
||||
@@ -768,6 +802,15 @@ class ListExpression extends Expression
|
||||
return '('.implode(', ', $aRes).')';
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
foreach ($this->m_aExpressions as $oExpr)
|
||||
{
|
||||
$oExpr->Browse($callback);
|
||||
}
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
$aRes = array();
|
||||
@@ -888,6 +931,15 @@ class FunctionExpression extends Expression
|
||||
return $this->m_sVerb.'('.implode(', ', $aRes).')';
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
foreach ($this->m_aArgs as $iPos => $oExpr)
|
||||
{
|
||||
$oExpr->Browse($callback);
|
||||
}
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
$aRes = array();
|
||||
@@ -1071,6 +1123,12 @@ class IntervalExpression extends Expression
|
||||
return 'INTERVAL '.$this->m_oValue->Render($aArgs, $bRetrofitParams).' '.$this->m_sUnit;
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
$this->m_oValue->Browse($callback);
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
if ($this->m_oValue instanceof VariableExpression)
|
||||
@@ -1151,6 +1209,15 @@ class CharConcatExpression extends Expression
|
||||
return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)";
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
foreach ($this->m_aExpressions as $oExpr)
|
||||
{
|
||||
$oExpr->Browse($callback);
|
||||
}
|
||||
}
|
||||
|
||||
public function ApplyParameters($aArgs)
|
||||
{
|
||||
$aRes = array();
|
||||
@@ -1255,6 +1322,15 @@ class CharConcatWSExpression extends CharConcatExpression
|
||||
return "CAST(CONCAT_WS($sSep, ".implode(', ', $aRes).") AS CHAR)";
|
||||
}
|
||||
|
||||
public function Browse(Closure $callback)
|
||||
{
|
||||
$callback($this);
|
||||
foreach ($this->m_aExpressions as $oExpr)
|
||||
{
|
||||
$oExpr->Browse($callback);
|
||||
}
|
||||
}
|
||||
|
||||
public function Translate($aTranslationData, $bMatchAll = true, $bMarkFieldsAsResolved = true)
|
||||
{
|
||||
$aRes = array();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2015 Combodo SARL
|
||||
// Copyright (C) 2010-2017 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Wrapper to execute the parser, lexical analyzer and normalization of an OQL query
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2015 Combodo SARL
|
||||
* @copyright Copyright (C) 2010-2017 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@@ -83,6 +83,9 @@ class OqlInterpreter
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OqlQuery
|
||||
*/
|
||||
public function ParseQuery()
|
||||
{
|
||||
$oRes = $this->Parse();
|
||||
@@ -93,6 +96,9 @@ class OqlInterpreter
|
||||
return $oRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Expression
|
||||
*/
|
||||
public function ParseExpression()
|
||||
{
|
||||
$oRes = $this->Parse();
|
||||
@@ -103,5 +109,3 @@ class OqlInterpreter
|
||||
return $oRes;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -775,6 +775,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Tag:Archived+' => 'Can be accessed only in archive mode',
|
||||
'Tag:Synchronized' => 'Synchronized',
|
||||
'ObjectRef:Archived' => 'Archived',
|
||||
'ObjectRef:Obsolete' => 'Obsolete',
|
||||
'UI:SearchResultsPageTitle' => 'iTop - Search Results',
|
||||
'UI:SearchResultsTitle' => 'Search Results',
|
||||
'UI:SearchResultsTitle+' => 'Full-text search results',
|
||||
|
||||
@@ -994,6 +994,14 @@ EOF
|
||||
$bEnabled = $this->GetPropBoolean($oArchive, 'enabled', false);
|
||||
$aClassParams['archive'] = $bEnabled;
|
||||
}
|
||||
if ($oObsolescence = $oProperties->GetOptionalElement('obsolescence'))
|
||||
{
|
||||
$sCondition = trim($this->GetPropString($oObsolescence, 'condition', ''));
|
||||
if ($sCondition != "''")
|
||||
{
|
||||
$aClassParams['obsolescence_expression'] = $sCondition;
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize class params declaration
|
||||
//
|
||||
@@ -1687,7 +1695,6 @@ EOF
|
||||
$sMethods .= "\t}\n";
|
||||
}
|
||||
|
||||
|
||||
// Let's make the whole class declaration
|
||||
//
|
||||
$sPHP = "\n\n$sCodeComment\n";
|
||||
|
||||
@@ -162,13 +162,9 @@ if (!empty($sExpression))
|
||||
{
|
||||
$aAliasToFields[$sClassAlias][] = $oAttDef->GetParentAttCode();
|
||||
}
|
||||
else if($oAttDef instanceof AttributeFriendlyname)
|
||||
else if($oAttDef instanceof AttributeExternalField && $oAttDef->IsFriendlyName())
|
||||
{
|
||||
$sKeyAttCode = $oAttDef->GetKeyAttCode();
|
||||
if ($sKeyAttCode != 'id')
|
||||
{
|
||||
$aAliasToFields[$sClassAlias][] = $sKeyAttCode;
|
||||
}
|
||||
$aAliasToFields[$sClassAlias][] = $sKeyAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user