When creating a menu and entering the node id# for a node that is published to a different domain, the menu will only use the node's domain path if I am on the same subdomain as the node's domain source; otherwise it will display the URL as 'node/id#'.

Example:

I have two pages:

Page1 is only published to domain1 and its domain source is also domain1; Page1 has a domain-specific path of '/Page1'. Its node id is 10.

Page2 is only published to domain2 and its domain source is also domain2; Page2 has a domain-specific path of '/Page2'. Its node is is 20.

I have a menu that has a link to both pages, and this menu is set to display on all my domains:
Page1 link = node/10
Page2 link = node/20

When I go to domain1.mysite.com the menu will have the following links:
Page1 link = domain1.mysite.com/Page1
Page2 link = domain2.mysite.com/node/20

Similarly, when I am on domain2.mysite.com the menu will be the following:
Page1 link = domain1.mysite.com/node/10
Page2 link = domain2.mysite.com/Page2

My expected result is for the menu to always use the domain path if one is set. So, no matter what domain I am in, I would like the menu to be:
Page1 link = domain1.mysite.com/Page1
Page2 link = domain2.mysite.com/Page2

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

agentrickard’s picture

Status: Active » Postponed (maintainer needs more info)

What are you using to display the menu? The default block provided by the menu module?

fkarczeski’s picture

Status: Postponed (maintainer needs more info) » Active
FileSize
1.21 KB

Yes, I am using the default block created by the menu module.

I took a stab at trying to figure this out but I am not 100% sure if my solution affects anything else. It seems that when domain_path_lookup_path gets called the current domain id is the one passed to it, which forces the function to query the DB for paths only on that domain.

What I tried to do is to pass the source domain for the node, so that the function looks for paths on the node's source domain instead of the current one. What do you think?

agentrickard’s picture

We definitely need to look at this, but I don't think $options['entity_type'] is set reliably for node links across all contrib.

fkarczeski’s picture

Ok, so I played with this a bit more and I came up with this:

// If looking for an Entity with multiple domains, make sure to look for the path on the source domain.
if (isset($options['entity']) && isset($options['entity']->domain_source)) {
	$domain_id = $options['entity']->domain_source;
}

The idea is that if we are dealing with an entity that makes use of domain access than the domain source is required, so if both are set we use the entity's source domain to look for the domain specific path. It is possible that the domain source is "Use active domain" (id -5?), but domain_path_lookup_path already defaults the domain_id to the current domain if a 'bad id' is given.

Does this seem like a more reliable fix?

agentrickard’s picture

Status: Active » Needs work

No, because the problem is the $options['entity'] is only set if the calling code uses entity_uri(), which most modules (and lots of core) doesn't do.

There are only 12 calls to that function in ALL of core.

Links generated using l() or url() won't have this data present.

Node module, for instance, calls l() 7 times and entity_uri() once.

fkarczeski’s picture

Ah, I see!

Well, after spending some more time with the code it turns our that the problem was simpler than I originally thought.

It seems that this was the culprit:

<?php
// Let's not muck with absolute paths.
if (!empty($options['absolute'])) {
    return;
}
?>

Paths that point to a different domain have the absolute flag and therefore do not go through the domain_path_lookup_path() function.

By adding a base_url catch, which seems to be added to the options array by Domain Access, internal Drupal urls are forced to go through the lookup and their aliases are found correctly.

So in the end, this was the only change needed to make it work for me:

<?php
// Let's not muck with absolute paths.
if (!empty($options['absolute']) && !isset($options['base_url'])) {
    return;
}
?>

Is this a more correct path? ;)

agentrickard’s picture

Better, but I suspect it may conflict with language handling. See the API: https://api.drupal.org/api/drupal/includes!common.inc/function/url/7

'base_url': Only used internally, to modify the base URL when a language dependent URL requires so.

However, I don't know that there is anything we can do about that conflict.

fkarczeski’s picture

Sorry I've been a little busy this last week.

I am fairly new to Drupal so please stop me when I start speaking nonsense.

As far as I understand, the base_url is used to rewrite the URL in case we need a language specific URL. Isn't that the base part of the URL displayed before the node alias? It seems that we are not changing the base_url in any way, we are only saying that if the base_url key is set in the array then we should look up the alias for that node, since we know that it is an internal URL.

If that is the case, would that cause any conflicts? Or am I misunderstanding the way this works?

agentrickard’s picture

Right, I think this is OK. We do it in Domain Access now. The only potential issue is with language, but the workarounds to avoid that collision are pretty well established.

fkarczeski’s picture

OK.

I have another question and I am not sure if this is a Domain Path or Domain Access thing.

Going back to the example in the beginning of this thread, I noticed that if I am in domain1.mysite.com menu links that point to nodes published to a different sub domain will not be displayed in the menu at all (Unless I am logged in as admin which will bypass permission checking).

The question is, is that by design or is that a bug? I am more than willing to open another issue and explain my use case and the problems I am running into, but I figured I would check if that was working as intended and if that is a Domain Access or a Domain Path issue (I am guessing Domain Access).

agentrickard’s picture

By design. That's how node access works. If you want to ensure the links are there on all domains, you have to enter the complete URL.

fkarczeski’s picture

Right, and that is what we have been doing with our links so far. But we are in the process of moving a very large static site into Drupal and our URLs are changing, so every time we update a URL we have to go through all the menus and update the links that have the complete URL.

Our hope was that by entering the internal node/id path, the menu item would be linked to that particular node and not its URL, so if the URL eventually changed, all the menus would then be updated to point to the most accurate URL.

Any ideas on how we can go about achieving something like that?