From d18369ec858933c4899da1aa654c60c2831ee787 Mon Sep 17 00:00:00 2001 From: Gregory Colpart Date: Fri, 22 Mar 2024 14:25:30 +0100 Subject: [PATCH] commit all small patches --- README.md | 4 + drupal10/drupal10.patch | 324 +++++++++++++++ drupal95/drupal95.patch | 79 ++++ drush8/DrupalBoot.php.patch | 29 ++ drush8/DrupalBoot10.php | 215 ++++++++++ drush8/Sql10.php | 7 + drush8/StatusInfoDrupal10.php | 179 +++++++++ drush8/User10.php | 20 + drush8/UserSingle10.php | 33 ++ drush8/drush-8-symfony-console-compat.patch | 76 ++++ hostmaster/field.form.inc.patch | 11 + hostmaster/hosting_platform.module.patch | 24 ++ hostmaster/http_basic_auth.drush.inc.patch | 5 + .../3353492-symfony-console-4-update_1.patch | 377 ++++++++++++++++++ provision/3374479-2.patch | 144 +++++++ provision/clear_10.inc | 9 + provision/cron_key_10.inc | 5 + provision/deploy_10.inc | 62 +++ provision/import_10.inc | 13 + provision/install_10.inc | 184 +++++++++ provision/packages_10.inc | 241 +++++++++++ 21 files changed, 2041 insertions(+) create mode 100644 drupal10/drupal10.patch create mode 100644 drupal95/drupal95.patch create mode 100644 drush8/DrupalBoot.php.patch create mode 100644 drush8/DrupalBoot10.php create mode 100644 drush8/Sql10.php create mode 100644 drush8/StatusInfoDrupal10.php create mode 100644 drush8/User10.php create mode 100644 drush8/UserSingle10.php create mode 100644 drush8/drush-8-symfony-console-compat.patch create mode 100644 hostmaster/field.form.inc.patch create mode 100644 hostmaster/hosting_platform.module.patch create mode 100644 hostmaster/http_basic_auth.drush.inc.patch create mode 100644 provision/3353492-symfony-console-4-update_1.patch create mode 100644 provision/3374479-2.patch create mode 100644 provision/clear_10.inc create mode 100644 provision/cron_key_10.inc create mode 100644 provision/deploy_10.inc create mode 100644 provision/import_10.inc create mode 100644 provision/install_10.inc create mode 100644 provision/packages_10.inc diff --git a/README.md b/README.md index e69de29..332f252 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,4 @@ +Repository to host AEGIR patchs for running on Debian11/12 with PHP 8.2 +to deploy Drupal 9.4 / 9.5 / 10 + +All instructions are on https://wiki.evolix.org/HowtoAegir diff --git a/drupal10/drupal10.patch b/drupal10/drupal10.patch new file mode 100644 index 0000000..146737d --- /dev/null +++ b/drupal10/drupal10.patch @@ -0,0 +1,324 @@ +diff --git a/core/lib/Drupal/Core/Logger/LoggerChannel.php b/core/lib/Drupal/Core/Logger/LoggerChannel.php +index ec5702f9..6778f43f 100644 +--- a/core/lib/Drupal/Core/Logger/LoggerChannel.php ++++ b/core/lib/Drupal/Core/Logger/LoggerChannel.php +@@ -91,7 +91,7 @@ public function __construct($channel) { + /** + * {@inheritdoc} + */ +- public function log($level, string|\Stringable $message, array $context = []): void { ++ public function log($level, $message, array $context = []) { + if ($this->callDepth == self::MAX_CALL_DEPTH) { + return; + } +diff --git a/core/lib/Drupal/Core/Logger/RfcLoggerTrait.php b/core/lib/Drupal/Core/Logger/RfcLoggerTrait.php +index def2e7ff..0152efe2 100644 +--- a/core/lib/Drupal/Core/Logger/RfcLoggerTrait.php ++++ b/core/lib/Drupal/Core/Logger/RfcLoggerTrait.php +@@ -17,62 +17,62 @@ trait RfcLoggerTrait { + /** + * {@inheritdoc} + */ +- public function emergency(string|\Stringable $message, array $context = []): void { ++ public function emergency($message, array $context = []) { + $this->log(RfcLogLevel::EMERGENCY, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function alert(string|\Stringable $message, array $context = []): void { ++ public function alert($message, array $context = []) { + $this->log(RfcLogLevel::ALERT, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function critical(string|\Stringable $message, array $context = []): void { ++ public function critical($message, array $context = []) { + $this->log(RfcLogLevel::CRITICAL, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function error(string|\Stringable $message, array $context = []): void { ++ public function error($message, array $context = []) { + $this->log(RfcLogLevel::ERROR, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function warning(string|\Stringable $message, array $context = []): void { ++ public function warning($message, array $context = []) { + $this->log(RfcLogLevel::WARNING, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function notice(string|\Stringable $message, array $context = []): void { ++ public function notice($message, array $context = []) { + $this->log(RfcLogLevel::NOTICE, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function info(string|\Stringable $message, array $context = []): void { ++ public function info($message, array $context = []) { + $this->log(RfcLogLevel::INFO, $message, $context); + } + + /** + * {@inheritdoc} + */ +- public function debug(string|\Stringable $message, array $context = []): void { ++ public function debug($message, array $context = []) { + $this->log(RfcLogLevel::DEBUG, $message, $context); + } + + /** + * {@inheritdoc} + */ +- abstract public function log($level, string|\Stringable $message, array $context = []): void; ++ abstract public function log($level, $message, array $context = []); + + } +diff --git a/core/modules/dblog/src/Logger/DbLog.php b/core/modules/dblog/src/Logger/DbLog.php +index c2219fd0..4207a5c9 100644 +--- a/core/modules/dblog/src/Logger/DbLog.php ++++ b/core/modules/dblog/src/Logger/DbLog.php +@@ -52,7 +52,7 @@ public function __construct(Connection $connection, LogMessageParserInterface $p + /** + * {@inheritdoc} + */ +- public function log($level, string|\Stringable $message, array $context = []): void { ++ public function log($level, $message, array $context = []) { + // Remove backtrace and exception since they may contain an unserializable variable. + unset($context['backtrace'], $context['exception']); + +diff --git a/vendor/psr/log/src/LoggerInterface.php b/vendor/psr/log/src/LoggerInterface.php +index b3a24b5f..b4d062b9 100644 +--- a/vendor/psr/log/src/LoggerInterface.php ++++ b/vendor/psr/log/src/LoggerInterface.php +@@ -27,7 +27,7 @@ interface LoggerInterface + * + * @return void + */ +- public function emergency(string|\Stringable $message, array $context = []): void; ++ public function emergency(string|\Stringable $message, array $context = []); + + /** + * Action must be taken immediately. +@@ -40,7 +40,7 @@ public function emergency(string|\Stringable $message, array $context = []): voi + * + * @return void + */ +- public function alert(string|\Stringable $message, array $context = []): void; ++ public function alert(string|\Stringable $message, array $context = []); + + /** + * Critical conditions. +@@ -52,7 +52,7 @@ public function alert(string|\Stringable $message, array $context = []): void; + * + * @return void + */ +- public function critical(string|\Stringable $message, array $context = []): void; ++ public function critical(string|\Stringable $message, array $context = []); + + /** + * Runtime errors that do not require immediate action but should typically +@@ -63,7 +63,7 @@ public function critical(string|\Stringable $message, array $context = []): void + * + * @return void + */ +- public function error(string|\Stringable $message, array $context = []): void; ++ public function error(string|\Stringable $message, array $context = []); + + /** + * Exceptional occurrences that are not errors. +@@ -76,7 +76,7 @@ public function error(string|\Stringable $message, array $context = []): void; + * + * @return void + */ +- public function warning(string|\Stringable $message, array $context = []): void; ++ public function warning(string|\Stringable $message, array $context = []); + + /** + * Normal but significant events. +@@ -86,7 +86,7 @@ public function warning(string|\Stringable $message, array $context = []): void; + * + * @return void + */ +- public function notice(string|\Stringable $message, array $context = []): void; ++ public function notice(string|\Stringable $message, array $context = []); + + /** + * Interesting events. +@@ -98,7 +98,7 @@ public function notice(string|\Stringable $message, array $context = []): void; + * + * @return void + */ +- public function info(string|\Stringable $message, array $context = []): void; ++ public function info(string|\Stringable $message, array $context = []); + + /** + * Detailed debug information. +@@ -108,7 +108,7 @@ public function info(string|\Stringable $message, array $context = []): void; + * + * @return void + */ +- public function debug(string|\Stringable $message, array $context = []): void; ++ public function debug(string|\Stringable $message, array $context = []); + + /** + * Logs with an arbitrary level. +@@ -121,5 +121,5 @@ public function debug(string|\Stringable $message, array $context = []): void; + * + * @throws \Psr\Log\InvalidArgumentException + */ +- public function log($level, string|\Stringable $message, array $context = []): void; ++ public function log($level, string|\Stringable $message, array $context = []); + } +diff --git a/vendor/psr/log/src/LoggerTrait.php b/vendor/psr/log/src/LoggerTrait.php +index 9c8733f9..66dfe483 100644 +--- a/vendor/psr/log/src/LoggerTrait.php ++++ b/vendor/psr/log/src/LoggerTrait.php +@@ -15,12 +15,12 @@ trait LoggerTrait + /** + * System is unusable. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function emergency(string|\Stringable $message, array $context = []): void ++ public function emergency($message, array $context = []): void + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } +@@ -31,12 +31,12 @@ public function emergency(string|\Stringable $message, array $context = []): voi + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function alert(string|\Stringable $message, array $context = []): void ++ public function alert($message, array $context = []): void + { + $this->log(LogLevel::ALERT, $message, $context); + } +@@ -46,12 +46,12 @@ public function alert(string|\Stringable $message, array $context = []): void + * + * Example: Application component unavailable, unexpected exception. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function critical(string|\Stringable $message, array $context = []): void ++ public function critical($message, array $context = []): void + { + $this->log(LogLevel::CRITICAL, $message, $context); + } +@@ -60,12 +60,12 @@ public function critical(string|\Stringable $message, array $context = []): void + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function error(string|\Stringable $message, array $context = []): void ++ public function error($message, array $context = []): void + { + $this->log(LogLevel::ERROR, $message, $context); + } +@@ -76,12 +76,12 @@ public function error(string|\Stringable $message, array $context = []): void + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function warning(string|\Stringable $message, array $context = []): void ++ public function warning($message, array $context = []): void + { + $this->log(LogLevel::WARNING, $message, $context); + } +@@ -89,12 +89,12 @@ public function warning(string|\Stringable $message, array $context = []): void + /** + * Normal but significant events. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function notice(string|\Stringable $message, array $context = []): void ++ public function notice($message, array $context = []): void + { + $this->log(LogLevel::NOTICE, $message, $context); + } +@@ -104,12 +104,12 @@ public function notice(string|\Stringable $message, array $context = []): void + * + * Example: User logs in, SQL logs. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function info(string|\Stringable $message, array $context = []): void ++ public function info($message, array $context = []): void + { + $this->log(LogLevel::INFO, $message, $context); + } +@@ -117,12 +117,12 @@ public function info(string|\Stringable $message, array $context = []): void + /** + * Detailed debug information. + * +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + */ +- public function debug(string|\Stringable $message, array $context = []): void ++ public function debug($message, array $context = []): void + { + $this->log(LogLevel::DEBUG, $message, $context); + } +@@ -131,12 +131,12 @@ public function debug(string|\Stringable $message, array $context = []): void + * Logs with an arbitrary level. + * + * @param mixed $level +- * @param string|\Stringable $message ++ * @param $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ +- abstract public function log($level, string|\Stringable $message, array $context = []): void; ++ abstract public function log($level, $message, array $context = []); + } diff --git a/drupal95/drupal95.patch b/drupal95/drupal95.patch new file mode 100644 index 0000000..2aff1c3 --- /dev/null +++ b/drupal95/drupal95.patch @@ -0,0 +1,79 @@ +diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php +index 8efc6232..0b6c1b36 100644 +--- a/vendor/symfony/console/Input/InputInterface.php ++++ b/vendor/symfony/console/Input/InputInterface.php +@@ -26,7 +26,7 @@ interface InputInterface + * + * @return string|null The value of the first argument or null otherwise + */ +- public function getFirstArgument(); ++ public function getFirstArgument(): ?string; + + /** + * Returns true if the raw parameters (not parsed) contain a value. +@@ -41,7 +41,7 @@ public function getFirstArgument(); + * + * @return bool true if the value is contained in the raw parameters + */ +- public function hasParameterOption($values, $onlyParams = false); ++ public function hasParameterOption(string|array $values, bool $onlyParams = false): bool; + + /** + * Returns the value of a raw option (not parsed). +@@ -57,7 +57,7 @@ public function hasParameterOption($values, $onlyParams = false); + * + * @return mixed The option value + */ +- public function getParameterOption($values, $default = false, $onlyParams = false); ++ public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false); + + /** + * Binds the current Input instance with the given arguments and options. +@@ -78,7 +78,8 @@ public function validate(); + * + * @return array + */ +- public function getArguments(); ++ public function getArguments(): array; ++ + + /** + * Returns the argument value for a given argument name. +@@ -108,14 +109,16 @@ public function setArgument($name, $value); + * + * @return bool true if the InputArgument object exists, false otherwise + */ +- public function hasArgument($name); ++ public function hasArgument($name): bool; ++ + + /** + * Returns all the given options merged with the default values. + * + * @return array + */ +- public function getOptions(); ++ public function getOptions(): array; ++ + + /** + * Returns the option value for a given option name. +@@ -145,14 +148,16 @@ public function setOption($name, $value); + * + * @return bool true if the InputOption object exists, false otherwise + */ +- public function hasOption($name); ++ public function hasOption($name): bool; ++ + + /** + * Is this input means interactive? + * + * @return bool + */ +- public function isInteractive(); ++ public function isInteractive(): bool; ++ + + /** + * Sets the input interactivity. diff --git a/drush8/DrupalBoot.php.patch b/drush8/DrupalBoot.php.patch new file mode 100644 index 0000000..ea633e9 --- /dev/null +++ b/drush8/DrupalBoot.php.patch @@ -0,0 +1,29 @@ +@@ -157,7 +157,12 @@ + $ignored_modules[] = $cached->data; + } + foreach (array_diff(drush_module_list(), $ignored_modules) as $module) { +- $filepath = drupal_get_path('module', $module); ++ if (drush_drupal_major_version() <= 9) { ++ $filepath = drupal_get_path('module', $module); ++ } ++ else { ++ $filepath = \Drupal::service('extension.list.module')->getPath($module); ++ } + if ($filepath && $filepath != '/') { + $searchpath[] = $filepath; + } +@@ -165,7 +170,12 @@ + + // Check all enabled themes including non-default and non-admin. + foreach (drush_theme_list() as $key => $value) { +- $searchpath[] = drupal_get_path('theme', $key); ++ if (drush_drupal_major_version() <= 9) { ++ $searchpath[] = drupal_get_path('theme', $key); ++ } ++ else { ++ $searchpath[] = \Drupal::service('extension.list.theme')->getPath($key); ++ } + } + break; + } + diff --git a/drush8/DrupalBoot10.php b/drush8/DrupalBoot10.php new file mode 100644 index 0000000..8902f77 --- /dev/null +++ b/drush8/DrupalBoot10.php @@ -0,0 +1,215 @@ +getSitePath(); + } + if (!isset($site_path) || empty($site_path)) { + $site_path = DrupalKernel::findSitePath($request, $require_settings); + } + return $site_path; + } + + function add_logger() { + // If we're running on Drupal 8 or later, we provide a logger which will send + // output to drush_log(). This should catch every message logged through every + // channel. + $container = \Drupal::getContainer(); + $parser = $container->get('logger.log_message_parser'); + $drushLogger = drush_get_context('DRUSH_LOG_CALLBACK'); + $logger = new \Drush\Log\DrushLog($parser, $drushLogger); + $container->get('logger.factory')->addLogger($logger); + } + + function contrib_modules_paths() { + return array( + $this->conf_path() . '/modules', + 'sites/all/modules', + 'modules', + ); + } + + /** + * @return array of strings - paths to directories where contrib + * themes can be found + */ + function contrib_themes_paths() { + return array( + $this->conf_path() . '/themes', + 'sites/all/themes', + 'themes', + ); + } + + function bootstrap_drupal_core($drupal_root) { + $core = DRUPAL_ROOT . '/core'; + + return $core; + } + + function bootstrap_drupal_database_validate() { + return parent::bootstrap_drupal_database_validate() && $this->bootstrap_drupal_database_has_table('key_value'); + } + + function bootstrap_drupal_database() { + // D8 omits this bootstrap level as nothing special needs to be done. + parent::bootstrap_drupal_database(); + } + + function bootstrap_drupal_configuration() { + $this->request = Request::createFromGlobals(); + $classloader = drush_drupal_load_autoloader(DRUPAL_ROOT); + // @todo - use Request::create() and then no need to set PHP superglobals + $kernelClass = new \ReflectionClass('\Drupal\Core\DrupalKernel'); + if ($kernelClass->hasMethod('addServiceModifier')) { + $this->kernel = DrupalKernel::createFromRequest($this->request, $classloader, 'prod'); + } + else { + $this->kernel = DrushDrupalKernel::createFromRequest($this->request, $classloader, 'prod'); + } + // @see Drush\Drupal\DrupalKernel::addServiceModifier() + $this->kernel->addServiceModifier(new DrushServiceModifier()); + + // Unset drupal error handler and restore Drush's one. + restore_error_handler(); + + // Disable automated cron if the module is enabled. + $GLOBALS['config']['automated_cron.settings']['interval'] = 0; + + parent::bootstrap_drupal_configuration(); + } + + function bootstrap_drupal_full() { + drush_log(dt('About to bootstrap the Drupal 10 Kernel.'), LogLevel::DEBUG); + // TODO: do we need to do ob_start any longer? + if (!drush_get_context('DRUSH_QUIET', FALSE)) { + ob_start(); + } + $this->kernel->boot(); + if (method_exists($this->kernel, 'preHandle')) { + $this->kernel->preHandle($this->request); + } + else { + $this->kernel->prepareLegacyRequest($this->request); + } + if (!drush_get_context('DRUSH_QUIET', FALSE)) { + ob_end_clean(); + } + drush_log(dt('Finished bootstraping the Drupal 10 Kernel.'), LogLevel::DEBUG); + + parent::bootstrap_drupal_full(); + + // Get a list of the modules to ignore + $ignored_modules = drush_get_option_list('ignored-modules', array()); + + // We have to get the service command list from the container, because + // it is constructed in an indirect way during the container initialization. + // The upshot is that the list of console commands is not available + // until after $kernel->boot() is called. + $container = \Drupal::getContainer(); + if ($container->has('drush.service.consolecommands')) { + $serviceCommandlist = $container->get('drush.service.consolecommands'); + foreach ($serviceCommandlist->getCommandList() as $command) { + if (!$this->commandIgnored($command, $ignored_modules)) { + drush_log(dt('Add a command: !name', ['!name' => $command->getName()]), LogLevel::DEBUG); + annotationcommand_adapter_cache_module_console_commands($command); + } + } + } + // Do the same thing with the annotation commands. + if ($container->has('drush.service.consolidationcommands')) { + $serviceCommandlist = $container->get('drush.service.consolidationcommands'); + foreach ($serviceCommandlist->getCommandList() as $commandhandler) { + if (!$this->commandIgnored($commandhandler, $ignored_modules)) { + drush_log(dt('Add a commandhandler: !name', ['!name' => get_class($commandhandler)]), LogLevel::DEBUG); + annotationcommand_adapter_cache_module_service_commands($commandhandler); + } + } + } + } + + public function commandIgnored($command, $ignored_modules) { + if (empty($ignored_modules)) { + return false; + } + $ignored_regex = '#\\\\(' . implode('|', $ignored_modules) . ')\\\\#'; + $class = new \ReflectionClass($command); + $commandNamespace = $class->getNamespaceName(); + return preg_match($ignored_regex, $commandNamespace); + } + + /** + * {@inheritdoc} + */ + public function terminate() { + parent::terminate(); + + if ($this->kernel) { + $response = new Response(''); + $this->kernel->terminate($this->request, $response); + } + } +} diff --git a/drush8/Sql10.php b/drush8/Sql10.php new file mode 100644 index 0000000..4d8a02c --- /dev/null +++ b/drush8/Sql10.php @@ -0,0 +1,7 @@ +engine_type = $type; + $this->engine = $engine; + $this->engine_config = $config; + } + + /** + * {@inheritdoc} + */ + function lastCheck() { + $last_check = \Drupal::state()->get('update.last_check') ?: 0; + return $last_check; + } + + /** + * {@inheritdoc} + */ + function refresh() { + update_refresh(); + } + + /** + * Perform adjustments before running get status. + * + * - Enforce check-disabled option on update module. + */ + function beforeGetStatus(&$projects, $check_disabled) { + // If check-disabled option was provided, alter Drupal settings temporarily. + // There's no other way to hook into this. + if (!is_null($check_disabled)) { + $config = \Drupal::config('update.settings'); + $this->update_check_disabled = $config->get('check.disabled_extensions'); + $config->set('check.disabled_extensions', (bool)$check_disabled); + } + } + + /** + * Get update information for all installed projects. + * + * @return + * Array of update status information. + */ + function getStatus($projects, $check_disabled) { + $this->beforeGetStatus($projects, $check_disabled); + $available = $this->getAvailableReleases(); + $update_info = $this->calculateUpdateStatus($available, $projects); + $this->afterGetStatus($update_info, $projects, $check_disabled); + return $update_info; + } + + /** + * Perform adjustments after running get status. + * + * - Restore check-disabled setting in update module. + * - Adjust project type for disabled projects. + */ + function afterGetStatus(&$update_info, $projects, $check_disabled) { + // Restore Drupal settings. + if (!is_null($check_disabled)) { + \Drupal::config('update.settings')->set('check.disabled_extensions', $this->update_check_disabled); + unset($this->update_check_disabled); + } + + // update.module sets a different project type + // for disabled projects. Here we normalize it. + if ($check_disabled) { + foreach ($update_info as $key => $project) { + if (in_array($project['project_type'], array('module-disabled', 'theme-disabled'))) { + $update_info[$key]['project_type'] = substr($project['project_type'], 0, strpos($project['project_type'], '-')); + } + } + } + } + + /** + * Obtains release info for all installed projects via update.module. + * + * @see update_get_available(). + * @see \Drupal\update\Controller\UpdateController::updateStatusManually() + */ + protected function getAvailableReleases() { + // Force to invalidate some caches that are only cleared + // when visiting update status report page. This allow to detect changes in + // .info.yml files. + \Drupal::keyValueExpirable('update')->deleteMultiple(array('update_project_projects', 'update_project_data')); + + // From update_get_available(): Iterate all projects and create a fetch task + // for those we have no information or is obsolete. + $available = \Drupal::keyValueExpirable('update_available_releases')->getAll(); + $update_projects = \Drupal::service('update.manager')->getProjects(); + foreach ($update_projects as $key => $project) { + if (empty($available[$key])) { + \Drupal::service('update.processor')->createFetchTask($project); + continue; + } + if ($project['info']['_info_file_ctime'] > $available[$key]['last_fetch']) { + $available[$key]['fetch_status'] = UPDATE_FETCH_PENDING; + } + if (empty($available[$key]['releases'])) { + $available[$key]['fetch_status'] = UPDATE_FETCH_PENDING; + } + if (!empty($available[$key]['fetch_status']) && $available[$key]['fetch_status'] == UPDATE_FETCH_PENDING) { + \Drupal::service('update.processor')->createFetchTask($project); + } + } + + // Set a batch to process all pending tasks. + if (drush_drupal_major_version() <= 9) { + $filepath = drupal_get_path('module', 'update'); + } + else { + $filepath = \Drupal::service('extension.list.module')->getPath('update'); + } + + $batch = array( + 'operations' => array( + array(array(\Drupal::service('update.manager'), 'fetchDataBatch'), array()), + ), + 'finished' => 'update_fetch_data_finished', + 'file' => $filepath . '/update.fetch.inc', + ); + batch_set($batch); + drush_backend_batch_process(); + + // Clear any error set by a failed update fetch task. This avoid rollbacks. + drush_clear_error(); + + return \Drupal::keyValueExpirable('update_available_releases')->getAll(); + } + + /** + * Calculates update status for all projects via update.module. + */ + protected function calculateUpdateStatus($available, $projects) { + module_load_include('inc', 'update', 'update.compare'); + $data = update_calculate_project_data($available); + + foreach ($data as $project_name => $project) { + // Discard custom projects. + if ($project['status'] == UPDATE_UNKNOWN) { + unset($data[$project_name]); + continue; + } + // Discard projects with unknown installation path. + if ($project_name != 'drupal' && !isset($projects[$project_name]['path'])) { + unset($data[$project_name]); + continue; + } + + // Add some info from the project to $data. + $data[$project_name] += array( + 'path' => isset($projects[$project_name]['path']) ? $projects[$project_name]['path'] : '', + 'label' => $projects[$project_name]['label'], + ); + // Store all releases, not just the ones selected by update.module. + // We use it to allow the user to update to a specific version. + if (isset($available[$project_name]['releases'])) { + $data[$project_name]['releases'] = $available[$project_name]['releases']; + } + } + + return $data; + } +} + diff --git a/drush8/User10.php b/drush8/User10.php new file mode 100644 index 0000000..2177cbd --- /dev/null +++ b/drush8/User10.php @@ -0,0 +1,20 @@ +getStorage('user') + ->create($properties); + $account->save(); + return new UserSingle10($account); + } +} diff --git a/drush8/UserSingle10.php b/drush8/UserSingle10.php new file mode 100644 index 0000000..180c650 --- /dev/null +++ b/drush8/UserSingle10.php @@ -0,0 +1,33 @@ + $this->account->id(), + 'name' => $this->account->getAccountName(), + 'password' => $this->account->getPassword(), + 'mail' => $this->account->getEmail(), + 'user_created' => $this->account->getCreatedTime(), + 'created' => drush_format_date($this->account->getCreatedTime()), + 'user_access' => $this->account->getLastAccessedTime(), + 'access' => drush_format_date($this->account->getLastAccessedTime()), + 'user_login' => $this->account->getLastLoginTime(), + 'login' => drush_format_date($this->account->getLastLoginTime()), + 'user_status' => $this->account->get('status')->value, + 'status' => $this->account->isActive() ? 'active' : 'blocked', + 'timezone' => $this->account->getTimeZone(), + 'roles' => $this->account->getRoles(), + 'langcode' => $this->account->getPreferredLangcode(), + 'uuid' => $this->account->uuid->value, + ); + } + +} diff --git a/drush8/drush-8-symfony-console-compat.patch b/drush8/drush-8-symfony-console-compat.patch new file mode 100644 index 0000000..2b8cd77 --- /dev/null +++ b/drush8/drush-8-symfony-console-compat.patch @@ -0,0 +1,76 @@ +diff --git a/lib/Drush/Command/DrushInputAdapter.php b/lib/Drush/Command/DrushInputAdapter.php +index 801b58c32..08988e68d 100644 +--- a/lib/Drush/Command/DrushInputAdapter.php ++++ b/lib/Drush/Command/DrushInputAdapter.php +@@ -51,7 +51,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function getFirstArgument() ++ public function getFirstArgument(): ?string + { + return reset($this->arguments); + } +@@ -59,7 +59,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function hasParameterOption($values, $onlyParams = false) ++ public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + $values = (array) $values; + +@@ -75,7 +75,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function getParameterOption($values, $default = false, $onlyParams = false) ++ public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false) + { + $values = (array) $values; + +@@ -107,7 +107,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function getArguments() ++ public function getArguments(): array + { + return $this->arguments; + } +@@ -132,7 +132,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function hasArgument($name) ++ public function hasArgument($name): bool + { + return isset($this->arguments[$name]); + } +@@ -140,7 +140,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function getOptions() ++ public function getOptions(): array + { + return $this->options; + } +@@ -164,7 +164,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function hasOption($name) ++ public function hasOption($name): bool + { + return isset($this->options[$name]); + } +@@ -172,7 +172,7 @@ class DrushInputAdapter implements InputInterface + /** + * {@inheritdoc} + */ +- public function isInteractive() ++ public function isInteractive(): bool + { + return $this->interactive; + } diff --git a/hostmaster/field.form.inc.patch b/hostmaster/field.form.inc.patch new file mode 100644 index 0000000..dc185c3 --- /dev/null +++ b/hostmaster/field.form.inc.patch @@ -0,0 +1,11 @@ +--- /var/aegir/hostmaster-7.x-3.192+nmu1/modules/field/field.form.inc 2023-12-06 15:25:06.000000000 +0100 ++++ field.form.inc 2024-02-20 12:11:12.437834696 +0100 +@@ -74,7 +74,7 @@ + $field_state = array( + 'field' => $field, + 'instance' => $instance, +- 'items_count' => count($items), ++ 'items_count' => count((array) $items), + 'array_parents' => array(), + 'errors' => array(), + ); diff --git a/hostmaster/hosting_platform.module.patch b/hostmaster/hosting_platform.module.patch new file mode 100644 index 0000000..a5711c7 --- /dev/null +++ b/hostmaster/hosting_platform.module.patch @@ -0,0 +1,24 @@ +--- /var/aegir/hostmaster-7.x-3.192+nmu1/profiles/hostmaster/modules/aegir/hosting/platform/hosting_platform.module.old 2024-02-20 13:15:41.490390915 +0100 ++++ /var/aegir/hostmaster-7.x-3.192+nmu1/profiles/hostmaster/modules/aegir/hosting/platform/hosting_platform.module 2024-02-20 13:18:07.850720426 +0100 +@@ -647,13 +647,13 @@ + } + + // Make sure the path is unique. Remote servers can't have the same path to a platform that is in use by another server. +- $exists = hosting_platform_path_exists($node->publish_path); +- if ($exists) { +- form_set_error('publish_path', +- t('Path is already in use by platform %name. Platform paths must be unique across all servers.', +- array('%name' => $result->name)) +- ); +- } ++ //$exists = hosting_platform_path_exists($node->publish_path); ++ //if ($exists) { ++ // form_set_error('publish_path', ++ // t('Path is already in use by platform %name. Platform paths must be unique across all servers.', ++ // array('%name' => $result->name)) ++ // ); ++ //} + + if (is_null($node->web_server)) { + form_set_error('web_server', t('Platform needs to be associated with a webserver. Make sure you have a verified webserver on this Aegir install!')); + diff --git a/hostmaster/http_basic_auth.drush.inc.patch b/hostmaster/http_basic_auth.drush.inc.patch new file mode 100644 index 0000000..fd5c1d5 --- /dev/null +++ b/hostmaster/http_basic_auth.drush.inc.patch @@ -0,0 +1,5 @@ +49c49,50 +< $pass = crypt($pass); +--- +> $salt = substr(str_replace('+', '.', base64_encode(pack('N4', mt_rand(), mt_rand(), mt_rand(), mt_rand()))), 0, 22); +> $pass = crypt($pass,$salt); diff --git a/provision/3353492-symfony-console-4-update_1.patch b/provision/3353492-symfony-console-4-update_1.patch new file mode 100644 index 0000000..168e43c --- /dev/null +++ b/provision/3353492-symfony-console-4-update_1.patch @@ -0,0 +1,377 @@ +diff --git a/Input/ArgvInput.php b/Input/ArgvInput.php +index 63f40f27..c576fbf6 100644 +--- a/Input/ArgvInput.php ++++ b/Input/ArgvInput.php +@@ -238,7 +238,7 @@ class ArgvInput extends Input + /** + * {@inheritdoc} + */ +- public function getFirstArgument() ++ public function getFirstArgument(): ?string + { + $isOption = false; + foreach ($this->tokens as $i => $token) { +@@ -273,7 +273,7 @@ class ArgvInput extends Input + /** + * {@inheritdoc} + */ +- public function hasParameterOption($values, $onlyParams = false) ++ public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + $values = (array) $values; + +@@ -298,7 +298,7 @@ class ArgvInput extends Input + /** + * {@inheritdoc} + */ +- public function getParameterOption($values, $default = false, $onlyParams = false) ++ public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false) + { + $values = (array) $values; + $tokens = $this->tokens; +diff --git a/Input/Input.php b/Input/Input.php +index d7f29073..58cfd676 100644 +--- a/Input/Input.php ++++ b/Input/Input.php +@@ -80,7 +80,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function isInteractive() ++ public function isInteractive(): bool + { + return $this->interactive; + } +@@ -96,7 +96,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function getArguments() ++ public function getArguments(): array + { + return array_merge($this->definition->getArgumentDefaults(), $this->arguments); + } +@@ -116,7 +116,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function setArgument($name, $value) ++ public function setArgument(string $name, mixed $value) + { + if (!$this->definition->hasArgument((string) $name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); +@@ -128,7 +128,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function hasArgument($name) ++ public function hasArgument($name): bool + { + return $this->definition->hasArgument((string) $name); + } +@@ -136,7 +136,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function getOptions() ++ public function getOptions(): array + { + return array_merge($this->definition->getOptionDefaults(), $this->options); + } +@@ -156,7 +156,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function setOption($name, $value) ++ public function setOption(string $name, mixed $value) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); +@@ -168,7 +168,7 @@ abstract class Input implements InputInterface, StreamableInputInterface + /** + * {@inheritdoc} + */ +- public function hasOption($name) ++ public function hasOption($name): bool + { + return $this->definition->hasOption($name); + } +diff --git a/Input/InputInterface.php b/Input/InputInterface.php +index 8efc6232..a723a5ae 100644 +--- a/Input/InputInterface.php ++++ b/Input/InputInterface.php +@@ -18,146 +18,133 @@ use Symfony\Component\Console\Exception\RuntimeException; + * InputInterface is the interface implemented by all input classes. + * + * @author Fabien Potencier ++ * ++ * @method string __toString() Returns a stringified representation of the args passed to the command. ++ * InputArguments MUST be escaped as well as the InputOption values passed to the command. + */ + interface InputInterface + { +- /** +- * Returns the first argument from the raw parameters (not parsed). +- * +- * @return string|null The value of the first argument or null otherwise +- */ +- public function getFirstArgument(); +- +- /** +- * Returns true if the raw parameters (not parsed) contain a value. +- * +- * This method is to be used to introspect the input parameters +- * before they have been validated. It must be used carefully. +- * Does not necessarily return the correct result for short options +- * when multiple flags are combined in the same option. +- * +- * @param string|array $values The values to look for in the raw parameters (can be an array) +- * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal +- * +- * @return bool true if the value is contained in the raw parameters +- */ +- public function hasParameterOption($values, $onlyParams = false); +- +- /** +- * Returns the value of a raw option (not parsed). +- * +- * This method is to be used to introspect the input parameters +- * before they have been validated. It must be used carefully. +- * Does not necessarily return the correct result for short options +- * when multiple flags are combined in the same option. +- * +- * @param string|array $values The value(s) to look for in the raw parameters (can be an array) +- * @param string|bool|int|float|array|null $default The default value to return if no result is found +- * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal +- * +- * @return mixed The option value +- */ +- public function getParameterOption($values, $default = false, $onlyParams = false); +- +- /** +- * Binds the current Input instance with the given arguments and options. +- * +- * @throws RuntimeException +- */ +- public function bind(InputDefinition $definition); +- +- /** +- * Validates the input. +- * +- * @throws RuntimeException When not enough arguments are given +- */ +- public function validate(); +- +- /** +- * Returns all the given arguments merged with the default values. +- * +- * @return array +- */ +- public function getArguments(); +- +- /** +- * Returns the argument value for a given argument name. +- * +- * @param string $name The argument name +- * +- * @return mixed +- * +- * @throws InvalidArgumentException When argument given doesn't exist +- */ +- public function getArgument($name); +- +- /** +- * Sets an argument value by name. +- * +- * @param string $name The argument name +- * @param mixed $value The argument value +- * +- * @throws InvalidArgumentException When argument given doesn't exist +- */ +- public function setArgument($name, $value); +- +- /** +- * Returns true if an InputArgument object exists by name or position. +- * +- * @param string $name The argument name +- * +- * @return bool true if the InputArgument object exists, false otherwise +- */ +- public function hasArgument($name); +- +- /** +- * Returns all the given options merged with the default values. +- * +- * @return array +- */ +- public function getOptions(); +- +- /** +- * Returns the option value for a given option name. +- * +- * @param string $name The option name +- * +- * @return mixed +- * +- * @throws InvalidArgumentException When option given doesn't exist +- */ +- public function getOption($name); +- +- /** +- * Sets an option value by name. +- * +- * @param string $name The option name +- * @param mixed $value The option value +- * +- * @throws InvalidArgumentException When option given doesn't exist +- */ +- public function setOption($name, $value); +- +- /** +- * Returns true if an InputOption object exists by name. +- * +- * @param string $name The InputOption name +- * +- * @return bool true if the InputOption object exists, false otherwise +- */ +- public function hasOption($name); +- +- /** +- * Is this input means interactive? +- * +- * @return bool +- */ +- public function isInteractive(); +- +- /** +- * Sets the input interactivity. +- * +- * @param bool $interactive If the input should be interactive +- */ +- public function setInteractive($interactive); +-} ++ /** ++ * Returns the first argument from the raw parameters (not parsed). ++ */ ++ public function getFirstArgument(): ?string; ++ ++ /** ++ * Returns true if the raw parameters (not parsed) contain a value. ++ * ++ * This method is to be used to introspect the input parameters ++ * before they have been validated. It must be used carefully. ++ * Does not necessarily return the correct result for short options ++ * when multiple flags are combined in the same option. ++ * ++ * @param string|array $values The values to look for in the raw parameters (can be an array) ++ * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal ++ */ ++ public function hasParameterOption(string|array $values, bool $onlyParams = false): bool; ++ ++ /** ++ * Returns the value of a raw option (not parsed). ++ * ++ * This method is to be used to introspect the input parameters ++ * before they have been validated. It must be used carefully. ++ * Does not necessarily return the correct result for short options ++ * when multiple flags are combined in the same option. ++ * ++ * @param string|array $values The value(s) to look for in the raw parameters (can be an array) ++ * @param string|bool|int|float|array|null $default The default value to return if no result is found ++ * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal ++ * ++ * @return mixed ++ */ ++ public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false); ++ ++ /** ++ * Binds the current Input instance with the given arguments and options. ++ * ++ * @return void ++ * ++ * @throws RuntimeException ++ */ ++ public function bind(InputDefinition $definition); ++ ++ /** ++ * Validates the input. ++ * ++ * @return void ++ * ++ * @throws RuntimeException When not enough arguments are given ++ */ ++ public function validate(); ++ ++ /** ++ * Returns all the given arguments merged with the default values. ++ * ++ * @return array ++ */ ++ public function getArguments(): array; ++ ++ /** ++ * Returns the argument value for a given argument name. ++ * ++ * @return mixed ++ * ++ * @throws InvalidArgumentException When argument given doesn't exist ++ */ ++ public function getArgument(string $name); ++ ++ /** ++ * Sets an argument value by name. ++ * ++ * @return void ++ * ++ * @throws InvalidArgumentException When argument given doesn't exist ++ */ ++ public function setArgument(string $name, mixed $value); ++ ++ /** ++ * Returns true if an InputArgument object exists by name or position. ++ */ ++ public function hasArgument(string $name): bool; ++ ++ /** ++ * Returns all the given options merged with the default values. ++ * ++ * @return array ++ */ ++ public function getOptions(): array; ++ ++ /** ++ * Returns the option value for a given option name. ++ * ++ * @return mixed ++ * ++ * @throws InvalidArgumentException When option given doesn't exist ++ */ ++ public function getOption(string $name); ++ ++ /** ++ * Sets an option value by name. ++ * ++ * @return void ++ * ++ * @throws InvalidArgumentException When option given doesn't exist ++ */ ++ public function setOption(string $name, mixed $value); ++ ++ /** ++ * Returns true if an InputOption object exists by name. ++ */ ++ public function hasOption(string $name): bool; ++ ++ /** ++ * Is this input means interactive? ++ */ ++ public function isInteractive(): bool; ++ ++ /** ++ * Sets the input interactivity. ++ * ++ * @return void ++ */ ++ public function setInteractive(bool $interactive); ++} +\ No newline at end of file diff --git a/provision/3374479-2.patch b/provision/3374479-2.patch new file mode 100644 index 0000000..fe93178 --- /dev/null +++ b/provision/3374479-2.patch @@ -0,0 +1,144 @@ +diff --git a/Provision/Config/Drupal/provision_drupal_settings_6.tpl.php b/Provision/Config/Drupal/provision_drupal_settings_6.tpl.php +index 6001497a..7b7aaec1 100644 +--- a/Provision/Config/Drupal/provision_drupal_settings_6.tpl.php ++++ b/Provision/Config/Drupal/provision_drupal_settings_6.tpl.php +@@ -59,19 +59,19 @@ if (isset($_SERVER['db_name'])) { + * places. + */ + if (function_exists('apache_setenv')) { +- apache_setenv('db_type', null); +- apache_setenv('db_user', null); +- apache_setenv('db_passwd', null); +- apache_setenv('db_host', null); +- apache_setenv('db_port', null); +- apache_setenv('db_name', null); ++ apache_setenv('db_type', ''); ++ apache_setenv('db_user', ''); ++ apache_setenv('db_passwd', ''); ++ apache_setenv('db_host', ''); ++ apache_setenv('db_port', ''); ++ apache_setenv('db_name', ''); + // no idea why they are also in REDIRECT_foo, but they are +- apache_setenv('REDIRECT_db_type', null); +- apache_setenv('REDIRECT_db_user', null); +- apache_setenv('REDIRECT_db_passwd', null); +- apache_setenv('REDIRECT_db_host', null); +- apache_setenv('REDIRECT_db_port', null); +- apache_setenv('REDIRECT_db_name', null); ++ apache_setenv('REDIRECT_db_type', ''); ++ apache_setenv('REDIRECT_db_user', ''); ++ apache_setenv('REDIRECT_db_passwd', ''); ++ apache_setenv('REDIRECT_db_host', ''); ++ apache_setenv('REDIRECT_db_port', ''); ++ apache_setenv('REDIRECT_db_name', ''); + } + unset($_SERVER['db_type']); + unset($_SERVER['db_user']); +diff --git a/Provision/Config/Drupal/provision_drupal_settings_7.tpl.php b/Provision/Config/Drupal/provision_drupal_settings_7.tpl.php +index f3278530..d6daab01 100644 +--- a/Provision/Config/Drupal/provision_drupal_settings_7.tpl.php ++++ b/Provision/Config/Drupal/provision_drupal_settings_7.tpl.php +@@ -65,19 +65,19 @@ if (isset($_SERVER['db_name'])) { + * places. + */ + if (function_exists('apache_setenv')) { +- apache_setenv('db_type', null); +- apache_setenv('db_user', null); +- apache_setenv('db_passwd', null); +- apache_setenv('db_host', null); +- apache_setenv('db_port', null); +- apache_setenv('db_name', null); ++ apache_setenv('db_type', ''); ++ apache_setenv('db_user', ''); ++ apache_setenv('db_passwd', ''); ++ apache_setenv('db_host', ''); ++ apache_setenv('db_port', ''); ++ apache_setenv('db_name', ''); + // no idea why they are also in REDIRECT_foo, but they are +- apache_setenv('REDIRECT_db_type', null); +- apache_setenv('REDIRECT_db_user', null); +- apache_setenv('REDIRECT_db_passwd', null); +- apache_setenv('REDIRECT_db_host', null); +- apache_setenv('REDIRECT_db_port', null); +- apache_setenv('REDIRECT_db_name', null); ++ apache_setenv('REDIRECT_db_type', ''); ++ apache_setenv('REDIRECT_db_user', ''); ++ apache_setenv('REDIRECT_db_passwd', ''); ++ apache_setenv('REDIRECT_db_host', ''); ++ apache_setenv('REDIRECT_db_port', ''); ++ apache_setenv('REDIRECT_db_name', ''); + } + unset($_SERVER['db_type']); + unset($_SERVER['db_user']); +diff --git a/Provision/Config/Drupal/provision_drupal_settings_8.tpl.php b/Provision/Config/Drupal/provision_drupal_settings_8.tpl.php +index f52e3c6f..ca9eab93 100644 +--- a/Provision/Config/Drupal/provision_drupal_settings_8.tpl.php ++++ b/Provision/Config/Drupal/provision_drupal_settings_8.tpl.php +@@ -64,19 +64,19 @@ if (isset($_SERVER['db_name'])) { + * places. + */ + if (function_exists('apache_setenv')) { +- apache_setenv('db_type', null); +- apache_setenv('db_user', null); +- apache_setenv('db_passwd', null); +- apache_setenv('db_host', null); +- apache_setenv('db_port', null); +- apache_setenv('db_name', null); ++ apache_setenv('db_type', ''); ++ apache_setenv('db_user', ''); ++ apache_setenv('db_passwd', ''); ++ apache_setenv('db_host', ''); ++ apache_setenv('db_port', ''); ++ apache_setenv('db_name', ''); + // no idea why they are also in REDIRECT_foo, but they are +- apache_setenv('REDIRECT_db_type', null); +- apache_setenv('REDIRECT_db_user', null); +- apache_setenv('REDIRECT_db_passwd', null); +- apache_setenv('REDIRECT_db_host', null); +- apache_setenv('REDIRECT_db_port', null); +- apache_setenv('REDIRECT_db_name', null); ++ apache_setenv('REDIRECT_db_type', ''); ++ apache_setenv('REDIRECT_db_user', ''); ++ apache_setenv('REDIRECT_db_passwd', ''); ++ apache_setenv('REDIRECT_db_host', ''); ++ apache_setenv('REDIRECT_db_port', ''); ++ apache_setenv('REDIRECT_db_name', ''); + } + unset($_SERVER['db_type']); + unset($_SERVER['db_user']); +diff --git a/Provision/Config/Drupal/provision_drupal_settings_9.tpl.php b/Provision/Config/Drupal/provision_drupal_settings_9.tpl.php +index 617583b1..1f0f0b23 100644 +--- a/Provision/Config/Drupal/provision_drupal_settings_9.tpl.php ++++ b/Provision/Config/Drupal/provision_drupal_settings_9.tpl.php +@@ -64,19 +64,19 @@ if (isset($_SERVER['db_name'])) { + * places. + */ + if (function_exists('apache_setenv')) { +- apache_setenv('db_type', null); +- apache_setenv('db_user', null); +- apache_setenv('db_passwd', null); +- apache_setenv('db_host', null); +- apache_setenv('db_port', null); +- apache_setenv('db_name', null); ++ apache_setenv('db_type', ''); ++ apache_setenv('db_user', ''); ++ apache_setenv('db_passwd', ''); ++ apache_setenv('db_host', ''); ++ apache_setenv('db_port', ''); ++ apache_setenv('db_name', ''); + // no idea why they are also in REDIRECT_foo, but they are +- apache_setenv('REDIRECT_db_type', null); +- apache_setenv('REDIRECT_db_user', null); +- apache_setenv('REDIRECT_db_passwd', null); +- apache_setenv('REDIRECT_db_host', null); +- apache_setenv('REDIRECT_db_port', null); +- apache_setenv('REDIRECT_db_name', null); ++ apache_setenv('REDIRECT_db_type', ''); ++ apache_setenv('REDIRECT_db_user', ''); ++ apache_setenv('REDIRECT_db_passwd', ''); ++ apache_setenv('REDIRECT_db_host', ''); ++ apache_setenv('REDIRECT_db_port', ''); ++ apache_setenv('REDIRECT_db_name', ''); + } + unset($_SERVER['db_type']); + unset($_SERVER['db_user']); diff --git a/provision/clear_10.inc b/provision/clear_10.inc new file mode 100644 index 0000000..48f1e61 --- /dev/null +++ b/provision/clear_10.inc @@ -0,0 +1,9 @@ +get('system.cron_key')); diff --git a/provision/deploy_10.inc b/provision/deploy_10.inc new file mode 100644 index 0000000..b766bb4 --- /dev/null +++ b/provision/deploy_10.inc @@ -0,0 +1,62 @@ +getEditable('system.file') + ->set('path.private', "sites/$new_url/private/files") + ->set('path.temporary', "sites/$new_url/private/temp") + ->save(); + + // Detect and update default site name, if needed + $old_name = \Drupal::config('system.site')->get('name'); + if ($old_name == $old_url) { + \Drupal::configFactory()->getEditable('system.site') + ->set('name', "$new_url") + ->save(); + } +} + +function _provision_platform_drupal_deploy_9_replace($old_url, $new_url) { + // Update absolute URLs to files for sites cloned/migrated/renamed in the multisite install. + $replace_abs_patterns = array( + ':old' => '//' . $old_url . '/sites/' . $old_url . '/files', + ':new' => '//' . $new_url . '/sites/' . $new_url . '/files', + ); + + // Update paths for sites cloned/migrated/renamed in the multisite install. + $replace_patterns = array( + ':old' => 'sites/' . $old_url, + ':new' => 'sites/' . $new_url, + ); + + drush_log( + dt('Changed paths from sites/@old_url to sites/@new_url', + array('@old_url' => $old_url, '@new_url' => $new_url))); +} + diff --git a/provision/import_10.inc b/provision/import_10.inc new file mode 100644 index 0000000..81a23f1 --- /dev/null +++ b/provision/import_10.inc @@ -0,0 +1,13 @@ +language, 'site'); +} diff --git a/provision/install_10.inc b/provision/install_10.inc new file mode 100644 index 0000000..b400e12 --- /dev/null +++ b/provision/install_10.inc @@ -0,0 +1,184 @@ +uri; +$GLOBALS['profile'] = d()->profile; +$GLOBALS['install_locale'] = d()->language; +$GLOBALS['base_url'] = provision_get_base_url(); + +define('MAINTENANCE_MODE', 'install'); + +function install_send_welcome_mail($url, $account, $language, $client_email, $onetime) { + global $base_url; + if ($client_email) { + // Mail one time login URL and instructions. + $from = \Drupal::config('system.site')->get('mail'); + $username = "admin"; + $site = \Drupal::config('system.site')->get('name'); + $uri_brief = preg_replace('!^https?://!', '', $base_url); + $edit_uri = $base_url . '/user/1/edit'; + $mailto = $account->getEmail(); + $date = \Drupal::service('date.formatter')->format(time()); + + $mail_params['variables'] = array( + '!username' => $username, + '!site' => $site, + '!login_url' => $onetime, + '!uri' => $base_url, + '!uri_brief' => $uri_brief, + '!edit_uri' => $edit_uri, + '!mailto' => $mailto, + '!date' => $date, + ); + + $langcode = $account->getPreferredLangcode(); + + $mail_success = \Drupal::service('plugin.manager.mail')->mail('install', 'welcome-admin', $mailto, $langcode, $mail_params, $from, TRUE); + + if ($mail_success) { + drush_log(dt('Sent welcome mail to @client', array('@client' => $client_email)), 'message'); + } + else { + drush_log(dt('Could not send welcome mail to @client', array('@client' => $client_email)), 'info'); + } + } +} + + +function install_mail($key, &$message, $params) { + global $profile; + switch ($key) { + case 'welcome-admin': + // allow the profile to override welcome email text + if (file_exists("./profiles/$profile/provision_welcome_mail.inc")) { + require_once "./profiles/$profile/provision_welcome_mail.inc"; + $custom = TRUE; + } + elseif (file_exists(dirname(__FILE__) . '/../provision_welcome_mail.inc')) { + /** use the module provided welcome email + * We can not use drupal_get_path here, + * as we are connected to the provisioned site's database + */ + require_once dirname(__FILE__) . '/../provision_welcome_mail.inc'; + $custom = TRUE; + } + else { + // last resort use the user-pass mail text + $custom = FALSE; + } + + if ($custom) { + $message['subject'] = dt($mail['subject'], $params['variables']); + $message['body'][] = dt($mail['body'], $params['variables']); + } + else { + $message['subject'] = _user_mail_text('pass_subject', $params['variables']); + $message['body'][] = _user_mail_text('pass_body', $params['variables']); + } + + break; + } +} + + +function install_main() { + global $profile, $install_locale, $conf, $url, $base_url; + + $client_email = drush_get_option('client_email'); + + require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; + + drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION); + + // We have an existing settings.php. + require_once DRUSH_BASE_PATH . '/commands/sql/sql.drush.inc'; + + $sql = drush_sql_get_class(); + $db_spec = $sql->db_spec(); + + $db_spec['db_prefix'] = $GLOBALS['db_prefix']; + + if ($db_spec['driver'] == 'mysqli') { + $db_spec['driver'] = 'mysql'; + } + + + unset($config['site_name']); + unset($config['site_mail']); + unset($GLOBALS['db_url']); + + $account_pass = provision_password(); + $settings = array( + 'parameters' => array( + 'profile' => $profile, + 'langcode' => $install_locale, + ), + 'settings_verified' => TRUE, + 'forms' => array( + 'install_settings_form' => $db_spec, + 'install_configure_form' => array( + 'site_name' => $url, + 'site_mail' => $client_email ? $client_email : 'admin@example.com', + 'account' => array( + 'name' => 'admin', + 'mail' => $client_email ? $client_email : 'admin@example.com', + 'pass' => array( + 'pass1' => $account_pass, + 'pass2' => $account_pass, + ), + ), + 'update_status_module' => array( + 1 => TRUE, + 2 => TRUE, + ), + 'clean_url' => drush_get_option('clean_url', TRUE), + ), + ), + ); + try { + $class_loader = drush_drupal_load_autoloader(DRUPAL_ROOT); + install_drupal($class_loader, $settings); + } + catch (Exception $e) { + drush_log('Site installation caused an exception: ' . $e->getMessage(), 'error'); + drush_log("Trace: \n" . $e->getTraceAsString(), 'debug'); + dlm($e); + + # Site install failed. Do no proceed further through install_main(); + return; + } + _provision_drupal_create_directories(); + + // Set files paths + \Drupal::configFactory()->getEditable('system.file') + ->set('path.private', "sites/$url/private/files") + ->set('path.temporary', "sites/$url/private/temp") + ->save(); + + $account = \Drupal\user\Entity\User::load(1); + + // If a redirect is defined, the symlink to the alias needs to exist before + // we generate the login link, below. + _provision_drupal_maintain_aliases(); + + // Store the one time login link in an option so the front end can direct the + // user to their new site. + $onetime = provision_generate_login_reset(); + drush_set_option('login_link', $onetime); + drush_log(dt('Login url: !onetime', array('!onetime' => $onetime)), 'message'); + + if ($client_email) { + install_send_welcome_mail($url, $account, $install_locale, $client_email, $onetime); + } +} +install_main(); + +function install_exception_handler() { + dlm(func_get_args()); +} diff --git a/provision/packages_10.inc b/provision/packages_10.inc new file mode 100644 index 0000000..bcbb618 --- /dev/null +++ b/provision/packages_10.inc @@ -0,0 +1,241 @@ + $file) { + $files[basename($name, '.info')] = $file; + unset($files[$name]); + } + + foreach ($files as $name => $file) { + $files[$name]->info = Symfony\Component\Yaml\Yaml::parse(file_get_contents($file->filename)); + if (!empty($files[$name]->info['name'])) { + $files[$name]->name = $files[$name]->info['name']; + } + + // If version is missing, or if version is set to 'VERSION', use "drush_drupal_version()". + // The VERSION constant used in Git checkouts. Also appears when using DEV modules in composer. + if (empty($files[$name]->info['version']) || $files[$name]->info['version'] == 'VERSION') { + $files[$name]->version = drush_drupal_version(); + } + else { + $files[$name]->version = $files[$name]->info['version']; + } + + // @TODO: This is copied from the D7 implementation and I'm almost certain + // that is doesn't even do anything in D7. + if (empty($files[$name]->info['engine'])) { + $filename = dirname($files[$name]->filename) . '/' . $files[$name]->name . '.theme'; + if (file_exists($filename)) { + $files[$name]->owner = $filename; + $files[$name]->prefix = $name; + } + } + else { + $engine = $files[$name]->info['engine']; + if (isset($engines[$engine])) { + $files[$name]->owner = $engines[$engine]->filename; + $files[$name]->prefix = $engines[$engine]->name; + $files[$name]->template = TRUE; + } + } + } + return $files; +} + +/** + * Map the system table to a packages multi-dimensional array component. + */ +function _provision_drupal_system_map() { + $profiles = _provision_find_profiles(); + foreach ($profiles as $profile => $info) { + if (empty($info->version)) { + $info->version = drush_drupal_version(); + } + $profiles[$profile] = $info; + } + $packages['platforms'] = _provision_find_platforms(); + + $profile = drush_get_option('profile'); + $packages['profiles'][$profile] = $profiles[$profile]; + if (isset($profile) && isset($packages['profiles'][$profile])) { + $packages['profiles'][$profile]->status = 1; + } + + $packages['modules'] = _provision_system_query('module'); + drush_log(dt("Found !count modules", array('!count' => count($packages['modules']))), 'info'); + + $packages['themes'] = _provision_system_query('theme'); + drush_log(dt("Found !count themes", array('!count' => count($packages['themes']))), 'info'); + + return $packages; +} + +/** + * Query the core system for packages of a certain type. + * + * @param string $type + * E.g. module or theme. + * + * @return array + * List of packages. + */ +function _provision_system_query($type) { + $packages = array(); + + if ($type == 'theme') { + /** @var \Drupal\Core\Extension\Extension[] $extensions_data */ + // Could be replaced with: + // \Drupal::service('extension.list.theme')->reset() + // \Drupal::service('extension.list.theme')->getList() + // https://www.drupal.org/project/drupal/issues/2942001 + $extensions_data = \Drupal::service('theme_handler')->rebuildThemeData(); + } + // Modules. + else { + /** @var \Drupal\Core\Extension\Extension[] $extensions_data */ + // $extensions_data = system_rebuild_module_data(); + // system_rebuild_module_data() is deprecated in D8 and removed in D9 + // https://www.drupal.org/project/drupal/issues/2926068 + $extensions_rset = \Drupal::service('extension.list.module')->reset(); + $extensions_data = \Drupal::service('extension.list.module')->getList(); + } + + foreach ($extensions_data as $name => $extension_data) { + $package = (object) $extension_data->info; + + if ($type == 'module') { + $package->filename = \Drupal::service('extension.list.module')->getPathname($name); + } + elseif ($type == 'theme') { + $package->filename = \Drupal::service('extension.list.theme')->getPathname($name); + } + + $frags = explode("/", $package->filename); + // Flag site-specific packages. + if ($frags[0] == 'sites' && $frags[1] != 'all') { + $package->platform = -1; + } + $package->status = $extension_data->status; + $package->filename = realpath($package->filename); + + if ($type == 'module') { + if (drush_drupal_major_version() <= 9) { + $package->schema_version = drupal_get_installed_schema_version($name); + } + else { + $package->schema_version = \Drupal::service('update.update_hook_registry')->getInstalledVersion($name); + } + + if(!file_exists($package->filename)) { + drush_log(dt("@name.info.yml not found.", array("@name" => $name)), 'notice'); + continue; + } + else { + $info = Symfony\Component\Yaml\Yaml::parse(file_get_contents($package->filename)); + // Skip hidden modules + if (isset($info['hidden']) && $info['hidden'] != FALSE) { + continue; + } + // The 'drupal_get_filename()' function is returning at least one profile as a module + // (profile 'standard'). Make sure this is really a module. If not, skip it. + if (isset($info['type']) && $info['type'] != 'module') { + continue; + } + } + } + + $packages[$name] = $package; + } + + return $packages; +} + +/** + * Find available profiles on this platform. + */ +function _provision_find_profiles() { + $profile_dirs = array('./core/profiles', './profiles'); + + $profiles = array(); + foreach($profile_dirs as $profile_dir) { + if (!is_dir($profile_dir)) { + drush_log(dt("Cannot find profiles directory %dir", array('%dir' => $profile_dir)), 'error'); + return FALSE; + } + + $info_files = drush_scan_directory($profile_dir, "/\.info.yml$/"); + foreach ($info_files as $path => $info_file) { + $path = realpath($path); + $info = Symfony\Component\Yaml\Yaml::parse(file_get_contents($path)); + if ($info['type'] == 'profile' && (!isset($info['hidden']) || !$info['hidden'])) { + $profile = new stdClass(); + $profile->name = $info['name']; + $profile->info = $info; + $profile->filename = $path; + $profile->path = dirname($path); + $profile->info['languages'] = _provision_find_profile_languages($profile->path); + + $profiles[basename($profile->path)] = $profile; + drush_log(dt('Found install profile %name', array('%name' => $profile->name)), 'info'); + } + } + } + return $profiles; +} + +/** + * Retrieve a list of paths to search in a certain scope + */ +function _provision_drupal_search_paths($scope, $key = '', $type = 'modules') { + $searchpaths = array(); + $drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT'); + switch ($scope) { + case 'base': + $searchpaths[] = sprintf("%s/%s", $drupal_root, $type); + $searchpaths[] = sprintf("%s/core/%s", $drupal_root, $type); + $searchpaths[] = sprintf("%s/sites/all/%s", $drupal_root, $type); + break; + case 'profiles': + $profiles = _provision_find_profiles(); + if ($key) { + if (isset($profiles[$key])) { + // Find $type within this single profile. + $searchpaths[] = sprintf("%s/%s", $profiles[$key]->path, $type); + } + } + else { + // Find $type within all profiles. + foreach ($profiles as $profile) { + $searchpaths[] = sprintf("%s/%s", $profile->path, $type); + } + } + break; + default: + if ($key) { + $searchpaths[] = sprintf("%s/%s/%s/%s", $drupal_root, $scope, $key, $type); + } + break; + + } + return $searchpaths; +} +