Add computed tag for attribute computation from OQL Expression

This commit is contained in:
XavierGR
2025-04-18 08:04:38 +02:00
parent 96382377ee
commit 5ba44a03ea
4 changed files with 58 additions and 3 deletions

View File

@@ -181,6 +181,23 @@ abstract class AttributeDefinition
return $this->GetSearchType() != static::SEARCH_WIDGET_TYPE_RAW;
}
/**
* @return bool
*/
public function IsComputed()
{
return $this->IsParam('expression');
}
/**
* @return array
* @throws \OQLException
*/
protected function GetComputedPrerequisiteAttributes(): array {
$oExpression = Expression::FromOQL($this->m_aParams['expression']);
return $oExpression->ListRequiredFields();
}
/** @var string */
protected $m_sCode;
/** @var array */
@@ -2717,7 +2734,11 @@ class AttributeDBFieldVoid extends AttributeDefinition
public function GetPrerequisiteAttributes($sClass = null)
{
return $this->Get("depends_on");
$aPrerequisiteAttributes = $this->Get("depends_on");
if($this->HasParam('expression')) {
$aPrerequisiteAttributes = array_merge($aPrerequisiteAttributes, $this->GetComputedPrerequisiteAttributes());
}
return $aPrerequisiteAttributes;
}
public static function IsBasedOnDBColumns()
@@ -2732,7 +2753,7 @@ class AttributeDBFieldVoid extends AttributeDefinition
public function IsWritable()
{
return !$this->IsMagic();
return !$this->IsMagic() && !$this->IsComputed();
}
public function GetSQLExpr()

View File

@@ -708,6 +708,8 @@ abstract class DBObject implements iDisplay
$this->UpdateMetaAttributes(array($sAttCode));
$this->UpdateDependentComputedAttributes($sAttCode);
// The object has changed, reset caches
$this->m_bCheckStatus = null;
@@ -6992,5 +6994,23 @@ abstract class DBObject implements iDisplay
{
return array_key_exists($sSection, $this->aContext);
}
/**
* @param string $sAttCode
*
* @return void
* @throws CoreException
* @throws OQLException
*/
private function UpdateDependentComputedAttributes(string $sAttCode): void
{
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode) {
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sCode);
if ($oAttDef->IsComputed()) {
$oExpression = Expression::FromOQL($oAttDef->GetParams()['expression']);
$this->_Set($sCode, $this->EvaluateExpression($oExpression));
}
}
}
}

View File

@@ -2661,7 +2661,6 @@ abstract class MetaModel
*/
public static function GetAttributeFlags($sClass, $sState, $sAttCode)
{
$iFlags = 0; // By default (if no life cycle) no flag at all
if (self::HasLifecycle($sClass)) {
$aStates = MetaModel::EnumStates($sClass);
if (!array_key_exists($sState, $aStates)) {

View File

@@ -2134,6 +2134,7 @@ EOF
$this->CompileCommonProperty('default_value', $oField, $aParameters, $sModuleRelativeDir, '');
$this->CompileCommonProperty('is_null_allowed', $oField, $aParameters, $sModuleRelativeDir, false);
$this->CompileCommonProperty('allowed_values', $oField, $aParameters, $sModuleRelativeDir);
$this->CompileCommonProperty('computed', $oField, $aParameters, $sModuleRelativeDir, false);
$aParameters['depends_on'] = $sDependencies;
} elseif ($sAttType == 'AttributeEnum') {
$this->CompileAttributeEnumValues($sModuleRelativeDir, $sClass, $sAttCode, $oField, $aParameters, $sCss);
@@ -2141,6 +2142,7 @@ EOF
$this->CompileCommonProperty('sql', $oField, $aParameters, $sModuleRelativeDir);
$this->CompileCommonProperty('default_value', $oField, $aParameters, $sModuleRelativeDir, '');
$this->CompileCommonProperty('is_null_allowed', $oField, $aParameters, $sModuleRelativeDir, false);
$this->CompileCommonProperty('computed', $oField, $aParameters, $sModuleRelativeDir, false);
$aParameters['depends_on'] = $sDependencies;
} elseif ($sAttType == 'AttributeMetaEnum') {
$this->CompileAttributeEnumValues($sModuleRelativeDir, $sClass, $sAttCode, $oField, $aParameters, $sCss);
@@ -2269,6 +2271,7 @@ EOF
$this->CompileCommonProperty('is_null_allowed', $oField, $aParameters, $sModuleRelativeDir, false);
$this->CompileCommonProperty('default_value', $oField, $aParameters, $sModuleRelativeDir, '');
$this->CompileCommonProperty('allowed_values', $oField, $aParameters, $sModuleRelativeDir);
$this->CompileCommonProperty('computed', $oField, $aParameters, $sModuleRelativeDir, false);
$aParameters['depends_on'] = $sDependencies;
}
@@ -2413,7 +2416,19 @@ EOF
}
$aParameters['thresholds'] = 'array('.implode(', ', $aThresholds).')';
break;
case 'computed':
$oComputed = $oField->GetOptionalElement('computed');
if(is_null($oComputed)) {
break;
}
$sExpression = self::QuoteForPHP($oComputed->GetChildText('expression'));
if(is_null($sExpression) || $sExpression === '') {
throw new DOMFormatException("missing (or empty) mandatory tag expression under the tag '".$oField->nodeName."'");
}
$aParameters['expression'] = $sExpression;
break;
default:
return false;
}