diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 0a5af24a8..799623557 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -6529,37 +6529,46 @@ class AttributeDateTime extends AttributeDBField } } - /** - * @inheritDoc - * - * @param int|string $proposedValue timestamp ({@see DateTime::getTimestamp()) or date as string, following the {@see GetInternalFormat} format. - */ + /** + * @inheritDoc + * + * @param int|DateTime|string $proposedValue possible values : + * - timestamp ({@see DateTime::getTimestamp()) + * - {@see \DateTime} PHP object + * - string, following the {@see GetInternalFormat} format. + * + * @throws \CoreUnexpectedValue if invalid value type or the string passed cannot be converted + */ public function MakeRealValue($proposedValue, $oHostObj) { if (is_null($proposedValue)) { return null; } - if (is_string($proposedValue) && ($proposedValue == "") && $this->IsNullAllowed()) - { - return null; + + if (is_numeric($proposedValue)) { + return date(static::GetInternalFormat(), $proposedValue); } - if (!is_numeric($proposedValue)) - { - // Check the format - try - { - $oFormat = new DateTimeFormat($this->GetInternalFormat()); + + if (is_object($proposedValue) && ($proposedValue instanceof DateTime)) { + return $proposedValue->format(static::GetInternalFormat()); + } + + if (is_string($proposedValue)) { + if (($proposedValue === '') && $this->IsNullAllowed()) { + return null; + } + try { + $oFormat = new DateTimeFormat(static::GetInternalFormat()); $oFormat->Parse($proposedValue); - } catch (Exception $e) - { - throw new Exception('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"'); + } catch (Exception $e) { + throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"'); } return $proposedValue; } - return date(static::GetInternalFormat(), $proposedValue); + throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode()); } public function ScalarToSQL($value) diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 7a850dba1..757508dc2 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -4745,7 +4745,7 @@ abstract class DBObject implements iDisplay } } $oDate->modify($sModifier); - $this->Set($sAttCode, $oDate->getTimestamp()); + $this->Set($sAttCode, $oDate); } /** diff --git a/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php b/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php index 94111d6eb..2c5eaa0d8 100644 --- a/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php +++ b/tests/php-unit-tests/unitary-tests/core/DBObjectTest.php @@ -20,9 +20,11 @@ namespace Combodo\iTop\Test\UnitTest\Core; use Attachment; +use AttributeDateTime; use Combodo\iTop\Service\Events\EventData; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; use CoreException; +use DateTime; use DBObject; use InvalidExternalKeyValueException; use lnkContactToFunctionalCI; @@ -412,7 +414,55 @@ class DBObjectTest extends ItopDataTestCase $oObject->Set('org_id', 3); $this->assertDBQueryCount(1, function() use (&$oObject){ static::assertNotEmpty($oObject->Get('org_name')); - }); } + }); + } + + /** + * @covers AttributeDateTime::MakeRealValue + */ + public function testSetAttributeDateTimeWithTimestamp(): void + { + $oUserRequest = $this->CreateUserRequest(0); + $iNow = time(); + $oMyDate = new DateTime('2024-02-14 18:12'); + $sMyDate = $oMyDate->format(AttributeDateTime::GetInternalFormat()); + + // First test string obtained with Get() converts into a standard DateTime object + $oUserRequest->Set('start_date', $iNow); + $sSavedDate = $oUserRequest->Get('start_date'); + $oSavedDate = new DateTime($sSavedDate); + $this->assertSame($iNow, $oSavedDate->getTimestamp()); + + // Second test that string obtained with Get() is of the \AttributeDateTime::GetInternalFormat format + $oUserRequest->Set('start_date', $oMyDate->getTimestamp()); + $this->assertEquals($sMyDate, $oUserRequest->Get('start_date')); + } + + /** + * @covers AttributeDateTime::MakeRealValue + */ + public function testSetAttributeDateTimeWithString(): void + { + $oUserRequest = $this->CreateUserRequest(0); + $oMyDate = new DateTime('2024-02-14 18:12'); + $sMyDate = $oMyDate->format(AttributeDateTime::GetInternalFormat()); + + $oUserRequest->Set('start_date', $sMyDate); + $this->assertEquals($sMyDate, $oUserRequest->Get('start_date')); + } + + /** + * @covers AttributeDateTime::MakeRealValue + */ + public function testSetAttributeDateTimeWithDateTime(): void + { + $oUserRequest = $this->CreateUserRequest(0); + $oMyDate = new DateTime('2024-02-14 18:12'); + $sMyDate = $oMyDate->format(AttributeDateTime::GetInternalFormat()); + + $oUserRequest->Set('start_date', $oMyDate); + $this->assertEquals($sMyDate, $oUserRequest->Get('start_date')); + } /** * @group Integration diff --git a/tests/php-unit-tests/unitary-tests/webservices/ImportTest.php b/tests/php-unit-tests/unitary-tests/webservices/ImportTest.php index 08663eed3..725f7ead0 100644 --- a/tests/php-unit-tests/unitary-tests/webservices/ImportTest.php +++ b/tests/php-unit-tests/unitary-tests/webservices/ImportTest.php @@ -127,7 +127,7 @@ class ImportTest extends ItopDataTestCase { '"first_name","name", "email", "org_id->name", obsolescence_date', sprintf('"%s", "%s", "%s", UID, toto', $sFirstName, $sLastName, $sEmail), sprintf( - 'Issue: Internal error: Exception, Wrong format for date attribute obsolescence_date, expecting "Y-m-d" and got "toto";n/a;n/a;n/a;%s;%s;%s;toto', $sFirstName, $sLastName, $sEmail + 'Issue: Internal error: CoreUnexpectedValue, Wrong format for date attribute obsolescence_date, expecting "Y-m-d" and got "toto";n/a;n/a;n/a;%s;%s;%s;toto', $sFirstName, $sLastName, $sEmail ), null, 1, @@ -174,7 +174,7 @@ CSVFILE; foreach (["ORGID" => $iOrgId, "UID" => $this->sUid] as $sSearch => $sReplace){ $sLastLineNeedle = str_replace($sSearch, $sReplace, $sLastLineNeedle); } - $this->assertStringContainsString($sLastLineNeedle, $sLastline, $sLastline); + $this->assertStringContainsString($sLastLineNeedle, $sLastline, 'The script we launched in an external process returned a value different than the expected error message'); $sPattern = "/Person;(\d+);/"; if (preg_match($sPattern,$sLastline,$aMatches)){