From 1cc5f3932e19bf8cbebc147f1da37cbd13221b59 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Wed, 6 May 2020 15:02:09 -0700 Subject: [PATCH] dev/translation#39 - Fix `core:install --lang`. Realign boot code. Overview -------- Suppose you run a command like: ``` cv core:install --lang=fr_FR --cms-base-url=http://example.com/ ``` This fixes that use-case by realigning some of the bootstrap steps under `setup/plugins/installDatabase/*`. Before ------ * The above `core:install` command crashes because the `paths` service is unavailable. * The `civi.setup.installDatabase` begins with these two steps: 1. `InstallSchema.civi-setup.php` manipulates some global options (to make certain services work), and it also installs the schema, and it also reboots the `Container`. 2. `BootstrapCivi.civi-setup.php` tries to boot again - e.g. it loads `civicrm.settings.php` and calls `CRM_Core_Config::singleton($loadFromDB=TRUE)`. But this is suspect because it neglects to set `$force=TRUE`. After ----- * The above `core:install` command runs. * The `civi.setup.installDatabase` begins with these *three* steps: 1. `Preboot.civi-setup.php` starts the system in a *partially booted* mode (ie with `$loadFromDB==FALSE`). 2. `InstallSchema.civi-setup.php` just installs the schema. 3. `BootstrapCivi.civi-setup.php` switches the system to a fully booted mode (ie with `$loadFromDB==TRUE`). Technical details ----------------- I tested this on a D7 build. My dev/test loop was basically these steps: ``` cv core:uninstall -f cv core:install --lang fr_FR --cms-base-url='http://dmaster.bknix:8001' -vvv echo 'select name, label, value from civicrm_option_value where name like "Meet%"' | cv sql ``` If the install succeeded, then the SQL command would display localized labels for "Meeting" ("Reunion"). --- .../BootstrapCivi.civi-setup.php | 26 +++++----- .../InstallSchema.civi-setup.php | 10 ---- .../installDatabase/Preboot.civi-setup.php | 49 +++++++++++++++++++ 3 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 setup/plugins/installDatabase/Preboot.civi-setup.php diff --git a/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php b/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php index b2c0a17446..a1d153154b 100644 --- a/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php +++ b/setup/plugins/installDatabase/BootstrapCivi.civi-setup.php @@ -2,7 +2,15 @@ /** * @file * - * Perform the first system bootstrap. + * Perform the full bootstrap. + * + * GOAL: All the standard services (database, DAOs, translations, settings, etc) should be loaded. + * + * MECHANICS: This is basically calls `CRM_Core_Config::singleton(TRUE,TRUE)`. + * + * NOTE: This is technically a *reboot*. `Preboot` started things off, but it + * booted with `CRM_Core_Config::singleton($loadFromDB==FALSE)`. Now, the DB is + * populated, so we can teardown the preboot stuff and start again with `$loadFromDB==TRUE`. */ if (!defined('CIVI_SETUP')) { @@ -13,19 +21,9 @@ if (!defined('CIVI_SETUP')) { ->addListener('civi.setup.installDatabase', function (\Civi\Setup\Event\InstallDatabaseEvent $e) { \Civi\Setup::log()->info(sprintf('[%s] Bootstrap CiviCRM', basename(__FILE__))); - if (!defined('CIVICRM_SETTINGS_PATH')) { - define('CIVICRM_SETTINGS_PATH', $e->getModel()->settingsPath); - } - - if (realpath(CIVICRM_SETTINGS_PATH) !== realpath($e->getModel()->settingsPath)) { - throw new \RuntimeException(sprintf("Cannot boot: The civicrm.settings.php path appears inconsistent (%s vs %s)", CIVICRM_SETTINGS_PATH, $e->getModel()->settingsPath)); - } - - include_once CIVICRM_SETTINGS_PATH; - - require_once 'CRM/Core/ClassLoader.php'; - CRM_Core_ClassLoader::singleton()->register(); + \CRM_Core_I18n::$SQL_ESCAPER = NULL; + unset(\Civi::$statics['testPreInstall']); - CRM_Core_Config::singleton(TRUE); + CRM_Core_Config::singleton(TRUE, TRUE); }, \Civi\Setup::PRIORITY_MAIN - 200); diff --git a/setup/plugins/installDatabase/InstallSchema.civi-setup.php b/setup/plugins/installDatabase/InstallSchema.civi-setup.php index fec273ce07..1455edab09 100644 --- a/setup/plugins/installDatabase/InstallSchema.civi-setup.php +++ b/setup/plugins/installDatabase/InstallSchema.civi-setup.php @@ -68,11 +68,6 @@ class InstallSchemaPlugin implements \Symfony\Component\EventDispatcher\EventSub $sqlPath = $model->srcPath . DIRECTORY_SEPARATOR . 'sql'; $spec = $this->loadSpecification($model->srcPath); - $conn = \Civi\Setup\DbUtil::connect($model->db); - \CRM_Core_I18n::$SQL_ESCAPER = function($text) use ($conn) { - return $conn->escape_string($text); - }; - \Civi\Setup::log()->info(sprintf('[%s] Load basic tables', basename(__FILE__))); \Civi\Setup\DbUtil::sourceSQL($model->db, \Civi\Setup\SchemaGenerator::generateCreateSql($model->srcPath, $spec->database, $spec->tables)); @@ -89,11 +84,6 @@ class InstallSchemaPlugin implements \Symfony\Component\EventDispatcher\EventSub \Civi\Setup::log()->info(sprintf('[%s] Load basic data', basename(__FILE__))); \Civi\Setup\DbUtil::sourceSQL($model->db, \Civi\Setup\SchemaGenerator::generateBasicData($model->srcPath)); } - - require_once $model->settingsPath; - \Civi\Core\Container::boot(TRUE); - - \CRM_Core_I18n::$SQL_ESCAPER = NULL; } /** diff --git a/setup/plugins/installDatabase/Preboot.civi-setup.php b/setup/plugins/installDatabase/Preboot.civi-setup.php new file mode 100644 index 0000000000..f3166d8297 --- /dev/null +++ b/setup/plugins/installDatabase/Preboot.civi-setup.php @@ -0,0 +1,49 @@ +addListener('civi.setup.checkRequirements', function (\Civi\Setup\Event\CheckRequirementsEvent $e) { + + }); + +\Civi\Setup::dispatcher() + ->addListener('civi.setup.installDatabase', function (\Civi\Setup\Event\InstallDatabaseEvent $e) { + \Civi\Setup::log()->info(sprintf('[%s] Load minimal (non-DB) services', basename(__FILE__))); + + if (!defined('CIVICRM_SETTINGS_PATH')) { + define('CIVICRM_SETTINGS_PATH', $e->getModel()->settingsPath); + } + + if (realpath(CIVICRM_SETTINGS_PATH) !== realpath($e->getModel()->settingsPath)) { + throw new \RuntimeException(sprintf("Cannot boot: The civicrm.settings.php path appears inconsistent (%s vs %s)", CIVICRM_SETTINGS_PATH, $e->getModel()->settingsPath)); + } + + include_once CIVICRM_SETTINGS_PATH; + + require_once 'CRM/Core/ClassLoader.php'; + CRM_Core_ClassLoader::singleton()->register(); + + $conn = \Civi\Setup\DbUtil::connect($e->getModel()->db); + \CRM_Core_I18n::$SQL_ESCAPER = function($text) use ($conn) { + return $conn->escape_string($text); + }; + + \Civi::$statics['testPreInstall'] = 1; + + CRM_Core_Config::singleton(FALSE, TRUE); + + }, \Civi\Setup::PRIORITY_PREPARE); -- 2.25.1