From 84c4258e9de8cc0bb7589cc2450b7385e48e7d89 Mon Sep 17 00:00:00 2001
From: Yash Rode <57207-yash.rode@users.noreply.drupalcode.org>
Date: Mon, 22 May 2023 19:40:44 +0000
Subject: [PATCH] Issue #3310729 by yash.rode, phenaproxima, Wim Leers, tedbow,
 TravisCarden: ComposerValidator should check if proc_open() is available

---
 dictionary.txt                                      |  1 +
 package_manager/package_manager.module              |  3 +++
 package_manager/src/Validator/ComposerValidator.php | 13 +++++++++++++
 3 files changed, 17 insertions(+)

diff --git a/dictionary.txt b/dictionary.txt
index ad242b1dbe..0ccd8f9ed6 100644
--- a/dictionary.txt
+++ b/dictionary.txt
@@ -11,3 +11,4 @@ filedate
 unshallow
 hhvm
 tmpdir
+proc_open
diff --git a/package_manager/package_manager.module b/package_manager/package_manager.module
index 55ca66e5d1..4847f83dbc 100644
--- a/package_manager/package_manager.module
+++ b/package_manager/package_manager.module
@@ -51,6 +51,9 @@ function package_manager_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<h3 id="package-manager-faq">' . t('FAQ') . '</h3>';
       $output .= '<h4 id="package-manager-composer-related-faq">' . t('FAQs related to Composer') . '</h4>';
       $output .= '<ul>';
+      $output .= '  <li>' . t('What if it says the <code>proc_open()</code> function is disabled on your PHP installation?');
+      $output .= '    <p>' . t('Ask your system administrator to remove <code>proc_open()</code> from the <a href=":url">disable_functions</a> setting in <code>php.ini</code>.', [':url' => 'https://www.php.net/manual/en/ini.core.php#ini.disable-functions']) . '</p>';
+      $output .= '  </li>';
       $output .= '  <li>' . t('What if it says the <code>composer</code> executable cannot be found?');
       $output .= '    <p>' . t("If the <code>composer</code> executable's path cannot be automatically determined, it can be explicitly set by adding the following line to <code>settings.php</code>:") . '</p>';
       $output .= "    <pre><code>\$config['package_manager.settings']['executables']['composer'] = '/full/path/to/composer.phar';</code></pre>";
diff --git a/package_manager/src/Validator/ComposerValidator.php b/package_manager/src/Validator/ComposerValidator.php
index e4aa6ced61..bb686a457d 100644
--- a/package_manager/src/Validator/ComposerValidator.php
+++ b/package_manager/src/Validator/ComposerValidator.php
@@ -46,6 +46,19 @@ final class ComposerValidator implements EventSubscriberInterface {
    * Validates that the Composer executable is the correct version.
    */
   public function validate(PreOperationStageEvent $event): void {
+    // If we can't stat processes, there's nothing else we can possibly do here.
+    // @see \Symfony\Component\Process\Process::__construct()
+    if (!\function_exists('proc_open')) {
+      $message = $this->t('Composer cannot be used because the <code>proc_open()</code> function is disabled.');
+      if ($this->moduleHandler->moduleExists('help')) {
+        $message = $this->t('@message See <a href=":package-manager-help">the help page</a> for information on how to resolve the problem.', [
+          ':package-manager-help' => self::getHelpUrl('package-manager-composer-related-faq'),
+        ]);
+      }
+      $event->addError([$message]);
+      return;
+    }
+
     $messages = [];
     $dir = $event instanceof PreApplyEvent
       ? $event->stage->getStageDirectory()
-- 
GitLab