CRM-19303 - Drupal - Fix various path computations for multisite
authorTim Otten <totten@civicrm.org>
Thu, 15 Jun 2017 06:42:59 +0000 (23:42 -0700)
committerTim Otten <totten@civicrm.org>
Thu, 15 Jun 2017 08:27:09 +0000 (01:27 -0700)
A few changes:
 * Move logic out of `CRM_Utils_System_Base` to `CRM_Utils_System_DrupalBase`
   so that it's easier to read.
 * Update `[civicrm.files]`:  First, try to use `sites/{$name}/files/civicrm`.
   Otherwise, use `sites/default/files/civicrm`.
    * Note: The `$name` is parsed/validated the same way as `civicrm.config.php`.
      It takes the full HTTP_HOST and then tries various substrings.
 * Update `[civicrm.root]`:  Compare `$civicrm_root` and `cmsRootPath()`
   to determine the relative path.  Then, combine `CIVICRM_UF_BASEURL` with
   relpath.  (This is the same as WordPress.)

CRM/Utils/System/Base.php
CRM/Utils/System/DrupalBase.php

index a66fba129e948b69ddf5b2c1a4254167cac3de7f..e71f7edfa57c90913b1701ff2f6ca493fa4f01b5 100644 (file)
@@ -593,15 +593,6 @@ abstract class CRM_Utils_System_Base {
       $tempURL = str_replace("/administrator/", "/", $baseURL);
       $filesURL = $tempURL . "media/civicrm/";
     }
-    elseif ($this->is_drupal) {
-      $siteName = $config->userSystem->parseDrupalSiteName($civicrm_root);
-      if ($siteName) {
-        $filesURL = $baseURL . "sites/$siteName/files/civicrm/";
-      }
-      else {
-        $filesURL = $baseURL . "sites/default/files/civicrm/";
-      }
-    }
     elseif ($config->userFramework == 'UnitTests') {
       $filesURL = $baseURL . "sites/default/files/civicrm/";
     }
@@ -648,23 +639,6 @@ abstract class CRM_Utils_System_Base {
     elseif ($config->userFramework == 'WordPress') {
       $userFrameworkResourceURL = CIVICRM_PLUGIN_URL . "civicrm/";
     }
-    elseif ($this->is_drupal) {
-      // Drupal setting
-      // check and see if we are installed in sites/all (for D5 and above)
-      // we dont use checkURL since drupal generates an error page and throws
-      // the system for a loop on lobo's macosx box
-      // or in modules
-      $cmsPath = $config->userSystem->cmsRootPath();
-      $userFrameworkResourceURL = $baseURL . str_replace("$cmsPath/", '',
-          str_replace('\\', '/', $civicrm_root)
-        );
-
-      $siteName = $config->userSystem->parseDrupalSiteName($civicrm_root);
-      if ($siteName) {
-        $civicrmDirName = trim(basename($civicrm_root));
-        $userFrameworkResourceURL = $baseURL . "sites/$siteName/modules/$civicrmDirName/";
-      }
-    }
     else {
       $userFrameworkResourceURL = NULL;
     }
index c0ce0f49c19672d9aca3f9d0de60f319fecc3eb5..bd5740c699549366b2ecb7a82a3a3f1aa3a7a249 100644 (file)
@@ -58,6 +58,51 @@ abstract class CRM_Utils_System_DrupalBase extends CRM_Utils_System_Base {
     $this->supports_form_extensions = TRUE;
   }
 
+  /**
+   * @inheritDoc
+   */
+  public function getCiviSourceStorage() {
+    global $civicrm_root;
+
+    // Don't use $config->userFrameworkBaseURL; it has garbage on it.
+    // More generally, we shouldn't be using $config here.
+    if (!defined('CIVICRM_UF_BASEURL')) {
+      throw new RuntimeException('Undefined constant: CIVICRM_UF_BASEURL');
+    }
+
+    $cmsUrl = CIVICRM_UF_BASEURL;
+    if (CRM_Utils_System::isSSL()) {
+      $cmsUrl = str_replace('http://', 'https://', $cmsUrl);
+    }
+    $civiRelPath = CRM_Utils_File::relativize(realpath($civicrm_root), realpath($this->cmsRootPath()));
+    $civiUrl = rtrim($cmsUrl, '/') . '/' . ltrim($civiRelPath, ' /');
+    return array(
+      'url' => CRM_Utils_File::addTrailingSlash($civiUrl, '/'),
+      'path' => CRM_Utils_File::addTrailingSlash($civicrm_root),
+    );
+  }
+
+  /**
+   * @inheritdoc
+   */
+  public function getDefaultFileStorage() {
+    $config = CRM_Core_Config::singleton();
+    $baseURL = CRM_Utils_System::languageNegotiationURL($config->userFrameworkBaseURL, FALSE, TRUE);
+
+    $siteName = $this->parseDrupalSiteName('/files/civicrm');
+    if ($siteName) {
+      $filesURL = $baseURL . "sites/$siteName/files/civicrm/";
+    }
+    else {
+      $filesURL = $baseURL . "sites/default/files/civicrm/";
+    }
+
+    return array(
+      'url' => $filesURL,
+      'path' => CRM_Utils_File::baseFilePath(),
+    );
+  }
+
   /**
    * @inheritDoc
    */
@@ -546,33 +591,50 @@ abstract class CRM_Utils_System_DrupalBase extends CRM_Utils_System_Base {
   }
 
   /**
-   * Parse the name of the drupal site.
-   *
-   * @param string $civicrm_root
+   * Determine if Drupal multi-site applies to the current request -- and,
+   * specifically, determine the name of the multisite folder.
    *
+   * @param string $flagFile
+   *   Check if $flagFile exists inside the site dir.
    * @return null|string
+   *   string, e.g. `bar.example.com` if using multisite.
+   *   NULL if using the default site.
    */
-  public function parseDrupalSiteName($civicrm_root) {
-    $siteName = NULL;
-    if (strpos($civicrm_root,
-        DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR . 'all' . DIRECTORY_SEPARATOR . 'modules'
-      ) === FALSE
-    ) {
-      $startPos = strpos($civicrm_root,
-        DIRECTORY_SEPARATOR . 'sites' . DIRECTORY_SEPARATOR
-      );
-      $endPos = strpos($civicrm_root,
-        DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR
-      );
-      if ($startPos && $endPos) {
-        // if component is in sites/SITENAME/modules
-        $siteName = substr($civicrm_root,
-          $startPos + 7,
-          $endPos - $startPos - 7
-        );
+  private function parseDrupalSiteName($flagFile = '') {
+    $phpSelf = array_key_exists('PHP_SELF', $_SERVER) ? $_SERVER['PHP_SELF'] : '';
+    $httpHost = array_key_exists('HTTP_HOST', $_SERVER) ? $_SERVER['HTTP_HOST'] : '';
+    if (empty($httpHost)) {
+      $httpHost = parse_url(CIVICRM_UF_BASEURL, PHP_URL_HOST);
+      if (parse_url(CIVICRM_UF_BASEURL, PHP_URL_PORT)) {
+        $httpHost .= ':' . parse_url(CIVICRM_UF_BASEURL, PHP_URL_PORT);
+      }
+    }
+
+    $confdir = $this->cmsRootPath() . '/sites';
+
+    if (file_exists($confdir . "/sites.php")) {
+      include $confdir . "/sites.php";
+    }
+    else {
+      $sites = array();
+    }
+
+    $uri = explode('/', $phpSelf);
+    $server = explode('.', implode('.', array_reverse(explode(':', rtrim($httpHost, '.')))));
+    for ($i = count($uri) - 1; $i > 0; $i--) {
+      for ($j = count($server); $j > 0; $j--) {
+        $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
+        if (file_exists("$confdir/$dir" . $flagFile)) {
+          \Civi::$statics[__CLASS__]['drupalSiteName'] = $dir;
+          return \Civi::$statics[__CLASS__]['drupalSiteName'];
+        }
+        // check for alias
+        if (isset($sites[$dir]) && file_exists("$confdir/{$sites[$dir]}" . $flagFile)) {
+          \Civi::$statics[__CLASS__]['drupalSiteName'] = $sites[$dir];
+          return \Civi::$statics[__CLASS__]['drupalSiteName'];
+        }
       }
     }
-    return $siteName;
   }
 
 }