From ea8695929790184f89c763c5b2cacbd71f882358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cornelius=20Wei=C3=9F?= Date: Wed, 26 Feb 2025 10:16:35 +0100 Subject: [PATCH 1/2] tweak(Tinebase): allow field feature config to be for different app --- tine20/Addressbook/Model/Contact.php | 6 +++++- tine20/Calendar/Model/Event.php | 4 ++++ tine20/Timetracker/Model/Timeaccount.php | 9 ++++++--- tine20/Timetracker/Model/Timesheet.php | 9 ++++++--- tine20/Tinebase/ModelConfiguration.php | 8 -------- tine20/Tinebase/ModelConfiguration/Const.php | 4 ++++ tine20/Tinebase/js/ApplicationStarter.js | 5 ++++- tine20/Tinebase/js/widgets/form/FieldManager.js | 5 +++++ tine20/Tinebase/js/widgets/grid/ColumnManager.js | 9 +++++++++ 9 files changed, 43 insertions(+), 16 deletions(-) diff --git a/tine20/Addressbook/Model/Contact.php b/tine20/Addressbook/Model/Contact.php index 55d45a23a5f..cc1203e8ad0 100644 --- a/tine20/Addressbook/Model/Contact.php +++ b/tine20/Addressbook/Model/Contact.php @@ -1059,7 +1059,11 @@ class Addressbook_Model_Contact extends Tinebase_Record_NewAbstract self::UI_CONFIG => [ 'filterOptions' => [ 'jsConfig' => ['filtertype' => 'tinebase.site'] - ] + ], + self::UI_CONFIG_FEATURE => [ + self::APP_NAME => Tinebase_Config::APP_NAME, + self::UI_CONFIG_FEATURE => Tinebase_Config::FEATURE_SITE + ], ] ], diff --git a/tine20/Calendar/Model/Event.php b/tine20/Calendar/Model/Event.php index d28d70564ae..d478ec65870 100644 --- a/tine20/Calendar/Model/Event.php +++ b/tine20/Calendar/Model/Event.php @@ -259,6 +259,10 @@ class Calendar_Model_Event extends Tinebase_Record_Abstract 'searchComboConfig' => [ 'useEditPlugin' => false, ], + self::UI_CONFIG_FEATURE => [ + self::APP_NAME => Tinebase_Config::APP_NAME, + self::UI_CONFIG_FEATURE => Tinebase_Config::FEATURE_SITE + ], ], ], 'organizer' => [ diff --git a/tine20/Timetracker/Model/Timeaccount.php b/tine20/Timetracker/Model/Timeaccount.php index 3a5f6295e2a..56eca41f897 100644 --- a/tine20/Timetracker/Model/Timeaccount.php +++ b/tine20/Timetracker/Model/Timeaccount.php @@ -229,10 +229,13 @@ class Timetracker_Model_Timeaccount extends Sales_Model_Accountable_Abstract 'appName' => 'Sales', 'modelName' => 'Invoice', 'idProperty' => 'id', - // TODO we should replace this with a generic approach to fetch configured models of an app - // -> APP_Frontend_Json::$_configuredModels should be moved from json to app controller - 'feature' => 'invoicesModule', // Sales_Config::FEATURE_INVOICES_MODULE ), + self::UI_CONFIG => [ + self::UI_CONFIG_FEATURE => [ + self::APP_NAME => 'Sales', + self::UI_CONFIG_FEATURE => 'invoicesModule' + ], + ], 'validators' => array(Zend_Filter_Input::ALLOW_EMPTY => true), 'copyOmit' => true, ), diff --git a/tine20/Timetracker/Model/Timesheet.php b/tine20/Timetracker/Model/Timesheet.php index 42c41dd3f02..abaa9ead6bf 100644 --- a/tine20/Timetracker/Model/Timesheet.php +++ b/tine20/Timetracker/Model/Timesheet.php @@ -186,10 +186,13 @@ class Timetracker_Model_Timesheet extends Tinebase_Record_Abstract implements Sa 'appName' => 'Sales', 'modelName' => 'Invoice', 'idProperty' => 'id', - // TODO we should replace this with a generic approach to fetch configured models of an app - // -> APP_Frontend_Json::$_configuredModels should be moved from json to app controller - 'feature' => 'invoicesModule', // Sales_Config::FEATURE_INVOICES_MODULE ), + self::UI_CONFIG => [ + self::UI_CONFIG_FEATURE => [ + self::APP_NAME => 'Sales', + self::UI_CONFIG_FEATURE => 'invoicesModule' + ], + ], 'copyOmit' => true, ), 'is_cleared' => array( diff --git a/tine20/Tinebase/ModelConfiguration.php b/tine20/Tinebase/ModelConfiguration.php index 038d293f2a9..1f726b875c9 100644 --- a/tine20/Tinebase/ModelConfiguration.php +++ b/tine20/Tinebase/ModelConfiguration.php @@ -2232,14 +2232,6 @@ protected function _isAvailable($_fieldConfig) $result = self::$_availableApplications[$fieldConfig['appName']]; } - if ($result && isset($fieldConfig['feature'])) { - $config = Tinebase_Config_Abstract::factory($fieldConfig['appName']); - $result = $config->featureEnabled($fieldConfig['feature']); - - if (! $result && Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ - . '::' . __LINE__ . ' Feature ' . $fieldConfig['feature'] . ' disables field'); - } - return $result; } diff --git a/tine20/Tinebase/ModelConfiguration/Const.php b/tine20/Tinebase/ModelConfiguration/Const.php index ec62ac3be26..b82629c3ab6 100644 --- a/tine20/Tinebase/ModelConfiguration/Const.php +++ b/tine20/Tinebase/ModelConfiguration/Const.php @@ -296,6 +296,10 @@ class Tinebase_ModelConfiguration_Const { public const UNIQUE_CONSTRAINTS = 'uniqueConstraints'; public const UNSIGNED = 'unsigned'; public const UI_CONFIG = 'uiconfig'; + /** + * define which feature is required to enable field or filter + */ + public const UI_CONFIG_FEATURE = 'feature'; public const UI_CONFIG_LAYOUT_SMALL = 'small'; public const UI_CONFIG_LAYOUT_MEDIUM = 'medium'; public const UI_CONFIG_LAYOUT_BIG = 'big'; diff --git a/tine20/Tinebase/js/ApplicationStarter.js b/tine20/Tinebase/js/ApplicationStarter.js index f8cc8892913..80cea5f0816 100644 --- a/tine20/Tinebase/js/ApplicationStarter.js +++ b/tine20/Tinebase/js/ApplicationStarter.js @@ -303,7 +303,10 @@ Ext.apply(Tine.Tinebase.ApplicationStarter,{ Tine.log.error('Application ' + owningAppName + ' not found!'); return null; } - + const feature = _.get(fieldconfig, 'uiconfig.feature') + if (feature && !Tine.Tinebase.featureEnabled(feature.feature, feature.appName)) { + return null; + } // check right on foreign app if (fieldconfig && (fieldconfig.type == 'record' || fieldconfig.type == 'records')) { var opt = fieldconfig.config; diff --git a/tine20/Tinebase/js/widgets/form/FieldManager.js b/tine20/Tinebase/js/widgets/form/FieldManager.js index 73d2054d8fb..a6efe7638d7 100644 --- a/tine20/Tinebase/js/widgets/form/FieldManager.js +++ b/tine20/Tinebase/js/widgets/form/FieldManager.js @@ -77,6 +77,11 @@ Tine.widgets.form.FieldManager = function() { return null; } + const feature = _.get(fieldDefinition, 'uiconfig.feature') + if (feature && !Tine.Tinebase.featureEnabled(feature.feature, feature.appName)) { + return null; + } + return this.getByFieldDefinition(fieldDefinition, category, config); }, diff --git a/tine20/Tinebase/js/widgets/grid/ColumnManager.js b/tine20/Tinebase/js/widgets/grid/ColumnManager.js index 429e602dd58..67b3894278e 100644 --- a/tine20/Tinebase/js/widgets/grid/ColumnManager.js +++ b/tine20/Tinebase/js/widgets/grid/ColumnManager.js @@ -68,6 +68,15 @@ Tine.widgets.grid.ColumnManager = function() { if (! app) return null; if (fieldDefinition) { + if (_.get(fieldDefinition, 'disabled') || _.get(fieldDefinition, 'uiconfig.disabled')) { + return null; + } + + const feature = _.get(fieldDefinition, 'uiconfig.feature') + if (feature && !Tine.Tinebase.featureEnabled(feature.feature, feature.appName)) { + return null; + } + if (['text', 'fulltext'].indexOf(fieldDefinition.type) >= 0) { config.hidden = true; } From dc6fc9241abc11bea904ebab396ec4bfb034da1a Mon Sep 17 00:00:00 2001 From: Paul Mehrer Date: Wed, 26 Feb 2025 15:17:34 +0100 Subject: [PATCH 2/2] tweak(tb) fix tests re property feature switch --- tests/tine20/Tinebase/Frontend/JsonTest.php | 28 +++++-------------- .../Tinebase/ModelConfigurationTest.php | 16 ----------- 2 files changed, 7 insertions(+), 37 deletions(-) diff --git a/tests/tine20/Tinebase/Frontend/JsonTest.php b/tests/tine20/Tinebase/Frontend/JsonTest.php index 134c67a5297..19637f28f6a 100644 --- a/tests/tine20/Tinebase/Frontend/JsonTest.php +++ b/tests/tine20/Tinebase/Frontend/JsonTest.php @@ -696,28 +696,14 @@ public function testGetAllRegistryData() $symbols = Zend_Locale::getTranslationList('symbols', $locale); self::assertEquals($symbols['decimal'], $registryData['Tinebase']['decimalSeparator']); - if (Sales_Config::getInstance()->featureEnabled(Sales_Config::FEATURE_INVOICES_MODULE)) { - $configuredSalesModels = array_keys($registryData['Sales']['models']); - self::assertTrue(in_array('Invoice', $configuredSalesModels), 'Invoices is missing from configured models: ' - . print_r($configuredSalesModels, true)); - $copyOmitFields = array( - 'billed_in', - 'invoice_id', - 'status', - 'cleared_at', - 'relations', - ); - } else { - $copyOmitFields = array( - 'billed_in', - 'status', - 'cleared_at', - 'relations', - ); - } - self::assertTrue(isset($registryData['Timetracker']['models']['Timeaccount']['copyOmitFields']), 'Timeaccount copyOmitFields empty/missing'); - self::assertEquals($copyOmitFields, $registryData['Timetracker']['models']['Timeaccount']['copyOmitFields']); + self::assertEquals([ + 'billed_in', + 'invoice_id', + 'status', + 'cleared_at', + 'relations', + ], $registryData['Timetracker']['models']['Timeaccount']['copyOmitFields']); self::assertTrue(is_array(($registryData['Timetracker']['relatableModels'][0])), 'relatableModels needs to be an numbered array'); $this->_assertImportExportDefinitions($registryData); diff --git a/tests/tine20/Tinebase/ModelConfigurationTest.php b/tests/tine20/Tinebase/ModelConfigurationTest.php index 94455c03bcd..ff0db6c915f 100644 --- a/tests/tine20/Tinebase/ModelConfigurationTest.php +++ b/tests/tine20/Tinebase/ModelConfigurationTest.php @@ -37,22 +37,6 @@ public function testModelCreationTraditional() $this->assertNull($cObj); } - /** - * tests if the modelconfiguration is created for foreign record keys that are disabled by a feature switch - */ - public function testModelConfigWithDisabledForeignRecords() - { - // TODO disable feature first - if (Sales_Config::getInstance()->featureEnabled(Sales_Config::FEATURE_INVOICES_MODULE)) { - $this->markTestSkipped('only testable when disabled'); - } - - $timesheet = new Timetracker_Model_Timesheet(array(), true); - $mcFields = $timesheet->getConfiguration()->getFields(); - $this->assertEquals('string', $mcFields['invoice_id']['type']); - $this->assertEquals(null, $mcFields['invoice_id']['label']); - } - /** * testModelConfigWithDisabledRelationApp */