This commit is contained in:
Eric Espie
2026-08-18 16:01:47 +02:00
parent 1bddb7cfd8
commit eb2dcbc425
5 changed files with 112 additions and 6 deletions

View File

@@ -40,7 +40,7 @@ class DBObjectSet implements iDBObjectSetIterator
/**
* @var array
*/
protected $m_aAttToLoad;
public $m_aAttToLoad;
/**
* @var null|array
*/

View File

@@ -1645,7 +1645,7 @@ abstract class MetaModel
if (array_key_exists($sClass, self::$m_aMagicFields) && in_array($sFilterCode, self::$m_aMagicFields[$sClass])) {
return true;
}
if (array_key_exists($sClass, self::$m_aFilterForbiddenAttributes) && array_key_exists($sFilterCode, self::$m_aFilterForbiddenAttributes[$sClass])) {
if (array_key_exists($sClass, self::$m_aFilterForbiddenAttributes) && in_array($sFilterCode, self::$m_aFilterForbiddenAttributes[$sClass])) {
return false;
}
return self::IsValidAttCode($sClass, $sFilterCode);
@@ -2963,7 +2963,7 @@ abstract class MetaModel
self::$m_aMagicFields[] = $sClass;
}
self::$m_aMagicFields[$sClass][] = $sCode;
self::$m_aAttribOrigins[$sClass][$sCode] = self::$m_aAttribOrigins[$sClass][$sAttCode] ;
//self::$m_aAttribOrigins[$sClass][$sCode] = self::$m_aAttribOrigins[$sClass][$sAttCode];
}
if (!$oAttDef->IsSearchable()) {
if (!array_key_exists($sClass, self::$m_aFilterForbiddenAttributes)) {

View File

@@ -60,15 +60,13 @@ class OQLActualClassTreeResolver
$aTranslateFields = [];
foreach ($aExpectedAttributes as $sAttCode => $oExpression) {
// 'id' is managed later
if ($sAttCode == 'id') {
if ($sAttCode === 'id') {
continue;
}
// Attributes can be stored in attributes list or for magic ones into filter codes list.
$sOriginClass = null;
if (MetaModel::IsValidAttCode($sClass, $sAttCode) || MetaModel::IsValidFilterCode($sClass, $sAttCode)) {
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
} elseif ($sAttCode == 'id') {
$sOriginClass = MetaModel::GetRootClass($sClass);
} else {
continue;
}

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<classes>
<class id="OQLResolverParent" _created_in="itop-structure" _delta="define">
<parent>cmdbAbstractObject</parent>
<properties>
<category>bizmodel</category>
<abstract>true</abstract>
<key_type>autoincrement</key_type>
<db_table>oqlresolverparent</db_table>
<db_key_field>id</db_key_field>
<fields_semantic>
<state_attribute>status</state_attribute>
</fields_semantic>
</properties>
<presentation/>
<methods/>
<fields>
<field id="cumulatedpending" xsi:type="AttributeStopWatch">
<states>
<state id="pending"/>
</states>
<working_time/>
<thresholds/>
<goal/>
</field><field id="status" xsi:type="AttributeEnum">
<always_load_in_tables>true</always_load_in_tables>
<sort_type>rank</sort_type>
<values>
<value id="new">
<code>new</code>
</value>
<value id="pending">
<code>pending</code>
</value>
</values>
<sql>status</sql>
<default_value>new</default_value>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
</class>
<class id="OQLResolverChild" _created_in="itop-structure" _delta="define">
<parent>OQLResolverParent</parent>
<properties>
<category>bizmodel</category>
<abstract>false</abstract>
<key_type>autoincrement</key_type>
<db_table>oqlresolverchild</db_table>
<db_key_field>id</db_key_field>
</properties>
<presentation/>
<methods/>
<fields>
<field id="name" xsi:type="AttributeString">
<sql>name</sql>
<default_value/>
<is_null_allowed>false</is_null_allowed>
</field>
</fields>
</class>
</classes>
</itop_design>

View File

@@ -0,0 +1,43 @@
<?php
/*
* @copyright Copyright (C) 2010-2026 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopCustomDatamodelTestCase;
use DBObjectSet;
use DBSearch;
use MetaModel;
class OQLResolverTest extends ItopCustomDatamodelTestCase
{
public function GetDatamodelDeltaAbsPath(): string
{
return __DIR__.'/Delta/delta_oql_resolver.xml';
}
public function testQueryOnMagicalFields()
{
// Given
$sObjectKey = $this->GivenObjectInDB('OQLResolverChild', ['name' => 'toto', 'status' => 'new']);
$oObject = MetaModel::GetObject('OQLResolverChild', $sObjectKey);
// When actions ApplyStimulus then next action fails
$sFilter = "SELECT OQLResolverChild WHERE ISNULL(cumulatedpending_laststart)";
$oSearch = DBSearch::FromOQL($sFilter);
$oSet = new DBObjectSet($oSearch);
$oSet->OptimizeColumnLoad(['OQLResolverChild' => ['cumulatedpending']]);
$sQuery = $oSet->GetFilter()->MakeSelectQuery([], [], $oSet->m_aAttToLoad);
echo $sQuery."\n";
$oActual = $oSet->Fetch();
// Then
// Check status...
$this->assertEquals($oObject->Get('name'), $oActual->Get('name'), 'The query should have returned the object');
}
}