From 9d114ab61c840acd8257734ff766582f4bb6d05e Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Mon, 27 Jan 2020 15:50:52 -0800 Subject: [PATCH] (REF) Civi\Test - Use de-minimis ts() while runnning installation When running early-stage installation helpers like `Civi\Test::headless()->...->apply()` or `Civi\Test:data()->...->populate()` it can be hard to call `CRM_CodeGen_*` functionality - because that relies on `ts()` which relies on other system services. This change basically suspends/swaps some of the default `ts()` behavior while the test system performs installation. The change is in two sub-parts: * Implement `asPreInstall()` (Files: `Civi/Test.php` and `CRM/Core/I18n.php`) * Add the helper `\Civi\Test::asPreInstall()` * Skip the use of "word replacements" during the pre-install phase * Use `asPreInstall()` (Files: `Civi/Test/Data.php` and `Civi/Test/CiviEnvBuilder.php`) * Wrap existing code with the helper `\Civi\Test::asPreInstall(). These changes look big, but that's just whitespace -- inserting `asPreInstall()` changes the indentation. This lays groundwork for another commit which will replace some references to `sql/civicrm*.mysql` with references to `CRM_CodeGen_*`. --- CRM/Core/I18n.php | 34 ++++++++++++++++-------- Civi/Test.php | 31 ++++++++++++++++++++++ Civi/Test/CiviEnvBuilder.php | 30 ++++++++++++---------- Civi/Test/Data.php | 50 +++++++++++++++++++----------------- 4 files changed, 96 insertions(+), 49 deletions(-) diff --git a/CRM/Core/I18n.php b/CRM/Core/I18n.php index 8a97d428c2..fe4e46110c 100644 --- a/CRM/Core/I18n.php +++ b/CRM/Core/I18n.php @@ -420,17 +420,7 @@ class CRM_Core_I18n { // do all wildcard translations first - // FIXME: Is there a constant we can reference instead of hardcoding en_US? - $replacementsLocale = $this->locale ? $this->locale : 'en_US'; - if (!isset(Civi::$statics[__CLASS__]) || !array_key_exists($replacementsLocale, Civi::$statics[__CLASS__])) { - if (defined('CIVICRM_DSN') && !CRM_Core_Config::isUpgradeMode()) { - Civi::$statics[__CLASS__][$replacementsLocale] = CRM_Core_BAO_WordReplacement::getLocaleCustomStrings($replacementsLocale); - } - else { - Civi::$statics[__CLASS__][$replacementsLocale] = []; - } - } - $stringTable = Civi::$statics[__CLASS__][$replacementsLocale]; + $stringTable = $this->getWordReplacements(); $exactMatch = FALSE; if (isset($stringTable['enabled']['exactMatch'])) { @@ -737,6 +727,28 @@ class CRM_Core_I18n { return $tsLocale ? $tsLocale : 'en_US'; } + /** + * @return array + * Ex: $stringTable['enabled']['wildcardMatch']['foo'] = 'bar'; + */ + private function getWordReplacements() { + if (isset(Civi::$statics['testPreInstall'])) { + return []; + } + + // FIXME: Is there a constant we can reference instead of hardcoding en_US? + $replacementsLocale = $this->locale ? $this->locale : 'en_US'; + if ((!isset(Civi::$statics[__CLASS__]) || !array_key_exists($replacementsLocale, Civi::$statics[__CLASS__]))) { + if (defined('CIVICRM_DSN') && !CRM_Core_Config::isUpgradeMode()) { + Civi::$statics[__CLASS__][$replacementsLocale] = CRM_Core_BAO_WordReplacement::getLocaleCustomStrings($replacementsLocale); + } + else { + Civi::$statics[__CLASS__][$replacementsLocale] = []; + } + } + return Civi::$statics[__CLASS__][$replacementsLocale]; + } + } /** diff --git a/Civi/Test.php b/Civi/Test.php index 51d929054d..f1c787f9f1 100644 --- a/Civi/Test.php +++ b/Civi/Test.php @@ -16,6 +16,37 @@ class Test { */ private static $singletons = []; + /** + * @var array + */ + public static $statics = []; + + /** + * Run code in a pre-boot fashion. + * + * @param callable $callback + * @return mixed + * Pass through the result of the callback. + */ + public static function asPreInstall($callback) { + $conn = \Civi\Test::pdo(); + + $oldEscaper = \CRM_Core_I18n::$SQL_ESCAPER; + \Civi::$statics['testPreInstall'] = (\Civi::$statics['testPreInstall'] ?? 0) + 1; + try { + \CRM_Core_I18n::$SQL_ESCAPER = function ($text) use ($conn) { + return substr($conn->quote($text), 1, -1); + }; + return $callback(); + } finally { + \CRM_Core_I18n::$SQL_ESCAPER = $oldEscaper; + \Civi::$statics['testPreInstall']--; + if (\Civi::$statics['testPreInstall'] <= 0) { + unset(\Civi::$statics['testPreInstall']); + } + } + } + /** * Get the data source used for testing. * diff --git a/Civi/Test/CiviEnvBuilder.php b/Civi/Test/CiviEnvBuilder.php index 767d34033a..3a6ab88393 100644 --- a/Civi/Test/CiviEnvBuilder.php +++ b/Civi/Test/CiviEnvBuilder.php @@ -168,24 +168,26 @@ class CiviEnvBuilder { * @return CiviEnvBuilder */ public function apply($force = FALSE) { - $dbName = \Civi\Test::dsn('database'); - $query = "USE {$dbName};" - . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));"; + return \Civi\Test::asPreInstall(function() use ($force) { + $dbName = \Civi\Test::dsn('database'); + $query = "USE {$dbName};" + . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));"; - if (\Civi\Test::execute($query) === FALSE) { - throw new \RuntimeException("Failed to flag schema version: $query"); - } + if (\Civi\Test::execute($query) === FALSE) { + throw new \RuntimeException("Failed to flag schema version: $query"); + } - $this->assertValid(); + $this->assertValid(); - if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) { + if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) { + return $this; + } + foreach ($this->steps as $step) { + $step->run($this); + } + $this->setSavedSignature($this->getTargetSignature()); return $this; - } - foreach ($this->steps as $step) { - $step->run($this); - } - $this->setSavedSignature($this->getTargetSignature()); - return $this; + }); } /** diff --git a/Civi/Test/Data.php b/Civi/Test/Data.php index 8b90b5d493..afa377febd 100644 --- a/Civi/Test/Data.php +++ b/Civi/Test/Data.php @@ -12,30 +12,32 @@ class Data { * @return bool */ public function populate() { - \Civi\Test::schema()->truncateAll(); - - \Civi\Test::schema()->setStrict(FALSE); - - // Ensure that when we populate the database it is done in utf8 mode - \Civi\Test::execute('SET NAMES utf8'); - $sqlDir = dirname(dirname(__DIR__)) . "/sql"; - - $query2 = file_get_contents("$sqlDir/civicrm_data.mysql"); - $query3 = file_get_contents("$sqlDir/test_data.mysql"); - $query4 = file_get_contents("$sqlDir/test_data_second_domain.mysql"); - if (\Civi\Test::execute($query2) === FALSE) { - throw new RuntimeException("Cannot load civicrm_data.mysql. Aborting."); - } - if (\Civi\Test::execute($query3) === FALSE) { - throw new RuntimeException("Cannot load test_data.mysql. Aborting."); - } - if (\Civi\Test::execute($query4) === FALSE) { - throw new RuntimeException("Cannot load test_data.mysql. Aborting."); - } - - unset($query, $query2, $query3); - - \Civi\Test::schema()->setStrict(TRUE); + \Civi\Test::asPreInstall(function() { + \Civi\Test::schema()->truncateAll(); + + \Civi\Test::schema()->setStrict(FALSE); + + // Ensure that when we populate the database it is done in utf8 mode + \Civi\Test::execute('SET NAMES utf8'); + $sqlDir = dirname(dirname(__DIR__)) . "/sql"; + + $query2 = file_get_contents("$sqlDir/civicrm_data.mysql"); + $query3 = file_get_contents("$sqlDir/test_data.mysql"); + $query4 = file_get_contents("$sqlDir/test_data_second_domain.mysql"); + if (\Civi\Test::execute($query2) === FALSE) { + throw new RuntimeException("Cannot load civicrm_data.mysql. Aborting."); + } + if (\Civi\Test::execute($query3) === FALSE) { + throw new RuntimeException("Cannot load test_data.mysql. Aborting."); + } + if (\Civi\Test::execute($query4) === FALSE) { + throw new RuntimeException("Cannot load test_data.mysql. Aborting."); + } + + unset($query, $query2, $query3); + + \Civi\Test::schema()->setStrict(TRUE); + }); // Rebuild triggers civicrm_api('system', 'flush', ['version' => 3, 'triggers' => 1]); -- 2.25.1