diff --git a/README.txt b/README.txt index 9092d68..df2c6a9 100644 --- a/README.txt +++ b/README.txt @@ -1,13 +1,27 @@ -Domain Meta Allows users to add domain specific keywords and descriptions in addition to global meta tags and page specific meta tags. +Domain Meta allows users to customize meta tag information provided via the +NodeWords module on a per-domain basis. The module allows custom keywords and +descriptions to be prepended to the global Nodewords meta-tags for each domain +configured with Domain Access. INSTALLATION AND USAGE ---------------------- 1. Enable the module normally -2. Users with 'administer domains' permissions will be able to add and update domain specific keywords and description by navigating to -Site building -> Domains -> Meta tags for non-default domains and Site building -> Domain settings for the default domain. Batch operations for +2. Users with 'administer domains' permissions will be able to add and update +domain-specific keywords and description by navigating to Site building > Domain +settings for the primary domain, and Site building > Domains > Meta tags for all +secondary domains configured with Domain Access module. Batch operations for both are provided. -3. When domain specific keywords and description are set they are appended to the collection of meta tags defined by other modules for each page. -Typically this means keywords etc defined for a node/view plus global setting value. \ No newline at end of file +3. When domain-specific keywords and description are configured, they are +prepended to the collection of meta tags defined by other modules for each page. +Typically this means keywords etc defined for a node/view plus global setting +value. + +4. Domain Meta module creates canonical URL tags that refer to a single source, +usually the primary domain for all page requests. To enable this feature, ensure +that the 'Canonical URL' is enabled in the NodeWords module settings and then go +to Site building > Domain settings, and enable the option that says 'Correct +Canonical URLs for content shared between multiple domains.' (This is enabled by +default). \ No newline at end of file diff --git a/domain_meta.module b/domain_meta.module index 2800e9d..ac5f294 100644 --- a/domain_meta.module +++ b/domain_meta.module @@ -47,11 +47,13 @@ function domain_meta_menu() { */ function domain_meta_nodewords_tags_alter($tags, $options) { global $conf; + $domain_settings = array( 'keywords' => $conf['domain_meta_keywords'], 'description' => $conf['domain_meta_description'], ); $domain_tags = $tags; + foreach ($tags as $name => $content) { if (array_key_exists($name, $domain_settings)) { if (!empty($domain_settings[$name])) { @@ -64,10 +66,133 @@ function domain_meta_nodewords_tags_alter($tags, $options) { if (count($domain_settings) > 0) { $domain_tags = array_merge($domain_tags, $domain_settings); } + + if (!empty($domain_tags['canonical']) && variable_get('domain_meta_canonical', 1)) { + $canonical_url = FALSE; + switch ($options['type']) { + + // Nodes may have different canonical URLs depending on the domain access configuration. + case NODEWORDS_TYPE_NODE: + $canonical_url = domain_meta_alter_node_canonical_url($domain_tags, $options); + break; + + // Front page and error page requests are currently ignored. + case NODEWORDS_TYPE_FRONTPAGE: + case NODEWORDS_TYPE_ERRORPAGE: + break; + + // Catch-all for regular non-node page requests should all point to the + // primary domain. Special cases for user pages, vocabulary, and taxonomy + // term pages are yet to be created due to lack of information about how + // they should be handled for domain access. They are currently lumped in + // with the default behavior to simply point to the primary domain. + case NODEWORDS_TYPE_PAGE: + default: + $canonical_url = domain_meta_alter_page_canonical_url($domain_tags, $options); + break; + } + if (!empty($canonical_url)) { + $domain_tags['canonical'] = $canonical_url; + } + } $tags = $domain_tags; } /** + * All regular page requests made from secondary domains should specify the + * primary domain as the Canonical URL to avoid penalties for duplicate content. + */ +function domain_meta_alter_page_canonical_url($tags, $options) { + // Only work on requests to pages that are not on the primary domain. + $default = domain_default(); + $domain = domain_get_domain(); + + if ($domain['domain_id'] != $default['domain_id']) { + // Replace the current domain with the default domain in the canonical URL. + if (strpos($tags['canonical'], $domain['path']) === 0) { + return str_replace($domain['path'], $default['path'], $tags['canonical']); + } + // Otherwise (assuming someone hasn't already specified the URI by hand) + // prepend the default domain to the URL for relative paths. This section + // will need further attention depending on the implementation in + // http://drupal.org/node/1244132 + elseif (strpos($tags['canonical'], $default['path']) === FALSE) { + return $default['path'] . $tags['canonical']; + } + } +} + +/** + * Determine the appropriate canonical URL for a given node, based on the Domain + * Access configuration for the node. + */ +function domain_meta_alter_node_canonical_url($tags, $options) { + // Automatic Canonical URL calculations are limited to nodes that are sent + // to all domains or nodes that are sent to multiple domains. + $domains = domain_get_node_domains($options['id']); + $current_domain = domain_get_domain(); + + // If the node is sent to all domains or more than one domain then the + // canonical URL should point to either the domain specified in Domain Source + // or for sitewide SEO rewrites or default to the primary domain. + // Domain Source node rewrites override SEO redirects if set. + $use_source = (bool) count(module_implements('domain_source_alter')); + if (!empty($domains['domain_site'])) { + $seo = $use_source ? FALSE : variable_get('domain_seo', 0); + // Domain Source specific rewrites (node based). + if ($use_source) { + $domain = domain_get_node_match($options['id']); + } + elseif ($seo) { + // Domain module SEO specific rewrites (site based). + $domain = domain_lookup(variable_get('domain_default_source', 0)); + if ($domain < 0) { + $domain = $current_domain; + } + } + else { + $domain = domain_default(); + } + } + else { + // It is possible that the list of valid domains for the given node + // specifically excludes the primary domain defined by Domain Access. In + // this case, there is no real way of determining which of them should be + // the canonical URL other, than using the first in the list. + $first_domain_id = reset($domains['domain_id']); + + // When the node is sent to multiple domains, or if the node is currently + // being viewed from a domain that is not in the list of valid domains, a + // canonical URL is created that points to the first valid listed domain. + // The latter case is a situation that may occur when an administrator has + // permission to view a node from any domain. + if (count($domains['domain_id']) > 1) { + // Domain Source specific rewrites (node based). + if ($use_source) { + $domain = domain_get_node_match($options['id']); + } + // No domain is set, first domain is not the current domain. + elseif ($first_domain_id != $current_domain['domain_id']) { + // Because of the way the list of domains is built, the primary domain, + // if selected, will be first. This special case is denoted with a value + // of -1 for the domain id. + if ($first_domain_id < 0) { + $domain = domain_default(); + } + else { + $domain = domain_lookup($first_domain_id); + } + } + } + } + // Create the nodewords Canonical URL based on the selected $domain's url, + // plus the local path. + if (isset($domain)) { + return $domain['path'] . trim(url('node/'. $options['id']), '/'); + } +} + +/** * Implements hook_domainlinks() */ function domain_meta_domainlinks($domain) { @@ -85,6 +210,14 @@ function domain_meta_domainlinks($domain) { * Implement hook_domainform() */ function domain_meta_domainform(&$form) { + // Add an advanced setting (enabled by default) for canonical URL integration. + $form['domain_advanced']['domain_meta_canonical'] = array( + '#type' => 'checkbox', + '#title' => 'Correct Canonical URLs for content shared between multiple domains.', + '#default_value' => variable_get('domain_meta_canonical', 1), + '#description' => t('If enabled, a canonical URL will be included on every page in the affiliate or secondary domains to point to the primary or default domain. If multiple affiliate domains are specified for a node and the primary domain is left out, then the first domain listed is considered the default.'), + ); + // Add the form element to the main screen. $maxlength = variable_get('nodewords_max_size', 255); $form['domain_meta'] = array(