From 58d1e21e44d0392974b0cf596d69e735c7fe9d2b Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Fri, 28 Aug 2020 09:59:22 +1000 Subject: [PATCH] [REF] Move Auto DSN Switching into a core function --- CRM/Admin/Form/Setting/UF.php | 3 ++- CRM/Core/BAO/SchemaHandler.php | 6 ++++-- CRM/Core/DAO.php | 1 + CRM/Core/Lock.php | 3 ++- CRM/Logging/Differ.php | 3 ++- CRM/Logging/ReportDetail.php | 3 ++- CRM/Logging/Reverter.php | 3 ++- CRM/Logging/Schema.php | 6 ++++-- CRM/Upgrade/Incremental/php/FourFive.php | 3 ++- CRM/Utils/File.php | 1 + CRM/Utils/SQL.php | 18 ++++++++++++++++++ CRM/Utils/System/Backdrop.php | 5 +++-- CRM/Utils/System/Drupal.php | 5 +++-- CRM/Utils/System/Drupal6.php | 5 +++-- Civi/Test.php | 3 ++- tests/phpunit/CiviTest/CiviUnitTestCase.php | 3 ++- tests/phpunit/api/v3/SyntaxConformanceTest.php | 3 ++- 17 files changed, 55 insertions(+), 19 deletions(-) diff --git a/CRM/Admin/Form/Setting/UF.php b/CRM/Admin/Form/Setting/UF.php index 62c12870f9..208b2f3cf1 100644 --- a/CRM/Admin/Form/Setting/UF.php +++ b/CRM/Admin/Form/Setting/UF.php @@ -61,7 +61,8 @@ class CRM_Admin_Form_Setting_UF extends CRM_Admin_Form_Setting { $config->dsn != $config->userFrameworkDSN || !empty($drupal_prefix) ) ) { - $dsnArray = DB::parseDSN($config->dsn); + $dsn = CRM_Utils_SQL::autoSwitchDSN($config->dsn); + $dsnArray = DB::parseDSN($dsn); $tableNames = CRM_Core_DAO::getTableNames(); asort($tableNames); $tablePrefixes = '$databases[\'default\'][\'default\'][\'prefix\']= array('; diff --git a/CRM/Core/BAO/SchemaHandler.php b/CRM/Core/BAO/SchemaHandler.php index 519b152cfd..a6c9845a22 100644 --- a/CRM/Core/BAO/SchemaHandler.php +++ b/CRM/Core/BAO/SchemaHandler.php @@ -592,7 +592,8 @@ MODIFY {$columnName} varchar( $length ) */ public static function checkFKExists($table_name, $constraint_name) { $config = CRM_Core_Config::singleton(); - $dbUf = DB::parseDSN($config->dsn); + $dsn = CRM_Utils_SQL::autoSwitchDSN($config->dsn); + $dbUf = DB::parseDSN($dsn); $query = " SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA = %1 @@ -832,7 +833,8 @@ MODIFY {$columnName} varchar( $length ) // If we specified a list of databases assume the user knows what they are doing. // If they specify the database they should also specify the pattern. if (!$databaseList) { - $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); + $dsn = defined('CIVICRM_LOGGING_DSN') ? CRM_Utils_SQL::autoSwitchDSN(CIVICRM_LOGGING_DSN) : CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsn = DB::parseDSN($dsn); $logging_database = $dsn['database']; $dao = CRM_Core_DAO::executeQuery("SHOW TABLE STATUS FROM `{$logging_database}` WHERE Engine <> 'MyISAM' AND (" . implode(' OR ', $logTableNameLikePatterns) . ")"); while ($dao->fetch()) { diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 2d3ce654ce..4c33f8002e 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -161,6 +161,7 @@ class CRM_Core_DAO extends DB_DataObject { public static function init($dsn) { Civi::$statics[__CLASS__]['init'] = 1; $options = &PEAR::getStaticProperty('DB_DataObject', 'options'); + $dsn = CRM_Utils_SQL::autoSwitchDSN($dsn); $options['database'] = $dsn; $options['quote_identifiers'] = TRUE; if (CRM_Utils_SQL::isSSLDSN($dsn)) { diff --git a/CRM/Core/Lock.php b/CRM/Core/Lock.php index da1366b424..894b913ab2 100644 --- a/CRM/Core/Lock.php +++ b/CRM/Core/Lock.php @@ -111,7 +111,8 @@ class CRM_Core_Lock implements \Civi\Core\Lock\LockInterface { */ public function __construct($name, $timeout = NULL, $serverWideLock = FALSE) { $config = CRM_Core_Config::singleton(); - $dsnArray = DB::parseDSN($config->dsn); + $dsn = CRM_Utils_SQL::autoSwitchDSN($config->dsn); + $dsnArray = DB::parseDSN($dsn); $database = $dsnArray['database']; $domainID = CRM_Core_Config::domainID(); if ($serverWideLock) { diff --git a/CRM/Logging/Differ.php b/CRM/Logging/Differ.php index a124a40069..863322bb2a 100644 --- a/CRM/Logging/Differ.php +++ b/CRM/Logging/Differ.php @@ -28,7 +28,8 @@ class CRM_Logging_Differ { * @param string $interval */ public function __construct($log_conn_id, $log_date, $interval = '10 SECOND') { - $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); + $dsn = defined('CIVICRM_LOGGING_DSN') ? CRM_Utils_SQL::autoSwitchDSN(CIVICRM_LOGGING_DSN) : CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsn = DB::parseDSN($dsn); $this->db = $dsn['database']; $this->log_conn_id = $log_conn_id; $this->log_date = $log_date; diff --git a/CRM/Logging/ReportDetail.php b/CRM/Logging/ReportDetail.php index d5822b183d..fdbd92216a 100644 --- a/CRM/Logging/ReportDetail.php +++ b/CRM/Logging/ReportDetail.php @@ -257,7 +257,8 @@ class CRM_Logging_ReportDetail extends CRM_Report_Form { * Store the dsn for the logging database in $this->db. */ protected function storeDB() { - $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); + $dsn = defined('CIVICRM_LOGGING_DSN') ? CRM_Utils_SQL::autoSwitchDSN(CIVICRM_LOGGING_DSN) : CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsn = DB::parseDSN($dsn); $this->db = $dsn['database']; } diff --git a/CRM/Logging/Reverter.php b/CRM/Logging/Reverter.php index 72d729d03a..eb1c9dedc1 100644 --- a/CRM/Logging/Reverter.php +++ b/CRM/Logging/Reverter.php @@ -33,7 +33,8 @@ class CRM_Logging_Reverter { * @param $log_date */ public function __construct($log_conn_id, $log_date) { - $dsn = defined('CIVICRM_LOGGING_DSN') ? DB::parseDSN(CIVICRM_LOGGING_DSN) : DB::parseDSN(CIVICRM_DSN); + $dsn = defined('CIVICRM_LOGGING_DSN') ? CRM_Utils_SQL::autoSwitchDSN(CIVICRM_LOGGING_DSN) : CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsn = DB::parseDSN($dsn); $this->db = $dsn['database']; $this->log_conn_id = $log_conn_id; $this->log_date = $log_date; diff --git a/CRM/Logging/Schema.php b/CRM/Logging/Schema.php index e9160bbdef..25b63413d2 100644 --- a/CRM/Logging/Schema.php +++ b/CRM/Logging/Schema.php @@ -158,11 +158,13 @@ AND TABLE_NAME LIKE 'civicrm_%' $nonStandardTableNameString = $this->getNonStandardTableNameFilterString(); if (defined('CIVICRM_LOGGING_DSN')) { - $dsn = DB::parseDSN(CIVICRM_LOGGING_DSN); + $dsn = CRM_Utils_SQL::autoSwitchDSN(CIVICRM_LOGGING_DSN); + $dsn = DB::parseDSN($dsn); $this->useDBPrefix = (CIVICRM_LOGGING_DSN != CIVICRM_DSN); } else { - $dsn = DB::parseDSN(CIVICRM_DSN); + $dsn = CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsn = DB::parseDSN($dsn); $this->useDBPrefix = FALSE; } $this->db = $dsn['database']; diff --git a/CRM/Upgrade/Incremental/php/FourFive.php b/CRM/Upgrade/Incremental/php/FourFive.php index d905ea536b..0f27a0be48 100644 --- a/CRM/Upgrade/Incremental/php/FourFive.php +++ b/CRM/Upgrade/Incremental/php/FourFive.php @@ -52,7 +52,8 @@ class CRM_Upgrade_Incremental_php_FourFive extends CRM_Upgrade_Incremental_Base // if DB is been into upgrade for 3.4.2 version, it would have pdf_format_id name for FK // else FK_civicrm_msg_template_pdf_format_id $config = CRM_Core_Config::singleton(); - $dbUf = DB::parseDSN($config->dsn); + $dsn = CRM_Utils_SQL::autoSwitchDSN($config->dsn); + $dbUf = DB::parseDSN($dsn); $query = " SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'civicrm_msg_template' diff --git a/CRM/Utils/File.php b/CRM/Utils/File.php index 67da4b10a6..c196b3dd71 100644 --- a/CRM/Utils/File.php +++ b/CRM/Utils/File.php @@ -325,6 +325,7 @@ class CRM_Utils_File { } else { require_once 'DB.php'; + $dsn = CRM_Utils_SQL::autoSwitchDSN($dsn); $db = DB::connect($dsn); } diff --git a/CRM/Utils/SQL.php b/CRM/Utils/SQL.php index 1cd1dc02b6..3b9167e626 100644 --- a/CRM/Utils/SQL.php +++ b/CRM/Utils/SQL.php @@ -185,4 +185,22 @@ class CRM_Utils_SQL { return (bool) preg_match('/[\?&](key|cert|ca|capath|cipher|ssl)=/', $dsn); } + /** + * If DB_DSN_MODE is auto then we should replace mysql with mysqli if mysqli is available or the other way around as appropriate + * @param string $dsn + * + * @return string + */ + public static function autoSwitchDSN($dsn) { + if (defined('DB_DSN_MODE') && DB_DSN_MODE === 'auto') { + if (extension_loaded('mysqli')) { + $dsn = preg_replace('/^mysql:/', 'mysqli:', $dsn); + } + else { + $dsn = preg_replace('/^mysqli:/', 'mysql:', $dsn); + } + } + return $dsn; + } + } diff --git a/CRM/Utils/System/Backdrop.php b/CRM/Utils/System/Backdrop.php index d46e56146c..83b66078cd 100644 --- a/CRM/Utils/System/Backdrop.php +++ b/CRM/Utils/System/Backdrop.php @@ -291,9 +291,10 @@ class CRM_Utils_System_Backdrop extends CRM_Utils_System_DrupalBase { public function authenticate($name, $password, $loadCMSBootstrap = FALSE, $realPath = NULL) { $config = CRM_Core_Config::singleton(); - $dbBackdrop = DB::connect($config->userFrameworkDSN); + $ufDSN = CRM_Utils_SQL::autoSwitchDSN($config->userFrameworkDSN); + $dbBackdrop = DB::connect($ufDSN); if (DB::isError($dbBackdrop)) { - throw new CRM_Core_Exception("Cannot connect to Backdrop database via $config->userFrameworkDSN, " . $dbBackdrop->getMessage()); + throw new CRM_Core_Exception("Cannot connect to Backdrop database via $ufDSN, " . $dbBackdrop->getMessage()); } $account = $userUid = $userMail = NULL; diff --git a/CRM/Utils/System/Drupal.php b/CRM/Utils/System/Drupal.php index bf4f8693cf..710e178355 100644 --- a/CRM/Utils/System/Drupal.php +++ b/CRM/Utils/System/Drupal.php @@ -317,9 +317,10 @@ class CRM_Utils_System_Drupal extends CRM_Utils_System_DrupalBase { $config = CRM_Core_Config::singleton(); - $dbDrupal = DB::connect($config->userFrameworkDSN); + $ufDSN = CRM_Utils_SQL::autoSwitchDSN($config->userFrameworkDSN); + $dbDrupal = DB::connect($ufDSN); if (DB::isError($dbDrupal)) { - throw new CRM_Core_Exception("Cannot connect to drupal db via $config->userFrameworkDSN, " . $dbDrupal->getMessage()); + throw new CRM_Core_Exception("Cannot connect to drupal db via $ufDSN, " . $dbDrupal->getMessage()); } $account = $userUid = $userMail = NULL; diff --git a/CRM/Utils/System/Drupal6.php b/CRM/Utils/System/Drupal6.php index 0ac291164e..343ec7fe74 100644 --- a/CRM/Utils/System/Drupal6.php +++ b/CRM/Utils/System/Drupal6.php @@ -300,9 +300,10 @@ class CRM_Utils_System_Drupal6 extends CRM_Utils_System_DrupalBase { $config = CRM_Core_Config::singleton(); - $dbDrupal = DB::connect($config->userFrameworkDSN); + $ufDSN = CRM_Utils_SQL::autoSwitchDSN($config->userFrameworkDSN); + $dbDrupal = DB::connect($ufDSN); if (DB::isError($dbDrupal)) { - throw new CRM_Core_Exception("Cannot connect to drupal db via $config->userFrameworkDSN, " . $dbDrupal->getMessage()); + throw new CRM_Core_Exception("Cannot connect to drupal db via $ufDSN, " . $dbDrupal->getMessage()); } $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower'; diff --git a/Civi/Test.php b/Civi/Test.php index 1d9db12079..cf9c841ab7 100644 --- a/Civi/Test.php +++ b/Civi/Test.php @@ -59,7 +59,8 @@ class Test { public static function dsn($part = NULL) { if (!isset(self::$singletons['dsn'])) { require_once "DB.php"; - self::$singletons['dsn'] = \DB::parseDSN(CIVICRM_DSN); + $dsn = \CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + self::$singletons['dsn'] = \DB::parseDSN($dsn); } if ($part === NULL) { diff --git a/tests/phpunit/CiviTest/CiviUnitTestCase.php b/tests/phpunit/CiviTest/CiviUnitTestCase.php index 7d05958487..8f4550ec44 100644 --- a/tests/phpunit/CiviTest/CiviUnitTestCase.php +++ b/tests/phpunit/CiviTest/CiviUnitTestCase.php @@ -228,7 +228,8 @@ class CiviUnitTestCase extends PHPUnit\Framework\TestCase { static $dbName = NULL; if ($dbName === NULL) { require_once "DB.php"; - $dsninfo = DB::parseDSN(CIVICRM_DSN); + $dsn = CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $dsninfo = DB::parseDSN($dsn); $dbName = $dsninfo['database']; } return $dbName; diff --git a/tests/phpunit/api/v3/SyntaxConformanceTest.php b/tests/phpunit/api/v3/SyntaxConformanceTest.php index 05819b0d2f..0f0e4003ac 100644 --- a/tests/phpunit/api/v3/SyntaxConformanceTest.php +++ b/tests/phpunit/api/v3/SyntaxConformanceTest.php @@ -578,7 +578,8 @@ class api_v3_SyntaxConformanceTest extends CiviUnitTestCase { // Re:^^^ => the failure was probably correct behavior, and test is now fixed, but yeah 5.5 is deprecated, and don't care enough to verify. // Test data providers should be able to run in pre-boot environment, so we connect directly to SQL server. require_once 'DB.php'; - $db = DB::connect(CIVICRM_DSN); + $dsn = CRM_Utils_SQL::autoSwitchDSN(CIVICRM_DSN); + $db = DB::connect($dsn); if ($db->connection instanceof mysqli && $db->connection->server_version < 50600) { $entitiesWithout[] = 'Dedupe'; } -- 2.25.1