From 041c30dd3948bfb74e41febaec286aad59cff757 Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass Date: Thu, 11 Sep 2025 08:15:59 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B08699=20-=20attributedef.class.inc.php=20?= =?UTF-8?q?to=20PSR4=20[3-PSR4]=20-=20Add=20namespaces=20-=20Add=20use=20s?= =?UTF-8?q?tatements=20-=20reformat=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/attributedef.class.inc.php | 86 +- core/oql/oqlquery.class.inc.php | 6 +- lib/composer/autoload_classmap.php | 122 +- lib/composer/autoload_static.php | 122 +- .../AttributeApplicationLanguage.php | 65 +- .../AttributeArchiveDate.php | 61 +- .../AttributeArchiveFlag.php | 80 +- .../AttributeDefinition/AttributeBlob.php | 629 ++-- .../AttributeDefinition/AttributeBoolean.php | 415 +-- .../AttributeDefinition/AttributeCaseLog.php | 683 ++--- .../AttributeDefinition/AttributeClass.php | 132 +- .../AttributeClassAttCodeSet.php | 389 +-- .../AttributeClassState.php | 124 +- .../AttributeCustomFields.php | 784 ++--- .../AttributeDefinition/AttributeDBField.php | 32 +- .../AttributeDBFieldVoid.php | 233 +- .../AttributeDashboard.php | 172 +- .../AttributeDefinition/AttributeDate.php | 168 +- .../AttributeDefinition/AttributeDateTime.php | 987 ++++--- .../AttributeDefinition/AttributeDeadline.php | 133 +- .../AttributeDefinition/AttributeDecimal.php | 262 +- .../AttributeDefinition.php | 2578 ++++++++--------- .../AttributeDefinition/AttributeDuration.php | 214 +- .../AttributeEmailAddress.php | 72 +- .../AttributeEncryptedString.php | 128 +- .../AttributeDefinition/AttributeEnum.php | 708 ++--- .../AttributeDefinition/AttributeEnumSet.php | 415 +-- .../AttributeExternalField.php | 1016 +++---- .../AttributeExternalKey.php | 561 ++-- .../AttributeFinalClass.php | 337 +-- .../AttributeFriendlyName.php | 322 +- .../AttributeDefinition/AttributeHTML.php | 82 +- .../AttributeHierarchicalKey.php | 306 +- .../AttributeIPAddress.php | 58 +- .../AttributeDefinition/AttributeImage.php | 331 ++- .../AttributeDefinition/AttributeInteger.php | 232 +- .../AttributeLinkedSet.php | 1830 ++++++------ .../AttributeLinkedSetIndirect.php | 162 +- .../AttributeDefinition/AttributeLongText.php | 75 +- .../AttributeDefinition/AttributeMetaEnum.php | 233 +- .../Core/AttributeDefinition/AttributeOQL.php | 50 +- .../AttributeObjectKey.php | 174 +- .../AttributeObsolescenceDate.php | 61 +- .../AttributeObsolescenceFlag.php | 207 +- .../AttributeOneWayPassword.php | 388 +-- .../AttributeDefinition/AttributePassword.php | 106 +- .../AttributePercentage.php | 88 +- .../AttributePhoneNumber.php | 79 +- .../AttributePropertySet.php | 190 +- .../AttributeQueryAttCodeSet.php | 318 +- .../AttributeRedundancySettings.php | 767 ++--- .../Core/AttributeDefinition/AttributeSet.php | 822 +++--- .../AttributeStopWatch.php | 1612 ++++++----- .../AttributeDefinition/AttributeString.php | 316 +- .../AttributeDefinition/AttributeSubItem.php | 411 +-- .../AttributeDefinition/AttributeTable.php | 286 +- .../AttributeDefinition/AttributeTagSet.php | 1133 ++++---- .../AttributeTemplateHTML.php | 86 +- .../AttributeTemplateString.php | 42 +- .../AttributeTemplateText.php | 42 +- .../AttributeDefinition/AttributeText.php | 677 ++--- .../Core/AttributeDefinition/AttributeURL.php | 189 +- .../MissingColumnException.php | 8 + .../iAttributeNoGroupBy.php | 8 +- sources/alias.php | 64 +- 65 files changed, 12100 insertions(+), 11369 deletions(-) diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 8043fc002..fcc2c3cb1 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -5,84 +5,14 @@ */ require_once('MyHelpers.class.inc.php'); +require_once('ormdocument.class.inc.php'); +require_once('ormstopwatch.class.inc.php'); +require_once('ormpassword.class.inc.php'); +require_once('ormcaselog.class.inc.php'); +require_once('ormlinkset.class.inc.php'); +require_once('ormset.class.inc.php'); +require_once('ormtagset.class.inc.php'); require_once('htmlsanitizer.class.inc.php'); require_once('customfieldshandler.class.inc.php'); +require_once('ormcustomfieldsvalue.class.inc.php'); require_once('datetimeformat.class.inc.php'); - -require_once(APPROOT.'/sources/Core/Orm/ormDocument.php'); -require_once(APPROOT.'/sources/Core/Orm/ormStopWatch.php'); -require_once(APPROOT.'/sources/Core/Orm/ormPassword.php'); -require_once(APPROOT.'/sources/Core/Orm/ormCaseLog.php'); -require_once(APPROOT.'/sources/Core/Orm/ormLinkSet.php'); -require_once(APPROOT.'/sources/Core/Orm/ormSet.php'); -require_once(APPROOT.'/sources/Core/Orm/ormTagSet.php'); -require_once(APPROOT.'/sources/Core/Orm/ormCustomFieldsValue.php'); - - -require_once(APPROOT.'/sources/Core/AttributeDefinition/MissingColumnException.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/iAttributeNoGroupBy.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDefinition.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDashboard.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeLinkedSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeLinkedSetIndirect.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDBField.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeInteger.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeObjectKey.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributePercentage.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDecimal.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeBoolean.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeString.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeClass.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeClassState.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeFinalClass.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributePassword.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeEncryptedString.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeText.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeLongText.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeCaseLog.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeHTML.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeEmailAddress.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeIPAddress.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributePhoneNumber.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeOQL.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeTemplateString.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeTemplateText.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeTemplateHTML.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeEnum.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeMetaEnum.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDateTime.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDuration.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDate.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeDeadline.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeExternalKey.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeHierarchicalKey.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeExternalField.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeURL.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeBlob.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeImage.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeStopWatch.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeSubItem.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeOneWayPassword.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeTable.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributePropertySet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeEnumSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeQueryAttCodeSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeTagSet.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeFriendlyName.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeRedundancySettings.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeObsolescenceDate.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeCustomFields.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeArchiveFlag.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeArchiveDate.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeObsolescenceFlag.php'); -require_once(APPROOT.'/sources/Core/AttributeDefinition/AttributeObsolescenceDate.php'); - - - -// Indexed array having two dimensions - -// The PHP value is a hash array, it is stored as a TEXT column diff --git a/core/oql/oqlquery.class.inc.php b/core/oql/oqlquery.class.inc.php index ef19b4725..24889d356 100644 --- a/core/oql/oqlquery.class.inc.php +++ b/core/oql/oqlquery.class.inc.php @@ -495,8 +495,8 @@ class OqlObjectQuery extends OqlQuery { throw new OqlNormalizeException('Unknown class in join condition (right expression)', $sSourceQuery, $oRightField->GetParentDetails(), array_keys($aAliases)); } - $aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], 'AttributeExternalKey'); - $aObjKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], 'AttributeObjectKey'); + $aExtKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeExternalKey::class); + $aObjKeys = $oModelReflection->ListAttributes($aAliases[$sFromClass], \Combodo\iTop\Core\AttributeDefinition\AttributeObjectKey::class); $aAllKeys = array_merge($aExtKeys, $aObjKeys); if (!array_key_exists($sExtKeyAttCode, $aAllKeys)) { @@ -557,7 +557,7 @@ class OqlObjectQuery extends OqlQuery } $aAttList = $oModelReflection->ListAttributes($aAliases[$sFromClass]); $sAttType = $aAttList[$sExtKeyAttCode]; - if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, 'AttributeHierarchicalKey') && ($sAttType != 'AttributeHierarchicalKey')) + if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !is_subclass_of($sAttType, \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class) && ($sAttType != \Combodo\iTop\Core\AttributeDefinition\AttributeHierarchicalKey::class)) { throw new OqlNormalizeException("The specified tree operator $sOperator is not applicable to the key", $sSourceQuery, $oLeftField->GetNameDetails()); } diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index 7cd4bcdad..a7c410d4b 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -27,64 +27,6 @@ return array( 'AsyncSendEmail' => $baseDir . '/core/asynctask.class.inc.php', 'AsyncSendNewsroom' => $baseDir . '/core/asynctask.class.inc.php', 'AsyncTask' => $baseDir . '/core/asynctask.class.inc.php', - 'AttributeApplicationLanguage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeArchiveDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeArchiveFlag' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeBlob' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeBoolean' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeCaseLog' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClass' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClassAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeClassState' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeCustomFields' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDBField' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDBFieldVoid' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDashboard' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDateTime' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDeadline' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDecimal' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDefinition' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeDuration' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEmailAddress' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEncryptedString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEnum' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeEnumSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeExternalField' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeExternalKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeFinalClass' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeFriendlyName' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeHTML' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeHierarchicalKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeIPAddress' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeImage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeInteger' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLinkedSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLinkedSetIndirect' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeLongText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeMetaEnum' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeOQL' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObjectKey' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceDate' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceFlag' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeOneWayPassword' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePassword' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePercentage' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePhoneNumber' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributePropertySet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeQueryAttCodeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeRedundancySettings' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeStopWatch' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeSubItem' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTable' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTagSet' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateHTML' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateString' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeTemplateText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeText' => $baseDir . '/core/attributedef.class.inc.php', - 'AttributeURL' => $baseDir . '/core/attributedef.class.inc.php', 'AuditCategory' => $baseDir . '/application/audit.category.class.inc.php', 'AuditDomain' => $baseDir . '/application/audit.domain.class.inc.php', 'AuditRule' => $baseDir . '/application/audit.rule.class.inc.php', @@ -405,6 +347,66 @@ return array( 'Combodo\\iTop\\Controller\\TemporaryObjects\\TemporaryObjectController' => $baseDir . '/sources/Controller/TemporaryObjects/TemporaryObjectController.php', 'Combodo\\iTop\\Controller\\WelcomePopupController' => $baseDir . '/sources/Controller/WelcomePopupController.php', 'Combodo\\iTop\\Controller\\iController' => $baseDir . '/sources/Controller/iController.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeApplicationLanguage' => $baseDir . '/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeArchiveDate' => $baseDir . '/sources/Core/AttributeDefinition/AttributeArchiveDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeArchiveFlag' => $baseDir . '/sources/Core/AttributeDefinition/AttributeArchiveFlag.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeBlob' => $baseDir . '/sources/Core/AttributeDefinition/AttributeBlob.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeBoolean' => $baseDir . '/sources/Core/AttributeDefinition/AttributeBoolean.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeCaseLog' => $baseDir . '/sources/Core/AttributeDefinition/AttributeCaseLog.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClass' => $baseDir . '/sources/Core/AttributeDefinition/AttributeClass.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClassAttCodeSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClassState' => $baseDir . '/sources/Core/AttributeDefinition/AttributeClassState.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeCustomFields' => $baseDir . '/sources/Core/AttributeDefinition/AttributeCustomFields.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDBField' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDBField.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDBFieldVoid' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDashboard' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDashboard.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDate' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDateTime' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDateTime.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDeadline' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDeadline.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDecimal' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDecimal.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDefinition' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDefinition.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDuration' => $baseDir . '/sources/Core/AttributeDefinition/AttributeDuration.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEmailAddress' => $baseDir . '/sources/Core/AttributeDefinition/AttributeEmailAddress.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEncryptedString' => $baseDir . '/sources/Core/AttributeDefinition/AttributeEncryptedString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEnum' => $baseDir . '/sources/Core/AttributeDefinition/AttributeEnum.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEnumSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeEnumSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeExternalField' => $baseDir . '/sources/Core/AttributeDefinition/AttributeExternalField.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeExternalKey' => $baseDir . '/sources/Core/AttributeDefinition/AttributeExternalKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeFinalClass' => $baseDir . '/sources/Core/AttributeDefinition/AttributeFinalClass.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeFriendlyName' => $baseDir . '/sources/Core/AttributeDefinition/AttributeFriendlyName.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeHTML' => $baseDir . '/sources/Core/AttributeDefinition/AttributeHTML.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeHierarchicalKey' => $baseDir . '/sources/Core/AttributeDefinition/AttributeHierarchicalKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeIPAddress' => $baseDir . '/sources/Core/AttributeDefinition/AttributeIPAddress.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeImage' => $baseDir . '/sources/Core/AttributeDefinition/AttributeImage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeInteger' => $baseDir . '/sources/Core/AttributeDefinition/AttributeInteger.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLinkedSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeLinkedSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLinkedSetIndirect' => $baseDir . '/sources/Core/AttributeDefinition/AttributeLinkedSetIndirect.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLongText' => $baseDir . '/sources/Core/AttributeDefinition/AttributeLongText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeMetaEnum' => $baseDir . '/sources/Core/AttributeDefinition/AttributeMetaEnum.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeOQL' => $baseDir . '/sources/Core/AttributeDefinition/AttributeOQL.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObjectKey' => $baseDir . '/sources/Core/AttributeDefinition/AttributeObjectKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObsolescenceDate' => $baseDir . '/sources/Core/AttributeDefinition/AttributeObsolescenceDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObsolescenceFlag' => $baseDir . '/sources/Core/AttributeDefinition/AttributeObsolescenceFlag.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeOneWayPassword' => $baseDir . '/sources/Core/AttributeDefinition/AttributeOneWayPassword.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePassword' => $baseDir . '/sources/Core/AttributeDefinition/AttributePassword.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePercentage' => $baseDir . '/sources/Core/AttributeDefinition/AttributePercentage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePhoneNumber' => $baseDir . '/sources/Core/AttributeDefinition/AttributePhoneNumber.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePropertySet' => $baseDir . '/sources/Core/AttributeDefinition/AttributePropertySet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeQueryAttCodeSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeQueryAttCodeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeRedundancySettings' => $baseDir . '/sources/Core/AttributeDefinition/AttributeRedundancySettings.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeStopWatch' => $baseDir . '/sources/Core/AttributeDefinition/AttributeStopWatch.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeString' => $baseDir . '/sources/Core/AttributeDefinition/AttributeString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeSubItem' => $baseDir . '/sources/Core/AttributeDefinition/AttributeSubItem.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTable' => $baseDir . '/sources/Core/AttributeDefinition/AttributeTable.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTagSet' => $baseDir . '/sources/Core/AttributeDefinition/AttributeTagSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateHTML' => $baseDir . '/sources/Core/AttributeDefinition/AttributeTemplateHTML.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateString' => $baseDir . '/sources/Core/AttributeDefinition/AttributeTemplateString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateText' => $baseDir . '/sources/Core/AttributeDefinition/AttributeTemplateText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeText' => $baseDir . '/sources/Core/AttributeDefinition/AttributeText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeURL' => $baseDir . '/sources/Core/AttributeDefinition/AttributeURL.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\MissingColumnException' => $baseDir . '/sources/Core/AttributeDefinition/MissingColumnException.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\iAttributeNoGroupBy' => $baseDir . '/sources/Core/AttributeDefinition/iAttributeNoGroupBy.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\IOAuthClientProvider' => $baseDir . '/sources/Core/Authentication/Client/OAuth/IOAuthClientProvider.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAbstract' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAbstract.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAzure' => $baseDir . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAzure.php', @@ -1116,7 +1118,6 @@ return array( 'MenuGroup' => $baseDir . '/application/menunode.class.inc.php', 'MenuNode' => $baseDir . '/application/menunode.class.inc.php', 'MetaModel' => $baseDir . '/core/metamodel.class.php', - 'MissingColumnException' => $baseDir . '/core/attributedef.class.inc.php', 'MissingQueryArgument' => $baseDir . '/core/oql/expression.class.inc.php', 'ModelReflection' => $baseDir . '/core/modelreflection.class.inc.php', 'ModelReflectionRuntime' => $baseDir . '/core/modelreflection.class.inc.php', @@ -3161,8 +3162,6 @@ return array( 'Twig\\Source' => $vendorDir . '/twig/twig/src/Source.php', 'Twig\\Template' => $vendorDir . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => $vendorDir . '/twig/twig/src/TemplateWrapper.php', - 'Twig\\Test\\IntegrationTestCase' => $vendorDir . '/twig/twig/src/Test/IntegrationTestCase.php', - 'Twig\\Test\\NodeTestCase' => $vendorDir . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => $vendorDir . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -3232,7 +3231,6 @@ return array( 'cmdbAbstractObject' => $baseDir . '/application/cmdbabstract.class.inc.php', 'cmdbDataGenerator' => $baseDir . '/core/data.generator.class.inc.php', 'iApplicationUIExtension' => $baseDir . '/application/applicationextension/backoffice/iApplicationUIExtension.php', - 'iAttributeNoGroupBy' => $baseDir . '/core/attributedef.class.inc.php', 'iBackgroundProcess' => $baseDir . '/core/backgroundprocess.inc.php', 'iBackofficeDictEntriesExtension' => $baseDir . '/application/applicationextension/backoffice/iBackofficeDictEntriesExtension.php', 'iBackofficeDictEntriesPrefixesExtension' => $baseDir . '/application/applicationextension/backoffice/iBackofficeDictEntriesPrefixesExtension.php', diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 1232f4358..b10aa872d 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -399,64 +399,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'AsyncSendEmail' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', 'AsyncSendNewsroom' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', 'AsyncTask' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', - 'AttributeApplicationLanguage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeArchiveDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeArchiveFlag' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeBlob' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeBoolean' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeCaseLog' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClassAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeClassState' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeCustomFields' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDBField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDBFieldVoid' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDashboard' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDateTime' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDeadline' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDecimal' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDefinition' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeDuration' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEmailAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEncryptedString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeEnumSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeExternalField' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeExternalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeFinalClass' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeFriendlyName' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeHTML' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeHierarchicalKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeIPAddress' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeImage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeInteger' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLinkedSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLinkedSetIndirect' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeLongText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeMetaEnum' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeOQL' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObjectKey' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeObsolescenceFlag' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeOneWayPassword' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePassword' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePercentage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePhoneNumber' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributePropertySet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeQueryAttCodeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeRedundancySettings' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeStopWatch' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeSubItem' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTable' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTagSet' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateHTML' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateString' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeTemplateText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeText' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', - 'AttributeURL' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'AuditCategory' => __DIR__ . '/../..' . '/application/audit.category.class.inc.php', 'AuditDomain' => __DIR__ . '/../..' . '/application/audit.domain.class.inc.php', 'AuditRule' => __DIR__ . '/../..' . '/application/audit.rule.class.inc.php', @@ -777,6 +719,66 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Controller\\TemporaryObjects\\TemporaryObjectController' => __DIR__ . '/../..' . '/sources/Controller/TemporaryObjects/TemporaryObjectController.php', 'Combodo\\iTop\\Controller\\WelcomePopupController' => __DIR__ . '/../..' . '/sources/Controller/WelcomePopupController.php', 'Combodo\\iTop\\Controller\\iController' => __DIR__ . '/../..' . '/sources/Controller/iController.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeApplicationLanguage' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeArchiveDate' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeArchiveDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeArchiveFlag' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeArchiveFlag.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeBlob' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeBlob.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeBoolean' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeBoolean.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeCaseLog' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeCaseLog.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClass' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeClass.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClassAttCodeSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeClassState' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeClassState.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeCustomFields' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeCustomFields.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDBField' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDBField.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDBFieldVoid' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDashboard' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDashboard.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDate' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDateTime' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDateTime.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDeadline' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDeadline.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDecimal' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDecimal.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDefinition' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDefinition.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeDuration' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeDuration.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEmailAddress' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeEmailAddress.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEncryptedString' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeEncryptedString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEnum' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeEnum.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeEnumSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeEnumSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeExternalField' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeExternalField.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeExternalKey' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeExternalKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeFinalClass' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeFinalClass.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeFriendlyName' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeFriendlyName.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeHTML' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeHTML.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeHierarchicalKey' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeHierarchicalKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeIPAddress' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeIPAddress.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeImage' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeImage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeInteger' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeInteger.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLinkedSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeLinkedSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLinkedSetIndirect' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeLinkedSetIndirect.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeLongText' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeLongText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeMetaEnum' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeMetaEnum.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeOQL' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeOQL.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObjectKey' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeObjectKey.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObsolescenceDate' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeObsolescenceDate.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeObsolescenceFlag' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeObsolescenceFlag.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeOneWayPassword' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeOneWayPassword.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePassword' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributePassword.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePercentage' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributePercentage.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePhoneNumber' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributePhoneNumber.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributePropertySet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributePropertySet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeQueryAttCodeSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeQueryAttCodeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeRedundancySettings' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeRedundancySettings.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeStopWatch' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeStopWatch.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeString' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeSubItem' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeSubItem.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTable' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeTable.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTagSet' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeTagSet.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateHTML' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeTemplateHTML.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateString' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeTemplateString.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeTemplateText' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeTemplateText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeText' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeText.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\AttributeURL' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/AttributeURL.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\MissingColumnException' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/MissingColumnException.php', + 'Combodo\\iTop\\Core\\AttributeDefinition\\iAttributeNoGroupBy' => __DIR__ . '/../..' . '/sources/Core/AttributeDefinition/iAttributeNoGroupBy.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\IOAuthClientProvider' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/IOAuthClientProvider.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAbstract' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAbstract.php', 'Combodo\\iTop\\Core\\Authentication\\Client\\OAuth\\OAuthClientProviderAzure' => __DIR__ . '/../..' . '/sources/Core/Authentication/Client/OAuth/OAuthClientProviderAzure.php', @@ -1488,7 +1490,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'MenuGroup' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', 'MenuNode' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', 'MetaModel' => __DIR__ . '/../..' . '/core/metamodel.class.php', - 'MissingColumnException' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'MissingQueryArgument' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', 'ModelReflection' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', 'ModelReflectionRuntime' => __DIR__ . '/../..' . '/core/modelreflection.class.inc.php', @@ -3533,8 +3534,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Twig\\Source' => __DIR__ . '/..' . '/twig/twig/src/Source.php', 'Twig\\Template' => __DIR__ . '/..' . '/twig/twig/src/Template.php', 'Twig\\TemplateWrapper' => __DIR__ . '/..' . '/twig/twig/src/TemplateWrapper.php', - 'Twig\\Test\\IntegrationTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/IntegrationTestCase.php', - 'Twig\\Test\\NodeTestCase' => __DIR__ . '/..' . '/twig/twig/src/Test/NodeTestCase.php', 'Twig\\Token' => __DIR__ . '/..' . '/twig/twig/src/Token.php', 'Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/AbstractTokenParser.php', 'Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/twig/twig/src/TokenParser/ApplyTokenParser.php', @@ -3604,7 +3603,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'cmdbAbstractObject' => __DIR__ . '/../..' . '/application/cmdbabstract.class.inc.php', 'cmdbDataGenerator' => __DIR__ . '/../..' . '/core/data.generator.class.inc.php', 'iApplicationUIExtension' => __DIR__ . '/../..' . '/application/applicationextension/backoffice/iApplicationUIExtension.php', - 'iAttributeNoGroupBy' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'iBackgroundProcess' => __DIR__ . '/../..' . '/core/backgroundprocess.inc.php', 'iBackofficeDictEntriesExtension' => __DIR__ . '/../..' . '/application/applicationextension/backoffice/iBackofficeDictEntriesExtension.php', 'iBackofficeDictEntriesPrefixesExtension' => __DIR__ . '/../..' . '/application/applicationextension/backoffice/iBackofficeDictEntriesPrefixesExtension.php', diff --git a/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php b/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php index a05efad66..52ebdc276 100644 --- a/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php +++ b/sources/Core/AttributeDefinition/AttributeApplicationLanguage.php @@ -1,4 +1,13 @@ m_sCode = $sCode; - $aAvailableLanguages = Dict::GetLanguages(); - $aLanguageCodes = array(); - foreach ($aAvailableLanguages as $sLangCode => $aInfo) { - $aLanguageCodes[$sLangCode] = $aInfo['description'] . ' (' . $aInfo['localized_description'] . ')'; - } + public function __construct($sCode, $aParams) + { + $this->m_sCode = $sCode; + $aAvailableLanguages = Dict::GetLanguages(); + $aLanguageCodes = array(); + foreach ($aAvailableLanguages as $sLangCode => $aInfo) { + $aLanguageCodes[$sLangCode] = $aInfo['description'].' ('.$aInfo['localized_description'].')'; + } - // N°6462 This should be sorted directly in \Dict during the compilation but we can't for 2 reasons: - // - Additional languages can be added on the fly even though it is not recommended - // - Formatting is done at run time (just above) - natcasesort($aLanguageCodes); + // N°6462 This should be sorted directly in \Dict during the compilation but we can't for 2 reasons: + // - Additional languages can be added on the fly even though it is not recommended + // - Formatting is done at run time (just above) + natcasesort($aLanguageCodes); - $aParams["allowed_values"] = new ValueSetEnum($aLanguageCodes); - parent::__construct($sCode, $aParams); - } + $aParams["allowed_values"] = new ValueSetEnum($aLanguageCodes); + parent::__construct($sCode, $aParams); + } - public function RequiresIndex() - { - return true; - } + public function RequiresIndex() + { + return true; + } - public function GetBasicFilterLooseOperator() - { - return '='; - } + public function GetBasicFilterLooseOperator() + { + return '='; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeArchiveDate.php b/sources/Core/AttributeDefinition/AttributeArchiveDate.php index cb52a92d7..49334d913 100644 --- a/sources/Core/AttributeDefinition/AttributeArchiveDate.php +++ b/sources/Core/AttributeDefinition/AttributeArchiveDate.php @@ -1,35 +1,44 @@ null, - "sql" => $sCode, - "default_value" => false, - "is_null_allowed" => false, - "depends_on" => array() - )); - } + public function __construct($sCode) + { + parent::__construct($sCode, array( + "allowed_values" => null, + "sql" => $sCode, + "default_value" => false, + "is_null_allowed" => false, + "depends_on" => array(), + )); + } - public function RequiresIndex() - { - return true; - } + public function RequiresIndex() + { + return true; + } - public function CopyOnAllTables() - { - return true; - } + public function CopyOnAllTables() + { + return true; + } - public function IsWritable() - { - return false; - } + public function IsWritable() + { + return false; + } - public function IsMagic() - { - return true; - } + public function IsMagic() + { + return true; + } - public function GetLabel($sDefault = null) - { - $sDefault = Dict::S('Core:AttributeArchiveFlag/Label', $sDefault); + public function GetLabel($sDefault = null) + { + $sDefault = Dict::S('Core:AttributeArchiveFlag/Label', $sDefault); - return parent::GetLabel($sDefault); - } + return parent::GetLabel($sDefault); + } - public function GetDescription($sDefault = null) - { - $sDefault = Dict::S('Core:AttributeArchiveFlag/Label+', $sDefault); + public function GetDescription($sDefault = null) + { + $sDefault = Dict::S('Core:AttributeArchiveFlag/Label+', $sDefault); - return parent::GetDescription($sDefault); - } + return parent::GetDescription($sDefault); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeBlob.php b/sources/Core/AttributeDefinition/AttributeBlob.php index 7520b3b9a..5306fe789 100644 --- a/sources/Core/AttributeDefinition/AttributeBlob.php +++ b/sources/Core/AttributeDefinition/AttributeBlob.php @@ -1,4 +1,19 @@ GetOptional("is_null_allowed", false); - } + public function IsNullAllowed(DBObject $oHostObject = null) + { + return $this->GetOptional("is_null_allowed", false); + } - public function GetEditValue($sValue, $oHostObj = null) - { - return ''; - } + public function GetEditValue($sValue, $oHostObj = null) + { + return ''; + } - /** - * {@inheritDoc} - * - * @param string $proposedValue Can be an URL (including an URL to iTop itself), or a local path (CSV import) - * - * @see AttributeDefinition::MakeRealValue() - */ - public function MakeRealValue($proposedValue, $oHostObj) - { - if ($proposedValue === null) { - return null; - } + /** + * {@inheritDoc} + * + * @see AttributeDefinition::MakeRealValue() + * + * @param string $proposedValue Can be an URL (including an URL to iTop itself), or a local path (CSV import) + * + */ + public function MakeRealValue($proposedValue, $oHostObj) + { + if ($proposedValue === null) { + return null; + } - if (is_object($proposedValue)) { - $proposedValue = clone $proposedValue; - } else { - try { - // Read the file from iTop, an URL (or the local file system - for admins only) - $proposedValue = Utils::FileGetContentsAndMIMEType($proposedValue); - } catch (Exception $e) { - IssueLog::Warning(get_class($this) . "::MakeRealValue - " . $e->getMessage()); - // Not a real document !! store is as text !!! (This was the default behavior before) - $proposedValue = new ormDocument($e->getMessage() . " \n" . $proposedValue, 'text/plain'); - } - } + if (is_object($proposedValue)) { + $proposedValue = clone $proposedValue; + } else { + try { + // Read the file from iTop, an URL (or the local file system - for admins only) + $proposedValue = utils::FileGetContentsAndMIMEType($proposedValue); + } + catch (Exception $e) { + IssueLog::Warning(get_class($this)."::MakeRealValue - ".$e->getMessage()); + // Not a real document !! store is as text !!! (This was the default behavior before) + $proposedValue = new ormDocument($e->getMessage()." \n".$proposedValue, 'text/plain'); + } + } - return $proposedValue; - } + return $proposedValue; + } - public function GetSQLExpressions($sPrefix = '') - { - if ($sPrefix == '') { - $sPrefix = $this->GetCode(); - } - $aColumns = array(); - // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix - $aColumns[''] = $sPrefix . '_mimetype'; - $aColumns['_data'] = $sPrefix . '_data'; - $aColumns['_filename'] = $sPrefix . '_filename'; - $aColumns['_downloads_count'] = $sPrefix . '_downloads_count'; + public function GetSQLExpressions($sPrefix = '') + { + if ($sPrefix == '') { + $sPrefix = $this->GetCode(); + } + $aColumns = array(); + // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix + $aColumns[''] = $sPrefix.'_mimetype'; + $aColumns['_data'] = $sPrefix.'_data'; + $aColumns['_filename'] = $sPrefix.'_filename'; + $aColumns['_downloads_count'] = $sPrefix.'_downloads_count'; - return $aColumns; - } + return $aColumns; + } - public function FromSQLToValue($aCols, $sPrefix = '') - { - if (!array_key_exists($sPrefix, $aCols)) { - $sAvailable = implode(', ', array_keys($aCols)); - throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}"); - } - $sMimeType = isset($aCols[$sPrefix]) ? $aCols[$sPrefix] : ''; + public function FromSQLToValue($aCols, $sPrefix = '') + { + if (!array_key_exists($sPrefix, $aCols)) { + $sAvailable = implode(', ', array_keys($aCols)); + throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}"); + } + $sMimeType = isset($aCols[$sPrefix]) ? $aCols[$sPrefix] : ''; - if (!array_key_exists($sPrefix . '_data', $aCols)) { - $sAvailable = implode(', ', array_keys($aCols)); - throw new MissingColumnException("Missing column '" . $sPrefix . "_data' from {$sAvailable}"); - } - $data = isset($aCols[$sPrefix . '_data']) ? $aCols[$sPrefix . '_data'] : null; + if (!array_key_exists($sPrefix.'_data', $aCols)) { + $sAvailable = implode(', ', array_keys($aCols)); + throw new MissingColumnException("Missing column '".$sPrefix."_data' from {$sAvailable}"); + } + $data = isset($aCols[$sPrefix.'_data']) ? $aCols[$sPrefix.'_data'] : null; - if (!array_key_exists($sPrefix . '_filename', $aCols)) { - $sAvailable = implode(', ', array_keys($aCols)); - throw new MissingColumnException("Missing column '" . $sPrefix . "_filename' from {$sAvailable}"); - } - $sFileName = isset($aCols[$sPrefix . '_filename']) ? $aCols[$sPrefix . '_filename'] : ''; + if (!array_key_exists($sPrefix.'_filename', $aCols)) { + $sAvailable = implode(', ', array_keys($aCols)); + throw new MissingColumnException("Missing column '".$sPrefix."_filename' from {$sAvailable}"); + } + $sFileName = isset($aCols[$sPrefix.'_filename']) ? $aCols[$sPrefix.'_filename'] : ''; - if (!array_key_exists($sPrefix . '_downloads_count', $aCols)) { - $sAvailable = implode(', ', array_keys($aCols)); - throw new MissingColumnException("Missing column '" . $sPrefix . "_downloads_count' from {$sAvailable}"); - } - $iDownloadsCount = isset($aCols[$sPrefix . '_downloads_count']) ? $aCols[$sPrefix . '_downloads_count'] : ormDocument::DEFAULT_DOWNLOADS_COUNT; + if (!array_key_exists($sPrefix.'_downloads_count', $aCols)) { + $sAvailable = implode(', ', array_keys($aCols)); + throw new MissingColumnException("Missing column '".$sPrefix."_downloads_count' from {$sAvailable}"); + } + $iDownloadsCount = isset($aCols[$sPrefix.'_downloads_count']) ? $aCols[$sPrefix.'_downloads_count'] : ormDocument::DEFAULT_DOWNLOADS_COUNT; - $value = new ormDocument($data, $sMimeType, $sFileName, $iDownloadsCount); + $value = new ormDocument($data, $sMimeType, $sFileName, $iDownloadsCount); - return $value; - } + return $value; + } - public function GetSQLValues($value) - { - // #@# Optimization: do not load blobs anytime - // As per mySQL doc, selecting blob columns will prevent mySQL from - // using memory in case a temporary table has to be created - // (temporary tables created on disk) - // We will have to remove the blobs from the list of attributes when doing the select - // then the use of Get() should finalize the load - if ($value instanceof ormDocument) { - $aValues = array(); - if (!$value->IsEmpty()) { - $aValues[$this->GetCode() . '_data'] = $value->GetData(); - } else { - $aValues[$this->GetCode() . '_data'] = ''; - } - $aValues[$this->GetCode() . '_mimetype'] = $value->GetMimeType(); - $aValues[$this->GetCode() . '_filename'] = $value->GetFileName(); - $aValues[$this->GetCode() . '_downloads_count'] = $value->GetDownloadsCount(); - } else { - $aValues = array(); - $aValues[$this->GetCode() . '_data'] = ''; - $aValues[$this->GetCode() . '_mimetype'] = ''; - $aValues[$this->GetCode() . '_filename'] = ''; - $aValues[$this->GetCode() . '_downloads_count'] = ormDocument::DEFAULT_DOWNLOADS_COUNT; - } + public function GetSQLValues($value) + { + // #@# Optimization: do not load blobs anytime + // As per mySQL doc, selecting blob columns will prevent mySQL from + // using memory in case a temporary table has to be created + // (temporary tables created on disk) + // We will have to remove the blobs from the list of attributes when doing the select + // then the use of Get() should finalize the load + if ($value instanceof ormDocument) { + $aValues = array(); + if (!$value->IsEmpty()) { + $aValues[$this->GetCode().'_data'] = $value->GetData(); + } else { + $aValues[$this->GetCode().'_data'] = ''; + } + $aValues[$this->GetCode().'_mimetype'] = $value->GetMimeType(); + $aValues[$this->GetCode().'_filename'] = $value->GetFileName(); + $aValues[$this->GetCode().'_downloads_count'] = $value->GetDownloadsCount(); + } else { + $aValues = array(); + $aValues[$this->GetCode().'_data'] = ''; + $aValues[$this->GetCode().'_mimetype'] = ''; + $aValues[$this->GetCode().'_filename'] = ''; + $aValues[$this->GetCode().'_downloads_count'] = ormDocument::DEFAULT_DOWNLOADS_COUNT; + } - return $aValues; - } + return $aValues; + } - public function GetSQLColumns($bFullSpec = false) - { - $aColumns = array(); - $aColumns[$this->GetCode() . '_data'] = 'LONGBLOB'; // 2^32 (4 Gb) - $aColumns[$this->GetCode() . '_mimetype'] = 'VARCHAR(255)' . CMDBSource::GetSqlStringColumnDefinition(); - $aColumns[$this->GetCode() . '_filename'] = 'VARCHAR(255)' . CMDBSource::GetSqlStringColumnDefinition(); - $aColumns[$this->GetCode() . '_downloads_count'] = 'INT(11) UNSIGNED'; + public function GetSQLColumns($bFullSpec = false) + { + $aColumns = array(); + $aColumns[$this->GetCode().'_data'] = 'LONGBLOB'; // 2^32 (4 Gb) + $aColumns[$this->GetCode().'_mimetype'] = 'VARCHAR(255)'.CMDBSource::GetSqlStringColumnDefinition(); + $aColumns[$this->GetCode().'_filename'] = 'VARCHAR(255)'.CMDBSource::GetSqlStringColumnDefinition(); + $aColumns[$this->GetCode().'_downloads_count'] = 'INT(11) UNSIGNED'; - return $aColumns; - } + return $aColumns; + } - public function GetBasicFilterOperators() - { - return array(); - } + public function GetBasicFilterOperators() + { + return array(); + } - public function GetBasicFilterLooseOperator() - { - return '='; - } + public function GetBasicFilterLooseOperator() + { + return '='; + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - return 'true'; - } + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + return 'true'; + } - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - if (is_object($value)) { - return $value->GetAsHTML(); - } + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + if (is_object($value)) { + return $value->GetAsHTML(); + } - return ''; - } + return ''; + } - /** - * @param string $sValue - * @param string $sSeparator - * @param string $sTextQualifier - * @param \DBObject $oHostObject - * @param bool $bLocalize - * @param bool $bConvertToPlainText - * - * @return string - */ - public function GetAsCSV( - $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - $sAttCode = $this->GetCode(); - if ($sValue instanceof ormDocument && !$sValue->IsEmpty()) { - return $sValue->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $sAttCode); - } + /** + * @param string $sValue + * @param string $sSeparator + * @param string $sTextQualifier + * @param DBObject $oHostObject + * @param bool $bLocalize + * @param bool $bConvertToPlainText + * + * @return string + */ + public function GetAsCSV( + $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + $sAttCode = $this->GetCode(); + if ($sValue instanceof ormDocument && !$sValue->IsEmpty()) { + return $sValue->GetDownloadURL(get_class($oHostObject), $oHostObject->GetKey(), $sAttCode); + } - return ''; // Not exportable in CSV ! - } + return ''; // Not exportable in CSV ! + } - /** - * @param $value - * @param \DBObject $oHostObject - * @param bool $bLocalize - * - * @return mixed|string - */ - public function GetAsXML($value, $oHostObject = null, $bLocalize = true) - { - $sRet = ''; - if (is_object($value)) { - /** @var \ormDocument $value */ - if (!$value->IsEmpty()) { - $sRet = '' . $value->GetMimeType() . ''; - $sRet .= '' . $value->GetFileName() . ''; - $sRet .= '' . base64_encode($value->GetData()) . ''; - $sRet .= '' . $value->GetDownloadsCount() . ''; - } - } + /** + * @param $value + * @param DBObject $oHostObject + * @param bool $bLocalize + * + * @return mixed|string + */ + public function GetAsXML($value, $oHostObject = null, $bLocalize = true) + { + $sRet = ''; + if (is_object($value)) { + /** @var ormDocument $value */ + if (!$value->IsEmpty()) { + $sRet = ''.$value->GetMimeType().''; + $sRet .= ''.$value->GetFileName().''; + $sRet .= ''.base64_encode($value->GetData()).''; + $sRet .= ''.$value->GetDownloadsCount().''; + } + } - return $sRet; - } + return $sRet; + } - public function GetForJSON($value) - { - if ($value instanceof ormDocument) { - $aValues = array(); - $aValues['data'] = base64_encode($value->GetData()); - $aValues['mimetype'] = $value->GetMimeType(); - $aValues['filename'] = $value->GetFileName(); - $aValues['downloads_count'] = $value->GetDownloadsCount(); - } else { - $aValues = null; - } + public function GetForJSON($value) + { + if ($value instanceof ormDocument) { + $aValues = array(); + $aValues['data'] = base64_encode($value->GetData()); + $aValues['mimetype'] = $value->GetMimeType(); + $aValues['filename'] = $value->GetFileName(); + $aValues['downloads_count'] = $value->GetDownloadsCount(); + } else { + $aValues = null; + } - return $aValues; - } + return $aValues; + } - public function FromJSONToValue($json) - { - if (isset($json->data)) { - $data = base64_decode($json->data); - $value = new ormDocument($data, $json->mimetype, $json->filename, $json->downloads_count); - } else { - $value = null; - } + public function FromJSONToValue($json) + { + if (isset($json->data)) { + $data = base64_decode($json->data); + $value = new ormDocument($data, $json->mimetype, $json->filename, $json->downloads_count); + } else { + $value = null; + } - return $value; - } + return $value; + } - public function Fingerprint($value) - { - $sFingerprint = ''; - if ($value instanceof ormDocument) { - $sFingerprint = $value->GetSignature(); - } + public function Fingerprint($value) + { + $sFingerprint = ''; + if ($value instanceof ormDocument) { + $sFingerprint = $value->GetSignature(); + } - return $sFingerprint; - } + return $sFingerprint; + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\BlobField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\BlobField'; + } - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - /** @var $oFormField \Combodo\iTop\Form\Field\BlobField */ - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - } + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + /** @var $oFormField BlobField */ + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + } - // Note: As of today we want this field to always be read-only - $oFormField->SetReadOnly(true); + // Note: As of today we want this field to always be read-only + $oFormField->SetReadOnly(true); - // Calling parent before so current value is set, then proceed - parent::MakeFormField($oObject, $oFormField); + // Calling parent before so current value is set, then proceed + parent::MakeFormField($oObject, $oFormField); - // Setting current value correctly as the default method returns an empty string when there is no file yet. - /** @var \ormDocument $value */ - $value = $oObject->Get($this->GetCode()); - if (!is_object($value)) { - $oFormField->SetCurrentValue(new ormDocument()); - } + // Setting current value correctly as the default method returns an empty string when there is no file yet. + /** @var ormDocument $value */ + $value = $oObject->Get($this->GetCode()); + if (!is_object($value)) { + $oFormField->SetCurrentValue(new ormDocument()); + } - // Generating urls - if (is_object($value) && !$value->IsEmpty()) { - $oFormField->SetDownloadUrl($value->GetDownloadURL(get_class($oObject), $oObject->GetKey(), $this->GetCode())); - $oFormField->SetDisplayUrl($value->GetDisplayURL(get_class($oObject), $oObject->GetKey(), $this->GetCode())); - } + // Generating urls + if (is_object($value) && !$value->IsEmpty()) { + $oFormField->SetDownloadUrl($value->GetDownloadURL(get_class($oObject), $oObject->GetKey(), $this->GetCode())); + $oFormField->SetDisplayUrl($value->GetDisplayURL(get_class($oObject), $oObject->GetKey(), $this->GetCode())); + } - return $oFormField; - } + return $oFormField; + } - /** - * @inheritDoc - */ - public function HasAValue($proposedValue): bool - { - if (false === ($proposedValue instanceof ormDocument)) { - return parent::HasAValue($proposedValue); - } + /** + * @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()); - } + // 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()); + } - /** - * @inheritDoc - * @param \ormDocument $original - * @param \ormDocument $value - * @since N°6502 - */ - public function RecordAttChange(DBObject $oObject, $original, $value): void - { - // N°6502 Don't record history if only the download count has changed - if ((null !== $original) && (null !== $value) && $original->EqualsExceptDownloadsCount($value)) { - return; - } + /** + * @inheritDoc + * + * @param ormDocument $original + * @param ormDocument $value + * + * @since N°6502 + */ + public function RecordAttChange(DBObject $oObject, $original, $value): void + { + // N°6502 Don't record history if only the download count has changed + if ((null !== $original) && (null !== $value) && $original->EqualsExceptDownloadsCount($value)) { + return; + } - parent::RecordAttChange($oObject, $original, $value); - } + parent::RecordAttChange($oObject, $original, $value); + } - protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void - { - if (is_null($original)) { - $original = new ormDocument(); - } - $oMyChangeOp->Set("prevdata", $original); - } + protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void + { + if (is_null($original)) { + $original = new ormDocument(); + } + $oMyChangeOp->Set("prevdata", $original); + } - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeBlob::class; - } + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeBlob::class; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeBoolean.php b/sources/Core/AttributeDefinition/AttributeBoolean.php index ae90fcdab..bf39c2052 100644 --- a/sources/Core/AttributeDefinition/AttributeBoolean.php +++ b/sources/Core/AttributeDefinition/AttributeBoolean.php @@ -1,4 +1,15 @@ GetSQLColSpec() : ''); - } + protected function GetSQLCol($bFullSpec = false) + { + return "TINYINT(1)".($bFullSpec ? $this->GetSQLColSpec() : ''); + } - public function MakeRealValue($proposedValue, $oHostObj) - { - if (is_null($proposedValue)) { - return null; - } - if ($proposedValue === '') { - return null; - } - if ((int)$proposedValue) { - return true; - } + public function MakeRealValue($proposedValue, $oHostObj) + { + if (is_null($proposedValue)) { + return null; + } + if ($proposedValue === '') { + return null; + } + if ((int)$proposedValue) { + return true; + } - return false; - } + return false; + } - public function ScalarToSQL($value) - { - if ($value) { - return 1; - } + public function ScalarToSQL($value) + { + if ($value) { + return 1; + } - return 0; - } + return 0; + } - public function GetValueLabel($bValue) - { - if (is_null($bValue)) { - $sLabel = Dict::S('Core:' . get_class($this) . '/Value:null'); - } else { - $sValue = $bValue ? 'yes' : 'no'; - $sDefault = Dict::S('Core:' . get_class($this) . '/Value:' . $sValue); - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue, $sDefault, true /*user lang*/); - } + public function GetValueLabel($bValue) + { + if (is_null($bValue)) { + $sLabel = Dict::S('Core:'.get_class($this).'/Value:null'); + } else { + $sValue = $bValue ? 'yes' : 'no'; + $sDefault = Dict::S('Core:'.get_class($this).'/Value:'.$sValue); + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, $sDefault, true /*user lang*/); + } - return $sLabel; - } + return $sLabel; + } - public function GetValueDescription($bValue) - { - if (is_null($bValue)) { - $sDescription = Dict::S('Core:' . get_class($this) . '/Value:null+'); - } else { - $sValue = $bValue ? 'yes' : 'no'; - $sDefault = Dict::S('Core:' . get_class($this) . '/Value:' . $sValue . '+'); - $sDescription = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue . '+', $sDefault, - true /*user lang*/); - } + public function GetValueDescription($bValue) + { + if (is_null($bValue)) { + $sDescription = Dict::S('Core:'.get_class($this).'/Value:null+'); + } else { + $sValue = $bValue ? 'yes' : 'no'; + $sDefault = Dict::S('Core:'.get_class($this).'/Value:'.$sValue.'+'); + $sDescription = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue.'+', $sDefault, + true /*user lang*/); + } - return $sDescription; - } + return $sDescription; + } - public function GetAsHTML($bValue, $oHostObject = null, $bLocalize = true) - { - if (is_null($bValue)) { - $sRes = ''; - } elseif ($bLocalize) { - $sLabel = $this->GetValueLabel($bValue); - $sDescription = $this->GetValueDescription($bValue); - // later, we could imagine a detailed description in the title - $sRes = "" . parent::GetAsHtml($sLabel) . ""; - } else { - $sRes = $bValue ? 'yes' : 'no'; - } + public function GetAsHTML($bValue, $oHostObject = null, $bLocalize = true) + { + if (is_null($bValue)) { + $sRes = ''; + } elseif ($bLocalize) { + $sLabel = $this->GetValueLabel($bValue); + $sDescription = $this->GetValueDescription($bValue); + // later, we could imagine a detailed description in the title + $sRes = "".parent::GetAsHtml($sLabel).""; + } else { + $sRes = $bValue ? 'yes' : 'no'; + } - return $sRes; - } + return $sRes; + } - public function GetAsXML($bValue, $oHostObject = null, $bLocalize = true) - { - if (is_null($bValue)) { - $sFinalValue = ''; - } elseif ($bLocalize) { - $sFinalValue = $this->GetValueLabel($bValue); - } else { - $sFinalValue = $bValue ? 'yes' : 'no'; - } - $sRes = parent::GetAsXML($sFinalValue, $oHostObject, $bLocalize); + public function GetAsXML($bValue, $oHostObject = null, $bLocalize = true) + { + if (is_null($bValue)) { + $sFinalValue = ''; + } elseif ($bLocalize) { + $sFinalValue = $this->GetValueLabel($bValue); + } else { + $sFinalValue = $bValue ? 'yes' : 'no'; + } + $sRes = parent::GetAsXML($sFinalValue, $oHostObject, $bLocalize); - return $sRes; - } + return $sRes; + } - public function GetAsCSV( - $bValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - if (is_null($bValue)) { - $sFinalValue = ''; - } elseif ($bLocalize) { - $sFinalValue = $this->GetValueLabel($bValue); - } else { - $sFinalValue = $bValue ? 'yes' : 'no'; - } - $sRes = parent::GetAsCSV($sFinalValue, $sSeparator, $sTextQualifier, $oHostObject, $bLocalize); + public function GetAsCSV( + $bValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + if (is_null($bValue)) { + $sFinalValue = ''; + } elseif ($bLocalize) { + $sFinalValue = $this->GetValueLabel($bValue); + } else { + $sFinalValue = $bValue ? 'yes' : 'no'; + } + $sRes = parent::GetAsCSV($sFinalValue, $sSeparator, $sTextQualifier, $oHostObject, $bLocalize); - return $sRes; - } + return $sRes; + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\SelectField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\SelectField'; + } - /** - * @param \DBObject $oObject - * @param \Combodo\iTop\Form\Field\SelectField $oFormField - * - * @return \Combodo\iTop\Form\Field\SelectField - * @throws \CoreException - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - } + /** + * @param DBObject $oObject + * @param SelectField $oFormField + * + * @return SelectField + * @throws CoreException + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + } - $oFormField->SetChoices(array('yes' => $this->GetValueLabel(true), 'no' => $this->GetValueLabel(false))); - parent::MakeFormField($oObject, $oFormField); + $oFormField->SetChoices(array('yes' => $this->GetValueLabel(true), 'no' => $this->GetValueLabel(false))); + parent::MakeFormField($oObject, $oFormField); - return $oFormField; - } + return $oFormField; + } - public function GetEditValue($value, $oHostObj = null) - { - if (is_null($value)) { - return ''; - } else { - return $this->GetValueLabel($value); - } - } + public function GetEditValue($value, $oHostObj = null) + { + if (is_null($value)) { + return ''; + } else { + return $this->GetValueLabel($value); + } + } - public function GetForJSON($value) - { - return (bool)$value; - } + public function GetForJSON($value) + { + return (bool)$value; + } - public function MakeValueFromString( - $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, - $sAttributeQualifier = null - ) - { - $sInput = mb_strtolower(trim($sProposedValue)); - if ($bLocalizedValue) { - switch ($sInput) { - case '1': // backward compatibility - case $this->GetValueLabel(true): - $value = true; - break; - case '0': // backward compatibility - case 'no': - case $this->GetValueLabel(false): - $value = false; - break; - default: - $value = null; - } - } else { - switch ($sInput) { - case '1': // backward compatibility - case 'yes': - $value = true; - break; - case '0': // backward compatibility - case 'no': - $value = false; - break; - default: - $value = null; - } - } + public function MakeValueFromString( + $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, + $sAttributeQualifier = null + ) + { + $sInput = mb_strtolower(trim($sProposedValue)); + if ($bLocalizedValue) { + switch ($sInput) { + case '1': // backward compatibility + case $this->GetValueLabel(true): + $value = true; + break; + case '0': // backward compatibility + case 'no': + case $this->GetValueLabel(false): + $value = false; + break; + default: + $value = null; + } + } else { + switch ($sInput) { + case '1': // backward compatibility + case 'yes': + $value = true; + break; + case '0': // backward compatibility + case 'no': + $value = false; + break; + default: + $value = null; + } + } - return $value; - } + return $value; + } - public function RecordAttChange(DBObject $oObject, $original, $value): void - { - parent::RecordAttChange($oObject, $original ? 1 : 0, $value ? 1 : 0); - } + public function RecordAttChange(DBObject $oObject, $original, $value): void + { + parent::RecordAttChange($oObject, $original ? 1 : 0, $value ? 1 : 0); + } - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeScalar::class; - } + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeScalar::class; + } - public function GetAllowedValues($aArgs = array(), $sContains = ''): array - { - return [ - 0 => $this->GetValueLabel(false), - 1 => $this->GetValueLabel(true) - ]; - } + public function GetAllowedValues($aArgs = array(), $sContains = ''): array + { + return [ + 0 => $this->GetValueLabel(false), + 1 => $this->GetValueLabel(true), + ]; + } - public function GetDisplayStyle() - { - return $this->GetOptional('display_style', 'select'); - } + public function GetDisplayStyle() + { + return $this->GetOptional('display_style', 'select'); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeCaseLog.php b/sources/Core/AttributeDefinition/AttributeCaseLog.php index 441a12ffb..fe276674d 100644 --- a/sources/Core/AttributeDefinition/AttributeCaseLog.php +++ b/sources/Core/AttributeDefinition/AttributeCaseLog.php @@ -1,4 +1,22 @@ GetText() == ''); - } + 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); - } + /** + * @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; - } + // 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)) { - throw new CoreWarning('Expected the attribute value to be a string', array( - 'found_type' => gettype($value), - 'value' => $value, - 'class' => $this->GetCode(), - 'attribute' => $this->GetHostClass() - )); - } + public function ScalarToSQL($value) + { + if (!is_string($value) && !is_null($value)) { + throw new CoreWarning('Expected the attribute value to be a string', array( + 'found_type' => gettype($value), + 'value' => $value, + 'class' => $this->GetCode(), + 'attribute' => $this->GetHostClass(), + )); + } - return $value; - } + return $value; + } - public function GetEditClass() - { - return "CaseLog"; - } + public function GetEditClass() + { + return "CaseLog"; + } - public function GetEditValue($sValue, $oHostObj = null) - { - if (!($sValue instanceof ormCaseLog)) { - return ''; - } + public function GetEditValue($sValue, $oHostObj = null) + { + if (!($sValue instanceof ormCaseLog)) { + return ''; + } - return $sValue->GetModifiedEntry(); - } + return $sValue->GetModifiedEntry(); + } - /** - * For fields containing a potential markup, return the value without this markup - * - * @param mixed $value - * @param \DBObject $oHostObj - * - * @return string - */ - public function GetAsPlainText($value, $oHostObj = null) - { - if ($value instanceof ormCaseLog) { - /** ormCaseLog $value */ - return $value->GetAsPlainText(); - } else { - return (string)$value; - } - } + /** + * For fields containing a potential markup, return the value without this markup + * + * @param mixed $value + * @param \DBObject $oHostObj + * + * @return string + */ + public function GetAsPlainText($value, $oHostObj = null) + { + if ($value instanceof ormCaseLog) { + /** ormCaseLog $value */ + return $value->GetAsPlainText(); + } else { + return (string)$value; + } + } - public function GetDefaultValue(DBObject $oHostObject = null) - { - return new ormCaseLog(); - } + public function GetDefaultValue(DBObject $oHostObject = null) + { + return new ormCaseLog(); + } - public function Equals($val1, $val2) - { - return ($val1->GetText() == $val2->GetText()); - } + public function Equals($val1, $val2) + { + return ($val1->GetText() == $val2->GetText()); + } - /** - * Facilitate things: allow the user to Set the value from a string - * - * @param $proposedValue - * @param \DBObject $oHostObj - * - * @return mixed|null|\ormCaseLog|string - * @throws \Exception - */ - public function MakeRealValue($proposedValue, $oHostObj) - { - if ($proposedValue instanceof ormCaseLog) { - // Passthrough - $ret = clone $proposedValue; - } else { - // Append the new value if an instance of the object is supplied - // - $oPreviousLog = null; - if ($oHostObj != null) { - $oPreviousLog = $oHostObj->Get($this->GetCode()); - if (!is_object($oPreviousLog)) { - $oPreviousLog = $oHostObj->GetOriginal($this->GetCode());; - } + /** + * Facilitate things: allow the user to Set the value from a string + * + * @param $proposedValue + * @param DBObject $oHostObj + * + * @return mixed|null|ormCaseLog|string + * @throws Exception + */ + public function MakeRealValue($proposedValue, $oHostObj) + { + if ($proposedValue instanceof ormCaseLog) { + // Passthrough + $ret = clone $proposedValue; + } else { + // Append the new value if an instance of the object is supplied + // + $oPreviousLog = null; + if ($oHostObj != null) { + $oPreviousLog = $oHostObj->Get($this->GetCode()); + if (!is_object($oPreviousLog)) { + $oPreviousLog = $oHostObj->GetOriginal($this->GetCode());; + } - } - if (is_object($oPreviousLog)) { - $oCaseLog = clone($oPreviousLog); - } else { - $oCaseLog = new ormCaseLog(); - } + } + if (is_object($oPreviousLog)) { + $oCaseLog = clone($oPreviousLog); + } else { + $oCaseLog = new ormCaseLog(); + } - if ($proposedValue instanceof stdClass) { - $oCaseLog->AddLogEntryFromJSON($proposedValue); - } else { - if (utils::StrLen($proposedValue) > 0) { - //N°5135 - add impersonation information in caselog - if (UserRights::IsImpersonated()) { - $sOnBehalfOf = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName()); - $oCaseLog->AddLogEntry($proposedValue, $sOnBehalfOf, UserRights::GetConnectedUserId()); - } else { - $oCaseLog->AddLogEntry($proposedValue); - } - } - } - $ret = $oCaseLog; - } + if ($proposedValue instanceof stdClass) { + $oCaseLog->AddLogEntryFromJSON($proposedValue); + } else { + if (utils::StrLen($proposedValue) > 0) { + //N°5135 - add impersonation information in caselog + if (UserRights::IsImpersonated()) { + $sOnBehalfOf = Dict::Format('UI:Archive_User_OnBehalfOf_User', UserRights::GetRealUserFriendlyName(), UserRights::GetUserFriendlyName()); + $oCaseLog->AddLogEntry($proposedValue, $sOnBehalfOf, UserRights::GetConnectedUserId()); + } else { + $oCaseLog->AddLogEntry($proposedValue); + } + } + } + $ret = $oCaseLog; + } - return $ret; - } + return $ret; + } - public function GetSQLExpressions($sPrefix = '') - { - if ($sPrefix == '') { - $sPrefix = $this->Get('sql'); - } - $aColumns = array(); - // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix - $aColumns[''] = $sPrefix; - $aColumns['_index'] = $sPrefix . '_index'; + public function GetSQLExpressions($sPrefix = '') + { + if ($sPrefix == '') { + $sPrefix = $this->Get('sql'); + } + $aColumns = array(); + // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix + $aColumns[''] = $sPrefix; + $aColumns['_index'] = $sPrefix.'_index'; - return $aColumns; - } + return $aColumns; + } - /** - * @param array $aCols - * @param string $sPrefix - * - * @return \ormCaseLog - * @throws \MissingColumnException - */ - public function FromSQLToValue($aCols, $sPrefix = '') - { - if (!array_key_exists($sPrefix, $aCols)) { - $sAvailable = implode(', ', array_keys($aCols)); - throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}"); - } - $sLog = $aCols[$sPrefix]; + /** + * @param array $aCols + * @param string $sPrefix + * + * @return ormCaseLog + * @throws MissingColumnException + */ + public function FromSQLToValue($aCols, $sPrefix = '') + { + if (!array_key_exists($sPrefix, $aCols)) { + $sAvailable = implode(', ', array_keys($aCols)); + throw new MissingColumnException("Missing column '$sPrefix' from {$sAvailable}"); + } + $sLog = $aCols[$sPrefix]; - if (isset($aCols[$sPrefix . '_index'])) { - $sIndex = $aCols[$sPrefix . '_index']; - } else { - // For backward compatibility, allow the current state to be: 1 log, no index - $sIndex = ''; - } + if (isset($aCols[$sPrefix.'_index'])) { + $sIndex = $aCols[$sPrefix.'_index']; + } else { + // For backward compatibility, allow the current state to be: 1 log, no index + $sIndex = ''; + } - if (strlen($sIndex) > 0) { - $aIndex = unserialize($sIndex); - $value = new ormCaseLog($sLog, $aIndex); - } else { - $value = new ormCaseLog($sLog); - } + if (strlen($sIndex) > 0) { + $aIndex = unserialize($sIndex); + $value = new ormCaseLog($sLog, $aIndex); + } else { + $value = new ormCaseLog($sLog); + } - return $value; - } + return $value; + } - public function GetSQLValues($value) - { - if (!($value instanceof ormCaseLog)) { - $value = new ormCaseLog(''); - } - $aValues = array(); - $aValues[$this->GetCode()] = $value->GetText(); - $aValues[$this->GetCode() . '_index'] = serialize($value->GetIndex()); + public function GetSQLValues($value) + { + if (!($value instanceof ormCaseLog)) { + $value = new ormCaseLog(''); + } + $aValues = array(); + $aValues[$this->GetCode()] = $value->GetText(); + $aValues[$this->GetCode().'_index'] = serialize($value->GetIndex()); - return $aValues; - } + return $aValues; + } - public function GetSQLColumns($bFullSpec = false) - { - $aColumns = array(); - $aColumns[$this->GetCode()] = 'LONGTEXT' // 2^32 (4 Gb) - . CMDBSource::GetSqlStringColumnDefinition(); - $aColumns[$this->GetCode() . '_index'] = 'BLOB'; + public function GetSQLColumns($bFullSpec = false) + { + $aColumns = array(); + $aColumns[$this->GetCode()] = 'LONGTEXT' // 2^32 (4 Gb) + .CMDBSource::GetSqlStringColumnDefinition(); + $aColumns[$this->GetCode().'_index'] = 'BLOB'; - return $aColumns; - } + return $aColumns; + } - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - if ($value instanceof ormCaseLog) { - $sContent = $value->GetAsHTML(null, false, array(__class__, 'RenderWikiHtml')); - } else { - $sContent = ''; - } - $aStyles = array(); - if ($this->GetWidth() != '') { - $aStyles[] = 'width:' . $this->GetWidth(); - } - if ($this->GetHeight() != '') { - $aStyles[] = 'height:' . $this->GetHeight(); - } - $sStyle = ''; - if (count($aStyles) > 0) { - $sStyle = 'style="' . implode(';', $aStyles) . '"'; - } + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + if ($value instanceof ormCaseLog) { + $sContent = $value->GetAsHTML(null, false, array(__class__, 'RenderWikiHtml')); + } else { + $sContent = ''; + } + $aStyles = array(); + if ($this->GetWidth() != '') { + $aStyles[] = 'width:'.$this->GetWidth(); + } + if ($this->GetHeight() != '') { + $aStyles[] = 'height:'.$this->GetHeight(); + } + $sStyle = ''; + if (count($aStyles) > 0) { + $sStyle = 'style="'.implode(';', $aStyles).'"'; + } - return "
" . $sContent . '
'; - } + return "
".$sContent.'
'; + } - public function GetAsCSV( - $value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - if ($value instanceof ormCaseLog) { - return parent::GetAsCSV($value->GetText($bConvertToPlainText), $sSeparator, $sTextQualifier, $oHostObject, - $bLocalize, $bConvertToPlainText); - } else { - return ''; - } - } + public function GetAsCSV( + $value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + if ($value instanceof ormCaseLog) { + return parent::GetAsCSV($value->GetText($bConvertToPlainText), $sSeparator, $sTextQualifier, $oHostObject, + $bLocalize, $bConvertToPlainText); + } else { + return ''; + } + } - public function GetAsXML($value, $oHostObject = null, $bLocalize = true) - { - if ($value instanceof ormCaseLog) { - return parent::GetAsXML($value->GetText(), $oHostObject, $bLocalize); - } else { - return ''; - } - } + public function GetAsXML($value, $oHostObject = null, $bLocalize = true) + { + if ($value instanceof ormCaseLog) { + return parent::GetAsXML($value->GetText(), $oHostObject, $bLocalize); + } else { + return ''; + } + } - /** - * List the available verbs for 'GetForTemplate' - */ - public function EnumTemplateVerbs() - { - return array( - '' => 'Plain text representation of all the log entries', - 'head' => 'Plain text representation of the latest entry', - 'head_html' => 'HTML representation of the latest entry', - 'html' => 'HTML representation of all the log entries', - ); - } + /** + * List the available verbs for 'GetForTemplate' + */ + public function EnumTemplateVerbs() + { + return array( + '' => 'Plain text representation of all the log entries', + 'head' => 'Plain text representation of the latest entry', + 'head_html' => 'HTML representation of the latest entry', + 'html' => 'HTML representation of all the log entries', + ); + } - /** - * Get various representations of the value, for insertion into a template (e.g. in Notifications) - * - * @param $value mixed The current value of the field - * @param $sVerb string The verb specifying the representation of the value - * @param $oHostObject DBObject The object - * @param $bLocalize bool Whether or not to localize the value - * - * @return mixed - * @throws \Exception - */ - public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) - { - switch ($sVerb) { - case '': - return $value->GetText(true); + /** + * Get various representations of the value, for insertion into a template (e.g. in Notifications) + * + * @param $value mixed The current value of the field + * @param $sVerb string The verb specifying the representation of the value + * @param $oHostObject DBObject The object + * @param $bLocalize bool Whether or not to localize the value + * + * @return mixed + * @throws \Exception + */ + public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) + { + switch ($sVerb) { + case '': + return $value->GetText(true); - case 'head': - return $value->GetLatestEntry('text'); + case 'head': + return $value->GetLatestEntry('text'); - case 'head_html': - return $value->GetLatestEntry('html'); + case 'head_html': + return $value->GetLatestEntry('html'); - case 'html': - return $value->GetAsEmailHtml(); + case 'html': + return $value->GetAsEmailHtml(); - default: - throw new Exception("Unknown verb '$sVerb' for attribute " . $this->GetCode() . ' in class ' . get_class($oHostObject)); - } - } + default: + throw new \Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObject)); + } + } - public function GetForJSON($value) - { - return $value->GetForJSON(); - } + public function GetForJSON($value) + { + return $value->GetForJSON(); + } - public function FromJSONToValue($json) - { - if (is_string($json)) { - // Will be correctly handled in MakeRealValue - $ret = $json; - } else { - if (isset($json->add_item)) { - // Will be correctly handled in MakeRealValue - $ret = $json->add_item; - if (!isset($ret->message)) { - throw new Exception("Missing mandatory entry: 'message'"); - } - } else { - $ret = ormCaseLog::FromJSON($json); - } - } + public function FromJSONToValue($json) + { + if (is_string($json)) { + // Will be correctly handled in MakeRealValue + $ret = $json; + } else { + if (isset($json->add_item)) { + // Will be correctly handled in MakeRealValue + $ret = $json->add_item; + if (!isset($ret->message)) { + throw new Exception("Missing mandatory entry: 'message'"); + } + } else { + $ret = ormCaseLog::FromJSON($json); + } + } - return $ret; - } + return $ret; + } - public function Fingerprint($value) - { - $sFingerprint = ''; - if ($value instanceof ormCaseLog) { - $sFingerprint = $value->GetText(); - } + public function Fingerprint($value) + { + $sFingerprint = ''; + if ($value instanceof ormCaseLog) { + $sFingerprint = $value->GetText(); + } - return $sFingerprint; - } + return $sFingerprint; + } - /** - * The actual formatting of the text: either text (=plain text) or html (= text with HTML markup) - * - * @return string - */ - public function GetFormat() - { - return $this->GetOptional('format', 'html'); // default format for case logs is now HTML - } + /** + * The actual formatting of the text: either text (=plain text) or html (= text with HTML markup) + * + * @return string + */ + public function GetFormat() + { + return $this->GetOptional('format', 'html'); // default format for case logs is now HTML + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\CaseLogField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\CaseLogField'; + } - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - // First we call the parent so the field is build - $oFormField = parent::MakeFormField($oObject, $oFormField); - // Then only we set the value - $oFormField->SetCurrentValue($this->GetEditValue($oObject->Get($this->GetCode()))); - // And we set the entries - $oFormField->SetEntries($oObject->Get($this->GetCode())->GetAsArray()); + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + // First we call the parent so the field is build + $oFormField = parent::MakeFormField($oObject, $oFormField); + // Then only we set the value + $oFormField->SetCurrentValue($this->GetEditValue($oObject->Get($this->GetCode()))); + // And we set the entries + $oFormField->SetEntries($oObject->Get($this->GetCode())->GetAsArray()); - return $oFormField; - } + return $oFormField; + } - protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void - { - /** @var \ormCaseLog $value */ - $oMyChangeOp->Set("lastentry", $value->GetLatestEntryIndex()); - } + protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void + { + /** @var ormCaseLog $value */ + $oMyChangeOp->Set("lastentry", $value->GetLatestEntryIndex()); + } - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeCaseLog::class; - } + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeCaseLog::class; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeClass.php b/sources/Core/AttributeDefinition/AttributeClass.php index dd48068fd..c604a288c 100644 --- a/sources/Core/AttributeDefinition/AttributeClass.php +++ b/sources/Core/AttributeDefinition/AttributeClass.php @@ -1,4 +1,14 @@ m_sCode = $sCode; - $aParams["allowed_values"] = new ValueSetEnumClasses($aParams['class_category'], $aParams['more_values']); - parent::__construct($sCode, $aParams); - } + public function __construct($sCode, $aParams) + { + $this->m_sCode = $sCode; + $aParams["allowed_values"] = new ValueSetEnumClasses($aParams['class_category'], $aParams['more_values']); + parent::__construct($sCode, $aParams); + } - public function GetDefaultValue(DBObject $oHostObject = null) - { - $sDefault = parent::GetDefaultValue($oHostObject); - if (!$this->IsNullAllowed() && $this->IsNull($sDefault)) { - // For this kind of attribute specifying null as default value - // is authorized even if null is not allowed + public function GetDefaultValue(DBObject $oHostObject = null) + { + $sDefault = parent::GetDefaultValue($oHostObject); + if (!$this->IsNullAllowed() && $this->IsNull($sDefault)) { + // For this kind of attribute specifying null as default value + // is authorized even if null is not allowed - // Pick the first one... - $aClasses = $this->GetAllowedValues(); - $sDefault = key($aClasses); - } + // Pick the first one... + $aClasses = $this->GetAllowedValues(); + $sDefault = key($aClasses); + } - return $sDefault; - } + return $sDefault; + } - /** - * @param array $aArgs - * @param string $sContains - * - * @return array|null - * @throws \CoreException - */ - public function GetAllowedValues($aArgs = array(), $sContains = '') - { - $oValSetDef = $this->GetValuesDef(); - if (!$oValSetDef) { - return null; - } + /** + * @param array $aArgs + * @param string $sContains + * + * @return array|null + * @throws \CoreException + */ + public function GetAllowedValues($aArgs = array(), $sContains = '') + { + $oValSetDef = $this->GetValuesDef(); + if (!$oValSetDef) { + return null; + } - $aListClass = $oValSetDef->GetValues($aArgs, $sContains); - /* @since 3.3.0 remove elements in class_exclusion_list */ - $sClassExclusionList = $this->GetOptional('class_exclusion_list', null); - if (!empty($sClassExclusionList)) { - foreach (explode(',', $sClassExclusionList) as $sClassName) { - unset($aListClass[trim($sClassName)]); - } - } + $aListClass = $oValSetDef->GetValues($aArgs, $sContains); + /* @since 3.3.0 remove elements in class_exclusion_list */ + $sClassExclusionList = $this->GetOptional('class_exclusion_list', null); + if (!empty($sClassExclusionList)) { + foreach (explode(',', $sClassExclusionList) as $sClassName) { + unset($aListClass[trim($sClassName)]); + } + } - return $aListClass; - } + return $aListClass; + } - public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) - { - if (empty($sValue)) { - return ''; - } + public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) + { + if (empty($sValue)) { + return ''; + } - return MetaModel::GetName($sValue); - } + return MetaModel::GetName($sValue); + } - public function RequiresIndex() - { - return true; - } + public function RequiresIndex() + { + return true; + } - public function GetBasicFilterLooseOperator() - { - return '='; - } + public function GetBasicFilterLooseOperator() + { + return '='; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php b/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php index 594b6adf3..700e2c4f2 100644 --- a/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php +++ b/sources/Core/AttributeDefinition/AttributeClassAttCodeSet.php @@ -1,214 +1,229 @@ aCSSClasses[] = 'attribute-class-attcode-set'; - } + public function __construct($sCode, array $aParams) + { + parent::__construct($sCode, $aParams); + $this->aCSSClasses[] = 'attribute-class-attcode-set'; + } - public static function ListExpectedParams() - { - return array_merge(parent::ListExpectedParams(), array('class_field', 'attribute_definition_list', 'attribute_definition_exclusion_list')); - } + public static function ListExpectedParams() + { + return array_merge(parent::ListExpectedParams(), array('class_field', 'attribute_definition_list', 'attribute_definition_exclusion_list')); + } - public function GetMaxSize() - { - return max(255, 15 * $this->GetMaxItems()); - } + public function GetMaxSize() + { + return max(255, 15 * $this->GetMaxItems()); + } - /** - * @param array $aArgs - * @param string $sContains - * - * @return array|null - * @throws \CoreException - */ - public function GetAllowedValues($aArgs = array(), $sContains = '') - { - if (!isset($aArgs['this'])) { - return null; - } + /** + * @param array $aArgs + * @param string $sContains + * + * @return array|null + * @throws \CoreException + */ + public function GetAllowedValues($aArgs = array(), $sContains = '') + { + if (!isset($aArgs['this'])) { + return null; + } - $oHostObj = $aArgs['this']; - $sTargetClass = $this->Get('class_field'); - $sRootClass = $oHostObj->Get($sTargetClass); - $bIncludeChildClasses = $this->GetOptional('include_child_classes_attributes', static::DEFAULT_PARAM_INCLUDE_CHILD_CLASSES_ATTRIBUTES); + $oHostObj = $aArgs['this']; + $sTargetClass = $this->Get('class_field'); + $sRootClass = $oHostObj->Get($sTargetClass); + $bIncludeChildClasses = $this->GetOptional('include_child_classes_attributes', static::DEFAULT_PARAM_INCLUDE_CHILD_CLASSES_ATTRIBUTES); - $aExcludeDefs = array(); - $sAttDefExclusionList = $this->Get('attribute_definition_exclusion_list'); - if (!empty($sAttDefExclusionList)) { - foreach (explode(',', $sAttDefExclusionList) as $sAttDefName) { - $sAttDefName = trim($sAttDefName); - $aExcludeDefs[$sAttDefName] = $sAttDefName; - } - } + $aExcludeDefs = array(); + $sAttDefExclusionList = $this->Get('attribute_definition_exclusion_list'); + if (!empty($sAttDefExclusionList)) { + foreach (explode(',', $sAttDefExclusionList) as $sAttDefName) { + $sAttDefName = trim($sAttDefName); + $aExcludeDefs[$sAttDefName] = $sAttDefName; + } + } - $aAllowedDefs = array(); - $sAttDefList = $this->Get('attribute_definition_list'); - if (!empty($sAttDefList)) { - foreach (explode(',', $sAttDefList) as $sAttDefName) { - $sAttDefName = trim($sAttDefName); - $aAllowedDefs[$sAttDefName] = $sAttDefName; - } - } + $aAllowedDefs = array(); + $sAttDefList = $this->Get('attribute_definition_list'); + if (!empty($sAttDefList)) { + foreach (explode(',', $sAttDefList) as $sAttDefName) { + $sAttDefName = trim($sAttDefName); + $aAllowedDefs[$sAttDefName] = $sAttDefName; + } + } - $aAllAttributes = array(); - if (!empty($sRootClass)) { - $aClasses = array($sRootClass); - if ($bIncludeChildClasses === true) { - $aClasses = $aClasses + MetaModel::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_EXCLUDETOP); - } + $aAllAttributes = array(); + if (!empty($sRootClass)) { + $aClasses = array($sRootClass); + if ($bIncludeChildClasses === true) { + $aClasses = $aClasses + MetaModel::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_EXCLUDETOP); + } - foreach ($aClasses as $sClass) { - foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) { - // Add attribute only if not already there (can be in leaf classes but not the root) - if (!array_key_exists($sAttCode, $aAllAttributes)) { - $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); - $sAttDefClass = get_class($oAttDef); + foreach ($aClasses as $sClass) { + foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) { + // Add attribute only if not already there (can be in leaf classes but not the root) + if (!array_key_exists($sAttCode, $aAllAttributes)) { + $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + $sAttDefClass = get_class($oAttDef); - // Skip excluded attdefs - if (isset($aExcludeDefs[$sAttDefClass])) { - continue; - } - // Skip not allowed attdefs only if list specified - if (!empty($aAllowedDefs) && !isset($aAllowedDefs[$sAttDefClass])) { - continue; - } + // Skip excluded attdefs + if (isset($aExcludeDefs[$sAttDefClass])) { + continue; + } + // Skip not allowed attdefs only if list specified + if (!empty($aAllowedDefs) && !isset($aAllowedDefs[$sAttDefClass])) { + continue; + } - $aAllAttributes[$sAttCode] = array( - 'classes' => array($sClass), - ); - } else { - $aAllAttributes[$sAttCode]['classes'][] = $sClass; - } - } - } - } + $aAllAttributes[$sAttCode] = array( + 'classes' => array($sClass), + ); + } else { + $aAllAttributes[$sAttCode]['classes'][] = $sClass; + } + } + } + } - $aAllowedAttributes = array(); - foreach ($aAllAttributes as $sAttCode => $aAttData) { - $iAttClassesCount = count($aAttData['classes']); - $sAttFirstClass = $aAttData['classes'][0]; - $sAttLabel = MetaModel::GetLabel($sAttFirstClass, $sAttCode); + $aAllowedAttributes = array(); + foreach ($aAllAttributes as $sAttCode => $aAttData) { + $iAttClassesCount = count($aAttData['classes']); + $sAttFirstClass = $aAttData['classes'][0]; + $sAttLabel = MetaModel::GetLabel($sAttFirstClass, $sAttCode); - if ($sAttFirstClass === $sRootClass) { - $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromClass', $sAttCode, $sAttLabel); - } elseif ($iAttClassesCount === 1) { - $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromOneChildClass', $sAttCode, $sAttLabel, MetaModel::GetName($sAttFirstClass)); - } else { - $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromSeveralChildClasses', $sAttCode, $sAttLabel); - } - $aAllowedAttributes[$sAttCode] = $sLabel; - } - // N°6460 Always sort on the labels, not on the datamodel definition order - natcasesort($aAllowedAttributes); + if ($sAttFirstClass === $sRootClass) { + $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromClass', $sAttCode, $sAttLabel); + } elseif ($iAttClassesCount === 1) { + $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromOneChildClass', $sAttCode, $sAttLabel, MetaModel::GetName($sAttFirstClass)); + } else { + $sLabel = Dict::Format('Core:AttributeClassAttCodeSet:ItemLabel:AttributeFromSeveralChildClasses', $sAttCode, $sAttLabel); + } + $aAllowedAttributes[$sAttCode] = $sLabel; + } + // N°6460 Always sort on the labels, not on the datamodel definition order + natcasesort($aAllowedAttributes); - return $aAllowedAttributes; - } + return $aAllowedAttributes; + } - /** - * force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing! - * - * @param $proposedValue - * @param \DBObject $oHostObj - * - * @param bool $bIgnoreErrors - * - * @return mixed - * @throws \CoreException - * @throws \CoreUnexpectedValue - * @throws \Exception - */ - public function MakeRealValue($proposedValue, $oHostObj, $bIgnoreErrors = false) - { - $oSet = new ormSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems()); - $aArgs = array(); - if (!empty($oHostObj)) { - $aArgs['this'] = $oHostObj; - } - $aAllowedAttributes = $this->GetAllowedValues($aArgs); - $aInvalidAttCodes = array(); - if (is_string($proposedValue) && !empty($proposedValue)) { - $aJsonFromWidget = json_decode($proposedValue, true); - if (is_null($aJsonFromWidget)) { - $proposedValue = trim($proposedValue); - $aProposedValues = $this->FromStringToArray($proposedValue); - $aValues = array(); - foreach ($aProposedValues as $sValue) { - $sAttCode = trim($sValue); - if (empty($aAllowedAttributes) || isset($aAllowedAttributes[$sAttCode])) { - $aValues[$sAttCode] = $sAttCode; - } else { - $aInvalidAttCodes[] = $sAttCode; - } - } - $oSet->SetValues($aValues); - } - } elseif ($proposedValue instanceof ormSet) { - $oSet = $proposedValue; - } - if (!empty($aInvalidAttCodes) && !$bIgnoreErrors) { - $sTargetClass = $this->Get('class_field'); - $sClass = $oHostObj->Get($sTargetClass); - throw new CoreUnexpectedValue("The attribute(s) " . implode(', ', $aInvalidAttCodes) . " are invalid for class {$sClass}"); - } + /** + * force an allowed value (type conversion and possibly forces a value as mySQL would do upon writing! + * + * @param $proposedValue + * @param DBObject $oHostObj + * + * @param bool $bIgnoreErrors + * + * @return mixed + * @throws CoreException + * @throws CoreUnexpectedValue + * @throws Exception + */ + public function MakeRealValue($proposedValue, $oHostObj, $bIgnoreErrors = false) + { + $oSet = new ormSet(MetaModel::GetAttributeOrigin($this->GetHostClass(), $this->GetCode()), $this->GetCode(), $this->GetMaxItems()); + $aArgs = array(); + if (!empty($oHostObj)) { + $aArgs['this'] = $oHostObj; + } + $aAllowedAttributes = $this->GetAllowedValues($aArgs); + $aInvalidAttCodes = array(); + if (is_string($proposedValue) && !empty($proposedValue)) { + $aJsonFromWidget = json_decode($proposedValue, true); + if (is_null($aJsonFromWidget)) { + $proposedValue = trim($proposedValue); + $aProposedValues = $this->FromStringToArray($proposedValue); + $aValues = array(); + foreach ($aProposedValues as $sValue) { + $sAttCode = trim($sValue); + if (empty($aAllowedAttributes) || isset($aAllowedAttributes[$sAttCode])) { + $aValues[$sAttCode] = $sAttCode; + } else { + $aInvalidAttCodes[] = $sAttCode; + } + } + $oSet->SetValues($aValues); + } + } elseif ($proposedValue instanceof ormSet) { + $oSet = $proposedValue; + } + if (!empty($aInvalidAttCodes) && !$bIgnoreErrors) { + $sTargetClass = $this->Get('class_field'); + $sClass = $oHostObj->Get($sTargetClass); + throw new CoreUnexpectedValue("The attribute(s) ".implode(', ', $aInvalidAttCodes)." are invalid for class {$sClass}"); + } - return $oSet; - } + return $oSet; + } - /** - * @param $value - * @param \DBObject $oHostObject - * @param bool $bLocalize - * - * @return string|null - * - * @throws \Exception - */ - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - if ($value instanceof ormSet) { - $value = $value->GetValues(); - } - if (is_array($value)) { - if (!empty($oHostObject) && $bLocalize) { - $sTargetClass = $this->Get('class_field'); - $sClass = $oHostObject->Get($sTargetClass); + /** + * @param $value + * @param DBObject $oHostObject + * @param bool $bLocalize + * + * @return string|null + * + * @throws Exception + */ + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + if ($value instanceof ormSet) { + $value = $value->GetValues(); + } + if (is_array($value)) { + if (!empty($oHostObject) && $bLocalize) { + $sTargetClass = $this->Get('class_field'); + $sClass = $oHostObject->Get($sTargetClass); - $aLocalizedValues = array(); - foreach ($value as $sAttCode) { - try { - $sAttClass = $sClass; + $aLocalizedValues = array(); + foreach ($value as $sAttCode) { + try { + $sAttClass = $sClass; - // Look for the first class (current or children) that have this attcode - foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { - if (MetaModel::IsValidAttCode($sChildClass, $sAttCode)) { - $sAttClass = $sChildClass; - break; - } - } + // Look for the first class (current or children) that have this attcode + foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { + if (MetaModel::IsValidAttCode($sChildClass, $sAttCode)) { + $sAttClass = $sChildClass; + break; + } + } - $sLabelForHtmlAttribute = utils::HtmlEntities(MetaModel::GetLabel($sAttClass, $sAttCode) . " ($sAttCode)"); - $aLocalizedValues[] = '' . $sAttCode . ''; - } catch (Exception $e) { - // Ignore bad values - } - } - $value = $aLocalizedValues; - } - $value = implode('', $value); - } - return '' . $value . ''; - } + $sLabelForHtmlAttribute = utils::HtmlEntities(MetaModel::GetLabel($sAttClass, $sAttCode)." ($sAttCode)"); + $aLocalizedValues[] = ''.$sAttCode.''; + } + catch (Exception $e) { + // Ignore bad values + } + } + $value = $aLocalizedValues; + } + $value = implode('', $value); + } - public function IsNull($proposedValue) - { - return (empty($proposedValue)); - } + return ''.$value.''; + } + + public function IsNull($proposedValue) + { + return (empty($proposedValue)); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeClassState.php b/sources/Core/AttributeDefinition/AttributeClassState.php index e2d66a13f..de790d544 100644 --- a/sources/Core/AttributeDefinition/AttributeClassState.php +++ b/sources/Core/AttributeDefinition/AttributeClassState.php @@ -1,4 +1,13 @@ Get('class_field'); - $sClass = $oHostObj->Get($sTargetClass); + public function GetAllowedValues($aArgs = array(), $sContains = '') + { + if (isset($aArgs['this'])) { + $oHostObj = $aArgs['this']; + $sTargetClass = $this->Get('class_field'); + $sClass = $oHostObj->Get($sTargetClass); - $aAllowedStates = array(); - foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { - $aValues = MetaModel::EnumStates($sChildClass); - foreach (array_keys($aValues) as $sState) { - $aAllowedStates[$sState] = $sState . ' (' . MetaModel::GetStateLabel($sChildClass, $sState) . ')'; - } - } - return $aAllowedStates; - } + $aAllowedStates = array(); + foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { + $aValues = MetaModel::EnumStates($sChildClass); + foreach (array_keys($aValues) as $sState) { + $aAllowedStates[$sState] = $sState.' ('.MetaModel::GetStateLabel($sChildClass, $sState).')'; + } + } - return null; - } + return $aAllowedStates; + } - public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) - { - if (empty($sValue)) { - return ''; - } + return null; + } - if (!empty($oHostObject)) { - $sTargetClass = $this->Get('class_field'); - $sClass = $oHostObject->Get($sTargetClass); - foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { - $aValues = MetaModel::EnumStates($sChildClass); - if (in_array($sValue, $aValues)) { - $sLabelForHtmlAttribute = utils::EscapeHtml($sValue . ' (' . MetaModel::GetStateLabel($sChildClass, $sValue) . ')'); - $sHTML = '' . $sValue . ''; + public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) + { + if (empty($sValue)) { + return ''; + } - return $sHTML; - } - } - } + if (!empty($oHostObject)) { + $sTargetClass = $this->Get('class_field'); + $sClass = $oHostObject->Get($sTargetClass); + foreach (MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL) as $sChildClass) { + $aValues = MetaModel::EnumStates($sChildClass); + if (in_array($sValue, $aValues)) { + $sLabelForHtmlAttribute = utils::EscapeHtml($sValue.' ('.MetaModel::GetStateLabel($sChildClass, $sValue).')'); + $sHTML = ''.$sValue.''; - return $sValue; - } + return $sHTML; + } + } + } + + return $sValue; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeCustomFields.php b/sources/Core/AttributeDefinition/AttributeCustomFields.php index e22c2fa99..b76aa7f47 100644 --- a/sources/Core/AttributeDefinition/AttributeCustomFields.php +++ b/sources/Core/AttributeDefinition/AttributeCustomFields.php @@ -1,4 +1,18 @@ GetCode()); - } + public function GetDefaultValue(DBObject $oHostObject = null) + { + return new ormCustomFieldsValue($oHostObject, $this->GetCode()); + } - public function GetBasicFilterOperators() - { - return array(); - } + public function GetBasicFilterOperators() + { + return array(); + } - public function GetBasicFilterLooseOperator() - { - return ''; - } + public function GetBasicFilterLooseOperator() + { + return ''; + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - return ''; - } + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + return ''; + } - /** - * @param DBObject $oHostObject - * @param array|null $aValues - * - * @return CustomFieldsHandler - */ - public function GetHandler($aValues = null) - { - $sHandlerClass = $this->Get('handler_class'); - /** @var \TemplateFieldsHandler $oHandler */ - $oHandler = new $sHandlerClass($this->GetCode()); - if (!is_null($aValues)) { - $oHandler->SetCurrentValues($aValues); - } + /** + * @param array|null $aValues + * + * @return TemplateFieldsHandler + */ + public function GetHandler($aValues = null) + { + $sHandlerClass = $this->Get('handler_class'); + /** @var TemplateFieldsHandler $oHandler */ + $oHandler = new $sHandlerClass($this->GetCode()); + if (!is_null($aValues)) { + $oHandler->SetCurrentValues($aValues); + } - return $oHandler; - } + return $oHandler; + } - public function GetPrerequisiteAttributes($sClass = null) - { - $sHandlerClass = $this->Get('handler_class'); + public function GetPrerequisiteAttributes($sClass = null) + { + $sHandlerClass = $this->Get('handler_class'); - return $sHandlerClass::GetPrerequisiteAttributes($sClass); - } + return $sHandlerClass::GetPrerequisiteAttributes($sClass); + } - public function GetEditValue($sValue, $oHostObj = null) - { - return $this->GetForTemplate($sValue, '', $oHostObj, true); - } + public function GetEditValue($sValue, $oHostObj = null) + { + return $this->GetForTemplate($sValue, '', $oHostObj, true); + } - /** - * Makes the string representation out of the values given by the form defined in GetDisplayForm - */ - public function ReadValueFromPostedForm($oHostObject, $sFormPrefix) - { - $aRawData = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->GetCode()}", '{}', 'raw_data'), true); - if ($aRawData != null) { - return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRawData); - } else { - return null; - } - } + /** + * Makes the string representation out of the values given by the form defined in GetDisplayForm + */ + public function ReadValueFromPostedForm($oHostObject, $sFormPrefix) + { + $aRawData = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->GetCode()}", '{}', 'raw_data'), true); + if ($aRawData != null) { + return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRawData); + } else { + return null; + } + } - public function MakeRealValue($proposedValue, $oHostObject) - { - if (is_object($proposedValue) && ($proposedValue instanceof ormCustomFieldsValue)) { - if (false === $oHostObject->IsNew()) { - // In that case we need additional keys : see \TemplateFieldsHandler::DoBuildForm - $aRequestTemplateValues = $proposedValue->GetValues(); - if (false === array_key_exists('current_template_id', $aRequestTemplateValues)) { - $aRequestTemplateValues['current_template_id'] = $aRequestTemplateValues['template_id']; - $aRequestTemplateValues['current_template_data'] = $aRequestTemplateValues['template_data']; - $proposedValue = new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRequestTemplateValues); - } - } + public function MakeRealValue($proposedValue, $oHostObject) + { + if (is_object($proposedValue) && ($proposedValue instanceof ormCustomFieldsValue)) { + if (false === $oHostObject->IsNew()) { + // In that case we need additional keys : see \TemplateFieldsHandler::DoBuildForm + $aRequestTemplateValues = $proposedValue->GetValues(); + if (false === array_key_exists('current_template_id', $aRequestTemplateValues)) { + $aRequestTemplateValues['current_template_id'] = $aRequestTemplateValues['template_id']; + $aRequestTemplateValues['current_template_data'] = $aRequestTemplateValues['template_data']; + $proposedValue = new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aRequestTemplateValues); + } + } - if (is_null($proposedValue->GetHostObject())) { - // the object might not be set : for example in \AttributeCustomFields::FromJSONToValue we don't have the object available :( - $proposedValue->SetHostObject($oHostObject); - } + if (is_null($proposedValue->GetHostObject())) { + // the object might not be set : for example in \AttributeCustomFields::FromJSONToValue we don't have the object available :( + $proposedValue->SetHostObject($oHostObject); + } - return $proposedValue; - } + return $proposedValue; + } - if (is_string($proposedValue)) { - $aValues = json_decode($proposedValue, true); + if (is_string($proposedValue)) { + $aValues = json_decode($proposedValue, true); - return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aValues); - } + return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aValues); + } - if (is_array($proposedValue)) { - return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $proposedValue); - } + if (is_array($proposedValue)) { + return new ormCustomFieldsValue($oHostObject, $this->GetCode(), $proposedValue); + } - if (is_null($proposedValue)) { - return new ormCustomFieldsValue($oHostObject, $this->GetCode()); - } + if (is_null($proposedValue)) { + return new ormCustomFieldsValue($oHostObject, $this->GetCode()); + } - throw new Exception('Unexpected type for the value of a custom fields attribute: ' . gettype($proposedValue)); - } + throw new Exception('Unexpected type for the value of a custom fields attribute: '.gettype($proposedValue)); + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\SubFormField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\SubFormField'; + } - /** - * Override to build the relevant form field - * - * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the - * $oFormField is passed, MakeFormField behaves more like a Prepare. - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - $oFormField->SetForm($this->GetForm($oObject)); - } - parent::MakeFormField($oObject, $oFormField); + /** + * Override to build the relevant form field + * + * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the + * $oFormField is passed, MakeFormField behaves more like a Prepare. + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + $oFormField->SetForm($this->GetForm($oObject)); + } + parent::MakeFormField($oObject, $oFormField); - return $oFormField; - } + return $oFormField; + } - /** - * @param DBObject $oHostObject - * @param null $sFormPrefix - * - * @return Combodo\iTop\Form\Form - * @throws \Exception - */ - public function GetForm(DBObject $oHostObject, $sFormPrefix = null) - { - try { - $oValue = $oHostObject->Get($this->GetCode()); - $oHandler = $this->GetHandler($oValue->GetValues()); - $sFormId = utils::IsNullOrEmptyString($sFormPrefix) ? 'cf_' . $this->GetCode() : $sFormPrefix . '_cf_' . $this->GetCode(); - $oHandler->BuildForm($oHostObject, $sFormId); - $oForm = $oHandler->GetForm(); - } catch (Exception $e) { - $oForm = new \Combodo\iTop\Form\Form(''); - $oField = new \Combodo\iTop\Form\Field\LabelField(''); - $oField->SetLabel('Custom field error: ' . $e->getMessage()); - $oForm->AddField($oField); - $oForm->Finalize(); - } + /** + * @param DBObject $oHostObject + * @param null $sFormPrefix + * + * @return Combodo\iTop\Form\Form + * @throws \Exception + */ + public function GetForm(DBObject $oHostObject, $sFormPrefix = null) + { + try { + $oValue = $oHostObject->Get($this->GetCode()); + $oHandler = $this->GetHandler($oValue->GetValues()); + $sFormId = utils::IsNullOrEmptyString($sFormPrefix) ? 'cf_'.$this->GetCode() : $sFormPrefix.'_cf_'.$this->GetCode(); + $oHandler->BuildForm($oHostObject, $sFormId); + $oForm = $oHandler->GetForm(); + } + catch (Exception $e) { + $oForm = new \Combodo\iTop\Form\Form(''); + $oField = new \Combodo\iTop\Form\Field\LabelField(''); + $oField->SetLabel('Custom field error: '.$e->getMessage()); + $oForm->AddField($oField); + $oForm->Finalize(); + } - return $oForm; - } + return $oForm; + } - /** - * Read the data from where it has been stored. This verb must be implemented as soon as LoadFromClassTables returns false - * and LoadInObject returns true - * - * @param DBObject $oHostObject - * - * @return mixed|null - * @since 3.1.0 - */ - public function ReadExternalValues(DBObject $oHostObject) - { - try { - $oHandler = $this->GetHandler(); - $aValues = $oHandler->ReadValues($oHostObject); - $oRet = new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aValues); - } catch (Exception $e) { - $oRet = new ormCustomFieldsValue($oHostObject, $this->GetCode()); - } + /** + * Read the data from where it has been stored. This verb must be implemented as soon as LoadFromClassTables returns false + * and LoadInObject returns true + * + * @param DBObject $oHostObject + * + * @return mixed|null + * @since 3.1.0 + */ + public function ReadExternalValues(DBObject $oHostObject) + { + try { + $oHandler = $this->GetHandler(); + $aValues = $oHandler->ReadValues($oHostObject); + $oRet = new ormCustomFieldsValue($oHostObject, $this->GetCode(), $aValues); + } + catch (Exception $e) { + $oRet = new ormCustomFieldsValue($oHostObject, $this->GetCode()); + } - return $oRet; - } + return $oRet; + } - /** - * @inheritDoc - * - * @since 3.1.0 N°6043 Move code contained in \AttributeCustomFields::WriteValue to this generic method - */ - public function WriteExternalValues(DBObject $oHostObject): void - { - $oValue = $oHostObject->Get($this->GetCode()); - if (!($oValue instanceof ormCustomFieldsValue)) { - $oHandler = $this->GetHandler(); - $aValues = array(); - } else { - // Pass the values through the form to make sure that they are correct - $oHandler = $this->GetHandler($oValue->GetValues()); - $oHandler->BuildForm($oHostObject, ''); - $oForm = $oHandler->GetForm(); - $aValues = $oForm->GetCurrentValues(); - } + /** + * @inheritDoc + * + * @since 3.1.0 N°6043 Move code contained in \AttributeCustomFields::WriteValue to this generic method + */ + public function WriteExternalValues(DBObject $oHostObject): void + { + $oValue = $oHostObject->Get($this->GetCode()); + if (!($oValue instanceof ormCustomFieldsValue)) { + $oHandler = $this->GetHandler(); + $aValues = array(); + } else { + // Pass the values through the form to make sure that they are correct + $oHandler = $this->GetHandler($oValue->GetValues()); + $oHandler->BuildForm($oHostObject, ''); + $oForm = $oHandler->GetForm(); + $aValues = $oForm->GetCurrentValues(); + } - $oHandler->WriteValues($oHostObject, $aValues); - } + $oHandler->WriteValues($oHostObject, $aValues); + } - /** - * The part of the current attribute in the object's signature, for the supplied value - * - * @param ormCustomFieldsValue $value The value of this attribute for the object - * - * @return string The "signature" for this field/attribute - */ - public function Fingerprint($value) - { - $oHandler = $this->GetHandler($value->GetValues()); + /** + * The part of the current attribute in the object's signature, for the supplied value + * + * @param ormCustomFieldsValue $value The value of this attribute for the object + * + * @return string The "signature" for this field/attribute + */ + public function Fingerprint($value) + { + $oHandler = $this->GetHandler($value->GetValues()); - return $oHandler->GetValueFingerprint(); - } + return $oHandler->GetValueFingerprint(); + } - /** - * Check the validity of the data - * - * @param DBObject $oHostObject - * @param $value - * - * @return bool|string true or error message - */ - public function CheckValue(DBObject $oHostObject, $value) - { - try { - $oHandler = $this->GetHandler($value->GetValues()); - $oHandler->BuildForm($oHostObject, ''); - $ret = $oHandler->Validate($oHostObject); - } catch (Exception $e) { - $ret = $e->getMessage(); - } + /** + * Check the validity of the data + * + * @param DBObject $oHostObject + * @param $value + * + * @return bool|string true or error message + */ + public function CheckValue(DBObject $oHostObject, $value) + { + try { + $oHandler = $this->GetHandler($value->GetValues()); + $oHandler->BuildForm($oHostObject, ''); + $ret = $oHandler->Validate($oHostObject); + } + catch (Exception $e) { + $ret = $e->getMessage(); + } - return $ret; - } + return $ret; + } - /** - * Cleanup data upon object deletion (object id still available here) - * - * @param DBObject $oHostObject - * - * @throws \CoreException - * @since 3.1.0 - */ - public function DeleteExternalValues(DBObject $oHostObject): void - { - $oValue = $oHostObject->Get($this->GetCode()); - $oHandler = $this->GetHandler($oValue->GetValues()); + /** + * Cleanup data upon object deletion (object id still available here) + * + * @param DBObject $oHostObject + * + * @throws \CoreException + * @since 3.1.0 + */ + public function DeleteExternalValues(DBObject $oHostObject): void + { + $oValue = $oHostObject->Get($this->GetCode()); + $oHandler = $this->GetHandler($oValue->GetValues()); - $oHandler->DeleteValues($oHostObject); - } + $oHandler->DeleteValues($oHostObject); + } - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - try { - /** @var \ormCustomFieldsValue $value */ - $sRet = $value->GetAsHTML($bLocalize); - } catch (Exception $e) { - $sRet = 'Custom field error: ' . utils::EscapeHtml($e->getMessage()); - } + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + try { + /** @var ormCustomFieldsValue $value */ + $sRet = $value->GetAsHTML($bLocalize); + } + catch (Exception $e) { + $sRet = 'Custom field error: '.utils::EscapeHtml($e->getMessage()); + } - return $sRet; - } + return $sRet; + } - public function GetAsXML($value, $oHostObject = null, $bLocalize = true) - { - try { - $sRet = $value->GetAsXML($bLocalize); - } catch (Exception $e) { - $sRet = Str::pure2xml('Custom field error: ' . $e->getMessage()); - } + public function GetAsXML($value, $oHostObject = null, $bLocalize = true) + { + try { + $sRet = $value->GetAsXML($bLocalize); + } + catch (Exception $e) { + $sRet = Str::pure2xml('Custom field error: '.$e->getMessage()); + } - return $sRet; - } + return $sRet; + } - /** - * @param \ormCustomFieldsValue $value - * @param string $sSeparator - * @param string $sTextQualifier - * @param \DBObject $oHostObject - * @param bool $bLocalize - * @param bool $bConvertToPlainText - * - * @return string - * @noinspection PhpParameterNameChangedDuringInheritanceInspection - */ - public function GetAsCSV( - $value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - try { - $sRet = $value->GetAsCSV($sSeparator, $sTextQualifier, $bLocalize, $bConvertToPlainText); - } catch (Exception $e) { - $sFrom = array("\r\n", $sTextQualifier); - $sTo = array("\n", $sTextQualifier . $sTextQualifier); - $sEscaped = str_replace($sFrom, $sTo, 'Custom field error: ' . $e->getMessage()); - $sRet = $sTextQualifier . $sEscaped . $sTextQualifier; - } + /** + * @param ormCustomFieldsValue $value + * @param string $sSeparator + * @param string $sTextQualifier + * @param DBObject $oHostObject + * @param bool $bLocalize + * @param bool $bConvertToPlainText + * + * @return string + * @noinspection PhpParameterNameChangedDuringInheritanceInspection + */ + public function GetAsCSV( + $value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + try { + $sRet = $value->GetAsCSV($sSeparator, $sTextQualifier, $bLocalize, $bConvertToPlainText); + } + catch (Exception $e) { + $sFrom = array("\r\n", $sTextQualifier); + $sTo = array("\n", $sTextQualifier.$sTextQualifier); + $sEscaped = str_replace($sFrom, $sTo, 'Custom field error: '.$e->getMessage()); + $sRet = $sTextQualifier.$sEscaped.$sTextQualifier; + } - return $sRet; - } + return $sRet; + } - /** - * List the available verbs for 'GetForTemplate' - */ - public function EnumTemplateVerbs() - { - $sHandlerClass = $this->Get('handler_class'); + /** + * List the available verbs for 'GetForTemplate' + */ + public function EnumTemplateVerbs() + { + $sHandlerClass = $this->Get('handler_class'); - return $sHandlerClass::EnumTemplateVerbs(); - } + return $sHandlerClass::EnumTemplateVerbs(); + } - /** - * Get various representations of the value, for insertion into a template (e.g. in Notifications) - * - * @param $value mixed The current value of the field - * @param $sVerb string The verb specifying the representation of the value - * @param $oHostObject DBObject The object - * @param $bLocalize bool Whether or not to localize the value - * - * @return string - */ - public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) - { - try { - $sRet = $value->GetForTemplate($sVerb, $bLocalize); - } catch (Exception $e) { - $sRet = 'Custom field error: ' . $e->getMessage(); - } + /** + * Get various representations of the value, for insertion into a template (e.g. in Notifications) + * + * @param $value mixed The current value of the field + * @param $sVerb string The verb specifying the representation of the value + * @param $oHostObject DBObject The object + * @param $bLocalize bool Whether or not to localize the value + * + * @return string + */ + public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) + { + try { + $sRet = $value->GetForTemplate($sVerb, $bLocalize); + } + catch (Exception $e) { + $sRet = 'Custom field error: '.$e->getMessage(); + } - return $sRet; - } + return $sRet; + } - public function MakeValueFromString( - $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, - $sAttributeQualifier = null - ) - { - return null; - } + public function MakeValueFromString( + $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, + $sAttributeQualifier = null + ) + { + return null; + } - /** - * @inheritDoc - * - * @param \ormCustomFieldsValue $value - * - * @return string|array - * - * @since 3.1.0 N°1150 now returns the value (was always returning null before) - */ - public function GetForJSON($value) - { - try { - $sRet = $value->GetForJSON(); - } catch (Exception $e) { - $sRet = 'Custom field error: ' . $e->getMessage(); - } + /** + * @inheritDoc + * + * @param ormCustomFieldsValue $value + * + * @return string|array + * + * @since 3.1.0 N°1150 now returns the value (was always returning null before) + */ + public function GetForJSON($value) + { + try { + $sRet = $value->GetForJSON(); + } + catch (Exception $e) { + $sRet = 'Custom field error: '.$e->getMessage(); + } - return $sRet; - } + return $sRet; + } - /** - * @inheritDoc - * - * @return ?\ormCustomFieldsValue with empty host object as we don't have it here (most consumers don't have an object in their context, for example in \RestUtils::GetObjectSetFromKey) - * The host object will be set in {@see MakeRealValue} - * All the necessary checks will be done in {@see CheckValue} - */ - public function FromJSONToValue($json) - { - return ormCustomFieldsValue::FromJSONToValue($json, $this); - } + /** + * @inheritDoc + * + * @return ?ormCustomFieldsValue with empty host object as we don't have it here (most consumers don't have an object in their context, for example in \RestUtils::GetObjectSetFromKey) + * The host object will be set in {@see MakeRealValue} + * All the necessary checks will be done in {@see CheckValue} + */ + public function FromJSONToValue($json) + { + return ormCustomFieldsValue::FromJSONToValue($json, $this); + } - public function Equals($val1, $val2) - { - try { - $bEquals = $val1->Equals($val2); - } catch (Exception $e) { - $bEquals = false; - } + public function Equals($val1, $val2) + { + try { + $bEquals = $val1->Equals($val2); + } + catch (Exception $e) { + $bEquals = false; + } - return $bEquals; - } + return $bEquals; + } - /** - * @inheritDoc - */ - public function HasAValue($proposedValue): bool - { - // Protection against wrong value type - if (false === ($proposedValue instanceof ormCustomFieldsValue)) { - return parent::HasAValue($proposedValue); - } + /** + * @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; - } + return count($proposedValue->GetValues()) > 0; + } - protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void - { - $oMyChangeOp->Set("prevdata", json_encode($original->GetValues())); - } + protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void + { + $oMyChangeOp->Set("prevdata", json_encode($original->GetValues())); + } - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeCustomFields::class; - } + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeCustomFields::class; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDBField.php b/sources/Core/AttributeDefinition/AttributeDBField.php index 7e2d9954c..13e0d1999 100644 --- a/sources/Core/AttributeDefinition/AttributeDBField.php +++ b/sources/Core/AttributeDefinition/AttributeDBField.php @@ -1,4 +1,12 @@ MakeRealValue($this->Get("default_value"), $oHostObject); - } + public function GetDefaultValue(DBObject $oHostObject = null) + { + return $this->MakeRealValue($this->Get("default_value"), $oHostObject); + } - public function IsNullAllowed() - { - return $this->Get("is_null_allowed"); - } + public function IsNullAllowed() + { + return $this->Get("is_null_allowed"); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php b/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php index ac61a0d49..f5b42318d 100644 --- a/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php +++ b/sources/Core/AttributeDefinition/AttributeDBFieldVoid.php @@ -1,4 +1,13 @@ GetSQLColSpec() : ''); - } + // To be overriden, used in GetSQLColumns + protected function GetSQLCol($bFullSpec = false) + { + return 'VARCHAR(255)' + .CMDBSource::GetSqlStringColumnDefinition() + .($bFullSpec ? $this->GetSQLColSpec() : ''); + } - protected function GetSQLColSpec() - { - $default = $this->ScalarToSQL($this->GetDefaultValue()); - if (is_null($default)) { - $sRet = ''; - } else { - if (is_numeric($default)) { - // Though it is a string in PHP, it will be considered as a numeric value in MySQL - // Then it must not be quoted here, to preserve the compatibility with the value returned by CMDBSource::GetFieldSpec - $sRet = " DEFAULT $default"; - } else { - $sRet = " DEFAULT " . CMDBSource::Quote($default); - } - } + protected function GetSQLColSpec() + { + $default = $this->ScalarToSQL($this->GetDefaultValue()); + if (is_null($default)) { + $sRet = ''; + } else { + if (is_numeric($default)) { + // Though it is a string in PHP, it will be considered as a numeric value in MySQL + // Then it must not be quoted here, to preserve the compatibility with the value returned by CMDBSource::GetFieldSpec + $sRet = " DEFAULT $default"; + } else { + $sRet = " DEFAULT ".CMDBSource::Quote($default); + } + } - return $sRet; - } + return $sRet; + } - public function GetEditClass() - { - return "String"; - } + public function GetEditClass() + { + return "String"; + } - public function GetValuesDef() - { - return $this->Get("allowed_values"); - } + public function GetValuesDef() + { + return $this->Get("allowed_values"); + } - public function GetPrerequisiteAttributes($sClass = null) - { - return $this->Get("depends_on"); - } + public function GetPrerequisiteAttributes($sClass = null) + { + return $this->Get("depends_on"); + } - public static function IsBasedOnDBColumns() - { - return true; - } + public static function IsBasedOnDBColumns() + { + return true; + } - public static function IsScalar() - { - return true; - } + public static function IsScalar() + { + return true; + } - public function IsWritable() - { - return !$this->IsMagic(); - } + public function IsWritable() + { + return !$this->IsMagic(); + } - public function GetSQLExpr() - { - return $this->Get("sql"); - } + public function GetSQLExpr() + { + return $this->Get("sql"); + } - public function GetDefaultValue(DBObject $oHostObject = null) - { - return $this->MakeRealValue("", $oHostObject); - } + public function GetDefaultValue(DBObject $oHostObject = null) + { + return $this->MakeRealValue("", $oHostObject); + } - public function IsNullAllowed() - { - return false; - } + public function IsNullAllowed() + { + return false; + } - // - protected function ScalarToSQL($value) - { - return $value; - } // format value as a valuable SQL literal (quoted outside) + // + protected function ScalarToSQL($value) + { + return $value; + } // format value as a valuable SQL literal (quoted outside) - public function GetSQLExpressions($sPrefix = '') - { - $aColumns = array(); - // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix - $aColumns[''] = $this->Get("sql"); + public function GetSQLExpressions($sPrefix = '') + { + $aColumns = array(); + // Note: to optimize things, the existence of the attribute is determined by the existence of one column with an empty suffix + $aColumns[''] = $this->Get("sql"); - return $aColumns; - } + return $aColumns; + } - public function FromSQLToValue($aCols, $sPrefix = '') - { - $value = $this->MakeRealValue($aCols[$sPrefix . ''], null); + public function FromSQLToValue($aCols, $sPrefix = '') + { + $value = $this->MakeRealValue($aCols[$sPrefix.''], null); - return $value; - } + return $value; + } - public function GetSQLValues($value) - { - $aValues = array(); - $aValues[$this->Get("sql")] = $this->ScalarToSQL($value); + public function GetSQLValues($value) + { + $aValues = array(); + $aValues[$this->Get("sql")] = $this->ScalarToSQL($value); - return $aValues; - } + return $aValues; + } - public function GetSQLColumns($bFullSpec = false) - { - $aColumns = array(); - $aColumns[$this->Get("sql")] = $this->GetSQLCol($bFullSpec); + public function GetSQLColumns($bFullSpec = false) + { + $aColumns = array(); + $aColumns[$this->Get("sql")] = $this->GetSQLCol($bFullSpec); - return $aColumns; - } + return $aColumns; + } - public function GetBasicFilterOperators() - { - return array("=" => "equals", "!=" => "differs from"); - } + public function GetBasicFilterOperators() + { + return array("=" => "equals", "!=" => "differs from"); + } - public function GetBasicFilterLooseOperator() - { - return "="; - } + public function GetBasicFilterLooseOperator() + { + return "="; + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - $sQValue = CMDBSource::Quote($value); - switch ($sOpCode) { - case '!=': - return $this->GetSQLExpr() . " != $sQValue"; - break; - case '=': - default: - return $this->GetSQLExpr() . " = $sQValue"; - } - } + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + $sQValue = CMDBSource::Quote($value); + switch ($sOpCode) { + case '!=': + return $this->GetSQLExpr()." != $sQValue"; + break; + case '=': + default: + return $this->GetSQLExpr()." = $sQValue"; + } + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDashboard.php b/sources/Core/AttributeDefinition/AttributeDashboard.php index 367a798c1..94493c0f6 100644 --- a/sources/Core/AttributeDefinition/AttributeDashboard.php +++ b/sources/Core/AttributeDefinition/AttributeDashboard.php @@ -1,98 +1,110 @@ GetCode(); - $sClass = MetaModel::GetAttributeOrigin($this->GetHostClass(), $sAttCode); - $sFilePath = APPROOT . 'env-' . utils::GetCurrentEnvironment() . '/' . $this->Get('definition_file'); - return RuntimeDashboard::GetDashboard($sFilePath, $sClass . '__' . $sAttCode); - } + public function GetDashboard() + { + $sAttCode = $this->GetCode(); + $sClass = MetaModel::GetAttributeOrigin($this->GetHostClass(), $sAttCode); + $sFilePath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/'.$this->Get('definition_file'); - public function IsUserEditable() - { - return $this->Get('is_user_editable'); - } + return RuntimeDashboard::GetDashboard($sFilePath, $sClass.'__'.$sAttCode); + } - public function IsWritable() - { - return false; - } + public function IsUserEditable() + { + return $this->Get('is_user_editable'); + } - public function GetEditClass() - { - return ""; - } + public function IsWritable() + { + return false; + } - public function GetDefaultValue(DBObject $oHostObject = null) - { - return null; - } + public function GetEditClass() + { + return ""; + } - public function GetBasicFilterOperators() - { - return array(); - } + public function GetDefaultValue(DBObject $oHostObject = null) + { + return null; + } - public function GetBasicFilterLooseOperator() - { - return '='; - } + public function GetBasicFilterOperators() + { + return array(); + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - return ''; - } + public function GetBasicFilterLooseOperator() + { + return '='; + } - /** - * @inheritdoc - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - return null; - } + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + return ''; + } - // if this verb returns false, then GetValue must be implemented - public static function LoadInObject() - { - return false; - } + /** + * @inheritdoc + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + return null; + } - public function GetValue($oHostObject) - { - return ''; - } + // if this verb returns false, then GetValue must be implemented + public static function LoadInObject() + { + return false; + } - /** - * @inheritDoc - */ - public function HasAValue($proposedValue): bool - { - // Always return false for now, we don't consider a custom version of a dashboard - return false; - } + public function GetValue($oHostObject) + { + return ''; + } + + /** + * @inheritDoc + */ + public function HasAValue($proposedValue): bool + { + // Always return false for now, we don't consider a custom version of a dashboard + return false; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDate.php b/sources/Core/AttributeDefinition/AttributeDate.php index 17f976b11..ae2daa6bf 100644 --- a/sources/Core/AttributeDefinition/AttributeDate.php +++ b/sources/Core/AttributeDefinition/AttributeDate.php @@ -1,4 +1,14 @@ GetCode()] = 'VARCHAR(10)' . CMDBSource::GetSqlStringColumnDefinition(); + public function GetImportColumns() + { + // Allow an empty string to be a valid value (synonym for "reset") + $aColumns = array(); + $aColumns[$this->GetCode()] = 'VARCHAR(10)'.CMDBSource::GetSqlStringColumnDefinition(); - return $aColumns; - } + return $aColumns; + } - /** - * Override to specify Field class - * - * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the - * $oFormField is passed, MakeFormField behave more like a Prepare. - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - $oFormField = parent::MakeFormField($oObject, $oFormField); - $oFormField->SetDateOnly(true); + /** + * Override to specify Field class + * + * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the + * $oFormField is passed, MakeFormField behave more like a Prepare. + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + $oFormField = parent::MakeFormField($oObject, $oFormField); + $oFormField->SetDateOnly(true); - return $oFormField; - } + return $oFormField; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDateTime.php b/sources/Core/AttributeDefinition/AttributeDateTime.php index 6321854bf..04a69e043 100644 --- a/sources/Core/AttributeDefinition/AttributeDateTime.php +++ b/sources/Core/AttributeDefinition/AttributeDateTime.php @@ -1,4 +1,27 @@ Get('date_and_time_format'); - $sLang = Dict::GetUserLanguage(); - $sDateFormat = isset($aFormats[$sLang]['date']) ? $aFormats[$sLang]['date'] : (isset($aFormats['default']['date']) ? $aFormats['default']['date'] : 'Y-m-d'); - $sTimeFormat = isset($aFormats[$sLang]['time']) ? $aFormats[$sLang]['time'] : (isset($aFormats['default']['time']) ? $aFormats['default']['time'] : 'H:i:s'); - $sDateAndTimeFormat = isset($aFormats[$sLang]['date_time']) ? $aFormats[$sLang]['date_time'] : (isset($aFormats['default']['date_time']) ? $aFormats['default']['date_time'] : '$date $time'); - - $sFullFormat = str_replace(array('$date', '$time'), array($sDateFormat, $sTimeFormat), $sDateAndTimeFormat); - - self::SetFormat(new DateTimeFormat($sFullFormat)); - AttributeDate::SetFormat(new DateTimeFormat($sDateFormat)); - } - - /** - * Returns the format string used for the date & time stored in memory - * - * @return string - */ - public static function GetInternalFormat() - { - return 'Y-m-d H:i:s'; - } - - /** - * Returns the format string used for the date & time written to MySQL - * - * @return string - */ - public static function GetSQLFormat() - { - return 'Y-m-d H:i:s'; - } - - public static function SetFormat(DateTimeFormat $oDateTimeFormat) - { - self::$oFormat = $oDateTimeFormat; - } - - public static function GetSQLTimeFormat() - { - return 'H:i:s'; - } - - /** - * Parses a search string coming from user input - * - * @param string $sSearchString - * - * @return string - */ - public function ParseSearchString($sSearchString) - { - try { - $oDateTime = $this->GetFormat()->Parse($sSearchString); - $sSearchString = $oDateTime->format($this->GetInternalFormat()); - } catch (Exception $e) { - $sFormatString = '!' . (string)AttributeDate::GetFormat(); // BEWARE: ! is needed to set non-parsed fields to zero !!! - $oDateTime = DateTime::createFromFormat($sFormatString, $sSearchString); - if ($oDateTime !== false) { - $sSearchString = $oDateTime->format($this->GetInternalFormat()); - } - } - - return $sSearchString; - } - - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\DateTimeField'; - } - - /** - * Override to specify Field class - * - * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the - * $oFormField is passed, MakeFormField behave more like a Prepare. - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - } - $oFormField->SetPHPDateTimeFormat((string)$this->GetFormat()); - $oFormField->SetJSDateTimeFormat($this->GetFormat()->ToMomentJS()); - - $oFormField = parent::MakeFormField($oObject, $oFormField); - - // After call to the parent as it sets the current value - $oValue = $oObject->Get($this->GetCode()); - if ($oValue === $this->GetNullValue()) { - $oValue = $this->GetDefaultValue($oObject); - } - $oFormField->SetCurrentValue($this->GetFormat()->Format($oValue)); - - - return $oFormField; - } - - /** - * @inheritdoc - */ - public function EnumTemplateVerbs() - { - return array( - '' => 'Formatted representation', - 'raw' => 'Not formatted representation', - ); - } - - /** - * @inheritdoc - */ - public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) - { - switch ($sVerb) { - case '': - case 'text': - return static::GetFormat()->format($value); - break; - case 'html': - // Note: Not passing formatted value as the method will format it. - return $this->GetAsHTML($value); - break; - case 'raw': - return $value; - break; - default: - return parent::GetForTemplate($value, $sVerb, $oHostObject, $bLocalize); - break; - } - } - - public static function ListExpectedParams() - { - return parent::ListExpectedParams(); - //return array_merge(parent::ListExpectedParams(), array()); - } - - public function GetEditClass() - { - return "DateTime"; - } - - - public function GetEditValue($sValue, $oHostObj = null) - { - return (string)static::GetFormat()->format($sValue); - } - - public function GetValueLabel($sValue, $oHostObj = null) - { - return (string)static::GetFormat()->format($sValue); - } - - protected function GetSQLCol($bFullSpec = false) - { - return "DATETIME"; - } - - public function GetImportColumns() - { - // Allow an empty string to be a valid value (synonym for "reset") - $aColumns = array(); - $aColumns[$this->GetCode()] = 'VARCHAR(19)' . CMDBSource::GetSqlStringColumnDefinition(); - - return $aColumns; - } - - public static function GetAsUnixSeconds($value) - { - $oDeadlineDateTime = new DateTime($value); - $iUnixSeconds = $oDeadlineDateTime->format('U'); - - return $iUnixSeconds; - } - - public function GetDefaultValue(DBObject $oHostObject = null) - { - $sDefaultValue = $this->Get('default_value'); - if (utils::IsNotNullOrEmptyString($sDefaultValue)) { - try { - $sDefaultDate = Expression::FromOQL($sDefaultValue)->Evaluate([]); - } catch (Exception $e) { - try { - $sDefaultDate = Expression::FromOQL('"' . $sDefaultValue . '"')->Evaluate([]); - } catch (Exception $e) { - IssueLog::Error("Invalid default value '$sDefaultValue' for field '{$this->GetCode()}' on class '{$this->GetHostClass()}', defaulting to null"); - - return $this->GetNullValue(); - } - } - try { - $oDate = new DateTimeImmutable($sDefaultDate); - } catch (Exception $e) { - IssueLog::Error("Invalid default value '$sDefaultValue' for field '{$this->GetCode()}' on class '{$this->GetHostClass()}', defaulting to null"); - return $this->GetNullValue(); - } - return $oDate->format($this->GetInternalFormat()); - } - return $this->GetNullValue(); - } - - public function GetValidationPattern() - { - return static::GetFormat()->ToRegExpr(); - } - - public function GetBasicFilterOperators() - { - return array( - "=" => "equals", - "!=" => "differs from", - "<" => "before", - "<=" => "before", - ">" => "after (strictly)", - ">=" => "after", - "SameDay" => "same day (strip time)", - "SameMonth" => "same year/month", - "SameYear" => "same year", - "Today" => "today", - ">|" => "after today + N days", - "<|" => "before today + N days", - "=|" => "equals today + N days", - ); - } - - public function GetBasicFilterLooseOperator() - { - // Unless we implement a "same xxx, depending on given precision" ! - return "="; - } - - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - $sQValue = CMDBSource::Quote($value); - - switch ($sOpCode) { - case '=': - case '!=': - case '<': - case '<=': - case '>': - case '>=': - return $this->GetSQLExpr() . " $sOpCode $sQValue"; - case 'SameDay': - return "DATE(" . $this->GetSQLExpr() . ") = DATE($sQValue)"; - case 'SameMonth': - return "DATE_FORMAT(" . $this->GetSQLExpr() . ", '%Y-%m') = DATE_FORMAT($sQValue, '%Y-%m')"; - case 'SameYear': - return "MONTH(" . $this->GetSQLExpr() . ") = MONTH($sQValue)"; - case 'Today': - return "DATE(" . $this->GetSQLExpr() . ") = CURRENT_DATE()"; - case '>|': - return "DATE(" . $this->GetSQLExpr() . ") > DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; - case '<|': - return "DATE(" . $this->GetSQLExpr() . ") < DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; - case '=|': - return "DATE(" . $this->GetSQLExpr() . ") = DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; - default: - return $this->GetSQLExpr() . " = $sQValue"; - } - } - - /** - * @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_numeric($proposedValue)) { - return date(static::GetInternalFormat(), $proposedValue); - } - - 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 CoreUnexpectedValue('Wrong format for date attribute ' . $this->GetCode() . ', expecting "' . $this->GetInternalFormat() . '" and got "' . $proposedValue . '"'); - } - - return $proposedValue; - } - - throw new CoreUnexpectedValue('Wrong format for date attribute ' . $this->GetCode()); - } - - public function ScalarToSQL($value) - { - if (empty($value)) { - return null; - } - - return $value; - } - - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - return Str::pure2html(static::GetFormat()->format($value)); - } - - public function GetAsXML($value, $oHostObject = null, $bLocalize = true) - { - return Str::pure2xml($value); - } - - public function GetAsCSV( - $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - if (empty($sValue) || ($sValue === '0000-00-00 00:00:00') || ($sValue === '0000-00-00')) { - return ''; - } else { - if ((string)static::GetFormat() !== static::GetInternalFormat()) { - // Format conversion - $oDate = new DateTime($sValue); - if ($oDate !== false) { - $sValue = static::GetFormat()->format($oDate); - } - } - } - $sFrom = array("\r\n", $sTextQualifier); - $sTo = array("\n", $sTextQualifier . $sTextQualifier); - $sEscaped = str_replace($sFrom, $sTo, (string)$sValue); - - return $sTextQualifier . $sEscaped . $sTextQualifier; - } - - /** - * Parses a string to find some smart search patterns and build the corresponding search/OQL condition - * Each derived class is reponsible for defining and processing their own smart patterns, the base class - * does nothing special, and just calls the default (loose) operator - * - * @param string $sSearchText The search string to analyze for smart patterns - * @param FieldExpression $oField The FieldExpression representing the atttribute code in this OQL query - * @param array $aParams Values of the query parameters - * @param bool $bParseSearchString - * - * @return Expression The search condition to be added (AND) to the current search - * @throws \CoreException - */ - public function GetSmartConditionExpression( - $sSearchText, FieldExpression $oField, &$aParams, $bParseSearchString = false - ) - { - // Possible smart patterns - $aPatterns = array( - 'between' => array('pattern' => '/^\[(.*),(.*)\]$/', 'operator' => 'n/a'), - 'greater than or equal' => array('pattern' => '/^>=(.*)$/', 'operator' => '>='), - 'greater than' => array('pattern' => '/^>(.*)$/', 'operator' => '>'), - 'less than or equal' => array('pattern' => '/^<=(.*)$/', 'operator' => '<='), - 'less than' => array('pattern' => '/^<(.*)$/', 'operator' => '<'), - ); - - $sPatternFound = ''; - $aMatches = array(); - foreach ($aPatterns as $sPatName => $sPattern) { - if (preg_match($sPattern['pattern'], $sSearchText, $aMatches)) { - $sPatternFound = $sPatName; - break; - } - } - - switch ($sPatternFound) { - case 'between': - - $sParamName1 = $oField->GetParent() . '_' . $oField->GetName() . '_1'; - $oRightExpr = new VariableExpression($sParamName1); - if ($bParseSearchString) { - $aParams[$sParamName1] = $this->ParseSearchString($aMatches[1]); - } else { - $aParams[$sParamName1] = $aMatches[1]; - } - $oCondition1 = new BinaryExpression($oField, '>=', $oRightExpr); - - $sParamName2 = $oField->GetParent() . '_' . $oField->GetName() . '_2'; - $oRightExpr = new VariableExpression($sParamName2); - if ($bParseSearchString) { - $aParams[$sParamName2] = $this->ParseSearchString($aMatches[2]); - } else { - $aParams[$sParamName2] = $aMatches[2]; - } - $oCondition2 = new BinaryExpression($oField, '<=', $oRightExpr); - - $oNewCondition = new BinaryExpression($oCondition1, 'AND', $oCondition2); - break; - - case 'greater than': - case 'greater than or equal': - case 'less than': - case 'less than or equal': - $sSQLOperator = $aPatterns[$sPatternFound]['operator']; - $sParamName = $oField->GetParent() . '_' . $oField->GetName(); - $oRightExpr = new VariableExpression($sParamName); - if ($bParseSearchString) { - $aParams[$sParamName] = $this->ParseSearchString($aMatches[1]); - } else { - $aParams[$sParamName] = $aMatches[1]; - } - $oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr); - - break; - - default: - $oNewCondition = parent::GetSmartConditionExpression($sSearchText, $oField, $aParams); - - } - - return $oNewCondition; - } - - - public function GetHelpOnSmartSearch() - { - $sDict = parent::GetHelpOnSmartSearch(); - - $oFormat = static::GetFormat(); - $sExample = $oFormat->Format(new DateTime('2015-07-19 18:40:00')); - - return vsprintf($sDict, array($oFormat->ToPlaceholder(), $sExample)); - } + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_DATE_TIME; + + public static $oFormat = null; + + /** + * Useless constructor, but if not present PHP 7.4.0/7.4.1 is crashing :( (N°2329) + * + * @see https://www.php.net/manual/fr/language.oop5.decon.php states that child constructor can be ommited + * @see https://bugs.php.net/bug.php?id=79010 bug solved in PHP 7.4.9 + * + * @param string $sCode + * @param array $aParams + * + * @throws Exception + * @noinspection SenselessProxyMethodInspection + */ + public function __construct($sCode, $aParams) + { + parent::__construct($sCode, $aParams); + } + + /** + * + * @return DateTimeFormat + */ + public static function GetFormat() + { + if (self::$oFormat == null) { + static::LoadFormatFromConfig(); + } + + return self::$oFormat; + } + + /** + * Load the 3 settings: date format, time format and data_time format from the configuration + */ + public static function LoadFormatFromConfig() + { + $aFormats = MetaModel::GetConfig()->Get('date_and_time_format'); + $sLang = Dict::GetUserLanguage(); + $sDateFormat = isset($aFormats[$sLang]['date']) ? $aFormats[$sLang]['date'] : (isset($aFormats['default']['date']) ? $aFormats['default']['date'] : 'Y-m-d'); + $sTimeFormat = isset($aFormats[$sLang]['time']) ? $aFormats[$sLang]['time'] : (isset($aFormats['default']['time']) ? $aFormats['default']['time'] : 'H:i:s'); + $sDateAndTimeFormat = isset($aFormats[$sLang]['date_time']) ? $aFormats[$sLang]['date_time'] : (isset($aFormats['default']['date_time']) ? $aFormats['default']['date_time'] : '$date $time'); + + $sFullFormat = str_replace(array('$date', '$time'), array($sDateFormat, $sTimeFormat), $sDateAndTimeFormat); + + self::SetFormat(new DateTimeFormat($sFullFormat)); + AttributeDate::SetFormat(new DateTimeFormat($sDateFormat)); + } + + /** + * Returns the format string used for the date & time stored in memory + * + * @return string + */ + public static function GetInternalFormat() + { + return 'Y-m-d H:i:s'; + } + + /** + * Returns the format string used for the date & time written to MySQL + * + * @return string + */ + public static function GetSQLFormat() + { + return 'Y-m-d H:i:s'; + } + + public static function SetFormat(DateTimeFormat $oDateTimeFormat) + { + self::$oFormat = $oDateTimeFormat; + } + + public static function GetSQLTimeFormat() + { + return 'H:i:s'; + } + + /** + * Parses a search string coming from user input + * + * @param string $sSearchString + * + * @return string + */ + public function ParseSearchString($sSearchString) + { + try { + $oDateTime = $this->GetFormat()->Parse($sSearchString); + $sSearchString = $oDateTime->format($this->GetInternalFormat()); + } + catch (Exception $e) { + $sFormatString = '!'.(string)AttributeDate::GetFormat(); // BEWARE: ! is needed to set non-parsed fields to zero !!! + $oDateTime = DateTime::createFromFormat($sFormatString, $sSearchString); + if ($oDateTime !== false) { + $sSearchString = $oDateTime->format($this->GetInternalFormat()); + } + } + + return $sSearchString; + } + + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\DateTimeField'; + } + + /** + * Override to specify Field class + * + * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the + * $oFormField is passed, MakeFormField behave more like a Prepare. + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + } + $oFormField->SetPHPDateTimeFormat((string)$this->GetFormat()); + $oFormField->SetJSDateTimeFormat($this->GetFormat()->ToMomentJS()); + + $oFormField = parent::MakeFormField($oObject, $oFormField); + + // After call to the parent as it sets the current value + $oValue = $oObject->Get($this->GetCode()); + if ($oValue === $this->GetNullValue()) { + $oValue = $this->GetDefaultValue($oObject); + } + $oFormField->SetCurrentValue($this->GetFormat()->Format($oValue)); + + + return $oFormField; + } + + /** + * @inheritdoc + */ + public function EnumTemplateVerbs() + { + return array( + '' => 'Formatted representation', + 'raw' => 'Not formatted representation', + ); + } + + /** + * @inheritdoc + */ + public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) + { + switch ($sVerb) { + case '': + case 'text': + return static::GetFormat()->format($value); + break; + case 'html': + // Note: Not passing formatted value as the method will format it. + return $this->GetAsHTML($value); + break; + case 'raw': + return $value; + break; + default: + return parent::GetForTemplate($value, $sVerb, $oHostObject, $bLocalize); + break; + } + } + + public static function ListExpectedParams() + { + return parent::ListExpectedParams(); + //return array_merge(parent::ListExpectedParams(), array()); + } + + public function GetEditClass() + { + return "DateTime"; + } + + + public function GetEditValue($sValue, $oHostObj = null) + { + return (string)static::GetFormat()->format($sValue); + } + + public function GetValueLabel($sValue, $oHostObj = null) + { + return (string)static::GetFormat()->format($sValue); + } + + protected function GetSQLCol($bFullSpec = false) + { + return "DATETIME"; + } + + public function GetImportColumns() + { + // Allow an empty string to be a valid value (synonym for "reset") + $aColumns = array(); + $aColumns[$this->GetCode()] = 'VARCHAR(19)'.CMDBSource::GetSqlStringColumnDefinition(); + + return $aColumns; + } + + public static function GetAsUnixSeconds($value) + { + $oDeadlineDateTime = new DateTime($value); + $iUnixSeconds = $oDeadlineDateTime->format('U'); + + return $iUnixSeconds; + } + + public function GetDefaultValue(DBObject $oHostObject = null) + { + $sDefaultValue = $this->Get('default_value'); + if (utils::IsNotNullOrEmptyString($sDefaultValue)) { + try { + $sDefaultDate = Expression::FromOQL($sDefaultValue)->Evaluate([]); + } + catch (Exception $e) { + try { + $sDefaultDate = Expression::FromOQL('"'.$sDefaultValue.'"')->Evaluate([]); + } + catch (Exception $e) { + IssueLog::Error("Invalid default value '$sDefaultValue' for field '{$this->GetCode()}' on class '{$this->GetHostClass()}', defaulting to null"); + + return $this->GetNullValue(); + } + } + try { + $oDate = new DateTimeImmutable($sDefaultDate); + } + catch (Exception $e) { + IssueLog::Error("Invalid default value '$sDefaultValue' for field '{$this->GetCode()}' on class '{$this->GetHostClass()}', defaulting to null"); + + return $this->GetNullValue(); + } + + return $oDate->format($this->GetInternalFormat()); + } + + return $this->GetNullValue(); + } + + public function GetValidationPattern() + { + return static::GetFormat()->ToRegExpr(); + } + + public function GetBasicFilterOperators() + { + return array( + "=" => "equals", + "!=" => "differs from", + "<" => "before", + "<=" => "before", + ">" => "after (strictly)", + ">=" => "after", + "SameDay" => "same day (strip time)", + "SameMonth" => "same year/month", + "SameYear" => "same year", + "Today" => "today", + ">|" => "after today + N days", + "<|" => "before today + N days", + "=|" => "equals today + N days", + ); + } + + public function GetBasicFilterLooseOperator() + { + // Unless we implement a "same xxx, depending on given precision" ! + return "="; + } + + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + $sQValue = CMDBSource::Quote($value); + + switch ($sOpCode) { + case '=': + case '!=': + case '<': + case '<=': + case '>': + case '>=': + return $this->GetSQLExpr()." $sOpCode $sQValue"; + case 'SameDay': + return "DATE(".$this->GetSQLExpr().") = DATE($sQValue)"; + case 'SameMonth': + return "DATE_FORMAT(".$this->GetSQLExpr().", '%Y-%m') = DATE_FORMAT($sQValue, '%Y-%m')"; + case 'SameYear': + return "MONTH(".$this->GetSQLExpr().") = MONTH($sQValue)"; + case 'Today': + return "DATE(".$this->GetSQLExpr().") = CURRENT_DATE()"; + case '>|': + return "DATE(".$this->GetSQLExpr().") > DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; + case '<|': + return "DATE(".$this->GetSQLExpr().") < DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; + case '=|': + return "DATE(".$this->GetSQLExpr().") = DATE_ADD(CURRENT_DATE(), INTERVAL $sQValue DAY)"; + default: + return $this->GetSQLExpr()." = $sQValue"; + } + } + + /** + * @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_numeric($proposedValue)) { + return date(static::GetInternalFormat(), $proposedValue); + } + + 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 CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"'); + } + + return $proposedValue; + } + + throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode()); + } + + public function ScalarToSQL($value) + { + if (empty($value)) { + return null; + } + + return $value; + } + + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + return Str::pure2html(static::GetFormat()->format($value)); + } + + public function GetAsXML($value, $oHostObject = null, $bLocalize = true) + { + return Str::pure2xml($value); + } + + public function GetAsCSV( + $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + if (empty($sValue) || ($sValue === '0000-00-00 00:00:00') || ($sValue === '0000-00-00')) { + return ''; + } else { + if ((string)static::GetFormat() !== static::GetInternalFormat()) { + // Format conversion + $oDate = new DateTime($sValue); + if ($oDate !== false) { + $sValue = static::GetFormat()->format($oDate); + } + } + } + $sFrom = array("\r\n", $sTextQualifier); + $sTo = array("\n", $sTextQualifier.$sTextQualifier); + $sEscaped = str_replace($sFrom, $sTo, (string)$sValue); + + return $sTextQualifier.$sEscaped.$sTextQualifier; + } + + /** + * Parses a string to find some smart search patterns and build the corresponding search/OQL condition + * Each derived class is reponsible for defining and processing their own smart patterns, the base class + * does nothing special, and just calls the default (loose) operator + * + * @param string $sSearchText The search string to analyze for smart patterns + * @param FieldExpression $oField The FieldExpression representing the atttribute code in this OQL query + * @param array $aParams Values of the query parameters + * @param bool $bParseSearchString + * + * @return Expression The search condition to be added (AND) to the current search + * @throws CoreException + */ + public function GetSmartConditionExpression( + $sSearchText, FieldExpression $oField, &$aParams, $bParseSearchString = false + ) + { + // Possible smart patterns + $aPatterns = array( + 'between' => array('pattern' => '/^\[(.*),(.*)\]$/', 'operator' => 'n/a'), + 'greater than or equal' => array('pattern' => '/^>=(.*)$/', 'operator' => '>='), + 'greater than' => array('pattern' => '/^>(.*)$/', 'operator' => '>'), + 'less than or equal' => array('pattern' => '/^<=(.*)$/', 'operator' => '<='), + 'less than' => array('pattern' => '/^<(.*)$/', 'operator' => '<'), + ); + + $sPatternFound = ''; + $aMatches = array(); + foreach ($aPatterns as $sPatName => $sPattern) { + if (preg_match($sPattern['pattern'], $sSearchText, $aMatches)) { + $sPatternFound = $sPatName; + break; + } + } + + switch ($sPatternFound) { + case 'between': + + $sParamName1 = $oField->GetParent().'_'.$oField->GetName().'_1'; + $oRightExpr = new VariableExpression($sParamName1); + if ($bParseSearchString) { + $aParams[$sParamName1] = $this->ParseSearchString($aMatches[1]); + } else { + $aParams[$sParamName1] = $aMatches[1]; + } + $oCondition1 = new BinaryExpression($oField, '>=', $oRightExpr); + + $sParamName2 = $oField->GetParent().'_'.$oField->GetName().'_2'; + $oRightExpr = new VariableExpression($sParamName2); + if ($bParseSearchString) { + $aParams[$sParamName2] = $this->ParseSearchString($aMatches[2]); + } else { + $aParams[$sParamName2] = $aMatches[2]; + } + $oCondition2 = new BinaryExpression($oField, '<=', $oRightExpr); + + $oNewCondition = new BinaryExpression($oCondition1, 'AND', $oCondition2); + break; + + case 'greater than': + case 'greater than or equal': + case 'less than': + case 'less than or equal': + $sSQLOperator = $aPatterns[$sPatternFound]['operator']; + $sParamName = $oField->GetParent().'_'.$oField->GetName(); + $oRightExpr = new VariableExpression($sParamName); + if ($bParseSearchString) { + $aParams[$sParamName] = $this->ParseSearchString($aMatches[1]); + } else { + $aParams[$sParamName] = $aMatches[1]; + } + $oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr); + + break; + + default: + $oNewCondition = parent::GetSmartConditionExpression($sSearchText, $oField, $aParams); + + } + + return $oNewCondition; + } + + + public function GetHelpOnSmartSearch() + { + $sDict = parent::GetHelpOnSmartSearch(); + + $oFormat = static::GetFormat(); + $sExample = $oFormat->Format(new DateTime('2015-07-19 18:40:00')); + + return vsprintf($sDict, array($oFormat->ToPlaceholder(), $sExample)); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDeadline.php b/sources/Core/AttributeDefinition/AttributeDeadline.php index 26d5b64ca..7ee418f57 100644 --- a/sources/Core/AttributeDefinition/AttributeDeadline.php +++ b/sources/Core/AttributeDefinition/AttributeDeadline.php @@ -1,4 +1,13 @@ Format($value); - $difference = $iValue - time(); + public static function FormatDeadline($value) + { + $sResult = ''; + if ($value !== null) { + $iValue = AttributeDateTime::GetAsUnixSeconds($value); + $sDate = AttributeDateTime::GetFormat()->Format($value); + $difference = $iValue - time(); - if ($difference >= 0) { - $sDifference = self::FormatDuration($difference); - } else { - $sDifference = Dict::Format('UI:DeadlineMissedBy_duration', self::FormatDuration(-$difference)); - } - $sFormat = MetaModel::GetConfig()->Get('deadline_format'); - $sResult = str_replace(array('$date$', '$difference$'), array($sDate, $sDifference), $sFormat); - } + if ($difference >= 0) { + $sDifference = self::FormatDuration($difference); + } else { + $sDifference = Dict::Format('UI:DeadlineMissedBy_duration', self::FormatDuration(-$difference)); + } + $sFormat = MetaModel::GetConfig()->Get('deadline_format'); + $sResult = str_replace(array('$date$', '$difference$'), array($sDate, $sDifference), $sFormat); + } - return $sResult; - } + return $sResult; + } - static function FormatDuration($duration) - { - $days = floor($duration / 86400); - $hours = floor(($duration - (86400 * $days)) / 3600); - $minutes = floor(($duration - (86400 * $days + 3600 * $hours)) / 60); + static function FormatDuration($duration) + { + $days = floor($duration / 86400); + $hours = floor(($duration - (86400 * $days)) / 3600); + $minutes = floor(($duration - (86400 * $days + 3600 * $hours)) / 60); - if ($duration < 60) { - // Less than 1 min - $sResult = Dict::S('UI:Deadline_LessThan1Min'); - } else { - if ($duration < 3600) { - // less than 1 hour, display it in minutes - $sResult = Dict::Format('UI:Deadline_Minutes', $minutes); - } else { - if ($duration < 86400) { - // Less that 1 day, display it in hours/minutes - $sResult = Dict::Format('UI:Deadline_Hours_Minutes', $hours, $minutes); - } else { - // Less that 1 day, display it in hours/minutes - $sResult = Dict::Format('UI:Deadline_Days_Hours_Minutes', $days, $hours, $minutes); - } - } - } + if ($duration < 60) { + // Less than 1 min + $sResult = Dict::S('UI:Deadline_LessThan1Min'); + } else { + if ($duration < 3600) { + // less than 1 hour, display it in minutes + $sResult = Dict::Format('UI:Deadline_Minutes', $minutes); + } else { + if ($duration < 86400) { + // Less that 1 day, display it in hours/minutes + $sResult = Dict::Format('UI:Deadline_Hours_Minutes', $hours, $minutes); + } else { + // Less that 1 day, display it in hours/minutes + $sResult = Dict::Format('UI:Deadline_Days_Hours_Minutes', $days, $hours, $minutes); + } + } + } - return $sResult; - } + return $sResult; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDecimal.php b/sources/Core/AttributeDefinition/AttributeDecimal.php index 69cc6aa3e..c473d2883 100644 --- a/sources/Core/AttributeDefinition/AttributeDecimal.php +++ b/sources/Core/AttributeDefinition/AttributeDecimal.php @@ -1,4 +1,14 @@ Get('digits') . "," . $this->Get('decimals') . ")" . ($bFullSpec ? $this->GetSQLColSpec() : ''); - } + protected function GetSQLCol($bFullSpec = false) + { + return "DECIMAL(".$this->Get('digits').",".$this->Get('decimals').")".($bFullSpec ? $this->GetSQLColSpec() : ''); + } - public function GetValidationPattern() - { - $iNbDigits = $this->Get('digits'); - $iPrecision = $this->Get('decimals'); - $iNbIntegerDigits = $iNbDigits - $iPrecision; + public function GetValidationPattern() + { + $iNbDigits = $this->Get('digits'); + $iPrecision = $this->Get('decimals'); + $iNbIntegerDigits = $iNbDigits - $iPrecision; - return "^[\-\+]?\d{1,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$"; - } + return "^[\-\+]?\d{1,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$"; + } - /** - * @inheritDoc - * @since 3.2.0 - */ - public function CheckFormat($value) - { - $sRegExp = $this->GetValidationPattern(); - return preg_match("/$sRegExp/", $value); - } + /** + * @inheritDoc + * @since 3.2.0 + */ + public function CheckFormat($value) + { + $sRegExp = $this->GetValidationPattern(); - public function GetBasicFilterOperators() - { - return array( - "!=" => "differs from", - "=" => "equals", - ">" => "greater (strict) than", - ">=" => "greater than", - "<" => "less (strict) than", - "<=" => "less than", - "in" => "in" - ); - } + return preg_match("/$sRegExp/", $value); + } - public function GetBasicFilterLooseOperator() - { - // Unless we implement an "equals approximately..." or "same order of magnitude" - return "="; - } + public function GetBasicFilterOperators() + { + return array( + "!=" => "differs from", + "=" => "equals", + ">" => "greater (strict) than", + ">=" => "greater than", + "<" => "less (strict) than", + "<=" => "less than", + "in" => "in", + ); + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - $sQValue = CMDBSource::Quote($value); - switch ($sOpCode) { - case '!=': - return $this->GetSQLExpr() . " != $sQValue"; - break; - case '>': - return $this->GetSQLExpr() . " > $sQValue"; - break; - case '>=': - return $this->GetSQLExpr() . " >= $sQValue"; - break; - case '<': - return $this->GetSQLExpr() . " < $sQValue"; - break; - case '<=': - return $this->GetSQLExpr() . " <= $sQValue"; - break; - case 'in': - if (!is_array($value)) { - throw new CoreException("Expected an array for argument value (sOpCode='$sOpCode')"); - } + public function GetBasicFilterLooseOperator() + { + // Unless we implement an "equals approximately..." or "same order of magnitude" + return "="; + } - return $this->GetSQLExpr() . " IN ('" . implode("', '", $value) . "')"; - break; + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + $sQValue = CMDBSource::Quote($value); + switch ($sOpCode) { + case '!=': + return $this->GetSQLExpr()." != $sQValue"; + break; + case '>': + return $this->GetSQLExpr()." > $sQValue"; + break; + case '>=': + return $this->GetSQLExpr()." >= $sQValue"; + break; + case '<': + return $this->GetSQLExpr()." < $sQValue"; + break; + case '<=': + return $this->GetSQLExpr()." <= $sQValue"; + break; + case 'in': + if (!is_array($value)) { + throw new CoreException("Expected an array for argument value (sOpCode='$sOpCode')"); + } - case '=': - default: - return $this->GetSQLExpr() . " = \"$value\""; - } - } + return $this->GetSQLExpr()." IN ('".implode("', '", $value)."')"; + break; - public function GetNullValue() - { - return null; - } + case '=': + default: + return $this->GetSQLExpr()." = \"$value\""; + } + } - public function IsNull($proposedValue) - { - return is_null($proposedValue); - } + public function GetNullValue() + { + return null; + } - /** - * @inheritDoc - */ - public function HasAValue($proposedValue): bool - { - return utils::IsNotNullOrEmptyString($proposedValue); - } + public function IsNull($proposedValue) + { + return is_null($proposedValue); + } - public function MakeRealValue($proposedValue, $oHostObj) - { - if (is_null($proposedValue)) { - return null; - } - if ($proposedValue === '') { - return null; - } + /** + * @inheritDoc + */ + public function HasAValue($proposedValue): bool + { + return utils::IsNotNullOrEmptyString($proposedValue); + } - return $this->ScalarToSQL($proposedValue); - } + public function MakeRealValue($proposedValue, $oHostObj) + { + if (is_null($proposedValue)) { + return null; + } + if ($proposedValue === '') { + return null; + } - public function ScalarToSQL($value) - { - assert(is_null($value) || preg_match('/' . $this->GetValidationPattern() . '/', $value)); + return $this->ScalarToSQL($proposedValue); + } - if (!is_null($value) && ($value !== '')) { - $value = sprintf("%1." . $this->Get('decimals') . "F", $value); - } - return $value; // null or string - } + public function ScalarToSQL($value) + { + assert(is_null($value) || preg_match('/'.$this->GetValidationPattern().'/', $value)); + + if (!is_null($value) && ($value !== '')) { + $value = sprintf("%1.".$this->Get('decimals')."F", $value); + } + + return $value; // null or string + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDefinition.php b/sources/Core/AttributeDefinition/AttributeDefinition.php index c43ccbfe9..3660bf186 100644 --- a/sources/Core/AttributeDefinition/AttributeDefinition.php +++ b/sources/Core/AttributeDefinition/AttributeDefinition.php @@ -1,4 +1,26 @@ aCSSClasses; - } - - /** - * Return the search widget type corresponding to this attribute - * - * @return string - */ - public function GetSearchType() - { - return static::SEARCH_WIDGET_TYPE; - } - - /** - * @return bool - */ - public function IsSearchable() - { - return $this->GetSearchType() != static::SEARCH_WIDGET_TYPE_RAW; - } - - /** @var string */ - protected $m_sCode; - /** @var array */ - protected $m_aParams; - /** @var string */ - protected $m_sHostClass = '!undefined!'; - - public function Get($sParamName) - { - return $this->m_aParams[$sParamName]; - } - - public function GetIndexLength() - { - $iMaxLength = $this->GetMaxSize(); - if (is_null($iMaxLength)) { - return null; - } - if ($iMaxLength > static::INDEX_LENGTH) { - return static::INDEX_LENGTH; - } - - return $iMaxLength; - } - - public function IsParam($sParamName) - { - return (array_key_exists($sParamName, $this->m_aParams)); - } - - protected function GetOptional($sParamName, $default) - { - if (array_key_exists($sParamName, $this->m_aParams)) { - return $this->m_aParams[$sParamName]; - } else { - return $default; - } - } - - /** - * AttributeDefinition constructor. - * - * @param string $sCode - * @param array $aParams - * - * @throws \Exception - */ - public function __construct($sCode, $aParams) - { - $this->m_sCode = $sCode; - $this->m_aParams = $aParams; - $this->ConsistencyCheck(); - $this->aCSSClasses = array('attribute'); - } - - public function GetParams() - { - return $this->m_aParams; - } - - public function HasParam($sParam) - { - return array_key_exists($sParam, $this->m_aParams); - } - - public function SetHostClass($sHostClass) - { - $this->m_sHostClass = $sHostClass; - } - - public function GetHostClass() - { - return $this->m_sHostClass; - } - - /** - * @return array - * - * @throws \CoreException - */ - public function ListSubItems() - { - $aSubItems = array(); - foreach (MetaModel::ListAttributeDefs($this->m_sHostClass) as $sAttCode => $oAttDef) { - if ($oAttDef instanceof AttributeSubItem) { - if ($oAttDef->Get('target_attcode') == $this->m_sCode) { - $aSubItems[$sAttCode] = $oAttDef; - } - } - } - - return $aSubItems; - } - - // Note: I could factorize this code with the parameter management made for the AttributeDef class - // to be overloaded - public static function ListExpectedParams() - { - return array(); - } - - /** - * @throws \Exception - */ - protected function ConsistencyCheck() - { - // Check that any mandatory param has been specified - // - $aExpectedParams = static::ListExpectedParams(); - foreach ($aExpectedParams as $sParamName) { - if (!array_key_exists($sParamName, $this->m_aParams)) { - $aBacktrace = debug_backtrace(); - $sTargetClass = $aBacktrace[2]["class"]; - $sCodeInfo = $aBacktrace[1]["file"] . " - " . $aBacktrace[1]["line"]; - throw new Exception("ERROR missing parameter '$sParamName' in " . get_class($this) . " declaration for class $sTargetClass ($sCodeInfo)"); - } - } - } - - /** - * Check the validity of the given value - * - * @param \DBObject $oHostObject - * @param $value Object error if any, null otherwise - * - * @return bool|string true for no errors, false or error message otherwise - */ - public function CheckValue(DBObject $oHostObject, $value) - { - // later: factorize here the cases implemented into DBObject - return true; - } - - // table, key field, name field - - /** - * @return string - * @deprecated never used - */ - public function ListDBJoins() - { - DeprecatedCallsLog::NotifyDeprecatedPhpMethod(); - - return ""; - // e.g: return array("Site", "infrid", "name"); - } - - public function GetFinalAttDef() - { - return $this; - } - - /** - * Deprecated - use IsBasedOnDBColumns instead - * - * @return bool - */ - public function IsDirectField() - { - return static::IsBasedOnDBColumns(); - } - - /** - * Returns true if the attribute value is built after DB columns - * - * @return bool - */ - public static function IsBasedOnDBColumns() - { - return false; - } - - /** - * Returns true if the attribute value is built after other attributes by the mean of an expression (obtained via - * GetOQLExpression) - * - * @return bool - */ - public static function IsBasedOnOQLExpression() - { - return false; - } - - /** - * Returns true if the attribute value can be shown as a string - * - * @return bool - */ - public static function IsScalar() - { - return false; - } - - /** - * Returns true if the attribute can be used in bulk modify. - * - * @return bool - * @since 3.1.0 N°3190 - * - */ - public static function IsBulkModifyCompatible(): bool - { - return static::IsScalar(); - } - - /** - * Returns true if the attribute value is a set of related objects (1-N or N-N) - * - * @return bool - */ - public static function IsLinkSet() - { - return false; - } - - /** - * @param int $iType - * - * @return bool true if the attribute is an external key, either directly (RELATIVE to the host class), or - * indirectly (ABSOLUTELY) - */ - public function IsExternalKey($iType = EXTKEY_RELATIVE) - { - return false; - } - - /** - * @return bool true if the attribute value is an external key, pointing to the host class - */ - public static function IsHierarchicalKey() - { - return false; - } - - /** - * @return bool true if the attribute value is stored on an object pointed to be an external key - */ - public static function IsExternalField() - { - return false; - } - - /** - * @return bool true if the attribute can be written (by essence : metamodel field option) - * @see \DBObject::IsAttributeReadOnlyForCurrentState() for a specific object instance (depending on its workflow) - */ - public function IsWritable() - { - return false; - } - - /** - * @return bool true if the attribute has been added automatically by the framework - */ - public function IsMagic() - { - return $this->GetOptional('magic', false); - } - - /** - * @return bool true if the attribute value is kept in the loaded object (in memory) - */ - public static function LoadInObject() - { - return true; - } - - /** - * @return bool true if the attribute value comes from the database in one way or another - */ - public static function LoadFromClassTables() - { - return true; - } - - /** - * Write attribute values outside the current class tables - * - * @param \DBObject $oHostObject - * - * @return void - * @since 3.1.0 Method creation, to offer a generic method for all attributes - before we were calling directly \AttributeCustomFields::WriteValue - * - * @used-by \DBObject::WriteExternalAttributes() - */ - public function WriteExternalValues(DBObject $oHostObject): void - { - } - - /** - * Read the data from where it has been stored (outside the current class tables). - * This verb must be implemented as soon as LoadFromClassTables returns false and LoadInObject returns true - * - * @param DBObject $oHostObject - * - * @return mixed|null - * @since 3.1.0 - */ - public function ReadExternalValues(DBObject $oHostObject) - { - return null; - } - - /** - * Cleanup data upon object deletion (outside the current class tables) - * object id still available here - * - * @param \DBObject $oHostObject - * - * @since 3.1.0 - */ - public function DeleteExternalValues(DBObject $oHostObject): void - { - } - - /** - * @return bool true if the attribute should be loaded anytime (in addition to the column selected by the user) - */ - public function AlwaysLoadInTables() - { - return $this->GetOptional('always_load_in_tables', false); - } - - /** - * @param \DBObject $oHostObject - * - * @return mixed Must return the value if LoadInObject returns false - */ - public function GetValue($oHostObject) - { - return null; - } - - /** - * Returns true if the attribute must not be stored if its current value is "null" (Cf. IsNull()) - * - * @return bool - */ - public function IsNullAllowed() - { - return true; - } - - /** - * Returns the attribute code (identifies the attribute in the host class) - * - * @return string - */ - public function GetCode() - { - return $this->m_sCode; - } - - /** - * Find the corresponding "link" attribute on the target class, if any - * - * @return null | AttributeDefinition - */ - public function GetMirrorLinkAttribute() - { - return null; - } - - /** - * Helper to browse the hierarchy of classes, searching for a label - * - * @param string $sDictEntrySuffix - * @param string $sDefault - * @param bool $bUserLanguageOnly - * - * @return string - * @throws \Exception - */ - protected function SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly) - { - $sLabel = Dict::S('Class:' . $this->m_sHostClass . $sDictEntrySuffix, '', $bUserLanguageOnly); - if (strlen($sLabel) == 0) { - // Nothing found: go higher in the hierarchy (if possible) - // - $sLabel = $sDefault; - $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); - if ($sParentClass) { - if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { - $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); - $sLabel = $oAttDef->SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly); - } - } - } - - return $sLabel; - } - - /** - * @param string|null $sDefault if null, will return the attribute code replacing "_" by " " - * - * @return string - * - * @throws \Exception - */ - public function GetLabel($sDefault = null) - { - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode, null, true /*user lang*/); - if (is_null($sLabel)) { - // If no default value is specified, let's define the most relevant one for developping purposes - if (is_null($sDefault)) { - $sDefault = str_replace('_', ' ', $this->m_sCode); - } - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode, $sDefault, false); - } - - return $sLabel; - } - - /** - * To be overloaded for localized enums - * - * @param string $sValue - * - * @return string label corresponding to the given value (in plain text) - */ - public function GetValueLabel($sValue) - { - return $sValue; - } - - /** - * Get the value from a given string (plain text, CSV import) - * - * @param string $sProposedValue - * @param bool $bLocalizedValue - * @param string $sSepItem - * @param string $sSepAttribute - * @param string $sSepValue - * @param string $sAttributeQualifier - * - * @return mixed null if no match could be found - */ - public function MakeValueFromString( - $sProposedValue, - $bLocalizedValue = false, - $sSepItem = null, - $sSepAttribute = null, - $sSepValue = null, - $sAttributeQualifier = null - ) - { - return $this->MakeRealValue($sProposedValue, null); - } - - /** - * Parses a search string coming from user input - * - * @param string $sSearchString - * - * @return string - */ - public function ParseSearchString($sSearchString) - { - return $sSearchString; - } - - /** - * @return string - * - * @throws \Exception - */ - public function GetLabel_Obsolete() - { - // Written for compatibility with a data model written prior to version 0.9.1 - if (array_key_exists('label', $this->m_aParams)) { - return $this->m_aParams['label']; - } else { - return $this->GetLabel(); - } - } - - /** - * @param string|null $sDefault - * - * @return string - * - * @throws \Exception - */ - public function GetDescription($sDefault = null) - { - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '+', null, true /*user lang*/); - if (is_null($sLabel)) { - // If no default value is specified, let's define the most relevant one for developping purposes - if (is_null($sDefault)) { - $sDefault = ''; - } - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '+', $sDefault, false); - } - - return $sLabel; - } - - /** - * @return bool True if the attribute has a description {@see \AttributeDefinition::GetDescription()} - * @throws \Exception - * @since 3.1.0 - */ - public function HasDescription(): bool - { - return utils::IsNotNullOrEmptyString($this->GetDescription()); - } - - /** - * @param string|null $sDefault - * - * @return string - * - * @throws \Exception - */ - public function GetHelpOnEdition($sDefault = null) - { - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '?', null, true /*user lang*/); - if (is_null($sLabel)) { - // If no default value is specified, let's define the most relevant one for developping purposes - if (is_null($sDefault)) { - $sDefault = ''; - } - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '?', $sDefault, false); - } - - return $sLabel; - } - - public function GetHelpOnSmartSearch() - { - $aParents = array_merge(array(get_class($this) => get_class($this)), class_parents($this)); - foreach ($aParents as $sClass) { - $sHelp = Dict::S("Core:$sClass?SmartSearch", '-missing-'); - if ($sHelp != '-missing-') { - return $sHelp; - } - } - - return ''; - } - - /** - * @return string - * - * @throws \Exception - */ - public function GetDescription_Obsolete() - { - // Written for compatibility with a data model written prior to version 0.9.1 - if (array_key_exists('description', $this->m_aParams)) { - return $this->m_aParams['description']; - } else { - return $this->GetDescription(); - } - } - - public function GetTrackingLevel() - { - return $this->GetOptional('tracking_level', ATTRIBUTE_TRACKING_ALL); - } - - /** - * @return \ValueSetObjects - */ - public function GetValuesDef() - { - return null; - } - - public function GetPrerequisiteAttributes($sClass = null) - { - return array(); - } - - public function GetNullValue() - { - return null; - } - - public function IsNull($proposedValue) - { - 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! - * - * @param mixed $proposedValue - * @param \DBObject $oHostObj - * - * @return mixed - */ - public function MakeRealValue($proposedValue, $oHostObj) - { - return $proposedValue; - } - - public function Equals($val1, $val2) - { - return ($val1 == $val2); - } - - /** - * @param string $sPrefix - * - * @return array suffix/expression pairs (1 in most of the cases), for READING (Select) - */ - public function GetSQLExpressions($sPrefix = '') - { - return array(); - } - - /** - * @param array $aCols - * @param string $sPrefix - * - * @return mixed a value out of suffix/value pairs, for SELECT result interpretation - */ - public function FromSQLToValue($aCols, $sPrefix = '') - { - return null; - } - - /** - * @param bool $bFullSpec - * - * @return array column/spec pairs (1 in most of the cases), for STRUCTURING (DB creation) - * @see \CMDBSource::GetFieldSpec() - */ - public function GetSQLColumns($bFullSpec = false) - { - return array(); - } - - /** - * @param $value - * - * @return array column/value pairs (1 in most of the cases), for WRITING (Insert, Update) - */ - public function GetSQLValues($value) - { - return array(); - } - - public function RequiresIndex() - { - return false; - } - - public function RequiresFullTextIndex() - { - return false; - } - - public function CopyOnAllTables() - { - return false; - } - - public function GetOrderBySQLExpressions($sClassAlias) - { - // Note: This is the responsibility of this function to place backticks around column aliases - return array('`' . $sClassAlias . $this->GetCode() . '`'); - } - - public function GetOrderByHint() - { - return ''; - } - - // Import - differs slightly from SQL input, but identical in most cases - // - public function GetImportColumns() - { - return $this->GetSQLColumns(); - } - - public function FromImportToValue($aCols, $sPrefix = '') - { - $aValues = array(); - foreach ($this->GetSQLExpressions($sPrefix) as $sAlias => $sExpr) { - // This is working, based on the assumption that importable fields - // are not computed fields => the expression is the name of a column - $aValues[$sPrefix . $sAlias] = $aCols[$sExpr]; - } - - return $this->FromSQLToValue($aValues, $sPrefix); - } - - public function GetValidationPattern() - { - return ''; - } - - public function CheckFormat($value) - { - return true; - } - - public function GetMaxSize() - { - return null; - } - - /** - * @return mixed|null - * @deprecated never used - */ - public function MakeValue() - { - DeprecatedCallsLog::NotifyDeprecatedPhpMethod(); - $sComputeFunc = $this->Get("compute_func"); - if (empty($sComputeFunc)) { - return null; - } - - return call_user_func($sComputeFunc); - } - - abstract public function GetDefaultValue(DBObject $oHostObject = null); - - // - // To be overloaded in subclasses - // - - abstract public function GetBasicFilterOperators(); // returns an array of "opCode"=>"description" - - abstract public function GetBasicFilterLooseOperator(); // returns an "opCode" - - //abstract protected GetBasicFilterHTMLInput(); - abstract public function GetBasicFilterSQLExpr($sOpCode, $value); - - public function GetMagicFields() - { - return []; - } - - public function GetEditValue($sValue, $oHostObj = null) - { - return (string)$sValue; - } - - /** - * For fields containing a potential markup, return the value without this markup - * - * @param string $sValue - * @param \DBObject $oHostObj - * - * @return string - */ - public function GetAsPlainText($sValue, $oHostObj = null) - { - return (string)$this->GetEditValue($sValue, $oHostObj); - } - - /** - * Helper to get a value that will be JSON encoded - * - * @param mixed $value field value - * - * @return string|array PHP struct that can be properly encoded - * - * @see FromJSONToValue for the reverse operation - * - */ - public function GetForJSON($value) - { - // In most of the cases, that will be the expected behavior... - return $this->GetEditValue($value); - } - - /** - * Helper to form a value, given JSON decoded data. This way the attribute itself handles the transformation from the JSON structure to the expected data (the one that - * needs to be used in the {@see \DBObject::Set()} method). - * - * Note that for CSV and XML this isn't done yet (no delegation to the attribute but switch/case inside controllers) :/ - * - * @param string $json JSON encoded value - * - * @return mixed JSON decoded data, depending on the attribute type - * - * @see GetForJSON for the reverse operation - * - */ - public function FromJSONToValue($json) - { - // Pass-through in most of the cases - return $json; - } - - /** - * Override to display the value in the GUI - * - * @param string $sValue - * @param \DBObject $oHostObject - * @param bool $bLocalize - * - * @return string - */ - public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) - { - return Str::pure2html((string)$sValue); - } - - /** - * Override to export the value in XML - * - * @param string $sValue - * @param \DBObject $oHostObject - * @param bool $bLocalize - * - * @return mixed - */ - public function GetAsXML($sValue, $oHostObject = null, $bLocalize = true) - { - return Str::pure2xml((string)$sValue); - } - - /** - * Override to escape the value when read by DBObject::GetAsCSV() - * - * @param string $sValue - * @param string $sSeparator - * @param string $sTextQualifier - * @param \DBObject $oHostObject - * @param bool $bLocalize - * @param bool $bConvertToPlainText - * - * @return string - */ - public function GetAsCSV( - $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - return (string)$sValue; - } - - /** - * Override to differentiate a value displayed in the UI or in the history - * - * @param string $sValue - * @param \DBObject $oHostObject - * @param bool $bLocalize - * - * @return string - */ - public function GetAsHTMLForHistory($sValue, $oHostObject = null, $bLocalize = true) - { - return $this->GetAsHTML($sValue, $oHostObject, $bLocalize); - } - - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\StringField'; - } - - /** - * Override to specify Field class - * - * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the - * $oFormField is passed, MakeFormField behave more like a Prepare. - * - * @param \DBObject $oObject - * @param \Combodo\iTop\Form\Field\Field|null $oFormField - * - * @return \Combodo\iTop\Form\Field\Field - * @throws \CoreException - * @throws \Exception - * - * @noinspection PhpMissingReturnTypeInspection - * @noinspection PhpMissingParamTypeInspection - * @noinspection ReturnTypeCanBeDeclaredInspection - */ - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - // This is a fallback in case the AttributeDefinition subclass has no overloading of this function. - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - //$oFormField->SetReadOnly(true); - } - - $oFormField->SetLabel($this->GetLabel()); - - // Attributes flags - // - Retrieving flags for the current object - if ($oObject->IsNew()) { - $iFlags = $oObject->GetInitialStateAttributeFlags($this->GetCode()); - } else { - $iFlags = $oObject->GetAttributeFlags($this->GetCode()); - } - - // - Comparing flags - if ($this->IsWritable() && (!$this->IsNullAllowed() || (($iFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY))) { - $oFormField->SetMandatory(true); - } - if ((!$oObject->IsNew() || !$oFormField->GetMandatory()) && (($iFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY)) { - $oFormField->SetReadOnly(true); - } - - // CurrentValue - $oFormField->SetCurrentValue($oObject->Get($this->GetCode())); - - // Validation pattern - if ($this->GetValidationPattern() !== '') { - $oFormField->AddValidator(new \Combodo\iTop\Form\Validator\CustomRegexpValidator($this->GetValidationPattern())); - } - - // Description - $sAttDescription = $this->GetDescription(); - if (!empty($sAttDescription)) { - $oFormField->SetDescription($this->GetDescription()); - } - - // Metadata - $oFormField->AddMetadata('attribute-code', $this->GetCode()); - $oFormField->AddMetadata('attribute-type', get_class($this)); - $oFormField->AddMetadata('attribute-label', $this->GetLabel()); - // - Attribute flags - $aPossibleAttFlags = MetaModel::EnumPossibleAttributeFlags(); - foreach ($aPossibleAttFlags as $sFlagCode => $iFlagValue) { - // Note: Skip normal flag as we don't need it. - if ($sFlagCode === 'normal') { - continue; - } - $sFormattedFlagCode = str_ireplace('_', '-', $sFlagCode); - $sFormattedFlagValue = (($iFlags & $iFlagValue) === $iFlagValue) ? 'true' : 'false'; - $oFormField->AddMetadata('attribute-flag-' . $sFormattedFlagCode, $sFormattedFlagValue); - } - // - Value raw - if ($this::IsScalar()) { - $oFormField->AddMetadata('value-raw', (string)$oObject->Get($this->GetCode())); - } - - // We don't want to invalidate field because of old untouched values that are no longer valid - $aModifiedAttCodes = $oObject->ListChanges(); - $bAttributeHasBeenModified = array_key_exists($this->GetCode(), $aModifiedAttCodes); - if (false === $bAttributeHasBeenModified) { - $oFormField->SetValidationDisabled(true); - } - - return $oFormField; - } - - /** - * List the available verbs for 'GetForTemplate' - */ - public function EnumTemplateVerbs() - { - return array( - '' => 'Plain text (unlocalized) representation', - 'html' => 'HTML representation', - 'label' => 'Localized representation', - 'text' => 'Plain text representation (without any markup)', - ); - } - - /** - * Get various representations of the value, for insertion into a template (e.g. in Notifications) - * - * @param mixed $value The current value of the field - * @param string $sVerb The verb specifying the representation of the value - * @param \DBObject $oHostObject - * @param bool $bLocalize Whether or not to localize the value - * - * @return mixed|null|string - * - * @throws \Exception - */ - public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) - { - if ($this->IsScalar()) { - switch ($sVerb) { - case '': - return $value; - - case 'html': - return $this->GetAsHtml($value, $oHostObject, $bLocalize); - - case 'label': - return $this->GetEditValue($value); - - case 'text': - return $this->GetAsPlainText($value); - break; - - default: - throw new Exception("Unknown verb '$sVerb' for attribute " . $this->GetCode() . ' in class ' . get_class($oHostObject)); - } - } - - return null; - } - - /** - * @param array $aArgs - * @param string $sContains - * - * @return array|null - * @throws \CoreException - * @throws \OQLException - */ - public function GetAllowedValues($aArgs = array(), $sContains = '') - { - $oValSetDef = $this->GetValuesDef(); - if (!$oValSetDef) { - return null; - } - - return $oValSetDef->GetValues($aArgs, $sContains); - } - - /** - * GetAllowedValuesForSelect is the same as GetAllowedValues except for field with obsolescence flag - * @param array $aArgs - * @param string $sContains - * - * @return array|null - * @throws \CoreException - * @throws \OQLException - */ - public function GetAllowedValuesForSelect($aArgs = array(), $sContains = '') - { - return $this->GetAllowedValues($aArgs, $sContains); - } - - /** - * Explain the change of the attribute (history) - * - * @param string $sOldValue - * @param string $sNewValue - * @param string $sLabel - * - * @return string - * @throws \ArchivedObjectException - * @throws \CoreException - * @throws \DictExceptionMissingString - * @throws \OQLException - * @throws \Exception - */ - public function DescribeChangeAsHTML($sOldValue, $sNewValue, $sLabel = null) - { - if (is_null($sLabel)) { - $sLabel = $this->GetLabel(); - } - - $sNewValueHtml = $this->GetAsHTMLForHistory($sNewValue); - $sOldValueHtml = $this->GetAsHTMLForHistory($sOldValue); - - if ($this->IsExternalKey()) { - /** @var \AttributeExternalKey $this */ - $sTargetClass = $this->GetTargetClass(); - $sOldValueHtml = (int)$sOldValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sOldValue) : null; - $sNewValueHtml = (int)$sNewValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sNewValue) : null; - } - if ((($this->GetType() == 'String') || ($this->GetType() == 'Text')) && - (strlen($sNewValue) > strlen($sOldValue))) { - // Check if some text was not appended to the field - if (substr($sNewValue, 0, strlen($sOldValue)) == $sOldValue) // Text added at the end - { - $sDelta = $this->GetAsHTML(substr($sNewValue, strlen($sOldValue))); - $sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel); - } else { - if (substr($sNewValue, -strlen($sOldValue)) == $sOldValue) // Text added at the beginning - { - $sDelta = $this->GetAsHTML(substr($sNewValue, 0, strlen($sNewValue) - strlen($sOldValue))); - $sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel); - } else { - if (strlen($sOldValue) == 0) { - $sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml); - } else { - if (is_null($sNewValue)) { - $sNewValueHtml = Dict::S('UI:UndefinedObject'); - } - $sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, - $sNewValueHtml, $sOldValueHtml); - } - } - } - } else { - if (strlen($sOldValue) == 0) { - $sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml); - } else { - if (is_null($sNewValue)) { - $sNewValueHtml = Dict::S('UI:UndefinedObject'); - } - $sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValueHtml, - $sOldValueHtml); - } - } - - return $sResult; - } - - /** - * @param \DBObject $oObject - * @param mixed $original - * @param mixed $value - * - * @throws \ArchivedObjectException - * @throws \CoreCannotSaveObjectException - * @throws \CoreException if cannot create object - * @throws \CoreUnexpectedValue - * @throws \CoreWarning - * @throws \MySQLException - * @throws \OQLException - * - * @uses GetChangeRecordAdditionalData - * @uses GetChangeRecordClassName - * - * @since 3.1.0 N°6042 - */ - public function RecordAttChange(DBObject $oObject, $original, $value): void - { - /** @var CMDBChangeOp $oMyChangeOp */ - $oMyChangeOp = MetaModel::NewObject($this->GetChangeRecordClassName()); - $oMyChangeOp->Set("objclass", get_class($oObject)); - $oMyChangeOp->Set("objkey", $oObject->GetKey()); - $oMyChangeOp->Set("attcode", $this->GetCode()); - - $this->GetChangeRecordAdditionalData($oMyChangeOp, $oObject, $original, $value); - - $oMyChangeOp->DBInsertNoReload(); - } - - /** - * Add attribute specific information in the {@link \CMDBChangeOp} instance - * - * @param \CMDBChangeOp $oMyChangeOp - * @param \DBObject $oObject - * @param $original - * @param $value - * - * @return void - * @used-by RecordAttChange - */ - protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void - { - $oMyChangeOp->Set("oldvalue", $original); - $oMyChangeOp->Set("newvalue", $value); - } - - /** - * @return string name of the children of {@link \CMDBChangeOp} class to use for the history record - * @used-by RecordAttChange - */ - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeScalar::class; - } - - /** - * Parses a string to find some smart search patterns and build the corresponding search/OQL condition - * Each derived class is reponsible for defining and processing their own smart patterns, the base class - * does nothing special, and just calls the default (loose) operator - * - * @param string $sSearchText The search string to analyze for smart patterns - * @param \FieldExpression $oField - * @param array $aParams Values of the query parameters - * - * @return \Expression The search condition to be added (AND) to the current search - * - * @throws \CoreException - */ - public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams) - { - $sParamName = $oField->GetParent() . '_' . $oField->GetName(); - $oRightExpr = new VariableExpression($sParamName); - $sOperator = $this->GetBasicFilterLooseOperator(); - switch ($sOperator) { - case 'Contains': - $aParams[$sParamName] = "%$sSearchText%"; - $sSQLOperator = 'LIKE'; - break; - - default: - $sSQLOperator = $sOperator; - $aParams[$sParamName] = $sSearchText; - } - $oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr); - - return $oNewCondition; - } - - /** - * Tells if an attribute is part of the unique fingerprint of the object (used for comparing two objects) - * All attributes which value is not based on a value from the object itself (like ExternalFields or LinkedSet) - * must be excluded from the object's signature - * - * @return boolean - */ - public function IsPartOfFingerprint() - { - return true; - } - - /** - * The part of the current attribute in the object's signature, for the supplied value - * - * @param mixed $value The value of this attribute for the object - * - * @return string The "signature" for this field/attribute - */ - public function Fingerprint($value) - { - return (string)$value; - } - - /* - * return string - */ - public function GetRenderForDataTable(string $sClassAlias): string - { - $sRenderFunction = "return data;"; - return $sRenderFunction; - } + const SEARCH_WIDGET_TYPE_RAW = 'raw'; + const SEARCH_WIDGET_TYPE_STRING = 'string'; + const SEARCH_WIDGET_TYPE_NUMERIC = 'numeric'; + const SEARCH_WIDGET_TYPE_ENUM = 'enum'; + const SEARCH_WIDGET_TYPE_EXTERNAL_KEY = 'external_key'; + const SEARCH_WIDGET_TYPE_HIERARCHICAL_KEY = 'hierarchical_key'; + const SEARCH_WIDGET_TYPE_EXTERNAL_FIELD = 'external_field'; + const SEARCH_WIDGET_TYPE_DATE_TIME = 'date_time'; + const SEARCH_WIDGET_TYPE_DATE = 'date'; + const SEARCH_WIDGET_TYPE_SET = 'set'; + const SEARCH_WIDGET_TYPE_TAG_SET = 'tag_set'; + + + const SEARCH_WIDGET_TYPE = self::SEARCH_WIDGET_TYPE_RAW; + + const INDEX_LENGTH = 95; + + protected $aCSSClasses; + + public function GetType() + { + return Dict::S('Core:'.get_class($this)); + } + + public function GetTypeDesc() + { + return Dict::S('Core:'.get_class($this).'+'); + } + + abstract public function GetEditClass(); + + /** + * @return array Css classes + * @since 3.1.0 N°3190 + */ + public function GetCssClasses(): array + { + return $this->aCSSClasses; + } + + /** + * Return the search widget type corresponding to this attribute + * + * @return string + */ + public function GetSearchType() + { + return static::SEARCH_WIDGET_TYPE; + } + + /** + * @return bool + */ + public function IsSearchable() + { + return $this->GetSearchType() != static::SEARCH_WIDGET_TYPE_RAW; + } + + /** @var string */ + protected $m_sCode; + /** @var array */ + protected $m_aParams; + /** @var string */ + protected $m_sHostClass = '!undefined!'; + + public function Get($sParamName) + { + return $this->m_aParams[$sParamName]; + } + + public function GetIndexLength() + { + $iMaxLength = $this->GetMaxSize(); + if (is_null($iMaxLength)) { + return null; + } + if ($iMaxLength > static::INDEX_LENGTH) { + return static::INDEX_LENGTH; + } + + return $iMaxLength; + } + + public function IsParam($sParamName) + { + return (array_key_exists($sParamName, $this->m_aParams)); + } + + protected function GetOptional($sParamName, $default) + { + if (array_key_exists($sParamName, $this->m_aParams)) { + return $this->m_aParams[$sParamName]; + } else { + return $default; + } + } + + /** + * AttributeDefinition constructor. + * + * @param string $sCode + * @param array $aParams + * + * @throws Exception + */ + public function __construct($sCode, $aParams) + { + $this->m_sCode = $sCode; + $this->m_aParams = $aParams; + $this->ConsistencyCheck(); + $this->aCSSClasses = array('attribute'); + } + + public function GetParams() + { + return $this->m_aParams; + } + + public function HasParam($sParam) + { + return array_key_exists($sParam, $this->m_aParams); + } + + public function SetHostClass($sHostClass) + { + $this->m_sHostClass = $sHostClass; + } + + public function GetHostClass() + { + return $this->m_sHostClass; + } + + /** + * @return array + * + * @throws \CoreException + */ + public function ListSubItems() + { + $aSubItems = array(); + foreach (MetaModel::ListAttributeDefs($this->m_sHostClass) as $sAttCode => $oAttDef) { + if ($oAttDef instanceof AttributeSubItem) { + if ($oAttDef->Get('target_attcode') == $this->m_sCode) { + $aSubItems[$sAttCode] = $oAttDef; + } + } + } + + return $aSubItems; + } + + // Note: I could factorize this code with the parameter management made for the AttributeDef class + // to be overloaded + public static function ListExpectedParams() + { + return array(); + } + + /** + * @throws Exception + */ + protected function ConsistencyCheck() + { + // Check that any mandatory param has been specified + // + $aExpectedParams = static::ListExpectedParams(); + foreach ($aExpectedParams as $sParamName) { + if (!array_key_exists($sParamName, $this->m_aParams)) { + $aBacktrace = debug_backtrace(); + $sTargetClass = $aBacktrace[2]["class"]; + $sCodeInfo = $aBacktrace[1]["file"]." - ".$aBacktrace[1]["line"]; + throw new Exception("ERROR missing parameter '$sParamName' in ".get_class($this)." declaration for class $sTargetClass ($sCodeInfo)"); + } + } + } + + /** + * Check the validity of the given value + * + * @param \DBObject $oHostObject + * @param $value Object error if any, null otherwise + * + * @return bool|string true for no errors, false or error message otherwise + */ + public function CheckValue(DBObject $oHostObject, $value) + { + // later: factorize here the cases implemented into DBObject + return true; + } + + // table, key field, name field + + public function GetFinalAttDef() + { + return $this; + } + + /** + * Deprecated - use IsBasedOnDBColumns instead + * + * @return bool + */ + public function IsDirectField() + { + return static::IsBasedOnDBColumns(); + } + + /** + * Returns true if the attribute value is built after DB columns + * + * @return bool + */ + public static function IsBasedOnDBColumns() + { + return false; + } + + /** + * Returns true if the attribute value is built after other attributes by the mean of an expression (obtained via + * GetOQLExpression) + * + * @return bool + */ + public static function IsBasedOnOQLExpression() + { + return false; + } + + /** + * Returns true if the attribute value can be shown as a string + * + * @return bool + */ + public static function IsScalar() + { + return false; + } + + /** + * Returns true if the attribute can be used in bulk modify. + * + * @return bool + * @since 3.1.0 N°3190 + * + */ + public static function IsBulkModifyCompatible(): bool + { + return static::IsScalar(); + } + + /** + * Returns true if the attribute value is a set of related objects (1-N or N-N) + * + * @return bool + */ + public static function IsLinkSet() + { + return false; + } + + /** + * @param int $iType + * + * @return bool true if the attribute is an external key, either directly (RELATIVE to the host class), or + * indirectly (ABSOLUTELY) + */ + public function IsExternalKey($iType = EXTKEY_RELATIVE) + { + return false; + } + + /** + * @return bool true if the attribute value is an external key, pointing to the host class + */ + public static function IsHierarchicalKey() + { + return false; + } + + /** + * @return bool true if the attribute value is stored on an object pointed to be an external key + */ + public static function IsExternalField() + { + return false; + } + + /** + * @see \DBObject::IsAttributeReadOnlyForCurrentState() for a specific object instance (depending on its workflow) + * @return bool true if the attribute can be written (by essence : metamodel field option) + */ + public function IsWritable() + { + return false; + } + + /** + * @return bool true if the attribute has been added automatically by the framework + */ + public function IsMagic() + { + return $this->GetOptional('magic', false); + } + + /** + * @return bool true if the attribute value is kept in the loaded object (in memory) + */ + public static function LoadInObject() + { + return true; + } + + /** + * @return bool true if the attribute value comes from the database in one way or another + */ + public static function LoadFromClassTables() + { + return true; + } + + /** + * Write attribute values outside the current class tables + * + * @param \DBObject $oHostObject + * + * @return void + * @since 3.1.0 Method creation, to offer a generic method for all attributes - before we were calling directly \AttributeCustomFields::WriteValue + * + * @used-by \DBObject::WriteExternalAttributes() + */ + public function WriteExternalValues(DBObject $oHostObject): void + { + } + + /** + * Read the data from where it has been stored (outside the current class tables). + * This verb must be implemented as soon as LoadFromClassTables returns false and LoadInObject returns true + * + * @param DBObject $oHostObject + * + * @return mixed|null + * @since 3.1.0 + */ + public function ReadExternalValues(DBObject $oHostObject) + { + return null; + } + + /** + * Cleanup data upon object deletion (outside the current class tables) + * object id still available here + * + * @param \DBObject $oHostObject + * + * @since 3.1.0 + */ + public function DeleteExternalValues(DBObject $oHostObject): void + { + } + + /** + * @return bool true if the attribute should be loaded anytime (in addition to the column selected by the user) + */ + public function AlwaysLoadInTables() + { + return $this->GetOptional('always_load_in_tables', false); + } + + /** + * @param \DBObject $oHostObject + * + * @return mixed Must return the value if LoadInObject returns false + */ + public function GetValue($oHostObject) + { + return null; + } + + /** + * Returns true if the attribute must not be stored if its current value is "null" (Cf. IsNull()) + * + * @return bool + */ + public function IsNullAllowed() + { + return true; + } + + /** + * Returns the attribute code (identifies the attribute in the host class) + * + * @return string + */ + public function GetCode() + { + return $this->m_sCode; + } + + /** + * Find the corresponding "link" attribute on the target class, if any + * + * @return null | AttributeDefinition + */ + public function GetMirrorLinkAttribute() + { + return null; + } + + /** + * Helper to browse the hierarchy of classes, searching for a label + * + * @param string $sDictEntrySuffix + * @param string $sDefault + * @param bool $bUserLanguageOnly + * + * @return string + * @throws \Exception + */ + protected function SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly) + { + $sLabel = Dict::S('Class:'.$this->m_sHostClass.$sDictEntrySuffix, '', $bUserLanguageOnly); + if (strlen($sLabel) == 0) { + // Nothing found: go higher in the hierarchy (if possible) + // + $sLabel = $sDefault; + $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); + if ($sParentClass) { + if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { + $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); + $sLabel = $oAttDef->SearchLabel($sDictEntrySuffix, $sDefault, $bUserLanguageOnly); + } + } + } + + return $sLabel; + } + + /** + * @param string|null $sDefault if null, will return the attribute code replacing "_" by " " + * + * @return string + * + * @throws \Exception + */ + public function GetLabel($sDefault = null) + { + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode, null, true /*user lang*/); + if (is_null($sLabel)) { + // If no default value is specified, let's define the most relevant one for developping purposes + if (is_null($sDefault)) { + $sDefault = str_replace('_', ' ', $this->m_sCode); + } + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode, $sDefault, false); + } + + return $sLabel; + } + + /** + * To be overloaded for localized enums + * + * @param string $sValue + * + * @return string label corresponding to the given value (in plain text) + */ + public function GetValueLabel($sValue) + { + return $sValue; + } + + /** + * Get the value from a given string (plain text, CSV import) + * + * @param string $sProposedValue + * @param bool $bLocalizedValue + * @param string $sSepItem + * @param string $sSepAttribute + * @param string $sSepValue + * @param string $sAttributeQualifier + * + * @return mixed null if no match could be found + */ + public function MakeValueFromString( + $sProposedValue, + $bLocalizedValue = false, + $sSepItem = null, + $sSepAttribute = null, + $sSepValue = null, + $sAttributeQualifier = null + ) + { + return $this->MakeRealValue($sProposedValue, null); + } + + /** + * Parses a search string coming from user input + * + * @param string $sSearchString + * + * @return string + */ + public function ParseSearchString($sSearchString) + { + return $sSearchString; + } + + /** + * @return string + * + * @throws \Exception + */ + public function GetLabel_Obsolete() + { + // Written for compatibility with a data model written prior to version 0.9.1 + if (array_key_exists('label', $this->m_aParams)) { + return $this->m_aParams['label']; + } else { + return $this->GetLabel(); + } + } + + /** + * @param string|null $sDefault + * + * @return string + * + * @throws \Exception + */ + public function GetDescription($sDefault = null) + { + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'+', null, true /*user lang*/); + if (is_null($sLabel)) { + // If no default value is specified, let's define the most relevant one for developping purposes + if (is_null($sDefault)) { + $sDefault = ''; + } + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'+', $sDefault, false); + } + + return $sLabel; + } + + /** + * @return bool True if the attribute has a description {@see \AttributeDefinition::GetDescription()} + * @throws \Exception + * @since 3.1.0 + */ + public function HasDescription(): bool + { + return utils::IsNotNullOrEmptyString($this->GetDescription()); + } + + /** + * @param string|null $sDefault + * + * @return string + * + * @throws \Exception + */ + public function GetHelpOnEdition($sDefault = null) + { + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'?', null, true /*user lang*/); + if (is_null($sLabel)) { + // If no default value is specified, let's define the most relevant one for developping purposes + if (is_null($sDefault)) { + $sDefault = ''; + } + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'?', $sDefault, false); + } + + return $sLabel; + } + + public function GetHelpOnSmartSearch() + { + $aParents = array_merge(array(get_class($this) => get_class($this)), class_parents($this)); + foreach ($aParents as $sClass) { + $sHelp = Dict::S("Core:$sClass?SmartSearch", '-missing-'); + if ($sHelp != '-missing-') { + return $sHelp; + } + } + + return ''; + } + + /** + * @return string + * + * @throws \Exception + */ + public function GetDescription_Obsolete() + { + // Written for compatibility with a data model written prior to version 0.9.1 + if (array_key_exists('description', $this->m_aParams)) { + return $this->m_aParams['description']; + } else { + return $this->GetDescription(); + } + } + + public function GetTrackingLevel() + { + return $this->GetOptional('tracking_level', ATTRIBUTE_TRACKING_ALL); + } + + /** + * @return \ValueSetObjects + */ + public function GetValuesDef() + { + return null; + } + + public function GetPrerequisiteAttributes($sClass = null) + { + return array(); + } + + public function GetNullValue() + { + return null; + } + + public function IsNull($proposedValue) + { + 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! + * + * @param mixed $proposedValue + * @param \DBObject $oHostObj + * + * @return mixed + */ + public function MakeRealValue($proposedValue, $oHostObj) + { + return $proposedValue; + } + + public function Equals($val1, $val2) + { + return ($val1 == $val2); + } + + /** + * @param string $sPrefix + * + * @return array suffix/expression pairs (1 in most of the cases), for READING (Select) + */ + public function GetSQLExpressions($sPrefix = '') + { + return array(); + } + + /** + * @param array $aCols + * @param string $sPrefix + * + * @return mixed a value out of suffix/value pairs, for SELECT result interpretation + */ + public function FromSQLToValue($aCols, $sPrefix = '') + { + return null; + } + + /** + * @see \CMDBSource::GetFieldSpec() + * + * @param bool $bFullSpec + * + * @return array column/spec pairs (1 in most of the cases), for STRUCTURING (DB creation) + */ + public function GetSQLColumns($bFullSpec = false) + { + return array(); + } + + /** + * @param $value + * + * @return array column/value pairs (1 in most of the cases), for WRITING (Insert, Update) + */ + public function GetSQLValues($value) + { + return array(); + } + + public function RequiresIndex() + { + return false; + } + + public function RequiresFullTextIndex() + { + return false; + } + + public function CopyOnAllTables() + { + return false; + } + + public function GetOrderBySQLExpressions($sClassAlias) + { + // Note: This is the responsibility of this function to place backticks around column aliases + return array('`'.$sClassAlias.$this->GetCode().'`'); + } + + public function GetOrderByHint() + { + return ''; + } + + // Import - differs slightly from SQL input, but identical in most cases + // + public function GetImportColumns() + { + return $this->GetSQLColumns(); + } + + public function FromImportToValue($aCols, $sPrefix = '') + { + $aValues = array(); + foreach ($this->GetSQLExpressions($sPrefix) as $sAlias => $sExpr) { + // This is working, based on the assumption that importable fields + // are not computed fields => the expression is the name of a column + $aValues[$sPrefix.$sAlias] = $aCols[$sExpr]; + } + + return $this->FromSQLToValue($aValues, $sPrefix); + } + + public function GetValidationPattern() + { + return ''; + } + + public function CheckFormat($value) + { + return true; + } + + public function GetMaxSize() + { + return null; + } + + abstract public function GetDefaultValue(DBObject $oHostObject = null); + + // + // To be overloaded in subclasses + // + + abstract public function GetBasicFilterOperators(); // returns an array of "opCode"=>"description" + + abstract public function GetBasicFilterLooseOperator(); // returns an "opCode" + + //abstract protected GetBasicFilterHTMLInput(); + abstract public function GetBasicFilterSQLExpr($sOpCode, $value); + + public function GetMagicFields() + { + return []; + } + + public function GetEditValue($sValue, $oHostObj = null) + { + return (string)$sValue; + } + + /** + * For fields containing a potential markup, return the value without this markup + * + * @param string $sValue + * @param \DBObject $oHostObj + * + * @return string + */ + public function GetAsPlainText($sValue, $oHostObj = null) + { + return (string)$this->GetEditValue($sValue, $oHostObj); + } + + /** + * Helper to get a value that will be JSON encoded + * + * @see FromJSONToValue for the reverse operation + * + * @param mixed $value field value + * + * @return string|array PHP struct that can be properly encoded + * + */ + public function GetForJSON($value) + { + // In most of the cases, that will be the expected behavior... + return $this->GetEditValue($value); + } + + /** + * Helper to form a value, given JSON decoded data. This way the attribute itself handles the transformation from the JSON structure to the expected data (the one that + * needs to be used in the {@see \DBObject::Set()} method). + * + * Note that for CSV and XML this isn't done yet (no delegation to the attribute but switch/case inside controllers) :/ + * + * @see GetForJSON for the reverse operation + * + * @param string $json JSON encoded value + * + * @return mixed JSON decoded data, depending on the attribute type + * + */ + public function FromJSONToValue($json) + { + // Pass-through in most of the cases + return $json; + } + + /** + * Override to display the value in the GUI + * + * @param string $sValue + * @param \DBObject $oHostObject + * @param bool $bLocalize + * + * @return string + */ + public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) + { + return Str::pure2html((string)$sValue); + } + + /** + * Override to export the value in XML + * + * @param string $sValue + * @param \DBObject $oHostObject + * @param bool $bLocalize + * + * @return mixed + */ + public function GetAsXML($sValue, $oHostObject = null, $bLocalize = true) + { + return Str::pure2xml((string)$sValue); + } + + /** + * Override to escape the value when read by DBObject::GetAsCSV() + * + * @param string $sValue + * @param string $sSeparator + * @param string $sTextQualifier + * @param \DBObject $oHostObject + * @param bool $bLocalize + * @param bool $bConvertToPlainText + * + * @return string + */ + public function GetAsCSV( + $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + return (string)$sValue; + } + + /** + * Override to differentiate a value displayed in the UI or in the history + * + * @param string $sValue + * @param \DBObject $oHostObject + * @param bool $bLocalize + * + * @return string + */ + public function GetAsHTMLForHistory($sValue, $oHostObject = null, $bLocalize = true) + { + return $this->GetAsHTML($sValue, $oHostObject, $bLocalize); + } + + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\StringField'; + } + + /** + * Override to specify Field class + * + * When called first, $oFormField is null and will be created (eg. Make). Then when the ::parent is called and the + * $oFormField is passed, MakeFormField behave more like a Prepare. + * + * @param DBObject $oObject + * @param Field|null $oFormField + * + * @return Field + * @throws CoreException + * @throws Exception + * + * @noinspection PhpMissingReturnTypeInspection + * @noinspection PhpMissingParamTypeInspection + * @noinspection ReturnTypeCanBeDeclaredInspection + */ + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + // This is a fallback in case the AttributeDefinition subclass has no overloading of this function. + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + //$oFormField->SetReadOnly(true); + } + + $oFormField->SetLabel($this->GetLabel()); + + // Attributes flags + // - Retrieving flags for the current object + if ($oObject->IsNew()) { + $iFlags = $oObject->GetInitialStateAttributeFlags($this->GetCode()); + } else { + $iFlags = $oObject->GetAttributeFlags($this->GetCode()); + } + + // - Comparing flags + if ($this->IsWritable() && (!$this->IsNullAllowed() || (($iFlags & OPT_ATT_MANDATORY) === OPT_ATT_MANDATORY))) { + $oFormField->SetMandatory(true); + } + if ((!$oObject->IsNew() || !$oFormField->GetMandatory()) && (($iFlags & OPT_ATT_READONLY) === OPT_ATT_READONLY)) { + $oFormField->SetReadOnly(true); + } + + // CurrentValue + $oFormField->SetCurrentValue($oObject->Get($this->GetCode())); + + // Validation pattern + if ($this->GetValidationPattern() !== '') { + $oFormField->AddValidator(new \Combodo\iTop\Form\Validator\CustomRegexpValidator($this->GetValidationPattern())); + } + + // Description + $sAttDescription = $this->GetDescription(); + if (!empty($sAttDescription)) { + $oFormField->SetDescription($this->GetDescription()); + } + + // Metadata + $oFormField->AddMetadata('attribute-code', $this->GetCode()); + $oFormField->AddMetadata('attribute-type', get_class($this)); + $oFormField->AddMetadata('attribute-label', $this->GetLabel()); + // - Attribute flags + $aPossibleAttFlags = MetaModel::EnumPossibleAttributeFlags(); + foreach ($aPossibleAttFlags as $sFlagCode => $iFlagValue) { + // Note: Skip normal flag as we don't need it. + if ($sFlagCode === 'normal') { + continue; + } + $sFormattedFlagCode = str_ireplace('_', '-', $sFlagCode); + $sFormattedFlagValue = (($iFlags & $iFlagValue) === $iFlagValue) ? 'true' : 'false'; + $oFormField->AddMetadata('attribute-flag-'.$sFormattedFlagCode, $sFormattedFlagValue); + } + // - Value raw + if ($this::IsScalar()) { + $oFormField->AddMetadata('value-raw', (string)$oObject->Get($this->GetCode())); + } + + // We don't want to invalidate field because of old untouched values that are no longer valid + $aModifiedAttCodes = $oObject->ListChanges(); + $bAttributeHasBeenModified = array_key_exists($this->GetCode(), $aModifiedAttCodes); + if (false === $bAttributeHasBeenModified) { + $oFormField->SetValidationDisabled(true); + } + + return $oFormField; + } + + /** + * List the available verbs for 'GetForTemplate' + */ + public function EnumTemplateVerbs() + { + return array( + '' => 'Plain text (unlocalized) representation', + 'html' => 'HTML representation', + 'label' => 'Localized representation', + 'text' => 'Plain text representation (without any markup)', + ); + } + + /** + * Get various representations of the value, for insertion into a template (e.g. in Notifications) + * + * @param mixed $value The current value of the field + * @param string $sVerb The verb specifying the representation of the value + * @param DBObject $oHostObject + * @param bool $bLocalize Whether or not to localize the value + * + * @return mixed|null|string + * + * @throws Exception + */ + public function GetForTemplate($value, $sVerb, $oHostObject = null, $bLocalize = true) + { + if ($this->IsScalar()) { + switch ($sVerb) { + case '': + return $value; + + case 'html': + return $this->GetAsHtml($value, $oHostObject, $bLocalize); + + case 'label': + return $this->GetEditValue($value); + + case 'text': + return $this->GetAsPlainText($value); + break; + + default: + throw new Exception("Unknown verb '$sVerb' for attribute ".$this->GetCode().' in class '.get_class($oHostObject)); + } + } + + return null; + } + + /** + * @param array $aArgs + * @param string $sContains + * + * @return array|null + * @throws CoreException + * @throws OQLException + */ + public function GetAllowedValues($aArgs = array(), $sContains = '') + { + $oValSetDef = $this->GetValuesDef(); + if (!$oValSetDef) { + return null; + } + + return $oValSetDef->GetValues($aArgs, $sContains); + } + + /** + * GetAllowedValuesForSelect is the same as GetAllowedValues except for field with obsolescence flag + * + * @param array $aArgs + * @param string $sContains + * + * @return array|null + * @throws CoreException + * @throws OQLException + */ + public function GetAllowedValuesForSelect($aArgs = array(), $sContains = '') + { + return $this->GetAllowedValues($aArgs, $sContains); + } + + /** + * Explain the change of the attribute (history) + * + * @param string $sOldValue + * @param string $sNewValue + * @param string $sLabel + * + * @return string + * @throws ArchivedObjectException + * @throws CoreException + * @throws DictExceptionMissingString + * @throws OQLException + * @throws Exception + */ + public function DescribeChangeAsHTML($sOldValue, $sNewValue, $sLabel = null) + { + if (is_null($sLabel)) { + $sLabel = $this->GetLabel(); + } + + $sNewValueHtml = $this->GetAsHTMLForHistory($sNewValue); + $sOldValueHtml = $this->GetAsHTMLForHistory($sOldValue); + + if ($this->IsExternalKey()) { + /** @var \AttributeExternalKey $this */ + $sTargetClass = $this->GetTargetClass(); + $sOldValueHtml = (int)$sOldValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sOldValue) : null; + $sNewValueHtml = (int)$sNewValue ? MetaModel::GetHyperLink($sTargetClass, (int)$sNewValue) : null; + } + if ((($this->GetType() == 'String') || ($this->GetType() == 'Text')) && + (strlen($sNewValue) > strlen($sOldValue))) { + // Check if some text was not appended to the field + if (substr($sNewValue, 0, strlen($sOldValue)) == $sOldValue) // Text added at the end + { + $sDelta = $this->GetAsHTML(substr($sNewValue, strlen($sOldValue))); + $sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel); + } else { + if (substr($sNewValue, -strlen($sOldValue)) == $sOldValue) // Text added at the beginning + { + $sDelta = $this->GetAsHTML(substr($sNewValue, 0, strlen($sNewValue) - strlen($sOldValue))); + $sResult = Dict::Format('Change:Text_AppendedTo_AttName', $sDelta, $sLabel); + } else { + if (strlen($sOldValue) == 0) { + $sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml); + } else { + if (is_null($sNewValue)) { + $sNewValueHtml = Dict::S('UI:UndefinedObject'); + } + $sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, + $sNewValueHtml, $sOldValueHtml); + } + } + } + } else { + if (strlen($sOldValue) == 0) { + $sResult = Dict::Format('Change:AttName_SetTo', $sLabel, $sNewValueHtml); + } else { + if (is_null($sNewValue)) { + $sNewValueHtml = Dict::S('UI:UndefinedObject'); + } + $sResult = Dict::Format('Change:AttName_SetTo_NewValue_PreviousValue_OldValue', $sLabel, $sNewValueHtml, + $sOldValueHtml); + } + } + + return $sResult; + } + + /** + * @param DBObject $oObject + * @param mixed $original + * @param mixed $value + * + * @throws ArchivedObjectException + * @throws CoreCannotSaveObjectException + * @throws CoreException if cannot create object + * @throws CoreUnexpectedValue + * @throws CoreWarning + * @throws MySQLException + * @throws OQLException + * + * @uses GetChangeRecordAdditionalData + * @uses GetChangeRecordClassName + * + * @since 3.1.0 N°6042 + */ + public function RecordAttChange(DBObject $oObject, $original, $value): void + { + /** @var CMDBChangeOp $oMyChangeOp */ + $oMyChangeOp = MetaModel::NewObject($this->GetChangeRecordClassName()); + $oMyChangeOp->Set("objclass", get_class($oObject)); + $oMyChangeOp->Set("objkey", $oObject->GetKey()); + $oMyChangeOp->Set("attcode", $this->GetCode()); + + $this->GetChangeRecordAdditionalData($oMyChangeOp, $oObject, $original, $value); + + $oMyChangeOp->DBInsertNoReload(); + } + + /** + * Add attribute specific information in the {@link \CMDBChangeOp} instance + * + * @param CMDBChangeOp $oMyChangeOp + * @param DBObject $oObject + * @param $original + * @param $value + * + * @return void + * @used-by RecordAttChange + */ + protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void + { + $oMyChangeOp->Set("oldvalue", $original); + $oMyChangeOp->Set("newvalue", $value); + } + + /** + * @return string name of the children of {@link CMDBChangeOp} class to use for the history record + * @used-by RecordAttChange + */ + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeScalar::class; + } + + /** + * Parses a string to find some smart search patterns and build the corresponding search/OQL condition + * Each derived class is reponsible for defining and processing their own smart patterns, the base class + * does nothing special, and just calls the default (loose) operator + * + * @param string $sSearchText The search string to analyze for smart patterns + * @param FieldExpression $oField + * @param array $aParams Values of the query parameters + * + * @return Expression The search condition to be added (AND) to the current search + * + * @throws CoreException + */ + public function GetSmartConditionExpression($sSearchText, FieldExpression $oField, &$aParams) + { + $sParamName = $oField->GetParent().'_'.$oField->GetName(); + $oRightExpr = new VariableExpression($sParamName); + $sOperator = $this->GetBasicFilterLooseOperator(); + switch ($sOperator) { + case 'Contains': + $aParams[$sParamName] = "%$sSearchText%"; + $sSQLOperator = 'LIKE'; + break; + + default: + $sSQLOperator = $sOperator; + $aParams[$sParamName] = $sSearchText; + } + $oNewCondition = new BinaryExpression($oField, $sSQLOperator, $oRightExpr); + + return $oNewCondition; + } + + /** + * Tells if an attribute is part of the unique fingerprint of the object (used for comparing two objects) + * All attributes which value is not based on a value from the object itself (like ExternalFields or LinkedSet) + * must be excluded from the object's signature + * + * @return boolean + */ + public function IsPartOfFingerprint() + { + return true; + } + + /** + * The part of the current attribute in the object's signature, for the supplied value + * + * @param mixed $value The value of this attribute for the object + * + * @return string The "signature" for this field/attribute + */ + public function Fingerprint($value) + { + return (string)$value; + } + + /* + * return string + */ + public function GetRenderForDataTable(string $sClassAlias): string + { + $sRenderFunction = "return data;"; + + return $sRenderFunction; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeDuration.php b/sources/Core/AttributeDefinition/AttributeDuration.php index f875f22b7..977470d09 100644 --- a/sources/Core/AttributeDefinition/AttributeDuration.php +++ b/sources/Core/AttributeDefinition/AttributeDuration.php @@ -1,4 +1,14 @@ $days, 'hours' => $hours, 'minutes' => $minutes, 'seconds' => $seconds); - } + return array('days' => $days, 'hours' => $hours, 'minutes' => $minutes, 'seconds' => $seconds); + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\DurationField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\DurationField'; + } - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - if ($oFormField === null) { - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - } - parent::MakeFormField($oObject, $oFormField); + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + if ($oFormField === null) { + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + } + parent::MakeFormField($oObject, $oFormField); - // Note : As of today, this attribute is -by nature- only supported in readonly mode, not edition - $sAttCode = $this->GetCode(); - $oFormField->SetCurrentValue($oObject->Get($sAttCode)); - $oFormField->SetReadOnly(true); + // Note : As of today, this attribute is -by nature- only supported in readonly mode, not edition + $sAttCode = $this->GetCode(); + $oFormField->SetCurrentValue($oObject->Get($sAttCode)); + $oFormField->SetReadOnly(true); - return $oFormField; - } + return $oFormField; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeEmailAddress.php b/sources/Core/AttributeDefinition/AttributeEmailAddress.php index 2305c99ea..573778a11 100644 --- a/sources/Core/AttributeDefinition/AttributeEmailAddress.php +++ b/sources/Core/AttributeDefinition/AttributeEmailAddress.php @@ -1,4 +1,12 @@ GetOptional('validation_pattern', '^' . utils::GetConfig()->Get('email_validation_pattern') . '$'); - } + public function GetValidationPattern() + { + return $this->GetOptional('validation_pattern', '^'.utils::GetConfig()->Get('email_validation_pattern').'$'); + } - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\EmailField'; - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\EmailField'; + } - public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) - { - if (empty($sValue)) { - return ''; - } + public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) + { + if (empty($sValue)) { + return ''; + } - $sUrlDecorationClass = utils::GetConfig()->Get('email_decoration_class'); + $sUrlDecorationClass = utils::GetConfig()->Get('email_decoration_class'); - return '' . parent::GetAsHTML($sValue) . ''; - } + return ''.parent::GetAsHTML($sValue).''; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeEncryptedString.php b/sources/Core/AttributeDefinition/AttributeEncryptedString.php index 30b07ce95..ed79fd8a7 100644 --- a/sources/Core/AttributeDefinition/AttributeEncryptedString.php +++ b/sources/Core/AttributeDefinition/AttributeEncryptedString.php @@ -1,4 +1,16 @@ GetEncryptionLibrary()); - $sValue = $oSimpleCrypt->Decrypt(MetaModel::GetConfig()->GetEncryptionKey(), $aCols[$sPrefix]); + /** + * Decrypt the value when reading from the database + * + * @param array $aCols + * @param string $sPrefix + * + * @return string + * @throws Exception + */ + public function FromSQLToValue($aCols, $sPrefix = '') + { + $oSimpleCrypt = new SimpleCrypt(MetaModel::GetConfig()->GetEncryptionLibrary()); + $sValue = $oSimpleCrypt->Decrypt(MetaModel::GetConfig()->GetEncryptionKey(), $aCols[$sPrefix]); - return $sValue; - } + return $sValue; + } - /** - * Encrypt the value before storing it in the database - * - * @param $value - * - * @return array - * @throws \Exception - */ - public function GetSQLValues($value) - { - $oSimpleCrypt = new SimpleCrypt(MetaModel::GetConfig()->GetEncryptionLibrary()); - $encryptedValue = $oSimpleCrypt->Encrypt(MetaModel::GetConfig()->GetEncryptionKey(), $value); + /** + * Encrypt the value before storing it in the database + * + * @param $value + * + * @return array + * @throws Exception + */ + public function GetSQLValues($value) + { + $oSimpleCrypt = new SimpleCrypt(MetaModel::GetConfig()->GetEncryptionLibrary()); + $encryptedValue = $oSimpleCrypt->Encrypt(MetaModel::GetConfig()->GetEncryptionKey(), $value); - $aValues = array(); - $aValues[$this->Get("sql")] = $encryptedValue; + $aValues = array(); + $aValues[$this->Get("sql")] = $encryptedValue; - return $aValues; - } + return $aValues; + } - protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void - { - if (is_null($original)) { - $original = ''; - } - $oMyChangeOp->Set("prevstring", $original); - } + protected function GetChangeRecordAdditionalData(CMDBChangeOp $oMyChangeOp, DBObject $oObject, $original, $value): void + { + if (is_null($original)) { + $original = ''; + } + $oMyChangeOp->Set("prevstring", $original); + } - protected function GetChangeRecordClassName(): string - { - return CMDBChangeOpSetAttributeEncrypted::class; - } + protected function GetChangeRecordClassName(): string + { + return CMDBChangeOpSetAttributeEncrypted::class; + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeEnum.php b/sources/Core/AttributeDefinition/AttributeEnum.php index 9a2add672..8a9fd8b96 100644 --- a/sources/Core/AttributeDefinition/AttributeEnum.php +++ b/sources/Core/AttributeDefinition/AttributeEnum.php @@ -1,4 +1,19 @@ IsParam('styled_values')) { - $aStyles = $this->Get('styled_values'); - if (array_key_exists($sValue, $aStyles)) { - return $aStyles[$sValue]; - } - } + /** + * @param string|null $sValue + * + * @return ormStyle|null + */ + public function GetStyle(?string $sValue): ?ormStyle + { + if ($this->IsParam('styled_values')) { + $aStyles = $this->Get('styled_values'); + if (array_key_exists($sValue, $aStyles)) { + return $aStyles[$sValue]; + } + } - if ($this->IsParam('default_style')) { - return $this->Get('default_style'); - } + if ($this->IsParam('default_style')) { + return $this->Get('default_style'); + } - return null; - } + return null; + } - protected function GetSQLCol($bFullSpec = false) - { - // Get the definition of the column, including the actual values present in the table - return $this->GetSQLColHelper($bFullSpec, true); - } + protected function GetSQLCol($bFullSpec = false) + { + // Get the definition of the column, including the actual values present in the table + return $this->GetSQLColHelper($bFullSpec, true); + } - /** - * A more versatile version of GetSQLCol - * @param bool $bFullSpec - * @param bool $bIncludeActualValues - * @param string $sSQLTableName The table where to look for the actual values (may be useful for data synchro tables) - * @return string - * @since 3.0.0 - */ - protected function GetSQLColHelper($bFullSpec = false, $bIncludeActualValues = false, $sSQLTableName = null) - { - $oValDef = $this->GetValuesDef(); - if ($oValDef) { - $aValues = CMDBSource::Quote(array_keys($oValDef->GetValues(array(), "")), true); - } else { - $aValues = array(); - } + /** + * A more versatile version of GetSQLCol + * + * @param bool $bFullSpec + * @param bool $bIncludeActualValues + * @param string $sSQLTableName The table where to look for the actual values (may be useful for data synchro tables) + * + * @return string + * @since 3.0.0 + */ + protected function GetSQLColHelper($bFullSpec = false, $bIncludeActualValues = false, $sSQLTableName = null) + { + $oValDef = $this->GetValuesDef(); + if ($oValDef) { + $aValues = CMDBSource::Quote(array_keys($oValDef->GetValues(array(), "")), true); + } else { + $aValues = array(); + } - // Preserve the values already present in the database to ease migrations - if ($bIncludeActualValues) { - if ($sSQLTableName == null) { - // No SQL table given, use the one of the attribute - $sHostClass = $this->GetHostClass(); - $sSQLTableName = MetaModel::DBGetTable($sHostClass, $this->GetCode()); - } - $aValues = array_unique(array_merge($aValues, $this->GetActualValuesInDB($sSQLTableName))); - } + // Preserve the values already present in the database to ease migrations + if ($bIncludeActualValues) { + if ($sSQLTableName == null) { + // No SQL table given, use the one of the attribute + $sHostClass = $this->GetHostClass(); + $sSQLTableName = MetaModel::DBGetTable($sHostClass, $this->GetCode()); + } + $aValues = array_unique(array_merge($aValues, $this->GetActualValuesInDB($sSQLTableName))); + } - if (count($aValues) > 0) { - // The syntax used here do matters - // In particular, I had to remove unnecessary spaces to - // make sure that this string will match the field type returned by the DB - // (used to perform a comparison between the current DB format and the data model) - return "ENUM(" . implode(",", $aValues) . ")" - . CMDBSource::GetSqlStringColumnDefinition() - . ($bFullSpec ? $this->GetSQLColSpec() : ''); - } else { - return "VARCHAR(255)" - . CMDBSource::GetSqlStringColumnDefinition() - . ($bFullSpec ? " DEFAULT ''" : ""); // ENUM() is not an allowed syntax! - } - } + if (count($aValues) > 0) { + // The syntax used here do matters + // In particular, I had to remove unnecessary spaces to + // make sure that this string will match the field type returned by the DB + // (used to perform a comparison between the current DB format and the data model) + return "ENUM(".implode(",", $aValues).")" + .CMDBSource::GetSqlStringColumnDefinition() + .($bFullSpec ? $this->GetSQLColSpec() : ''); + } else { + return "VARCHAR(255)" + .CMDBSource::GetSqlStringColumnDefinition() + .($bFullSpec ? " DEFAULT ''" : ""); // ENUM() is not an allowed syntax! + } + } - /** - * @since 3.0.0 - * {@inheritDoc} - * @see AttributeDefinition::GetImportColumns() - */ - public function GetImportColumns() - { - // Note: this is used by the Data Synchro to build the "data" table - // Right now the function is not passed the "target" SQL table, but if we improve this in the future - // we may call $this->GetSQLColHelper(true, true, $sDBTable); to take into account the actual 'enum' values - // in this table - return array($this->GetCode() => $this->GetSQLColHelper(false, false)); - } + /** + * @see AttributeDefinition::GetImportColumns() + * @since 3.0.0 + * {@inheritDoc} + */ + public function GetImportColumns() + { + // Note: this is used by the Data Synchro to build the "data" table + // Right now the function is not passed the "target" SQL table, but if we improve this in the future + // we may call $this->GetSQLColHelper(true, true, $sDBTable); to take into account the actual 'enum' values + // in this table + return array($this->GetCode() => $this->GetSQLColHelper(false, false)); + } - /** - * Get the list of the actual 'enum' values present in the database - * @return string[] - * @since 3.0.0 - */ - protected function GetActualValuesInDB(string $sDBTable) - { - $aValues = array(); - try { - $sSQL = "SELECT DISTINCT `" . $this->GetSQLExpr() . "` AS value FROM `$sDBTable`;"; - $aValuesInDB = CMDBSource::QueryToArray($sSQL); - foreach ($aValuesInDB as $aRow) { - if ($aRow['value'] !== null) { - $aValues[] = $aRow['value']; - } - } - } catch (MySQLException $e) { - // Never mind, maybe the table does not exist yet (new installation from scratch) - // It seems more efficient to try and ignore errors than to test if the table & column really exists - } - return CMDBSource::Quote($aValues); - } + /** + * Get the list of the actual 'enum' values present in the database + * + * @return string[] + * @since 3.0.0 + */ + protected function GetActualValuesInDB(string $sDBTable) + { + $aValues = array(); + try { + $sSQL = "SELECT DISTINCT `".$this->GetSQLExpr()."` AS value FROM `$sDBTable`;"; + $aValuesInDB = CMDBSource::QueryToArray($sSQL); + foreach ($aValuesInDB as $aRow) { + if ($aRow['value'] !== null) { + $aValues[] = $aRow['value']; + } + } + } + catch (MySQLException $e) { + // Never mind, maybe the table does not exist yet (new installation from scratch) + // It seems more efficient to try and ignore errors than to test if the table & column really exists + } - protected function GetSQLColSpec() - { - $default = $this->ScalarToSQL($this->GetDefaultValue()); - if (is_null($default)) { - $sRet = ''; - } else { - // ENUMs values are strings so the default value must be a string as well, - // otherwise MySQL interprets the number as the zero-based index of the value in the list (i.e. the nth value in the list) - $sRet = " DEFAULT " . CMDBSource::Quote($default); - } + return CMDBSource::Quote($aValues); + } - return $sRet; - } + protected function GetSQLColSpec() + { + $default = $this->ScalarToSQL($this->GetDefaultValue()); + if (is_null($default)) { + $sRet = ''; + } else { + // ENUMs values are strings so the default value must be a string as well, + // otherwise MySQL interprets the number as the zero-based index of the value in the list (i.e. the nth value in the list) + $sRet = " DEFAULT ".CMDBSource::Quote($default); + } - public function ScalarToSQL($value) - { - // Note: for strings, the null value is an empty string and it is recorded as such in the DB - // but that wasn't working for enums, because '' is NOT one of the allowed values - // that's why a null value must be forced to a real null - $value = parent::ScalarToSQL($value); - if ($this->IsNull($value)) { - return null; - } else { - return $value; - } - } + return $sRet; + } - public function RequiresIndex() - { - return false; - } + public function ScalarToSQL($value) + { + // Note: for strings, the null value is an empty string and it is recorded as such in the DB + // but that wasn't working for enums, because '' is NOT one of the allowed values + // that's why a null value must be forced to a real null + $value = parent::ScalarToSQL($value); + if ($this->IsNull($value)) { + return null; + } else { + return $value; + } + } - public function GetBasicFilterOperators() - { - return parent::GetBasicFilterOperators(); - } + public function RequiresIndex() + { + return false; + } - public function GetBasicFilterLooseOperator() - { - return '='; - } + public function GetBasicFilterOperators() + { + return parent::GetBasicFilterOperators(); + } - public function GetBasicFilterSQLExpr($sOpCode, $value) - { - return parent::GetBasicFilterSQLExpr($sOpCode, $value); - } + public function GetBasicFilterLooseOperator() + { + return '='; + } - public function GetValueLabel($sValue) - { - if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label - $sLabel = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue, - Dict::S('Enum:Undefined')); - } else { - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue, null, true /*user lang*/); - if (is_null($sLabel)) { - $sDefault = str_replace('_', ' ', $sValue); - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue, $sDefault, false); - } - } + public function GetBasicFilterSQLExpr($sOpCode, $value) + { + return parent::GetBasicFilterSQLExpr($sOpCode, $value); + } - return $sLabel; - } + public function GetValueLabel($sValue) + { + if (is_null($sValue)) { + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + $sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, + Dict::S('Enum:Undefined')); + } else { + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, null, true /*user lang*/); + if (is_null($sLabel)) { + $sDefault = str_replace('_', ' ', $sValue); + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, $sDefault, false); + } + } - public function GetValueDescription($sValue) - { - if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label - $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', - Dict::S('Enum:Undefined')); - } else { - $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', - '', true /* user language only */); - if (strlen($sDescription) == 0) { - $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); - if ($sParentClass) { - if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { - $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); - $sDescription = $oAttDef->GetValueDescription($sValue); - } - } - } - } + return $sLabel; + } - return $sDescription; - } + public function GetValueDescription($sValue) + { + if (is_null($sValue)) { + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', + Dict::S('Enum:Undefined')); + } else { + $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', + '', true /* user language only */); + if (strlen($sDescription) == 0) { + $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); + if ($sParentClass) { + if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { + $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); + $sDescription = $oAttDef->GetValueDescription($sValue); + } + } + } + } - public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) - { - if ($bLocalize) { - $sLabel = $this->GetValueLabel($sValue); - // $sDescription = $this->GetValueDescription($sValue); - $oStyle = $this->GetStyle($sValue); - // later, we could imagine a detailed description in the title - // $sRes = "".parent::GetAsHtml($sLabel).""; - $oBadge = \Combodo\iTop\Application\UI\Base\Component\FieldBadge\FieldBadgeUIBlockFactory::MakeForField($sLabel, $oStyle); - $oRenderer = new \Combodo\iTop\Renderer\BlockRenderer($oBadge); - $sRes = $oRenderer->RenderHtml(); - } else { - $sRes = parent::GetAsHtml($sValue, $oHostObject, $bLocalize); - } + return $sDescription; + } - return $sRes; - } + public function GetAsHTML($sValue, $oHostObject = null, $bLocalize = true) + { + if ($bLocalize) { + $sLabel = $this->GetValueLabel($sValue); + // $sDescription = $this->GetValueDescription($sValue); + $oStyle = $this->GetStyle($sValue); + // later, we could imagine a detailed description in the title + // $sRes = "".parent::GetAsHtml($sLabel).""; + $oBadge = FieldBadgeUIBlockFactory::MakeForField($sLabel, $oStyle); + $oRenderer = new BlockRenderer($oBadge); + $sRes = $oRenderer->RenderHtml(); + } else { + $sRes = parent::GetAsHtml($sValue, $oHostObject, $bLocalize); + } - public function GetAsXML($value, $oHostObject = null, $bLocalize = true) - { - if (is_null($value)) { - $sFinalValue = ''; - } elseif ($bLocalize) { - $sFinalValue = $this->GetValueLabel($value); - } else { - $sFinalValue = $value; - } - $sRes = parent::GetAsXML($sFinalValue, $oHostObject, $bLocalize); + return $sRes; + } - return $sRes; - } + public function GetAsXML($value, $oHostObject = null, $bLocalize = true) + { + if (is_null($value)) { + $sFinalValue = ''; + } elseif ($bLocalize) { + $sFinalValue = $this->GetValueLabel($value); + } else { + $sFinalValue = $value; + } + $sRes = parent::GetAsXML($sFinalValue, $oHostObject, $bLocalize); - public function GetAsCSV( - $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, - $bConvertToPlainText = false - ) - { - if (is_null($sValue)) { - $sFinalValue = ''; - } elseif ($bLocalize) { - $sFinalValue = $this->GetValueLabel($sValue); - } else { - $sFinalValue = $sValue; - } - $sRes = parent::GetAsCSV($sFinalValue, $sSeparator, $sTextQualifier, $oHostObject, $bLocalize); + return $sRes; + } - return $sRes; - } + public function GetAsCSV( + $sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, + $bConvertToPlainText = false + ) + { + if (is_null($sValue)) { + $sFinalValue = ''; + } elseif ($bLocalize) { + $sFinalValue = $this->GetValueLabel($sValue); + } else { + $sFinalValue = $sValue; + } + $sRes = parent::GetAsCSV($sFinalValue, $sSeparator, $sTextQualifier, $oHostObject, $bLocalize); - public static function GetFormFieldClass() - { - return '\\Combodo\\iTop\\Form\\Field\\SelectField'; - } + return $sRes; + } - public function MakeFormField(DBObject $oObject, $oFormField = null) - { - if ($oFormField === null) { - // Later : We should check $this->Get('display_style') and create a Radio / Select / ... regarding its value - $sFormFieldClass = static::GetFormFieldClass(); - $oFormField = new $sFormFieldClass($this->GetCode()); - } + public static function GetFormFieldClass() + { + return '\\Combodo\\iTop\\Form\\Field\\SelectField'; + } - $oFormField->SetChoices($this->GetAllowedValues($oObject->ToArgsForQuery())); - parent::MakeFormField($oObject, $oFormField); + public function MakeFormField(DBObject $oObject, $oFormField = null) + { + if ($oFormField === null) { + // Later : We should check $this->Get('display_style') and create a Radio / Select / ... regarding its value + $sFormFieldClass = static::GetFormFieldClass(); + $oFormField = new $sFormFieldClass($this->GetCode()); + } - return $oFormField; - } + $oFormField->SetChoices($this->GetAllowedValues($oObject->ToArgsForQuery())); + parent::MakeFormField($oObject, $oFormField); - public function GetEditValue($sValue, $oHostObj = null) - { - if (is_null($sValue)) { - return ''; - } else { - return $this->GetValueLabel($sValue); - } - } + return $oFormField; + } - public function GetForJSON($value) - { - return $value; - } + public function GetEditValue($sValue, $oHostObj = null) + { + if (is_null($sValue)) { + return ''; + } else { + return $this->GetValueLabel($sValue); + } + } - public function GetAllowedValues($aArgs = array(), $sContains = '') - { - $aRawValues = parent::GetAllowedValues($aArgs, $sContains); - if (is_null($aRawValues)) { - return null; - } - $aLocalizedValues = array(); - foreach ($aRawValues as $sKey => $sValue) { - $aLocalizedValues[$sKey] = $this->GetValueLabel($sKey); - } + public function GetForJSON($value) + { + return $value; + } - // Sort by label only if necessary - // See N°1646 and {@see \MFCompiler::CompileAttributeEnumValues()} for complete information as for why sort on labels is done at runtime while other sorting are done at compile time - /** @var \ValueSetEnum $oValueSetDef */ - $oValueSetDef = $this->GetValuesDef(); - if ($oValueSetDef->IsSortedByValues()) { - asort($aLocalizedValues); - } + public function GetAllowedValues($aArgs = array(), $sContains = '') + { + $aRawValues = parent::GetAllowedValues($aArgs, $sContains); + if (is_null($aRawValues)) { + return null; + } + $aLocalizedValues = array(); + foreach ($aRawValues as $sKey => $sValue) { + $aLocalizedValues[$sKey] = $this->GetValueLabel($sKey); + } - return $aLocalizedValues; - } + // Sort by label only if necessary + // See N°1646 and {@see \MFCompiler::CompileAttributeEnumValues()} for complete information as for why sort on labels is done at runtime while other sorting are done at compile time + /** @var \ValueSetEnum $oValueSetDef */ + $oValueSetDef = $this->GetValuesDef(); + if ($oValueSetDef->IsSortedByValues()) { + asort($aLocalizedValues); + } - public function GetMaxSize() - { - return null; - } + return $aLocalizedValues; + } - /** - * An enum can be localized - */ - public function MakeValueFromString( - $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, - $sAttributeQualifier = null - ) - { - if ($bLocalizedValue) { - // Lookup for the value matching the input - // - $sFoundValue = null; - $aRawValues = parent::GetAllowedValues(); - if (!is_null($aRawValues)) { - foreach ($aRawValues as $sKey => $sValue) { - $sRefValue = $this->GetValueLabel($sKey); - if ($sProposedValue == $sRefValue) { - $sFoundValue = $sKey; - break; - } - } - } - if (is_null($sFoundValue)) { - return null; - } + public function GetMaxSize() + { + return null; + } - return $this->MakeRealValue($sFoundValue, null); - } else { - return parent::MakeValueFromString($sProposedValue, $bLocalizedValue, $sSepItem, $sSepAttribute, $sSepValue, - $sAttributeQualifier); - } - } + /** + * An enum can be localized + */ + public function MakeValueFromString( + $sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, + $sAttributeQualifier = null + ) + { + if ($bLocalizedValue) { + // Lookup for the value matching the input + // + $sFoundValue = null; + $aRawValues = parent::GetAllowedValues(); + if (!is_null($aRawValues)) { + foreach ($aRawValues as $sKey => $sValue) { + $sRefValue = $this->GetValueLabel($sKey); + if ($sProposedValue == $sRefValue) { + $sFoundValue = $sKey; + break; + } + } + } + if (is_null($sFoundValue)) { + return null; + } - /** - * Processes the input value to align it with the values supported - * by this type of attribute. In this case: turns empty strings into nulls - * - * @param mixed $proposedValue The value to be set for the attribute - * - * @return mixed The actual value that will be set - */ - public function MakeRealValue($proposedValue, $oHostObj) - { - if ($proposedValue == '') { - return null; - } + return $this->MakeRealValue($sFoundValue, null); + } else { + return parent::MakeValueFromString($sProposedValue, $bLocalizedValue, $sSepItem, $sSepAttribute, $sSepValue, + $sAttributeQualifier); + } + } - return parent::MakeRealValue($proposedValue, $oHostObj); - } + /** + * Processes the input value to align it with the values supported + * by this type of attribute. In this case: turns empty strings into nulls + * + * @param mixed $proposedValue The value to be set for the attribute + * + * @return mixed The actual value that will be set + */ + public function MakeRealValue($proposedValue, $oHostObj) + { + if ($proposedValue == '') { + return null; + } - public function GetOrderByHint() - { - $aValues = $this->GetAllowedValues(); + return parent::MakeRealValue($proposedValue, $oHostObj); + } - return Dict::Format('UI:OrderByHint_Values', implode(', ', $aValues)); - } + public function GetOrderByHint() + { + $aValues = $this->GetAllowedValues(); + + return Dict::Format('UI:OrderByHint_Values', implode(', ', $aValues)); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeEnumSet.php b/sources/Core/AttributeDefinition/AttributeEnumSet.php index 2580a1765..43c0b1a01 100644 --- a/sources/Core/AttributeDefinition/AttributeEnumSet.php +++ b/sources/Core/AttributeDefinition/AttributeEnumSet.php @@ -1,230 +1,243 @@ GetRawPossibleValues(); - $iMaxItems = $this->GetMaxItems(); - $aLengths = array(); - foreach (array_keys($aRawValues) as $sKey) { - $aLengths[] = strlen($sKey); - } - rsort($aLengths, SORT_NUMERIC); - $iMaxSize = 2; - for ($i = 0; $i < min($iMaxItems, count($aLengths)); $i++) { - $iMaxSize += $aLengths[$i] + 1; - } - return max(255, $iMaxSize); - } + public function GetMaxSize() + { + $aRawValues = $this->GetRawPossibleValues(); + $iMaxItems = $this->GetMaxItems(); + $aLengths = array(); + foreach (array_keys($aRawValues) as $sKey) { + $aLengths[] = strlen($sKey); + } + rsort($aLengths, SORT_NUMERIC); + $iMaxSize = 2; + for ($i = 0; $i < min($iMaxItems, count($aLengths)); $i++) { + $iMaxSize += $aLengths[$i] + 1; + } - private function GetRawPossibleValues($aArgs = array(), $sContains = '') - { - /** @var ValueSetEnumPadded $oValSetDef */ - $oValSetDef = $this->Get('possible_values'); - if (!$oValSetDef) { - return array(); - } + return max(255, $iMaxSize); + } - return $oValSetDef->GetValues($aArgs, $sContains); - } + private function GetRawPossibleValues($aArgs = array(), $sContains = '') + { + /** @var ValueSetEnumPadded $oValSetDef */ + $oValSetDef = $this->Get('possible_values'); + if (!$oValSetDef) { + return array(); + } - public function GetPossibleValues($aArgs = array(), $sContains = '') - { - $aRawValues = $this->GetRawPossibleValues($aArgs, $sContains); - $aLocalizedValues = array(); - foreach ($aRawValues as $sKey => $sValue) { - $aLocalizedValues[$sKey] = $this->GetValueLabel($sKey); - } + return $oValSetDef->GetValues($aArgs, $sContains); + } - return $aLocalizedValues; - } + public function GetPossibleValues($aArgs = array(), $sContains = '') + { + $aRawValues = $this->GetRawPossibleValues($aArgs, $sContains); + $aLocalizedValues = array(); + foreach ($aRawValues as $sKey => $sValue) { + $aLocalizedValues[$sKey] = $this->GetValueLabel($sKey); + } - public function GetValueLabel($sValue) - { - if ($sValue instanceof ormSet) { - $sValue = implode(', ', $sValue->GetValues()); - } + return $aLocalizedValues; + } - $aValues = $this->GetRawPossibleValues(); - if (is_array($aValues) && is_string($sValue) && isset($aValues[$sValue])) { - $sValue = $aValues[$sValue]; - } + public function GetValueLabel($sValue) + { + if ($sValue instanceof ormSet) { + $sValue = implode(', ', $sValue->GetValues()); + } - if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label - $sLabel = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue, - Dict::S('Enum:Undefined')); - } else { - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue, null, true /*user lang*/); - if (is_null($sLabel)) { - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sValue, null, false); - if (is_null($sLabel)) { - $sDefault = trim(str_replace('_', ' ', $sValue)); - // Browse the hierarchy again, accepting default (english) translations - $sLabel = $this->SearchLabel('/Attribute:' . $this->m_sCode . '/Value:' . $sDefault, $sDefault, false); - } - } - } + $aValues = $this->GetRawPossibleValues(); + if (is_array($aValues) && is_string($sValue) && isset($aValues[$sValue])) { + $sValue = $aValues[$sValue]; + } - return $sLabel; - } + if (is_null($sValue)) { + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + $sLabel = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue, + Dict::S('Enum:Undefined')); + } else { + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, null, true /*user lang*/); + if (is_null($sLabel)) { + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sValue, null, false); + if (is_null($sLabel)) { + $sDefault = trim(str_replace('_', ' ', $sValue)); + // Browse the hierarchy again, accepting default (english) translations + $sLabel = $this->SearchLabel('/Attribute:'.$this->m_sCode.'/Value:'.$sDefault, $sDefault, false); + } + } + } - public function GetValueDescription($sValue) - { - if (is_null($sValue)) { - // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label - $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', - Dict::S('Enum:Undefined')); - } else { - $sDescription = Dict::S('Class:' . $this->GetHostClass() . '/Attribute:' . $this->GetCode() . '/Value:' . $sValue . '+', - '', true /* user language only */); - if (strlen($sDescription) == 0) { - $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); - if ($sParentClass) { - if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { - $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); - $sDescription = $oAttDef->GetValueDescription($sValue); - } - } - } - } + return $sLabel; + } - return $sDescription; - } + public function GetValueDescription($sValue) + { + if (is_null($sValue)) { + // Unless a specific label is defined for the null value of this enum, use a generic "undefined" label + $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', + Dict::S('Enum:Undefined')); + } else { + $sDescription = Dict::S('Class:'.$this->GetHostClass().'/Attribute:'.$this->GetCode().'/Value:'.$sValue.'+', + '', true /* user language only */); + if (strlen($sDescription) == 0) { + $sParentClass = MetaModel::GetParentClass($this->m_sHostClass); + if ($sParentClass) { + if (MetaModel::IsValidAttCode($sParentClass, $this->m_sCode)) { + $oAttDef = MetaModel::GetAttributeDef($sParentClass, $this->m_sCode); + $sDescription = $oAttDef->GetValueDescription($sValue); + } + } + } + } - public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) - { - if ($bLocalize) { - if ($value instanceof ormSet) { - $sRes = $this->GenerateViewHtmlForValues($value->GetValues()); - } else { - $sLabel = $this->GetValueLabel($value); - $sDescription = $this->GetValueDescription($value); - $sRes = "" . parent::GetAsHtml($sLabel) . ""; - } - } else { - $sRes = parent::GetAsHtml($value, $oHostObject, $bLocalize); - } + return $sDescription; + } - return $sRes; - } + public function GetAsHTML($value, $oHostObject = null, $bLocalize = true) + { + if ($bLocalize) { + if ($value instanceof ormSet) { + $sRes = $this->GenerateViewHtmlForValues($value->GetValues()); + } else { + $sLabel = $this->GetValueLabel($value); + $sDescription = $this->GetValueDescription($value); + $sRes = "".parent::GetAsHtml($sLabel).""; + } + } else { + $sRes = parent::GetAsHtml($value, $oHostObject, $bLocalize); + } + + return $sRes; + } - /** - * @param ormSet $value - * @param string $sSeparator - * @param string $sTextQualifier - * @param \DBObject $oHostObject - * @param bool $bLocalize - * @param bool $bConvertToPlainText - * - * @return mixed|string - * @throws \Exception - */ - public function GetAsCSV($value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false) - { - $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator'); - if (is_object($value) && ($value instanceof ormSet)) { - $aValues = $value->GetValues(); - if ($bLocalize) { - $aLocalizedValues = array(); - foreach ($aValues as $sValue) { - $aLocalizedValues[] = $this->GetValueLabel($sValue); - } - $aValues = $aLocalizedValues; - } - $sRes = implode($sSepItem, $aValues); - } else { - $sRes = ''; - } + /** + * @param ormSet $value + * @param string $sSeparator + * @param string $sTextQualifier + * @param DBObject $oHostObject + * @param bool $bLocalize + * @param bool $bConvertToPlainText + * + * @return mixed|string + * @throws Exception + */ + public function GetAsCSV($value, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null, $bLocalize = true, $bConvertToPlainText = false) + { + $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator'); + if (is_object($value) && ($value instanceof ormSet)) { + $aValues = $value->GetValues(); + if ($bLocalize) { + $aLocalizedValues = array(); + foreach ($aValues as $sValue) { + $aLocalizedValues[] = $this->GetValueLabel($sValue); + } + $aValues = $aLocalizedValues; + } + $sRes = implode($sSepItem, $aValues); + } else { + $sRes = ''; + } - return "{$sTextQualifier}{$sRes}{$sTextQualifier}"; - } + return "{$sTextQualifier}{$sRes}{$sTextQualifier}"; + } - /** - * Get the value from a given string (plain text, CSV import) - * - * @param string $sProposedValue - * @param bool $bLocalizedValue - * @param string $sSepItem - * @param string $sSepAttribute - * @param string $sSepValue - * @param string $sAttributeQualifier - * - * @return mixed null if no match could be found - * @throws \Exception - */ - public function MakeValueFromString($sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null) - { - if ($bLocalizedValue) { - // Lookup for the values matching the input - // - $aValues = $this->FromStringToArray($sProposedValue); - $aFoundValues = array(); - $aRawValues = $this->GetPossibleValues(); - foreach ($aValues as $sValue) { - $bFound = false; - foreach ($aRawValues as $sCode => $sRawValue) { - if ($sValue == $sRawValue) { - $aFoundValues[] = $sCode; - $bFound = true; - break; - } - } - if (!$bFound) { - // Not found, break the import - return null; - } - } + /** + * Get the value from a given string (plain text, CSV import) + * + * @param string $sProposedValue + * @param bool $bLocalizedValue + * @param string $sSepItem + * @param string $sSepAttribute + * @param string $sSepValue + * @param string $sAttributeQualifier + * + * @return mixed null if no match could be found + * @throws Exception + */ + public function MakeValueFromString($sProposedValue, $bLocalizedValue = false, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null) + { + if ($bLocalizedValue) { + // Lookup for the values matching the input + // + $aValues = $this->FromStringToArray($sProposedValue); + $aFoundValues = array(); + $aRawValues = $this->GetPossibleValues(); + foreach ($aValues as $sValue) { + $bFound = false; + foreach ($aRawValues as $sCode => $sRawValue) { + if ($sValue == $sRawValue) { + $aFoundValues[] = $sCode; + $bFound = true; + break; + } + } + if (!$bFound) { + // Not found, break the import + return null; + } + } - return $this->MakeRealValue(implode(',', $aFoundValues), null); - } else { - return $this->MakeRealValue($sProposedValue, null, false); - } - } + return $this->MakeRealValue(implode(',', $aFoundValues), null); + } else { + return $this->MakeRealValue($sProposedValue, null, false); + } + } - /** - * @param string $proposedValue Search string used for MATCHES - * - * @param string $sDefaultSepItem word separator to extract items - * - * @return array of EnumSet codes - * @throws \Exception - */ - public function FromStringToArray($proposedValue, $sDefaultSepItem = ',') - { - $aValues = array(); - if (!empty($proposedValue)) { - $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator'); - // convert also other separators - if ($sSepItem !== $sDefaultSepItem) { - $proposedValue = str_replace($sDefaultSepItem, $sSepItem, $proposedValue); - } - foreach (explode($sSepItem, $proposedValue) as $sCode) { - $sValue = trim($sCode); - if (strlen($sValue) > 2) { - $sLabel = $this->GetValueLabel($sValue); - $aValues[$sLabel] = $sValue; - } - } - } - return $aValues; - } + /** + * @param string $proposedValue Search string used for MATCHES + * + * @param string $sDefaultSepItem word separator to extract items + * + * @return array of EnumSet codes + * @throws Exception + */ + public function FromStringToArray($proposedValue, $sDefaultSepItem = ',') + { + $aValues = array(); + if (!empty($proposedValue)) { + $sSepItem = MetaModel::GetConfig()->Get('tag_set_item_separator'); + // convert also other separators + if ($sSepItem !== $sDefaultSepItem) { + $proposedValue = str_replace($sDefaultSepItem, $sSepItem, $proposedValue); + } + foreach (explode($sSepItem, $proposedValue) as $sCode) { + $sValue = trim($sCode); + if (strlen($sValue) > 2) { + $sLabel = $this->GetValueLabel($sValue); + $aValues[$sLabel] = $sValue; + } + } + } - public function Equals($val1, $val2) - { - return $val1->Equals($val2); - } + return $aValues; + } + + public function Equals($val1, $val2) + { + return $val1->Equals($val2); + } } \ No newline at end of file diff --git a/sources/Core/AttributeDefinition/AttributeExternalField.php b/sources/Core/AttributeDefinition/AttributeExternalField.php index 087fbb40d..bcb2ceacd 100644 --- a/sources/Core/AttributeDefinition/AttributeExternalField.php +++ b/sources/Core/AttributeDefinition/AttributeExternalField.php @@ -1,4 +1,15 @@ IsFriendlyName()) { - return self::SEARCH_WIDGET_TYPE_RAW; - } - - try { - $oRemoteAtt = $this->GetFinalAttDef(); - switch (true) { - case ($oRemoteAtt instanceof AttributeString): - return self::SEARCH_WIDGET_TYPE_EXTERNAL_FIELD; - case ($oRemoteAtt instanceof AttributeExternalKey): - return self::SEARCH_WIDGET_TYPE_EXTERNAL_KEY; - } - } catch (CoreException $e) { - } - - return self::SEARCH_WIDGET_TYPE_RAW; - } - - function IsSearchable() - { - if ($this->IsFriendlyName()) { - return true; - } - return parent::IsSearchable(); - } - - public static function ListExpectedParams() - { - return array_merge(parent::ListExpectedParams(), array("extkey_attcode", "target_attcode")); - } - - public function GetEditClass() - { - return "ExtField"; - } - - /** - * @return \AttributeDefinition - * @throws \CoreException - */ - public function GetFinalAttDef() - { - $oExtAttDef = $this->GetExtAttDef(); - - return $oExtAttDef->GetFinalAttDef(); - } - - protected function GetSQLCol($bFullSpec = false) - { - // throw new CoreException("external attribute: does it make any sense to request its type ?"); - $oExtAttDef = $this->GetExtAttDef(); - - return $oExtAttDef->GetSQLCol($bFullSpec); - } - - public function GetSQLExpressions($sPrefix = '') - { - if ($sPrefix == '') { - return array('' => $this->GetCode()); // Warning: Use GetCode() since AttributeExternalField does not have any 'sql' property - } else { - return $sPrefix; - } - } - - /** - * @param string $sDefault - * - * @return string dict entry if defined, otherwise : - *