? 227947-redirect.patch
? 615258-path-source.patch
? 615294-enforce.patch
? 617312-user.patch
? test.patch
Index: API.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/domain/API.php,v
retrieving revision 1.49
diff -u -p -r1.49 API.php
--- API.php	24 Oct 2009 22:11:26 -0000	1.49
+++ API.php	31 Oct 2009 17:21:01 -0000
@@ -334,6 +334,42 @@ function hook_domainwarnings() {
 }
 
 /**
+ * Allows modules to specify the target link for a node or other Drupal object.
+ *
+ * @param &$source
+ *   The domain array from domain_get_node_match(), passed by reference.
+ * @param $nid
+ *   The node id.
+ * @return
+ *   No return value; modify $source by reference.
+ */
+function hook_domain_source_alter(&$source, $nid) {
+  // Taken from the Domain Source module
+  $source = domain_source_lookup($nid);
+}
+
+/**
+ * Allows modules to specify the target link for a Drupal path.
+ *
+ * This hook is split from hook_domain_source_alter() for performance.
+ *
+ * @param &$source
+ *   The domain array from domain_get_node_match(), passed by reference.
+ * @param $nid
+ *   The identifier of the obect being rewritten. For nodes, this is the node id.
+ *   In other instances, we may pass a $path string or other variable.
+ * @return
+ *   No return value; modify $source by reference.
+ */
+function hook_domain_source_path_alter(&$source, $path) {
+  // Always make admin links go to the primary domain.
+  $base = arg(0, $path);
+  if ($base == 'admin') {
+    $source = domain_default();
+  }
+}
+
+/**
  * Allows modules to add additional form elements for saving as domain-specific
  * settings.
  *
Index: domain.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/domain/domain.module,v
retrieving revision 1.130
diff -u -p -r1.130 domain.module
--- domain.module	27 Oct 2009 13:17:55 -0000	1.130
+++ domain.module	31 Oct 2009 17:21:05 -0000
@@ -305,10 +305,8 @@ function domain_block($op = 'list', $del
             if (!empty($this_node->subdomains)) {
               $output .= theme('item_list', $this_node->subdomains, t('Assigned domains'));
             }
-            if (isset($this_node->domain_source)) {
-              $this_domain = domain_lookup($this_node->domain_source);
-              $output .= theme('item_list', array($this_domain['sitename']), t('Source domain'));
-            }
+            $this_domain = domain_get_node_match($this_node->nid);
+            $output .= theme('item_list', array($this_domain['sitename']), t('Source domain'));
             if (empty($output)) {
               $output = t('This node is not assigned to a domain.');
             }
@@ -1145,6 +1143,45 @@ function domain_nodeapi(&$node, $op, $a3
 }
 
 /**
+ * Get the best matching domain for a node link.
+ *
+ * @param $nid
+ *   The node id.
+ * @return
+ *   The domain array for the best matching domain for links to this node.
+ */
+function domain_get_node_match($nid) {
+  static $domain = array();
+  if (isset($domain[$nid])) {
+    return $domain[$nid];
+  }
+  // Load the domain data for this node -- but only take the first match.
+  $id = db_result(db_query_range("SELECT gid FROM {domain_access} WHERE nid = %d AND realm = '%s' ORDER BY gid", $nid, 'domain_id', 0, 1));
+  $source = domain_lookup($id);
+  drupal_alter('domain_source', $source, $nid);
+  $domain[$nid] = $source;
+  return $source;
+}
+
+/**
+ * Allow the lookup of path rewrites.
+ *
+ * Note that unlinke domain_get_node_match(), this function assumes
+ * that all links will be written to the current domain.
+ *
+ * @param $path
+ *   The link path.
+ * @return
+ *   The domain array for the best matching domain for links to this node.
+ */
+function domain_get_path_match($path) {
+  global $_domain;
+  $source = $_domain;
+  drupal_alter('domain_source_path', $source, $path);
+  return $source;
+}
+
+/**
  * Get the domains for a node.
  *
  * @param $nid
@@ -1838,24 +1875,24 @@ function domain_invalid_domain_requested
   }
   // Try to find the proper redirect for a node.
   $path = "node/$node->nid";
-  if (isset($node->domain_source)) {
-    $domain = domain_lookup($node->domain_source);
-    if ($domain['valid']) {
-      $redirect = $domain;
-    }
-    else if (!empty($node->domains)) {
-      foreach ($node->domains as $domain_id) {
-        if ($domain_id == -1) {
-          $domain_id = 0;
-        }
-        $domain = domain_lookup($domain_id);
-        if ($domain['valid']) {
-          $redirect = $domain;
-          break;
-        }
+
+  $domain = domain_get_node_match($node->nid);
+  if ($domain['valid']) {
+    $redirect = $domain;
+  }
+  else if (!empty($node->domains)) {
+    foreach ($node->domains as $domain_id) {
+      if ($domain_id == -1) {
+        $domain_id = 0;
+      }
+      $domain = domain_lookup($domain_id);
+      if ($domain['valid']) {
+        $redirect = $domain;
+        break;
       }
     }
   }
+
   // If we found no node matches, just go to the home page.
   $extra = ' '. t('node page.');
   if (empty($redirect)) {
Index: settings_custom_url.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/domain/settings_custom_url.inc,v
retrieving revision 1.24
diff -u -p -r1.24 settings_custom_url.inc
--- settings_custom_url.inc	24 Oct 2009 16:18:52 -0000	1.24
+++ settings_custom_url.inc	31 Oct 2009 17:21:06 -0000
@@ -40,43 +40,63 @@ function domain_url_outbound_alter(&$pat
   }
 
   // Set static variables for the node lookups, to remove redundant queries.
-  static $domain_site, $domain, $nodepaths, $path_rewrite;
+  static $domain_site, $domain, $nodepaths, $path_rewrite, $use_source, $root, $check_nodes, $path_lookup, $path_alter;
 
   // This routine only needs to be run from certain urls or if we want to
   // force all links to go to a single domain for SEO.
   // See http://drupal.org/node/195366 for the background.
+
+  // These two functions are statically cached elsewhere.
+  // Are we viewing nodes from all sites?
   $check = domain_grant_all();
+  // Are we forcing path rewrites?
   $seo = variable_get('domain_seo', 0);
-  // If using Domain Source, we force links to a specific domain.
-  $use_source = function_exists('domain_source_lookup');
-
-  if ($check || $seo || $use_source) {
-    // Check to see if this is a node or comment link and set $nid accordingly.
-    // We static the $nid results to make this more efficient.
-    $pattern = explode('/', $original_path);
+  // Check for source rewrites.
+  if (!isset($use_source)) {
+    $use_source = (bool) count(module_implements('domain_source_alter'));
+  }
+  // Querying for nodepaths is expensive, so only do it if needed.
+  if (!isset($check_nodes)) {
+    $check_nodes = $check || $seo || $use_source;
+  }
+  // Check for path rewrites.
+  if (!isset($path_alter)) {
+    $path_alter = (bool) count(module_implements('domain_source_path_alter'));
+  }
+  // Get the root url.
+  if (!isset($root)) {
+    $root = domain_lookup(variable_get('domain_default_source', 0));
+  }
 
-    // Advanced pattern matching, we find the node id based on token %n in the path string.
-    if (!isset($nodepaths)) {
-      $pathdata = variable_get('domain_paths', "node/%n\r\nnode/%n/edit\r\ncomment/reply/%n\r\nnode/add/book/parent/%n\r\nbook/export/html/%n\r\nnode/%n/outline");
-      $path_match = preg_replace('/(\r\n?|\n)/', '|', $pathdata);
-      $nodepaths = explode("|", $path_match);
-    }
+  // Now run the path rewrite sequence, if necessary.
+  if ($check_nodes || $path_alter) {
     $nid = FALSE;
-    foreach ($nodepaths as $match) {
-      $match_array = explode('/', $match);
-      $placeholder = array_search('%n', $match_array);
-      if (isset($pattern[$placeholder])) {
-        $match_array[$placeholder] = $pattern[$placeholder];
-        if (is_numeric($pattern[$placeholder]) && $match_array == $pattern) {
-          $nid = (int) $pattern[$placeholder];
-          break;
+    $target_domain_id = $_domain['domain_id'];
+    if ($check_nodes) {
+      // Check to see if this is a node or comment link and set $nid accordingly.
+      // We static the $nid results to make this more efficient.
+      $pattern = explode('/', $original_path);
+  
+      // Advanced pattern matching, we find the node id based on token %n in the path string.
+      if (!isset($nodepaths)) {
+        $pathdata = variable_get('domain_paths', "node/%n\r\nnode/%n/edit\r\ncomment/reply/%n\r\nnode/add/book/parent/%n\r\nbook/export/html/%n\r\nnode/%n/outline");
+        $path_match = preg_replace('/(\r\n?|\n)/', '|', $pathdata);
+        $nodepaths = explode("|", $path_match);
+      }
+      foreach ($nodepaths as $match) {
+        $match_array = explode('/', $match);
+        $placeholder = array_search('%n', $match_array);
+        if (isset($pattern[$placeholder])) {
+          $match_array[$placeholder] = $pattern[$placeholder];
+          if (is_numeric($pattern[$placeholder]) && $match_array == $pattern) {
+            $nid = (int) $pattern[$placeholder];
+            break;
+          }
         }
       }
     }
-    $target_domain_id = $_domain['domain_id'];
     // This path has matched a node id, so it may need to be rewritten.
-    if ($nid) {
-      $root = domain_lookup(variable_get('domain_default_source', 0));
+    if (!empty($nid)) {
       // Remove redundancy from the domain_site check.
       if (!isset($domain_site[$nid])) {
         // If this check works, we don't need to rewrite the path unless SEO rules demand it.
@@ -85,16 +105,7 @@ function domain_url_outbound_alter(&$pat
       if (!$domain_site[$nid] || $use_source) {
         // Remove rendundancy from the domain_id check.
         if (!isset($domain[$nid])) {
-          // The Domain Source module is optional, and allows nodes to be assigned to specific domains for the
-          // purpose of this check.
-          if ($use_source) {
-            $domain[$nid] = domain_source_lookup($nid);
-          }
-          else {
-            // Load the domain data for this node -- but only take the first match.
-            $id = db_result(db_query_range("SELECT gid FROM {domain_access} WHERE nid = %d AND realm = '%s' ORDER BY gid", $nid, 'domain_id', 0, 1));
-            $domain[$nid] = domain_lookup($id);
-          }
+          $domain[$nid] = domain_get_node_match($nid);
         }
         // Can we and do we need to rewrite this path?
         if ($domain[$nid] != -1 && $domain[$nid]['domain_id'] != $_domain['domain_id']) {
@@ -117,6 +128,21 @@ function domain_url_outbound_alter(&$pat
         $target_domain_id = $root['domain_id'];
       }
     }
+    // Hook for non-node paths.
+    else if (!empty($path_alter)) {
+      // Must use md5 here, to prevent array keys from breaking.
+      $name = md5($path);
+      if (!isset($path_lookup[$name])) {
+        $path_lookup[$name] = domain_get_path_match($path);
+      }
+      if ($path_lookup[$name] != $_domain) {
+        $options['absolute'] = TRUE;
+        // In this case, the $base_url cannot have a trailing slash
+        $options['base_url'] = rtrim($path_lookup[$name]['path'], '/');
+        $target_domain_id = $path_lookup[$name]['domain_id'];
+        // TODO: merge this code with the above for cleanup.
+      }
+    }
     // We may have to implement hook_domainpath().
     if (!isset($path_rewrite)) {
       $path_rewrite = count(_domain_path_modules());
Index: domain_source/domain_source.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/domain/domain_source/domain_source.module,v
retrieving revision 1.17
diff -u -p -r1.17 domain_source.module
--- domain_source/domain_source.module	24 Oct 2009 21:02:51 -0000	1.17
+++ domain_source/domain_source.module	31 Oct 2009 17:21:06 -0000
@@ -180,7 +180,7 @@ function domain_source_nodeapi(&$node, $
       break;
     case 'load':
       if ($node->nid) {
-        $source = domain_source_lookup($node, $node->domains, $node->domain_site);
+        $source = domain_source_lookup($node->nid, $node->domains, $node->domain_site);
         $node->domain_source = $source['domain_id'];
       }
       break;
@@ -190,7 +190,7 @@ function domain_source_nodeapi(&$node, $
       // calls that are neither a teaser nor a page view.
       if ($a3 !== FALSE || $a4 !== FALSE) {
         if (variable_get('domain_debug', 0) && user_access('set domain access') && isset($node->domain_source)) {
-          $source = domain_lookup($node->domain_source);
+          $source = domain_get_node_match($node->nid);
           $extra = ' ';
           $use_active = db_result(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $node->nid));
           if (empty($use_active)) {
@@ -218,7 +218,9 @@ function domain_source_nodeapi(&$node, $
  */
 function domain_source_lookup($nid, $domains = array(), $domain_site = FALSE) {
   global $_domain;
+
   $source = db_result(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $nid));
+
   if (empty($source)) {
     $source = variable_get('domain_default_source', 0);
   }
@@ -244,6 +246,20 @@ function domain_source_lookup($nid, $dom
 }
 
 /**
+ * Implement hook_domain_source_node_alter().
+ *
+ * @param &$source
+ *   The domain array from domain_get_node_match(), passed by reference.
+ * @param $nid
+ *   The node id.
+ * @return
+ *   No return value; modify $source by reference.
+ */
+function domain_source_domain_source_alter(&$source, $nid) {
+  $source = domain_source_lookup($nid);
+}
+
+/**
  * FormAPI function that lets us update access rules.
  */
 function domain_source_update_nodes($form, &$form_state) {
