From f008885c52f1ea03bc273d02237b5d1d748479d3 Mon Sep 17 00:00:00 2001 From: Edsel Date: Mon, 14 Mar 2016 16:11:00 +0530 Subject: [PATCH] CRM-18231 Added settings on developer page --- CRM/Admin/Form/Setting.php | 27 +++++++-- CRM/Admin/Form/Setting/Debugging.php | 24 ++++++++ CRM/Admin/Page/Job.php | 4 ++ CRM/Core/BAO/Setting.php | 24 ++++++++ CRM/Core/Config.php | 29 ++++++++++ CRM/Core/JobManager.php | 11 ++++ CRM/Upgrade/Incremental/sql/4.7.10.mysql.tpl | 12 ++++ CRM/Utils/Check/Component/Env.php | 20 +++++++ api/v3/Job.php | 1 + settings/Developer.setting.php | 17 ++++++ .../CRM/Admin/Form/Setting/Debugging.tpl | 5 ++ .../CRM/common/civicrm.settings.php.template | 11 ++++ tests/phpunit/CRM/Core/BAO/SettingTest.php | 14 +++++ .../Admin/Form/Setting/DebuggingTest.php | 55 +++++++++++++++++++ .../phpunit/api/v3/JobProcessMailingTest.php | 34 ++++++++++++ tests/phpunit/api/v3/SettingTest.php | 23 ++++++++ xml/templates/civicrm_data.tpl | 9 ++- 17 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 tests/phpunit/WebTest/Admin/Form/Setting/DebuggingTest.php diff --git a/CRM/Admin/Form/Setting.php b/CRM/Admin/Form/Setting.php index 103b436803..c378b53d80 100644 --- a/CRM/Admin/Form/Setting.php +++ b/CRM/Admin/Form/Setting.php @@ -68,6 +68,7 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form { $this->_defaults['contact_reference_options'] = self::getAutocompleteContactReference(); $this->_defaults['enableSSL'] = Civi::settings()->get('enableSSL'); $this->_defaults['verifySSL'] = Civi::settings()->get('verifySSL'); + $this->_defaults['environment'] = CRM_Core_Config::environment(); $this->_defaults['enableComponents'] = Civi::settings()->get('enable_components'); } @@ -97,9 +98,23 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form { foreach ($settingMetaData as $setting => $props) { if (isset($props['quick_form_type'])) { if (isset($props['pseudoconstant'])) { - $options = civicrm_api3('Setting', 'getoptions', array( - 'field' => $setting, - )); + if (array_key_exists('optionGroupName', $props['pseudoconstant'])) { + $optionValues = civicrm_api3('OptionValue', 'get', array( + 'return' => array("label", "value"), + 'option_group_id' => $setting, + )); + if ($optionValues['count'] > 0) { + foreach ($optionValues['values'] as $key => $values) { + $vals[$values['value']] = $values['label']; + } + $options['values'] = $vals; + } + } + else { + $options = civicrm_api3('Setting', 'getoptions', array( + 'field' => $setting, + )); + } } else { $options = NULL; @@ -116,7 +131,11 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form { ); } elseif ($add == 'addSelect') { - $this->addElement('select', $setting, ts($props['title']), $options['values'], CRM_Utils_Array::value('html_attributes', $props)); + $element = $this->addElement('select', $setting, ts($props['title']), $options['values'], CRM_Utils_Array::value('html_attributes', $props)); + if (defined('CIVICRM_ENVIRONMENT')) { + $element->freeze(); + CRM_Core_Session::setStatus(ts('The environment settings have been disabled because it has been overridden in the settings file.'), ts('Environment settings'), 'info'); + } } elseif ($add == 'addCheckBox') { $this->addCheckBox($setting, ts($props['title']), $options['values'], NULL, CRM_Utils_Array::value('html_attributes', $props), NULL, NULL, array('  ')); diff --git a/CRM/Admin/Form/Setting/Debugging.php b/CRM/Admin/Form/Setting/Debugging.php index b254b893ee..0d7219a2f3 100644 --- a/CRM/Admin/Form/Setting/Debugging.php +++ b/CRM/Admin/Form/Setting/Debugging.php @@ -41,6 +41,7 @@ class CRM_Admin_Form_Setting_Debugging extends CRM_Admin_Form_Setting { 'backtrace' => CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, 'fatalErrorHandler' => CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, 'assetCache' => CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, + 'environment' => CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, ); /** @@ -55,4 +56,27 @@ class CRM_Admin_Form_Setting_Debugging extends CRM_Admin_Form_Setting { parent::buildQuickForm(); } + /** + * Process the form submission. + */ + public function postProcess() { + $params = $this->controller->exportValues($this->_name); + + if ($params['environment'] != 'Production') { + $mailing = Civi::settings()->get('mailing_backend'); + if ($mailing['outBound_option'] != 2) { + Civi::settings()->set('mailing_backend_store', $mailing); + } + Civi::settings()->set('mailing_backend', array('outBound_option' => CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED)); + CRM_Core_Session::setStatus(ts('Outbound emails have been disabled. Scheduled jobs will not run unless runInNonProductionEnvironment=TRUE is added as a parameter for a specific job'), ts("Non-production environment set"), "success"); + } + else { + $mailing = Civi::settings()->get('mailing_backend_store'); + if ($mailing) { + Civi::settings()->set('mailing_backend', $mailing); + } + } + parent::postProcess(); + } + } diff --git a/CRM/Admin/Page/Job.php b/CRM/Admin/Page/Job.php index ce8ab72ddc..3c838b392c 100644 --- a/CRM/Admin/Page/Job.php +++ b/CRM/Admin/Page/Job.php @@ -142,6 +142,10 @@ class CRM_Admin_Page_Job extends CRM_Core_Page_Basic { * @param null $action */ public function browse($action = NULL) { + // check if non-prod mode is enabled. + if (CRM_Core_Config::environment() != 'Production') { + CRM_Core_Session::setStatus(ts('Execution of scheduled jobs has been turned off by default since this is a non-production environment. You can override this for particular jobs by adding runInNonProductionEnvironment=TRUE as a parameter.'), ts("Non-production Environment"), "warning", array('expires' => 0)); + } // using Export action for Execute. Doh. if ($this->_action & CRM_Core_Action::EXPORT) { diff --git a/CRM/Core/BAO/Setting.php b/CRM/Core/BAO/Setting.php index cb735b9ad1..9b45f11aa8 100644 --- a/CRM/Core/BAO/Setting.php +++ b/CRM/Core/BAO/Setting.php @@ -490,4 +490,28 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting { return FALSE; } + /** + * Check if environment is explicitly set. + * + * @return bool + */ + public static function isEnvironmentSet($setting, $value = NULL) { + $environment = CRM_Core_Config::environment(); + if ($setting == 'environment' && $environment) { + return TRUE; + } + return FALSE; + } + + /** + * Check if job is able to be executed by API. + * + * @throws API_Exception + */ + public static function isAPIJobAllowedToRun($params) { + if (CRM_Core_Config::environment() != 'Production' && !CRM_Utils_Array::value('runInNonProductionEnvironment', $params)) { + throw new Exception("Job has not been executed as it is a non-production environment."); + } + } + } diff --git a/CRM/Core/Config.php b/CRM/Core/Config.php index 3ed5ed7d62..2a61e5eb30 100644 --- a/CRM/Core/Config.php +++ b/CRM/Core/Config.php @@ -260,6 +260,35 @@ class CRM_Core_Config extends CRM_Core_Config_MagicMerge { return $domain; } + /** + * Function to get environment. + * + * @param string $env + * @param bool $reset + * + * @return string + */ + public static function environment($env = NULL, $reset = FALSE) { + static $environment; + if ($env) { + $environment = $env; + } + if ($reset || empty($environment)) { + if (defined('CIVICRM_ENVIRONMENT')) { + $environment = CIVICRM_ENVIRONMENT; + global $civicrm_setting; + $civicrm_setting[CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME]['environment'] = $environment; + } + else { + $environment = Civi::settings()->get('environment'); + } + } + if (!$environment) { + $environment = 'Production'; + } + return $environment; + } + /** * Do general cleanup of caches, temp directories and temp tables * CRM-8739 diff --git a/CRM/Core/JobManager.php b/CRM/Core/JobManager.php index 2c9ab2c77e..6c3b1bec61 100644 --- a/CRM/Core/JobManager.php +++ b/CRM/Core/JobManager.php @@ -118,6 +118,17 @@ class CRM_Core_JobManager { */ public function executeJob($job) { $this->currentJob = $job; + + // CRM-18231 check if non-production environment. + try { + CRM_Core_BAO_Setting::isAPIJobAllowedToRun($job->apiParams); + } + catch (Exception $e) { + $this->logEntry('Error while executing ' . $job->name . ': ' . $e->getMessage()); + $this->currentJob = FALSE; + return FALSE; + } + $this->logEntry('Starting execution of ' . $job->name); $job->saveLastRun(); diff --git a/CRM/Upgrade/Incremental/sql/4.7.10.mysql.tpl b/CRM/Upgrade/Incremental/sql/4.7.10.mysql.tpl index 52e04cca5f..c977b84726 100644 --- a/CRM/Upgrade/Incremental/sql/4.7.10.mysql.tpl +++ b/CRM/Upgrade/Incremental/sql/4.7.10.mysql.tpl @@ -13,6 +13,7 @@ ALTER TABLE civicrm_pledge_block ADD is_pledge_start_date_visible TINYINT(4) NOT ALTER TABLE civicrm_pledge_block ADD is_pledge_start_date_editable TINYINT(4) NOT NULL DEFAULT 0 COMMENT 'If true - recurring start date is editable.'; ALTER TABLE civicrm_contribution_page ADD adjust_recur_start_date TINYINT(4) NOT NULL DEFAULT 0 COMMENT 'If true - user is able to adjust payment start date.' AFTER is_recur_installments; + -- CRM-17608 Merge to DOCx or ODT template SELECT @option_group_id_ext := max(id) from civicrm_option_group where name = 'safe_file_extension'; SELECT @option_group_id_ext_wt := MAX(weight) FROM civicrm_option_value WHERE option_group_id = @option_group_id_ext; @@ -21,3 +22,14 @@ INSERT INTO `civicrm_option_value` (`option_group_id`, {localize field='label'}label{/localize}, `value`, `name`, `grouping`, `filter`, `is_default`, `weight`, `is_optgroup`, `is_reserved`, `is_active`) VALUES (@option_group_id_ext, {localize}'{ts escape="sql"}odt{/ts}'{/localize}, @option_group_id_ext_val+1, 'odt', NULL, 0, 0, @option_group_id_ext_wt+1, 0, 1, 1); + +-- CRM-18231 +INSERT INTO civicrm_option_group + (name, {localize field='title'}title{/localize}, is_reserved, is_active) VALUES ('environment', {localize}'{ts escape="sql"}Environment{/ts}'{/localize}, 0, 1); + +SELECT @option_group_id_env := max(id) from civicrm_option_group where name = 'environment'; +INSERT INTO civicrm_option_value (option_group_id, {localize field='label'}label{/localize}, value, name, grouping, filter, is_default, weight, {localize field='description'}description{/localize}, is_optgroup, is_reserved, is_active, component_id, visibility_id) +VALUES + (@option_group_id_env, {localize}'{ts escape="sql"}Production{/ts}'{/localize}, 'Production', 'Production', NULL, 0, 1, 1, {localize}'{ts escape="sql"}Production Environment{/ts}'{/localize}, 0, 0, 1, NULL, NULL), + (@option_group_id_env, {localize}'{ts escape="sql"}Staging{/ts}'{/localize}, 'Staging', 'Staging', NULL, 0, NULL, 2, {localize}'{ts escape="sql"}Staging Environment{/ts}'{/localize}, 0, 0, 1, NULL, NULL), + (@option_group_id_env, {localize}'{ts escape="sql"}Development{/ts}'{/localize}, 'Development', 'Development', NULL, 0, NULL, 3, {localize}'{ts escape="sql"}Development Environment{/ts}'{/localize}, 0, 0, 1, NULL, NULL); diff --git a/CRM/Utils/Check/Component/Env.php b/CRM/Utils/Check/Component/Env.php index 6c74b21b96..583e09409d 100644 --- a/CRM/Utils/Check/Component/Env.php +++ b/CRM/Utils/Check/Component/Env.php @@ -863,4 +863,24 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component { return $messages; } + /** + * Check if environment is Production. + * @return array + */ + public function checkEnvironment() { + $messages = array(); + + $environment = CRM_Core_Config::environment(); + if ($environment != 'Production') { + $messages[] = new CRM_Utils_Check_Message( + __FUNCTION__, + ts('The environment of this CiviCRM instance is set to \'%1\'. Certain functionality like scheduled jobs has been disabled.', array(1 => $environment)), + ts('Non-Production Environment'), + \Psr\Log\LogLevel::ALERT, + 'fa-bug' + ); + } + return $messages; + } + } diff --git a/api/v3/Job.php b/api/v3/Job.php index 8cd1b2af27..bbc62b8819 100644 --- a/api/v3/Job.php +++ b/api/v3/Job.php @@ -494,6 +494,7 @@ function civicrm_api3_job_process_batch_merge($params) { 'options' => array('limit' => 1), )); } + $rgid = CRM_Utils_Array::value('rgid', $params); $gid = CRM_Utils_Array::value('gid', $params); $mode = CRM_Utils_Array::value('mode', $params, 'safe'); diff --git a/settings/Developer.setting.php b/settings/Developer.setting.php index 3d7715e089..2c0902ba6a 100644 --- a/settings/Developer.setting.php +++ b/settings/Developer.setting.php @@ -100,6 +100,23 @@ return array( 'is_contact' => 0, 'description' => "Set this value to Yes if you want to display a backtrace listing when a fatal error is encountered. This feature should NOT be enabled for production sites", ), + 'environment' => array( + 'group_name' => 'Developer Preferences', + 'group' => 'developer', + 'name' => 'environment', + 'type' => 'String', + 'html_type' => 'Select', + 'quick_form_type' => 'Select', + 'default' => 'Production', + 'pseudoconstant' => array( + 'optionGroupName' => 'environment', + ), + 'add' => '4.7', + 'title' => 'Environment', + 'is_domain' => 1, + 'is_contact' => 0, + 'description' => "Setting to define the environment in which this CiviCRM instance is running.", + ), 'fatalErrorHandler' => array( 'group_name' => 'Developer Preferences', 'group' => 'developer', diff --git a/templates/CRM/Admin/Form/Setting/Debugging.tpl b/templates/CRM/Admin/Form/Setting/Debugging.tpl index 02f65c2101..45a1edbc18 100644 --- a/templates/CRM/Admin/Form/Setting/Debugging.tpl +++ b/templates/CRM/Admin/Form/Setting/Debugging.tpl @@ -46,6 +46,11 @@ {$form.backtrace.html}
{ts}This feature should NOT be enabled for production sites.
Set this value to Yes if you want to display a backtrace listing when a fatal error is encountered.{/ts}
+ + {$form.environment.label} + {$form.environment.html}
+ {ts}Set this value to Staging/Development to prevent cron jobs & mailings from being executed.{/ts} + {$form.fatalErrorHandler.label} {$form.fatalErrorHandler.html}
diff --git a/templates/CRM/common/civicrm.settings.php.template b/templates/CRM/common/civicrm.settings.php.template index 10e2f28de4..1c3b64f0fd 100644 --- a/templates/CRM/common/civicrm.settings.php.template +++ b/templates/CRM/common/civicrm.settings.php.template @@ -308,6 +308,17 @@ if (!defined('CIVICRM_DOMAIN_ID')) { define( 'CIVICRM_DOMAIN_ID', 1); } +/** + * Setting to define the environment in which this CiviCRM instance is running. + * Note the setting here must be value from the option group 'Environment', + * (see Administration > System Settings > Option Groups, Options beside Environment) + * which by default has three option values: 'Production', 'Staging', 'Development'. + * NB: defining a value from CIVICRM_ENVIRONMENT here prevents it from being set + * via the browser. + */ + +// define( 'CIVICRM_ENVIRONMENT', 'Production' ); + /** * Settings to enable external caching using a cache server. This is an * advanced feature, and you should read and understand the documentation diff --git a/tests/phpunit/CRM/Core/BAO/SettingTest.php b/tests/phpunit/CRM/Core/BAO/SettingTest.php index 10dbca65bd..bb1cad2c7b 100644 --- a/tests/phpunit/CRM/Core/BAO/SettingTest.php +++ b/tests/phpunit/CRM/Core/BAO/SettingTest.php @@ -180,4 +180,18 @@ class CRM_Core_BAO_SettingTest extends CiviUnitTestCase { $_testOnChange_hookCalls['metadata'] = $metadata; } + /** + * Test to set isProductionEnvironment + * + */ + public function testSetCivicrmEnvironment() { + CRM_Core_BAO_Setting::setItem('Staging', CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, 'environment'); + $values = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME, 'environment'); + $this->assertEquals('Staging', $values); + + define('CIVICRM_ENVIRONMENT', 'Development'); + $environment = CRM_Core_Config::environment(); + $this->assertEquals('Development', $environment); + } + } diff --git a/tests/phpunit/WebTest/Admin/Form/Setting/DebuggingTest.php b/tests/phpunit/WebTest/Admin/Form/Setting/DebuggingTest.php new file mode 100644 index 0000000000..d1f2ca191a --- /dev/null +++ b/tests/phpunit/WebTest/Admin/Form/Setting/DebuggingTest.php @@ -0,0 +1,55 @@ +webtestLogin(); + $this->openCiviPage('admin/setting/debug', 'reset=1'); + $this->select('environment', 'Staging'); + $this->click('_qf_Debugging_next-top'); + + $this->waitForPageToLoad($this->getTimeoutMsec()); + try { + $this->assertFalse($this->isTextPresent('Your changes have been saved.')); + } + catch (PHPUnit_Framework_AssertionFailedError$e) { + array_push($this->verificationErrors, $e->toString()); + } + $envi = $this->getValue("environment"); + $this->assertEquals('Staging', $envi); + } + +} diff --git a/tests/phpunit/api/v3/JobProcessMailingTest.php b/tests/phpunit/api/v3/JobProcessMailingTest.php index 346446d442..08d4c2600d 100644 --- a/tests/phpunit/api/v3/JobProcessMailingTest.php +++ b/tests/phpunit/api/v3/JobProcessMailingTest.php @@ -36,6 +36,9 @@ * */ +//@todo - why doesn't class loader find these (I tried renaming) +require_once 'CiviTest/CiviMailUtils.php'; + /** * Class api_v3_JobTest * @group headless @@ -108,6 +111,37 @@ class api_v3_JobProcessMailingTest extends CiviUnitTestCase { $this->_mut->assertRecipients($this->getRecipients(1, 2)); } + /** + * Test mail when in non-production environment. + * + */ + public function testMailNonProductionRun() { + // Test in non-production mode. + $params = array( + 'environment' => 'Staging', + ); + $this->callAPISuccess('Setting', 'create', $params); + $this->createContactsInGroup(10, $this->_groupID); + Civi::settings()->add(array( + 'mailerBatchLimit' => 2, + )); + $this->callAPISuccess('mailing', 'create', $this->_params); + $this->_mut->assertRecipients(array()); + $this->callAPIFailure('job', 'process_mailing', "Failure in api call for job process_mailing: Job has not been executed as it is a non-production environment."); + + // Test with runInNonProductionEnvironment param. + $this->callAPISuccess('job', 'process_mailing', array('runInNonProductionEnvironment' => TRUE)); + $this->_mut->assertRecipients($this->getRecipients(1, 2)); + + // Test in production mode. + $params = array( + 'environment' => 'Production', + ); + $this->callAPISuccess('Setting', 'create', $params); + $this->callAPISuccess('job', 'process_mailing', array()); + $this->_mut->assertRecipients($this->getRecipients(1, 2)); + } + public function concurrencyExamples() { $es = array(); diff --git a/tests/phpunit/api/v3/SettingTest.php b/tests/phpunit/api/v3/SettingTest.php index 5727487e15..1dfaf1ebd2 100644 --- a/tests/phpunit/api/v3/SettingTest.php +++ b/tests/phpunit/api/v3/SettingTest.php @@ -527,4 +527,27 @@ class api_v3_SettingTest extends CiviUnitTestCase { $this->assertEquals('Unconfirmed', $result['values'][$dom['id']]['tag_unconfirmed']); } + /** + * Test to set isProductionEnvironment + * + */ + public function testSetCivicrmEnvironment() { + $params = array( + 'environment' => 'Staging', + ); + $result = $this->callAPISuccess('Setting', 'create', $params); + $params = array( + 'name' => 'environment', + 'group' => 'Developer Preferences', + ); + $result = $this->callAPISuccess('Setting', 'getvalue', $params); + $this->assertEquals('Staging', $result); + + global $civicrm_setting; + $civicrm_setting[CRM_Core_BAO_Setting::DEVELOPER_PREFERENCES_NAME]['environment'] = 'Production'; + Civi::service('settings_manager')->useMandatory(); + $result = $this->callAPISuccess('Setting', 'getvalue', $params); + $this->assertEquals('Production', $result); + } + } diff --git a/xml/templates/civicrm_data.tpl b/xml/templates/civicrm_data.tpl index 91f5ec37e8..0b3cf95dc2 100644 --- a/xml/templates/civicrm_data.tpl +++ b/xml/templates/civicrm_data.tpl @@ -211,7 +211,8 @@ VALUES ('contact_date_reminder_options' , '{ts escape="sql"}Contact Date Reminder Options{/ts}' , NULL, 1, 1, 1), ('wysiwyg_presets' , '{ts escape="sql"}WYSIWYG Editor Presets{/ts}' , NULL, 1, 1, 0), ('relative_date_filters' , '{ts escape="sql"}Relative Date Filters{/ts}' , NULL, 1, 1, 0), - ('pledge_status' , '{ts escape="sql"}Pledge Status{/ts}' , NULL, 1, 1, 1); + ('pledge_status' , '{ts escape="sql"}Pledge Status{/ts}' , NULL, 1, 1, 1), + ('environment' , '{ts escape="sql"}Environment{/ts}' , NULL, 0, 1, 0); SELECT @option_group_id_pcm := max(id) from civicrm_option_group where name = 'preferred_communication_method'; SELECT @option_group_id_act := max(id) from civicrm_option_group where name = 'activity_type'; @@ -292,6 +293,7 @@ SELECT @option_group_id_contactDateMode := max(id) from civicrm_option_group whe SELECT @option_group_id_date_filter := max(id) from civicrm_option_group where name = 'relative_date_filters'; SELECT @option_group_id_wysiwyg_presets := max(id) from civicrm_option_group where name = 'wysiwyg_presets'; SELECT @option_group_id_ps := max(id) from civicrm_option_group where name = 'pledge_status'; +SELECT @option_group_id_env := max(id) from civicrm_option_group where name = 'environment'; SELECT @contributeCompId := max(id) FROM civicrm_component where name = 'CiviContribute'; SELECT @eventCompId := max(id) FROM civicrm_component where name = 'CiviEvent'; @@ -965,6 +967,11 @@ VALUES (@option_group_id_wysiwyg_presets, '{ts escape="sql"}CiviMail{/ts}', '2', 'civimail', NULL, NULL, 0, 2, NULL, 0, 1, 1, @mailCompId, NULL, NULL), (@option_group_id_wysiwyg_presets, '{ts escape="sql"}CiviEvent{/ts}', '3', 'civievent', NULL, NULL, 0, 3, NULL, 0, 1, 1, @eventCompId, NULL, NULL), +-- Environment +(@option_group_id_env, '{ts escape="sql"}Production{/ts}', 'Production', 'Production', NULL, NULL, 1, 1, 'Production Environment', 0, 1, 1, NULL, NULL), +(@option_group_id_env, '{ts escape="sql"}Staging{/ts}', 'Staging', 'Staging', NULL, NULL, 0, 2, 'Staging Environment', 0, 1, 1, NULL, NULL), +(@option_group_id_env, '{ts escape="sql"}Development{/ts}', 'Development', 'Development', NULL, NULL, 0, 3, 'Development Environment', 0, 1, 1, NULL, NULL), + -- Relative Date Filters (@option_group_id_date_filter, '{ts escape="sql"}Today{/ts}', 'this.day', 'this.day', NULL, NULL, NULL,1, NULL, 0, 0, 1, NULL, NULL, NULL), (@option_group_id_date_filter, '{ts escape="sql"}This week{/ts}', 'this.week', 'this.week', NULL, NULL, NULL,2, NULL, 0, 0, 1, NULL, NULL, NULL), -- 2.25.1