Make civicrm-setup work with unix-socket as database connection
authorlasse <lasse@dev-lasse>
Tue, 3 Nov 2020 09:42:35 +0000 (10:42 +0100)
committerlasse <lasse@dev-lasse>
Tue, 3 Nov 2020 09:42:35 +0000 (10:42 +0100)
Civi/Install/Requirements.php
setup/plugins/blocks/advanced.tpl.php
setup/plugins/checkRequirements/CoreRequirementsAdapter.civi-setup.php
setup/plugins/init/Backdrop.civi-setup.php
setup/plugins/init/Drupal.civi-setup.php
setup/plugins/init/Drupal8.civi-setup.php
setup/plugins/init/WordPress.civi-setup.php
setup/src/Setup/DbUtil.php

index 7d30855076b79c0380a1d6746f7deece5ce0e2b0..813b2f6f19391bc9296f0c79276bccba02877f24 100644 (file)
@@ -133,7 +133,7 @@ class Requirements {
       $host = $db_config['server'];
     }
     if (empty($db_config['ssl_params'])) {
-      $conn = @mysqli_connect($host, $db_config['username'], $db_config['password'], $db_config['database'], !empty($db_config['port']) ? $db_config['port'] : NULL);
+      $conn = @mysqli_connect($host, $db_config['username'], $db_config['password'], $db_config['database'], !empty($db_config['port']) ? $db_config['port'] : NULL, $db_config['socket'] ?? NULL);
     }
     else {
       $conn = NULL;
@@ -146,7 +146,7 @@ class Requirements {
         $db_config['ssl_params']['capath'] ?? NULL,
         $db_config['ssl_params']['cipher'] ?? NULL
       );
-      if (@mysqli_real_connect($init, $host, $db_config['username'], $db_config['password'], $db_config['database'], (!empty($db_config['port']) ? $db_config['port'] : NULL), NULL, MYSQLI_CLIENT_SSL)) {
+      if (@mysqli_real_connect($init, $host, $db_config['username'], $db_config['password'], $db_config['database'], (!empty($db_config['port']) ? $db_config['port'] : NULL), $db_config['socket'] ?? NULL, MYSQLI_CLIENT_SSL)) {
         $conn = $init;
       }
     }
index abfc0392604922e9ef9663e0eed42870d09358e0..52665827de2d3e4af241825552df2a4a2009705b 100644 (file)
@@ -39,6 +39,7 @@ endif; ?>
           <p><?php echo ts('By default, CiviCRM uses the same database as your website. You may install on a separate database if you need more fine-grained control over permissions, replication, hardware capacity, etc.'); ?></p>
           <p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@localhost/civicrm')); ?></p>
           <p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@127.0.0.1:3306/otherdb')); ?></p>
+          <p><?php echo ts('<strong>Example</strong>: <code>%1</code>', array(1 => 'mysql://admin:secret@unix(/var/lib/mysql/mysql.sock)/otherdb')); ?></p>
         </div>
       </td>
     </tr>
index 4e4e051f31a759dafe229fea743fba5dedf557de..a4fc784f90634cffed522431ebb16e8def9f64c7 100644 (file)
@@ -22,10 +22,11 @@ if (!defined('CIVI_SETUP')) {
     _corereqadapter_addMessages($e, 'system', $systemMsgs);
 
     \Civi\Setup::log()->info(sprintf('[%s] Run Requirements::checkDatabase()', basename(__FILE__)));
-    list ($host, $port) = \Civi\Setup\DbUtil::decodeHostPort($model->db['server']);
+    list ($host, $port, $socket) = \Civi\Setup\DbUtil::decodeHostPort($model->db['server']);
     $dbMsgs = $r->checkDatabase(array(
       'host' => $host,
       'port' => $port,
+      'socket' => $socket,
       'username' => $model->db['username'],
       'password' => $model->db['password'],
       'database' => $model->db['database'],
index 2320b88dace623244d904118b1d3147093f953bc..4805d998f46b6c8e3e411a3989207a4217b668cb 100644 (file)
@@ -40,6 +40,7 @@ if (!defined('CIVI_SETUP')) {
     // Compute DSN.
     global $databases;
     $ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($databases['default']['default']);
+    // @todo Does Backdrop support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
     $model->db = $model->cmsDb = array(
       'server' => \Civi\Setup\DbUtil::encodeHostPort($databases['default']['default']['host'], $databases['default']['default']['port'] ?: NULL),
       'username' => $databases['default']['default']['username'],
index d57ff432c21cfa4f80be5129073b00d7e4a9dceb..c65d12f220ff445e04d0dce18b27240fdf843a73 100644 (file)
@@ -38,6 +38,7 @@ if (!defined('CIVI_SETUP')) {
     // Compute DSN.
     global $databases;
     $ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($databases['default']['default']);
+    // @todo Does Drupal support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
     $model->db = $model->cmsDb = array(
       'server' => \Civi\Setup\DbUtil::encodeHostPort($databases['default']['default']['host'], $databases['default']['default']['port'] ?: NULL),
       'username' => $databases['default']['default']['username'],
index 3522907e0fd0edc520ed72fc6ed283b92f249d6b..98586c695e0f89d5ca0eab75fbe6cc42201f30a9 100644 (file)
@@ -41,6 +41,7 @@ if (!defined('CIVI_SETUP')) {
     // Compute DSN.
     $connectionOptions = \Drupal::database()->getConnectionOptions();
     $ssl_params = \Civi\Setup\DrupalUtil::guessSslParams($connectionOptions);
+    // @todo Does Drupal support unixsocket in config? Set 'server' => 'unix(/path/to/socket.sock)'
     $model->db = $model->cmsDb = array(
       'server' => \Civi\Setup\DbUtil::encodeHostPort($connectionOptions['host'], $connectionOptions['port'] ?: NULL),
       'username' => $connectionOptions['username'],
index 21294a6e2a0d83eaf6177d7bf6589166a0f120e7..f273231d0c8e32f0eb60106b27d432a34c8e90c9 100644 (file)
@@ -50,8 +50,9 @@ if (!defined('CIVI_SETUP')) {
     $model->templateCompilePath = implode(DIRECTORY_SEPARATOR, [$uploadDir['basedir'], 'civicrm', 'templates_c']);
 
     // Compute DSN.
+    list(/*$host*/, /*$port*/, $socket) = Civi\Setup\DbUtil::decodeHostPort(DB_HOST);
     $model->db = $model->cmsDb = array(
-      'server' => DB_HOST,
+      'server' => $socket ? sprintf('unix(%s)', $socket) : DB_HOST,
       'username' => DB_USER,
       'password' => DB_PASSWORD,
       'database' => DB_NAME,
index 87849057c6d896932e818dc87d7a01a38f104f90..6c35dbca87bb814f4e664181725039cd5db1bd3d 100644 (file)
@@ -11,11 +11,27 @@ class DbUtil {
    */
   public static function parseDsn($dsn) {
     $parsed = parse_url($dsn);
+    // parse_url parses 'mysql://admin:secret@unix(/var/lib/mysql/mysql.sock)/otherdb' like:
+    // [
+    //   'host'   => 'unix(',
+    //   'path'   => '/var/lib/mysql/mysql.sock)/otherdb',
+    //   ...
+    // ]
+    if ($parsed['host'] == 'unix(') {
+       preg_match('/(unix\(.*\))(\/(.+)?)?$/', $dsn, $matches);
+       $server = $matches[1];
+       $database = $matches[3] ?? NULL;
+    }
+    else {
+      $server = self::encodeHostPort($parsed['host'], $parsed['port'] ?? NULL);
+      $database = $parsed['path'] ? ltrim($parsed['path'], '/') : NULL;
+    }
+
     return array(
-      'server' => self::encodeHostPort($parsed['host'], $parsed['port'] ?? NULL),
+      'server' => $server,
       'username' => $parsed['user'] ?: NULL,
       'password' => $parsed['pass'] ?: NULL,
-      'database' => $parsed['path'] ? ltrim($parsed['path'], '/') : NULL,
+      'database' => $database,
       'ssl_params' => self::parseSSL($parsed['query'] ?? NULL),
     );
   }
@@ -41,9 +57,9 @@ class DbUtil {
    * @return \mysqli
    */
   public static function softConnect($db) {
-    list($host, $port) = self::decodeHostPort($db['server']);
+    list($host, $port, $socket) = self::decodeHostPort($db['server']);
     if (empty($db['ssl_params'])) {
-      $conn = @mysqli_connect($host, $db['username'], $db['password'], $db['database'], $port);
+      $conn = @mysqli_connect($host, $db['username'], $db['password'], $db['database'], $port, $socket);
     }
     else {
       $conn = NULL;
@@ -56,8 +72,7 @@ class DbUtil {
         $db['ssl_params']['capath'] ?? NULL,
         $db['ssl_params']['cipher'] ?? NULL
       );
-      // @todo socket parameter, but if you're using sockets do you need SSL?
-      if (@mysqli_real_connect($init, $host, $db['username'], $db['password'], $db['database'], $port, NULL, MYSQLI_CLIENT_SSL)) {
+      if (@mysqli_real_connect($init, $host, $db['username'], $db['password'], $db['database'], $port, $socket, MYSQLI_CLIENT_SSL)) {
         $conn = $init;
       }
     }
@@ -84,21 +99,34 @@ class DbUtil {
    *   Ex: '127.0.0.1:123'
    *   Ex: '[1234:abcd]'
    *   Ex: '[1234:abcd]:123'
+   *   Ex: 'localhost:/path/to/socket.sock
+   *   Ex: 'unix(/path/to/socket.sock)
    * @return array
-   *   Combination: [0 => string $host, 1 => numeric|NULL $port].
-   *   Ex: ['localhost', NULL].
-   *   Ex: ['127.0.0.1', 3306]
+   *   Combination: [0 => string $host, 1 => numeric|NULL $port, 2 => string|NULL].
+   *   Ex: ['localhost', NULL, NULL].
+   *   Ex: ['127.0.0.1', 3306, NULL]
    */
   public static function decodeHostPort($host) {
-    $hostParts = explode(':', $host);
-    if (count($hostParts) > 1 && strrpos($host, ']') !== strlen($host) - 1) {
-      $port = array_pop($hostParts);
-      $host = implode(':', $hostParts);
+    $port = NULL;
+    $socket = NULL;
+    if(preg_match('/^unix\(([^)]+)\)$/', $host, $matches) === 1) {
+       $host = 'localhost';
+       $socket = $matches[1];
     }
     else {
-      $port = NULL;
+      $hostParts = explode(':', $host);
+      if (count($hostParts) > 1 && strrpos($host, ']') !== strlen($host) - 1) {
+        $portOrSocket = array_pop($hostParts);
+        if (substr($portOrSocket, /*start*/ 0, /*length*/ 1) == '/') {
+          $socket = $portOrSocket;
+        }
+        else {
+          $port = $portOrSocket;
+        }
+        $host = implode(':', $hostParts);
+      }
     }
-    return array($host, $port);
+    return array($host, $port, $socket);
   }
 
   /**