diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 4493ade73..a6642306d 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -6040,6 +6040,10 @@ class AttributeTagSet extends AttributeDBFieldVoid public function IsNull($proposedValue) { + if (is_null($proposedValue)) + { + return true; + } /** @var \ormTagSet $proposedValue */ return count($proposedValue->GetValue()) == 0; } diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index 79718081a..026789f57 100644 --- a/core/dbobjectset.class.php +++ b/core/dbobjectset.class.php @@ -815,8 +815,8 @@ class DBObjectSet implements iDBObjectSetIterator if ($resQuery) { $aRow = CMDBSource::FetchArray($resQuery); - CMDBSource::FreeResult($resQuery); $iCount = intval($aRow['COUNT']); + CMDBSource::FreeResult($resQuery); } else { diff --git a/core/tagsetfield.class.inc.php b/core/tagsetfield.class.inc.php index b765bd7e3..3970d04b5 100644 --- a/core/tagsetfield.class.inc.php +++ b/core/tagsetfield.class.inc.php @@ -102,22 +102,24 @@ abstract class TagSetFieldData extends cmdbAbstractObject /** * @param \DeletionPlan $oDeletionPlan * - * @return bool * @throws \CoreException */ public function DoCheckToDelete(&$oDeletionPlan) { + parent::DoCheckToDelete($oDeletionPlan); + $sTagCode = $this->Get('tag_code'); $sClass = $this->Get('tag_class'); $sAttCode = $this->Get('tag_attcode'); $oSearch = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'"); $oSet = new DBObjectSet($oSearch); - if ($oSet->CountExceeds(1)) + if ($oSet->CountExceeds(0)) { $this->m_aDeleteIssues[] = Dict::S('Core:TagSetFieldData:ErrorDeleteUsedTag'); } - - return parent::DoCheckToDelete($oDeletionPlan); + // Clear cache + $sTagDataClass = MetaModel::GetTagDataClass($sClass, $sAttCode); + unset(self::$m_aAllowedValues[$sTagDataClass]); } public function DoCheckToWrite() @@ -127,12 +129,24 @@ abstract class TagSetFieldData extends cmdbAbstractObject $sTagLabel = $this->Get('tag_label'); $id = $this->GetKey(); $sClassName = get_class($this); - $oSearch = DBSearch::FromOQL("SELECT $sClassName WHERE id != $id AND (tag_code = '$sTagCode' OR tag_label = '$sTagLabel')"); + if (empty($id)) + { + $oSearch = DBSearch::FromOQL("SELECT $sClassName WHERE (tag_code = '$sTagCode' OR tag_label = '$sTagLabel')"); + } + else + { + $oSearch = DBSearch::FromOQL("SELECT $sClassName WHERE id != $id AND (tag_code = '$sTagCode' OR tag_label = '$sTagLabel')"); + } $oSet = new DBObjectSet($oSearch); - if ($oSet->CountExceeds(1)) + if ($oSet->CountExceeds(0)) { $this->m_aCheckIssues[] = Dict::S('Core:TagSetFieldData:ErrorDuplicateTagCodeOrLabel'); } + // Clear cache + $sClass = $this->Get('tag_class'); + $sAttCode = $this->Get('tag_attcode'); + $sTagDataClass = MetaModel::GetTagDataClass($sClass, $sAttCode); + unset(self::$m_aAllowedValues[$sTagDataClass]); parent::DoCheckToWrite(); } diff --git a/test/ItopDataTestCase.php b/test/ItopDataTestCase.php index bccbe4021..737b7d236 100644 --- a/test/ItopDataTestCase.php +++ b/test/ItopDataTestCase.php @@ -51,7 +51,11 @@ use VirtualMachine; */ class ItopDataTestCase extends ItopTestCase { - protected $testOrgId; + private $iTestOrgId; + // For cleanup + private $aCreatedObjects = array(); + + const USE_TRANSACTION = true; /** * @throws Exception @@ -68,11 +72,11 @@ class ItopDataTestCase extends ItopTestCase $sConfigFile = APPCONF.$sEnv.'/'.ITOP_CONFIG_FILE; MetaModel::Startup($sConfigFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sEnv); - CMDBSource::Query('START TRANSACTION'); - - // Create a specific organization for the tests - $oOrg = $this->CreateOrganization('UnitTestOrganization'); - $this->testOrgId = $oOrg->GetKey(); + if (static::USE_TRANSACTION) + { + CMDBSource::Query('START TRANSACTION'); + } + $this->CreateTestOrganization(); } /** @@ -80,7 +84,30 @@ class ItopDataTestCase extends ItopTestCase */ protected function tearDown() { - CMDBSource::Query('ROLLBACK'); + if (static::USE_TRANSACTION) + { + $this->debug("ROLLBACK !!!"); + CMDBSource::Query('ROLLBACK'); + } + else + { + $this->debug(""); + $this->aCreatedObjects = array_reverse($this->aCreatedObjects); + foreach($this->aCreatedObjects as $oObject) + { + /** @var DBObject $oObject */ + try + { + $sClass = get_class($oObject); + $iKey = $oObject->GetKey(); + $this->debug("Removing $sClass::$iKey"); + $oObject->DBDelete(); + } catch (Exception $e) + { + $this->debug($e->getMessage()); + } + } + } } /** @@ -88,7 +115,7 @@ class ItopDataTestCase extends ItopTestCase */ public function getTestOrgId() { - return $this->testOrgId; + return $this->iTestOrgId; } ///////////////////////////////////////////////////////////////////////////// @@ -101,7 +128,7 @@ class ItopDataTestCase extends ItopTestCase * @return DBObject * @throws Exception */ - protected static function createObject($sClass, $aParams) + protected function createObject($sClass, $aParams) { $oMyObj = MetaModel::NewObject($sClass); foreach($aParams as $sAttCode => $oValue) @@ -109,6 +136,9 @@ class ItopDataTestCase extends ItopTestCase $oMyObj->Set($sAttCode, $oValue); } $oMyObj->DBInsert(); + $iKey = $oMyObj->GetKey(); + $this->debug("Created $sClass::$iKey"); + $this->aCreatedObjects[] = $oMyObj; return $oMyObj; } @@ -137,16 +167,16 @@ class ItopDataTestCase extends ItopTestCase * Create an Organization in database * * @param string $sName - * @return Organization + * @return \Organization * @throws Exception */ protected function CreateOrganization($sName) { - /** @var Organization $oObj */ - $oObj = self::createObject('Organization', array( + /** @var \Organization $oObj */ + $oObj = $this->createObject('Organization', array( 'name' => $sName, )); - $this->debug("\nCreated Organization {$oObj->Get('name')}"); + $this->debug("Created Organization {$oObj->Get('name')}"); return $oObj; } @@ -160,45 +190,81 @@ class ItopDataTestCase extends ItopTestCase protected function CreateTicket($iNum) { /** @var Ticket $oTicket */ - $oTicket = self::createObject('UserRequest', array( + $oTicket = $this->createObject('UserRequest', array( 'ref' => 'Ticket_'.$iNum, - 'title' => 'BUG 789_'.$iNum, + 'title' => 'TICKET_'.$iNum, //'request_type' => 'incident', - 'description' => 'method UpdateImpactedItems() reconstruit le lnkContactToTicket donc impossible de rajouter des champs dans cette classe', + 'description' => 'Created for unit tests.', 'org_id' => $this->getTestOrgId(), )); - $this->debug("\nCreated {$oTicket->Get('title')} ({$oTicket->Get('ref')})"); + $this->debug("Created {$oTicket->Get('title')} ({$oTicket->Get('ref')})"); return $oTicket; } - /** - * Create a Ticket in database - * - * @param string $sClass - * @param string $sAttCode - * @param string $sTagCode - * @param string $sTagLabel - * @param string $sTagDescription - * - * @return \TagSetFieldData - * @throws \CoreException - */ - protected function CreateTagData($sClass, $sAttCode, $sTagCode, $sTagLabel, $sTagDescription = '') + protected function RemoveTicket($iNum) { - $sTagClass = MetaModel::GetTagDataClass($sClass, $sAttCode); - $oTagData = self::createObject($sTagClass, array( - 'tag_code' => $sTagCode, - 'tag_label' => $sTagLabel, - 'tag_class' => $sClass, - 'tag_attcode' => $sAttCode, - 'tag_description' => $sTagDescription, - )); - $this->debug("\nCreated {$oTagData->Get('tag_code')} ({$oTagData->Get('tag_label')})"); - - /** @var \TagSetFieldData $oTagData */ - return $oTagData; + $this->RemoveObjects('UserRequest', "SELECT UserRequest WHERE ref = 'Ticket_$iNum'"); } + /** + * Create a Ticket in database + * + * @param string $sClass + * @param string $sAttCode + * @param string $sTagCode + * @param string $sTagLabel + * @param string $sTagDescription + * + * @return \TagSetFieldData + * @throws \CoreException + */ + protected function CreateTagData($sClass, $sAttCode, $sTagCode, $sTagLabel, $sTagDescription = '') + { + $sTagClass = MetaModel::GetTagDataClass($sClass, $sAttCode); + $oTagData = $this->createObject($sTagClass, array( + 'tag_code' => $sTagCode, + 'tag_label' => $sTagLabel, + 'tag_class' => $sClass, + 'tag_attcode' => $sAttCode, + 'tag_description' => $sTagDescription, + )); + $this->debug("Created {$oTagData->Get('tag_code')} ({$oTagData->Get('tag_label')})"); + + /** @var \TagSetFieldData $oTagData */ + return $oTagData; + } + + /** + * Create a Ticket in database + * + * @param string $sClass + * @param string $sAttCode + * @param string $sTagCode + * + * @throws \CoreException + */ + protected function RemoveTagData($sClass, $sAttCode, $sTagCode) + { + $sTagClass = MetaModel::GetTagDataClass($sClass, $sAttCode); + $this->RemoveObjects($sTagClass, "SELECT $sTagClass WHERE tag_code = '$sTagCode'"); + } + + private function RemoveObjects($sClass, $sOQL) + { + $oFilter = \DBSearch::FromOQL($sOQL); + $aRes = $oFilter->ToDataArray(array('id')); + foreach($aRes as $aRow) + { + $this->debug($aRow); + $iKey = $aRow['id']; + if (!empty($iKey)) + { + $oObject = MetaModel::GetObject($sClass, $iKey); + $oObject->DBDelete(); + } + } + } + /** * Create a UserRequest in database * @@ -206,13 +272,13 @@ class ItopDataTestCase extends ItopTestCase * @param int $iTimeSpent * @param int $iOrgId * @param int $iCallerId - * @return UserRequest + * @return \UserRequest * @throws Exception */ protected function CreateUserRequest($iNum, $iTimeSpent = 0, $iOrgId = 0, $iCallerId = 0) { - /** @var UserRequest $oTicket */ - $oTicket = self::createObject('UserRequest', array( + /** @var \UserRequest $oTicket */ + $oTicket = $this->createObject('UserRequest', array( 'ref' => 'Ticket_'.$iNum, 'title' => 'BUG 1161_'.$iNum, //'request_type' => 'incident', @@ -221,7 +287,7 @@ class ItopDataTestCase extends ItopTestCase 'caller_id' => $iCallerId, 'org_id' => ($iOrgId == 0 ? $this->getTestOrgId() : $iOrgId), )); - $this->debug("\nCreated {$oTicket->Get('title')} ({$oTicket->Get('ref')})"); + $this->debug("Created {$oTicket->Get('title')} ({$oTicket->Get('ref')})"); return $oTicket; } @@ -237,7 +303,7 @@ class ItopDataTestCase extends ItopTestCase protected function CreateServer($iNum, $iRackUnit = null) { /** @var Server $oServer */ - $oServer = self::createObject('Server', array( + $oServer = $this->createObject('Server', array( 'name' => 'Server_'.$iNum, 'org_id' => $this->getTestOrgId(), 'nb_u' => $iRackUnit, @@ -256,7 +322,7 @@ class ItopDataTestCase extends ItopTestCase */ protected function CreatePhysicalInterface($iNum, $iSpeed, $iConnectableCiId) { - $oObj = self::createObject('PhysicalInterface', array( + $oObj = $this->createObject('PhysicalInterface', array( 'name' => "$iNum", 'speed' => $iSpeed, 'connectableci_id' => $iConnectableCiId, @@ -275,7 +341,7 @@ class ItopDataTestCase extends ItopTestCase */ protected function CreateFiberChannelInterface($iNum, $iSpeed, $iConnectableCiId) { - $oObj = self::createObject('FiberChannelInterface', array( + $oObj = $this->createObject('FiberChannelInterface', array( 'name' => "$iNum", 'speed' => $iSpeed, 'datacenterdevice_id' => $iConnectableCiId, @@ -294,7 +360,7 @@ class ItopDataTestCase extends ItopTestCase protected function CreatePerson($iNum, $iOrgId = 0) { /** @var Person $oPerson */ - $oPerson = self::createObject('Person', array( + $oPerson = $this->createObject('Person', array( 'name' => 'Person_'.$iNum, 'first_name' => 'Test', 'org_id' => ($iOrgId == 0 ? $this->getTestOrgId() : $iOrgId), @@ -315,7 +381,7 @@ class ItopDataTestCase extends ItopTestCase $oUserProfile->Set('profileid', $iProfileId); $oUserProfile->Set('reason', 'UNIT Tests'); $oSet = DBObjectSet::FromObject($oUserProfile); - $oUser = self::createObject('UserLocal', array( + $oUser = $this->createObject('UserLocal', array( 'contactid' => 2, 'login' => $sLogin, 'password' => $sLogin, @@ -338,7 +404,7 @@ class ItopDataTestCase extends ItopTestCase protected function CreateHypervisor($iNum, $oServer, $oFarm = null) { /** @var Hypervisor $oHypervisor */ - $oHypervisor = self::createObject('Hypervisor', array( + $oHypervisor = $this->createObject('Hypervisor', array( 'name' => 'Hypervisor_'.$iNum, 'org_id' => $this->getTestOrgId(), 'server_id' => $oServer->GetKey(), @@ -365,7 +431,7 @@ class ItopDataTestCase extends ItopTestCase protected function CreateFarm($iNum, $sRedundancy = '1') { /** @var Farm $oFarm */ - $oFarm = self::createObject('Farm', array( + $oFarm = $this->createObject('Farm', array( 'name' => 'Farm_'.$iNum, 'org_id' => $this->getTestOrgId(), 'redundancy' => $sRedundancy, @@ -384,7 +450,7 @@ class ItopDataTestCase extends ItopTestCase protected function CreateVirtualMachine($iNum, $oVirtualHost) { /** @var VirtualMachine $oVirtualMachine */ - $oVirtualMachine = self::createObject('VirtualMachine', array( + $oVirtualMachine = $this->createObject('VirtualMachine', array( 'name' => 'VirtualMachine_'.$iNum, 'org_id' => $this->getTestOrgId(), 'virtualhost_id' => $oVirtualHost->GetKey(), @@ -537,13 +603,15 @@ class ItopDataTestCase extends ItopTestCase } } - /** - * Reload a Ticket from the database. - * - * @param DBObject $oObject - * @throws ArchivedObjectException - * @throws Exception - */ + /** + * Reload a Ticket from the database. + * + * @param DBObject $oObject + * + * @return \DBObject|null + * @throws ArchivedObjectException + * @throws Exception + */ protected function ReloadObject(&$oObject) { $oObject = MetaModel::GetObject(get_class($oObject), $oObject->GetKey()); @@ -601,5 +669,12 @@ class ItopDataTestCase extends ItopTestCase } } + protected function CreateTestOrganization() + { + // Create a specific organization for the tests + $oOrg = $this->CreateOrganization('UnitTestOrganization'); + $this->iTestOrgId = $oOrg->GetKey(); + } + } \ No newline at end of file diff --git a/test/core/TagSetFieldDataTest.php b/test/core/TagSetFieldDataTest.php new file mode 100644 index 000000000..d7fb057da --- /dev/null +++ b/test/core/TagSetFieldDataTest.php @@ -0,0 +1,94 @@ +debug("Currently $iInitialCount tags defined"); + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag2', 'Second'); + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag3', 'Third'); + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag4', 'Fourth'); + $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); + $iCurrCount = count($aAllowedValues); + static::assertEquals(4, $iCurrCount - $iInitialCount); + + try + { + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag4', 'Fourth'); + } catch (\CoreException $e) + { + $this->debug($e->getMessage()); + } + $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); + $iCurrCount = count($aAllowedValues); + static::assertEquals(4, $iCurrCount - $iInitialCount); + + try + { + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag4', 'zembrek'); + } catch (\CoreException $e) + { + $this->debug($e->getMessage()); + } + $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); + $iCurrCount = count($aAllowedValues); + static::assertEquals(4, $iCurrCount - $iInitialCount); + + try + { + $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag5', 'Fourth'); + } catch (\CoreException $e) + { + $this->debug($e->getMessage()); + } + $aAllowedValues = TagSetFieldData::GetAllowedValues(TAG_CLASS, TAG_ATTCODE); + $iCurrCount = count($aAllowedValues); + static::assertEquals(4, $iCurrCount - $iInitialCount); + } + + /** + * @expectedException \CoreException + * + * @throws \CoreException + * @throws \CoreUnexpectedValue + */ + public function testDoCheckToDelete() + { + $oTagData = $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); + $oTagData->DBDelete(); + $oTagData = $this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First'); + $oTicket = $this->CreateTicket(1); + $oTicket->Set(TAG_ATTCODE, 'tag1'); + $oTicket->DBWrite(); + $oTagData->DBDelete($oDeletionPlan); + } + + public function testComputeValues() + { + } + + public function testGetAllowedValues() + { + + } +}