(REF) Civi\Test - Use de-minimis ts() while runnning installation
authorTim Otten <totten@civicrm.org>
Mon, 27 Jan 2020 23:50:52 +0000 (15:50 -0800)
committerTim Otten <totten@civicrm.org>
Tue, 28 Jan 2020 22:20:46 +0000 (14:20 -0800)
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
Civi/Test.php
Civi/Test/CiviEnvBuilder.php
Civi/Test/Data.php

index 8a97d428c29709c866a4e9932291d0cd1ac684a1..fe4e46110c255d71b1c4b3658d3b51ef9d3bd51f 100644 (file)
@@ -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];
+  }
+
 }
 
 /**
index 51d929054daba3313c9292e58342d8456100655c..f1c787f9f1fc0c6bad0c96f8732677c897a2816d 100644 (file)
@@ -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.
    *
index 767d34033a814f3de3072fabb884d91bb149f9d8..3a6ab883935abf630bee0a8c1f9db714185c086d 100644 (file)
@@ -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;
+    });
   }
 
   /**
index 8b90b5d493a8a4679656aea7f05b22fddd11a8ff..afa377febd84dbcc29ef910acb4c0a5d23c0abae 100644 (file)
@@ -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]);