mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge remote-tracking branch 'origin/support/3.1' into develop
This commit is contained in:
@@ -3712,7 +3712,7 @@ HTML;
|
||||
if ($oAttDef->GetEditClass() == 'Document') {
|
||||
/** @var \ormDocument $oDocument */
|
||||
$oDocument = $this->Get($sAttCode);
|
||||
if (!$oDocument->IsEmpty()) {
|
||||
if (is_object($oDocument) && !$oDocument->IsEmpty()) {
|
||||
$sFieldAsHtml = $this->GetAsHTML($sAttCode);
|
||||
|
||||
$sDisplayLabel = Dict::S('UI:OpenDocumentInNewWindow_');
|
||||
|
||||
@@ -758,9 +758,10 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
$iMaxSize = $oAttDef->GetMaxSize();
|
||||
if ($iMaxSize && (strlen($sValue) > $iMaxSize))
|
||||
{
|
||||
$sValue = substr($sValue, 0, $iMaxSize);
|
||||
$sLength = mb_strlen($sValue);
|
||||
if ($iMaxSize && ($sLength > $iMaxSize)) {
|
||||
$sMessage = " -truncated ($sLength chars)";
|
||||
$sValue = mb_substr($sValue, 0, $iMaxSize - mb_strlen($sMessage)).$sMessage;
|
||||
}
|
||||
$this->Set($sAttCode, $sValue);
|
||||
}
|
||||
@@ -2112,33 +2113,26 @@ abstract class DBObject implements iDisplay
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($toCheck instanceof ormSet)
|
||||
{
|
||||
if ($toCheck instanceof ormSet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return "Bad type";
|
||||
}
|
||||
elseif ($oAtt->IsScalar())
|
||||
{
|
||||
} elseif ($oAtt->IsScalar()) {
|
||||
|
||||
$aValues = $oAtt->GetAllowedValues($this->ToArgsForQuery());
|
||||
if (is_array($aValues) && (count($aValues) > 0))
|
||||
{
|
||||
if (!array_key_exists($toCheck, $aValues))
|
||||
{
|
||||
if (is_array($aValues) && (count($aValues) > 0)) {
|
||||
if (!array_key_exists($toCheck, $aValues)) {
|
||||
return "Value not allowed [$toCheck]";
|
||||
}
|
||||
}
|
||||
if (!is_null($iMaxSize = $oAtt->GetMaxSize()))
|
||||
{
|
||||
$iLen = strlen($toCheck);
|
||||
if ($iLen > $iMaxSize)
|
||||
{
|
||||
if (!is_null($iMaxSize = $oAtt->GetMaxSize())) {
|
||||
$iLen = mb_strlen($toCheck);
|
||||
if ($iLen > $iMaxSize) {
|
||||
return "String too long (found $iLen, limited to $iMaxSize)";
|
||||
}
|
||||
}
|
||||
if (!$oAtt->CheckFormat($toCheck))
|
||||
{
|
||||
if (!$oAtt->CheckFormat($toCheck)) {
|
||||
return "Wrong format [$toCheck]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class DisplayableNode extends GraphNode
|
||||
|
||||
public function GetWidth()
|
||||
{
|
||||
return max(32, 5*strlen($this->GetProperty('label'))); // approximation of the text's bounding box
|
||||
return max(32, 5 * mb_strlen($this->GetProperty('label'))); // approximation of the text's bounding box
|
||||
}
|
||||
|
||||
public function GetHeight()
|
||||
@@ -494,7 +494,7 @@ class DisplayableNode extends GraphNode
|
||||
if ($bNoLabel)
|
||||
{
|
||||
// simulate a fake label with the approximate same size as the true label
|
||||
$sLabel = str_repeat('x',strlen($this->GetProperty('label', $this->GetId())));
|
||||
$sLabel = str_repeat('x', mb_strlen($this->GetProperty('label', $this->GetId())));
|
||||
$sDot = 'label="'.$sLabel.'"';
|
||||
}
|
||||
else
|
||||
|
||||
@@ -245,44 +245,33 @@ class EventIssue extends Event
|
||||
{
|
||||
if (is_string($sValue))
|
||||
{
|
||||
if (strlen($sValue) < 256)
|
||||
{
|
||||
if (mb_strlen($sValue) < 256) {
|
||||
$aPost[$sKey] = $sValue;
|
||||
} else {
|
||||
$aPost[$sKey] = "!long string: ".mb_strlen($sValue)." chars";
|
||||
}
|
||||
else
|
||||
{
|
||||
$aPost[$sKey] = "!long string: ".strlen($sValue). " chars";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Not a string (avoid warnings in case the value cannot be easily casted into a string)
|
||||
$aPost[$sKey] = @(string) $sValue;
|
||||
$aPost[$sKey] = @(string)$sValue;
|
||||
}
|
||||
}
|
||||
$this->Set('arguments_post', $aPost);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$this->Set('arguments_post', array());
|
||||
}
|
||||
|
||||
$sLength = strlen($this->Get('issue'));
|
||||
if ($sLength > 255)
|
||||
{
|
||||
$this->Set('issue', substr($this->Get('issue'), 0, 200)." -truncated ($sLength chars)");
|
||||
$sLength = mb_strlen($this->Get('issue'));
|
||||
if ($sLength > 255) {
|
||||
$this->Set('issue', mb_substr($this->Get('issue'), 0, 210)." -truncated ($sLength chars)");
|
||||
}
|
||||
|
||||
$sLength = strlen($this->Get('impact'));
|
||||
if ($sLength > 255)
|
||||
{
|
||||
$this->Set('impact', substr($this->Get('impact'), 0, 200)." -truncated ($sLength chars)");
|
||||
$sLength = mb_strlen($this->Get('impact'));
|
||||
if ($sLength > 255) {
|
||||
$this->Set('impact', mb_substr($this->Get('impact'), 0, 210)." -truncated ($sLength chars)");
|
||||
}
|
||||
|
||||
$sLength = strlen($this->Get('page'));
|
||||
if ($sLength > 255)
|
||||
{
|
||||
$this->Set('page', substr($this->Get('page'), 0, 200)." -truncated ($sLength chars)");
|
||||
$sLength = mb_strlen($this->Get('page'));
|
||||
if ($sLength > 255) {
|
||||
$this->Set('page', mb_substr($this->Get('page'), 0, 210)." -truncated ($sLength chars)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1932,17 +1932,13 @@ class SynchroLog extends DBObject
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'traces');
|
||||
$iMaxSize = $oAttDef->GetMaxSize();
|
||||
if (strlen($sPrevTrace) > 0)
|
||||
{
|
||||
if (strlen($sPrevTrace) > 0) {
|
||||
$sTrace = $sPrevTrace."\n".implode("\n", $this->m_aTraces);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sTrace = implode("\n", $this->m_aTraces);
|
||||
}
|
||||
if (strlen($sTrace) >= $iMaxSize)
|
||||
{
|
||||
$sTrace = substr($sTrace, 0, $iMaxSize - 255)."...\nTruncated (size: ".strlen($sTrace).')';
|
||||
if (mb_strlen($sTrace) >= $iMaxSize) {
|
||||
$sTrace = mb_substr($sTrace, 0, $iMaxSize - 40)."...\nTruncated (size: ".mb_strlen($sTrace).')';
|
||||
}
|
||||
$this->Set('traces', $sTrace);
|
||||
|
||||
@@ -2147,9 +2143,8 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
break;
|
||||
}
|
||||
|
||||
if (strlen($sWarningMessage) > $MAX_WARNING_LENGTH)
|
||||
{
|
||||
$sWarningMessage = substr($sWarningMessage, 0, $MAX_WARNING_LENGTH - 3).'...';
|
||||
if (mb_strlen($sWarningMessage) > $MAX_WARNING_LENGTH) {
|
||||
$sWarningMessage = mb_substr($sWarningMessage, 0, $MAX_WARNING_LENGTH - 3).'...';
|
||||
}
|
||||
|
||||
$this->Set('status_last_warning', $sWarningMessage);
|
||||
@@ -2189,17 +2184,13 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
|
||||
public function SetLastError($sMessage, $oException = null)
|
||||
{
|
||||
if ($oException)
|
||||
{
|
||||
if ($oException) {
|
||||
$sText = $sMessage.$oException->getMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sText = $sMessage;
|
||||
}
|
||||
if (strlen($sText) > 255)
|
||||
{
|
||||
$sText = substr($sText, 0, 200).'...('.strlen($sText).' chars)...';
|
||||
if (mb_strlen($sText) > 255) {
|
||||
$sText = mb_substr($sText, 0, 200).'...('.mb_strlen($sText).' chars)...';
|
||||
}
|
||||
$this->Set('status_last_error', $sText);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ use Organization;
|
||||
use Person;
|
||||
use Team;
|
||||
use User;
|
||||
use UserRequest;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
@@ -47,6 +48,7 @@ class DBObjectTest extends ItopDataTestCase
|
||||
// Counts
|
||||
public $aReloadCount = [];
|
||||
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
@@ -1199,7 +1201,7 @@ class DBObjectTest extends ItopDataTestCase
|
||||
{
|
||||
return $this->aReloadCount[$sClass][$sKey] ?? 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 3.1.0-3 3.1.1 3.2.0 N°6716 test creation
|
||||
*/
|
||||
@@ -1235,4 +1237,97 @@ class DBObjectTest extends ItopDataTestCase
|
||||
$fTotalDuration = microtime(true) - $fStart;
|
||||
echo 'Total duration: '.sprintf('%.3f s', $fTotalDuration)."\n\n";
|
||||
}
|
||||
|
||||
public function CheckLongValueInAttributeProvider() {
|
||||
return [
|
||||
// UserRequest.title is an AttributeString (maxsize = 255)
|
||||
'title 250 chars' => ['title', 250],
|
||||
'title 254 chars' => ['title', 254],
|
||||
'title 255 chars' => ['title', 255],
|
||||
'title 256 chars' => ['title', 256],
|
||||
'title 300 chars' => ['title', 300],
|
||||
|
||||
// UserRequest.solution is an AttributeText (maxsize=65535) with format=text
|
||||
'solution 250 chars' => ['solution', 250],
|
||||
'solution 60000 chars' => ['solution', 60000],
|
||||
'solution 65534 chars' => ['solution', 65534],
|
||||
'solution 65535 chars' => ['solution', 65535],
|
||||
'solution 65536 chars' => ['solution', 65536],
|
||||
'solution 70000 chars' => ['solution', 70000],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test check long field with non ascii characters
|
||||
*
|
||||
* @covers DBObject::Set
|
||||
* @covers DBObject::CheckToWrite
|
||||
* @covers DBObject::SetTrim
|
||||
*
|
||||
* @dataProvider CheckLongValueInAttributeProvider
|
||||
*
|
||||
* @since 3.1.2 N°3448 - Framework field size check not correctly implemented for multi-bytes languages/strings
|
||||
*/
|
||||
public function testCheckLongValueInAttribute(string $sAttrCode, int $iValueLength)
|
||||
{
|
||||
$sPrefix = 'a'; // just a small prefix so that the emoji bytes won't have a power of 2 (we want a non even value)
|
||||
$sEmojiToRepeat = '😎'; // this emoji is 4 bytes long
|
||||
$sEmojiRepeats = str_repeat($sEmojiToRepeat, $iValueLength - mb_strlen($sPrefix));
|
||||
$sValueToSet = $sPrefix . $sEmojiRepeats;
|
||||
|
||||
$oTicket = MetaModel::NewObject('UserRequest', [
|
||||
'ref' => 'Test Ticket',
|
||||
'title' => 'Create OK',
|
||||
'description' => 'Create OK',
|
||||
'caller_id' => 15,
|
||||
'org_id' => 3,
|
||||
]);
|
||||
|
||||
$oTicket->Set($sAttrCode, $sValueToSet);
|
||||
$sValueInObject = $oTicket->Get($sAttrCode);
|
||||
$this->assertSame($sValueToSet, $sValueInObject, 'Set should not alter the value even if the value is too long');
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef(UserRequest::class, $sAttrCode);
|
||||
$iAttrMaxSize = $oAttDef->GetMaxSize();
|
||||
$bIsValueToSetBelowAttrMaxSize = ($iValueLength <= $iAttrMaxSize);
|
||||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||||
[$bCheckStatus, $aCheckIssues, $bSecurityIssue] = $oTicket->CheckToWrite();
|
||||
$this->assertEquals($bIsValueToSetBelowAttrMaxSize, $bCheckStatus, "CheckResult result:" . var_export($aCheckIssues, true));
|
||||
|
||||
$oTicket->SetTrim($sAttrCode, $sValueToSet);
|
||||
$sValueInObject = $oTicket->Get($sAttrCode);
|
||||
if ($bIsValueToSetBelowAttrMaxSize) {
|
||||
$this->assertEquals($sValueToSet, $sValueInObject,'Should not alter string that is already shorter than attribute max length');
|
||||
} else {
|
||||
$this->assertEquals($iAttrMaxSize, mb_strlen($sValueInObject),'Should truncate at the same length than attribute max length');
|
||||
$sLastCharsOfValueInObject = mb_substr($sValueInObject, -30);
|
||||
$this->assertStringContainsString(' -truncated', $sLastCharsOfValueInObject, 'Should end with "truncated" comment');
|
||||
}
|
||||
}
|
||||
|
||||
public function SetTrimProvider()
|
||||
{
|
||||
return [
|
||||
'short string should not be truncated' => ['name','name'],
|
||||
'simple ascii string longer than 255 characters truncated' => [
|
||||
str_repeat('e',300),
|
||||
str_repeat('e',232) . ' -truncated (300 chars)'
|
||||
],
|
||||
'smiley string longer than 255 characters truncated' => [
|
||||
str_repeat('😃',300),
|
||||
str_repeat('😃',232) . ' -truncated (300 chars)'
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider SetTrimProvider
|
||||
* @return void
|
||||
*/
|
||||
public function testSetTrim($sName, $sResult){
|
||||
$oOrganisation = MetaModel::NewObject(Organization::class);
|
||||
$oOrganisation->SetTrim('name', $sName);
|
||||
$this->assertEquals($sResult, $oOrganisation->Get('name'), 'SetTrim must limit string to 255 characters');
|
||||
}
|
||||
}
|
||||
|
||||
69
tests/php-unit-tests/unitary-tests/core/EventIssueTest.php
Normal file
69
tests/php-unit-tests/unitary-tests/core/EventIssueTest.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
class EventIssueTest extends ItopDataTestCase
|
||||
{
|
||||
/**
|
||||
* Data provider for test EventIssue Creation
|
||||
*
|
||||
* @return array data
|
||||
* @since 3.1.2 N°3448 - Framework field size check not correctly implemented for multi-bytes languages/strings
|
||||
*/
|
||||
public function OnInsertProvider()
|
||||
{
|
||||
return [
|
||||
'all with ééé' => [
|
||||
str_repeat('é', 120),
|
||||
str_repeat('é', 120),
|
||||
str_repeat('é', 120),
|
||||
str_repeat('é', 120),
|
||||
],
|
||||
'all with 255 smiley' => [
|
||||
str_repeat('😎', 255),
|
||||
str_repeat('😎', 255),
|
||||
str_repeat('😎', 255),
|
||||
str_repeat('😎', 255),
|
||||
],
|
||||
'all with 255 characters, us-ascii only' => [
|
||||
str_repeat('a', 255),
|
||||
str_repeat('a', 255),
|
||||
str_repeat('a', 255),
|
||||
str_repeat('a', 255),
|
||||
],
|
||||
'all with 255 é' => [
|
||||
str_repeat('é', 255),
|
||||
str_repeat('é', 255),
|
||||
str_repeat('é', 255),
|
||||
str_repeat('é', 255),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* EventIssue has a OnInsert override that uses mb_strlen, so we need to test this specific case
|
||||
*
|
||||
* @covers EventIssue::OnInsert
|
||||
*
|
||||
* @dataProvider OnInsertProvider
|
||||
*
|
||||
* @since 3.1.2 N°3448 - Framework field size check not correctly implemented for multi-bytes languages/strings
|
||||
*/
|
||||
public function testOnInsert(string $sIssue, string $sImpact, string $sPage, string $sMessage)
|
||||
{
|
||||
$oEventIssue = MetaModel::NewObject('EventIssue', [
|
||||
'issue' => $sIssue,
|
||||
'impact' => $sImpact,
|
||||
'page' => $sPage,
|
||||
'message' => $sMessage,
|
||||
]);
|
||||
|
||||
try {
|
||||
$oEventIssue->DBInsert();
|
||||
}
|
||||
catch (CoreException $e) {
|
||||
$this->fail('we should be able to persist the object though it contains long values in its attributes');
|
||||
}
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
@@ -298,9 +298,8 @@ abstract class WebServicesBase
|
||||
if (is_object($oAttDef))
|
||||
{
|
||||
$iMaxSize = $oAttDef->GetMaxSize();
|
||||
if ($iMaxSize && (strlen($sValue) > $iMaxSize))
|
||||
{
|
||||
$sValue = substr($sValue, 0, $iMaxSize);
|
||||
if ($iMaxSize && (mb_strlen($sValue) > $iMaxSize)) {
|
||||
$sValue = mb_substr($sValue, 0, $iMaxSize);
|
||||
}
|
||||
$oLog->Set($sAttCode, $sValue);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user