From 29c75f626b1ae9a6000c6123d80b56658d658a9b Mon Sep 17 00:00:00 2001 From: jf-cbd Date: Thu, 13 Mar 2025 15:29:00 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B08259=20-=20Problem=20with=20GetMaxSize?= =?UTF-8?q?=20on=20AttributeText?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/attributedef.class.inc.php | 2 +- core/dbobject.class.php | 26 +++++++++++++++--- .../core/AttributeDefinitionTest.php | 27 +++++++++++++++++++ .../core/DBObject/DBObjectTest.php | 19 +++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 1295bdcc1..5633dae89 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -4440,7 +4440,7 @@ class AttributeText extends AttributeString { // Is there a way to know the current limitation for mysql? // See mysql_field_len() - return 65535; + return 16383; // number of characters (that can be 1-4 bytes long), not of bytes } public static function RenderWikiHtml($sText, $bWikiOnly = false) diff --git a/core/dbobject.class.php b/core/dbobject.class.php index fec3d472a..4068819e8 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -760,10 +760,10 @@ abstract class DBObject implements iDisplay */ public function SetTrim($sAttCode, $sValue) { - $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); - $iMaxSize = $oAttDef->GetMaxSize(); - $sLength = mb_strlen($sValue); - if ($iMaxSize && ($sLength > $iMaxSize)) { + if (!$this->StringFitsInField($sAttCode, $sValue)) { + $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); + $iMaxSize = $oAttDef->GetMaxSize(); + $sLength = mb_strlen($sValue); $sMessage = " -truncated ($sLength chars)"; $sValue = mb_substr($sValue, 0, $iMaxSize - mb_strlen($sMessage)).$sMessage; } @@ -818,6 +818,24 @@ abstract class DBObject implements iDisplay $oKPI->ComputeStatsForExtension($this, 'AfterDelete'); } + /** + * @param string $sAttCode + * @param string $sValue + * + * @return bool + * @throws \Exception + * + * @Since 3.2.2 + */ + public function StringFitsInField(string $sAttCode, string $sValue): bool + { + $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode); + $iMaxSize = $oAttDef->GetMaxSize(); + $sLength = mb_strlen($sValue); + + return !($iMaxSize && ($sLength > $iMaxSize)); + } + /** * Compute (and optionally start) the StopWatches deadlines * diff --git a/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php b/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php index 047f39462..58881762e 100644 --- a/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php +++ b/tests/php-unit-tests/unitary-tests/core/AttributeDefinitionTest.php @@ -2,11 +2,19 @@ namespace Combodo\iTop\Test\UnitTest\Core; +use ArchivedObjectException; use AttributeDate; use AttributeDateTime; use Change; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; +use CoreCannotSaveObjectException; +use CoreException; +use CoreUnexpectedValue; +use CoreWarning; +use EventRestService; use MetaModel; +use MySQLException; +use OQLException; use UserRequest; class AttributeDefinitionTest extends ItopDataTestCase { @@ -343,4 +351,23 @@ PHP return $oAttribute; } + /** + * @throws CoreException + * @throws CoreUnexpectedValue + * @throws OQLException + * @throws ArchivedObjectException + * @throws CoreCannotSaveObjectException + * @throws CoreWarning + * @throws MySQLException + */ + public function testTrimLogOnAttributeText() + { + // will throw MySQLException if GetMaxSize() of AttributeText is incorrect (should be number of bytes, not of characters) + $oLog = new EventRestService(); + $sLongString = json_encode(array_fill(0, 5000, 'é😃 '), + JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + $oLog->SetTrim('json_input', $sLongString); + static::assertNotEquals($oLog->Get('json_input'), $sLongString); + static::assertStringContainsString('truncated', $oLog->Get('json_input')); + } } \ No newline at end of file diff --git a/tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php b/tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php index 7c97e4044..92ac10703 100644 --- a/tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php +++ b/tests/php-unit-tests/unitary-tests/core/DBObject/DBObjectTest.php @@ -22,6 +22,7 @@ namespace Combodo\iTop\Test\UnitTest\Core; use Attachment; use AttributeDateTime; use Combodo\iTop\Service\Events\EventData; +use EventRestService; use Combodo\iTop\Test\UnitTest\ItopDataTestCase; use CoreException; use DateTime; @@ -1415,4 +1416,22 @@ class DBObjectTest extends ItopDataTestCase $this->assertEquals("2024-01-15 09:45:00", $oObject->Get('end_date'), 'SetComputedDate +2 weeks on a WorkOrder DateTimeAttribute'); } + + public function testStringFitsInField() + { + //🎁 character is 4 bytes long + $sTooLongText = str_repeat('🎁', 17000); + $oLog = new EventRestService(); + $this->assertFalse($oLog->StringFitsInField('json_output', $sTooLongText)); + + $sCorrectLengthText = str_repeat('🎁', 16383); + $this->assertTrue($oLog->StringFitsInField('json_output', $sCorrectLengthText)); + + + $sCorrectLengthString = str_repeat('🎁', 255); + $this->assertTrue($oLog->StringFitsInField('operation', $sCorrectLengthString)); + + $sTooLongString = str_repeat('🎁', 256); + $this->assertFalse($oLog->StringFitsInField('operation', $sTooLongString)); + } }