mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Merge remote-tracking branch 'origin/support/3.0' into develop
This commit is contained in:
@@ -3342,13 +3342,14 @@ EOF
|
||||
// Consider only the "expected" fields for the target state
|
||||
if (array_key_exists($sAttCode, $aExpectedAttributes)) {
|
||||
$iExpectCode = $aExpectedAttributes[$sAttCode];
|
||||
|
||||
// Prompt for an attribute if
|
||||
// - the attribute must be changed or must be displayed to the user for confirmation
|
||||
// - or the field is mandatory and currently empty
|
||||
if (($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && ($this->Get($sAttCode) == ''))) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
(($iExpectCode & OPT_ATT_MANDATORY) && (false === $this->HasAValue($sAttCode)))) {
|
||||
$aArgs = array('this' => $this);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
// If the field is mandatory, set it to the only possible value
|
||||
if ((!$oAttDef->IsNullAllowed()) || ($iExpectCode & OPT_ATT_MANDATORY)) {
|
||||
if ($oAttDef->IsExternalKey()) {
|
||||
|
||||
@@ -746,6 +746,18 @@ abstract class AttributeDefinition
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $proposedValue
|
||||
*
|
||||
* @return bool True if $proposedValue is an actual value set in the attribute, false is the attribute remains "empty"
|
||||
* @since 3.0.3, 3.1.0 N°5784
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Default implementation, we don't really know what type $proposedValue will be
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing!
|
||||
*
|
||||
@@ -1430,6 +1442,15 @@ class AttributeDashboard extends AttributeDefinition
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Always return false for now, we don't consider a custom version of a dashboard
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2317,6 +2338,22 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @param \ormLinkSet $proposedValue
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormLinkSet))
|
||||
{
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// We test if there is at least 1 item in the linkset (new or existing), not if an item is being added to it.
|
||||
return $proposedValue->Count() > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2714,6 +2751,14 @@ class AttributeInteger extends AttributeDBField
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -2813,6 +2858,14 @@ class AttributeObjectKey extends AttributeDBFieldVoid
|
||||
return ($proposedValue == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return ((int) $proposedValue) !== 0;
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -3012,6 +3065,14 @@ class AttributeDecimal extends AttributeDBField
|
||||
return is_null($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -3423,6 +3484,14 @@ class AttributeString extends AttributeDBField
|
||||
return ($proposedValue == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return utils::IsNotNullOrEmptyString($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -4579,6 +4648,22 @@ class AttributeCaseLog extends AttributeLongText
|
||||
return ($proposedValue->GetText() == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @param \ormCaseLog $proposedValue
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormCaseLog)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// We test if there is at least 1 entry in the log, not if the user is adding one
|
||||
return $proposedValue->GetEntryCount() > 0;
|
||||
}
|
||||
|
||||
|
||||
public function ScalarToSQL($value)
|
||||
{
|
||||
if (!is_string($value) && !is_null($value))
|
||||
@@ -6901,6 +6986,14 @@ class AttributeExternalKey extends AttributeDBFieldVoid
|
||||
return ($proposedValue == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return ((int) $proposedValue) !== 0;
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
@@ -7650,6 +7743,16 @@ class AttributeExternalField extends AttributeDefinition
|
||||
return $oExtAttDef->IsNull($proposedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
|
||||
return $oExtAttDef->HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
@@ -8236,6 +8339,20 @@ class AttributeBlob extends AttributeDefinition
|
||||
return $oFormField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
if (false === ($proposedValue instanceof ormDocument)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
// Empty file (no content, just a filename) are supported since PR {@link https://github.com/Combodo/combodo-email-synchro/pull/17}, so we check for both empty content and empty filename to determine that a document has no value
|
||||
return utils::IsNotNullOrEmptyString($proposedValue->GetData()) && utils::IsNotNullOrEmptyString($proposedValue->GetFileName());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9266,6 +9383,17 @@ class AttributeStopWatch extends AttributeDefinition
|
||||
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// A stopwatch always has a value
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -9751,6 +9879,19 @@ class AttributeOneWayPassword extends AttributeDefinition implements iAttributeN
|
||||
return '*****';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormPassword)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return $proposedValue->IsEmpty() !== false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Indexed array having two dimensions
|
||||
@@ -9800,6 +9941,15 @@ class AttributeTable extends AttributeDBField
|
||||
return (count($proposedValue) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
return count($proposedValue) > 0;
|
||||
}
|
||||
|
||||
|
||||
public function GetEditValue($sValue, $oHostObj = null)
|
||||
{
|
||||
return '';
|
||||
@@ -10321,6 +10471,18 @@ abstract class AttributeSet extends AttributeDBFieldVoid
|
||||
return $proposedValue->Count() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
if (false === ($proposedValue instanceof ormSet)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return $proposedValue->Count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be overloaded for localized enums
|
||||
*
|
||||
@@ -13035,6 +13197,21 @@ class AttributeCustomFields extends AttributeDefinition
|
||||
|
||||
return $bEquals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function HasAValue($proposedValue): bool
|
||||
{
|
||||
// Protection against wrong value type
|
||||
if (false === ($proposedValue instanceof ormCustomFieldsValue)) {
|
||||
return parent::HasAValue($proposedValue);
|
||||
}
|
||||
|
||||
return count($proposedValue->GetValues()) > 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class AttributeArchiveFlag extends AttributeBoolean
|
||||
|
||||
@@ -4080,6 +4080,20 @@ abstract class DBObject implements iDisplay
|
||||
return $bSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return bool True if $sAttCode has an actual value set, false is the attribute remains "empty"
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @since 3.0.3, 3.1.0 N°5784
|
||||
*/
|
||||
public function HasAValue(string $sAttCode): bool
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAttDef->HasAValue($this->Get($sAttCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to recover the default value (aka when an object is being created)
|
||||
* Suitable for use as a lifecycle action
|
||||
|
||||
@@ -29,4 +29,148 @@ class AttributeDefinitionTest extends ItopDataTestCase {
|
||||
$this->assertEquals(["status" => "ENUM('active','inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"],
|
||||
$aImportColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider HasAValueProvider
|
||||
* @covers AttributeDefinition::HasAValue
|
||||
*
|
||||
* @param $sObjectClass
|
||||
* @param $sAttCode
|
||||
* @param $sUpdateCode
|
||||
* @param $bHasAValueInitially
|
||||
* @param $bHasAValueOnceSet
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function testHasAValue($sObjectClass, $sAttCode, $sUpdateCode, $bHasAValueInitially, $bHasAValueOnceSet)
|
||||
{
|
||||
$oObject = MetaModel::NewObject($sObjectClass);
|
||||
|
||||
// Test attribute without a value yet
|
||||
$this->assertEquals($bHasAValueInitially, $oObject->HasAValue($sAttCode));
|
||||
|
||||
eval($sUpdateCode);
|
||||
|
||||
// Test attribute once a value has been set
|
||||
$this->assertEquals($bHasAValueOnceSet, $oObject->HasAValue($sAttCode));
|
||||
}
|
||||
|
||||
public function HasAValueProvider(): array
|
||||
{
|
||||
// Note: This is test is not great as we are datamodel dependent and don't have a class with all the attribute types
|
||||
return [
|
||||
'AttributeDashboard' => [
|
||||
'Organization',
|
||||
'overview',
|
||||
'',
|
||||
false,
|
||||
false,
|
||||
],
|
||||
'AttributeLinkedSet' => [
|
||||
'UserRequest',
|
||||
'workorders_list',
|
||||
<<<PHP
|
||||
/** @var \ormLinkSet \$ormLinkset */
|
||||
\$ormLinkset = \$oObject->Get('workorders_list');
|
||||
\$ormLinkset->AddItem(MetaModel::NewObject('WorkOrder', []));
|
||||
\$oObject->Set('workorders_list', \$ormLinkset);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeLinkedSetIndirect' => [
|
||||
'UserRequest',
|
||||
'contacts_list',
|
||||
<<<PHP
|
||||
/** @var \ormLinkSet \$ormLinkset */
|
||||
\$ormLinkset = \$oObject->Get('contacts_list');
|
||||
\$ormLinkset->AddItem(MetaModel::NewObject('Person', []));
|
||||
\$oObject->Set('contacts_list', \$ormLinkset);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeInteger' => [
|
||||
'SLT',
|
||||
'value',
|
||||
<<<PHP
|
||||
\$oObject->Set('value', 100);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeDecimal' => [
|
||||
'PhysicalInterface',
|
||||
'speed',
|
||||
<<<PHP
|
||||
\$oObject->Set('speed', 1024.5);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeString' => [
|
||||
'UserRequest',
|
||||
'title',
|
||||
<<<PHP
|
||||
\$oObject->Set('title', 'Some title');
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeObjectKey' => [
|
||||
'Attachment',
|
||||
'item_id',
|
||||
<<<PHP
|
||||
\$oObject->Set('item_id', 12);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeExternalKey' => [
|
||||
'UserRequest',
|
||||
'org_id',
|
||||
<<<PHP
|
||||
\$oObject->Set('org_id', 3);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeBlob' => [
|
||||
'DocumentFile',
|
||||
'file',
|
||||
<<<PHP
|
||||
\$oObject->Set('file', new ormDocument('something', 'text/plain', 'something.txt'));
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'AttributeStopWatch' => [
|
||||
'UserRequest',
|
||||
'tto',
|
||||
'',
|
||||
true,
|
||||
true,
|
||||
],
|
||||
'AttributeSubItem' => [
|
||||
'UserRequest',
|
||||
'tto_escalation_deadline',
|
||||
'',
|
||||
true,
|
||||
true,
|
||||
],
|
||||
'AttributeOneWayPassword' => [
|
||||
'UserLocal',
|
||||
'password',
|
||||
<<<PHP
|
||||
$/** @var \ormPassword \$ormPassword */
|
||||
\$ormPassword = new ormPassword('somehash', 'somesalt');
|
||||
\$oObject->Set('password', \$ormPassword);
|
||||
PHP,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user