mirror of
https://github.com/Combodo/iTop.git
synced 2026-08-20 21:28:25 +02:00
WIP
This commit is contained in:
@@ -40,7 +40,7 @@ class DBObjectSet implements iDBObjectSetIterator
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $m_aAttToLoad;
|
||||
public $m_aAttToLoad;
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
43
tests/php-unit-tests/unitary-tests/core/OQLResolverTest.php
Normal file
43
tests/php-unit-tests/unitary-tests/core/OQLResolverTest.php
Normal 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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user