You are here

domain_path.module in Domain Path 6

Same filename and directory in other branches
  1. 8 domain_path.module
  2. 7 domain_path.module

Path alias handling for multiple domains.

File

domain_path.module
View source
<?php

/**
 * @file
 *  Path alias handling for multiple domains.
 */

/**
 * Implements hook_perm().
 */
function domain_path_perm() {
  return array(
    'edit domain paths',
  );
}

/**
 * Implements hook_domainpath().
 */
function domain_path_domainpath($domain_id, &$path, $path_language = '') {
  $domain = domain_get_domain();
  $did = $domain['domain_id'];
  $alias = $path;
  $paths = domain_path_paths('alias');
  if (isset($paths[$path][$did])) {
    $alias = $paths[$path][$did];
    $nid = arg(1, $alias);
  }
  else {
    $nid = domain_path_is_node_path($alias, $path_language);
    $alias = "node/{$nid}";
  }
  if (empty($nid)) {
    return;
  }
  $paths = domain_path_paths('nid', $nid);
  if (isset($paths[$domain_id])) {
    $path = $paths[$domain_id];
  }
  else {
    $path = drupal_get_path_alias($alias, $path_language);
  }
  $options['alias'] = TRUE;
}

/**
 * Implements hook_boot
 */
function domain_path_boot() {
  return;
}

/**
 * Implements hook_url_inbound_alter().
 */
function domain_path_url_inbound_alter(&$path, $original_path, $path_language) {
  $domain = domain_get_domain();
  $did = $domain['domain_id'];
  $paths = domain_path_paths('alias');
  if (!isset($paths[$original_path][$did])) {
    return;
  }
  $path = $paths[$original_path][$did];
}

/**
 * Tell us if the given path is a node link.
 */
function domain_path_is_node_path($path, $language) {
  $lookup = drupal_lookup_path('source', $path, $language);
  if (!empty($lookup)) {
    $path = $lookup;
  }
  if (arg(0, $path) != 'node') {
    return NULL;
  }
  $arg2 = arg(2, $path);
  if (!empty($arg2)) {
    return NULL;
  }
  $arg1 = intval(arg(1, $path));
  if (empty($arg1)) {
    return NULL;
  }
  return $arg1;
}

/**
 * Return an array of all paths.
 *
 * We cache this for performance.
 *
 * @param $key
 *  The type of data to return. Currently, 'nid' returns an array
 *  keyed by node id. 'alias' returns an array keyed by path alias.
 * @param $nid
 *  A specific node id to return alias matches.
 * @param $reset
 *  Boolean value to reset the static variable.
 * @return
 *  An array of matches.
 */
function domain_path_paths($key = 'nid', $nid = NULL, $reset = FALSE) {
  static $paths;

  // Cache routine. Only run this once.
  if (!isset($paths) || $reset) {

    // Try to get the data from cache.
    $cache = cache_get('domain_path');
    if (isset($cache->data)) {
      $paths = $cache->data;
    }

    // No cache, run the database query.
    if (!isset($paths)) {
      $paths = array(
        'nid' => array(),
        'alias' => array(),
      );

      // TODO: better handling for different entities.
      // TODO: Language support!
      $result = db_query("SELECT domain_id, source, alias, language, entity_type, entity_id FROM {domain_path} WHERE entity_type = 'node'");
      while ($path = db_fetch_object($result)) {
        $paths['nid'][$path->entity_id][$path->domain_id] = $path->alias;
        $paths['alias'][$path->alias][$path->domain_id] = $path->source;
      }

      // Cache for performance.
      // TODO: test.
      cache_set('domain_path', $paths);

      // Return data for a single node?
    }
  }

  // If returning results for a single node, pass back only matches.
  if (!is_null($nid)) {
    if (!isset($paths[$key][$nid])) {
      $paths[$key][$nid] = array();
    }
    return $paths[$key][$nid];
  }

  // Return requested data.
  return $paths[$key];
}

/**
 * Implements hook_form_alter().
 */
function domain_path_form_alter(&$form, $form_state, $form_id) {

  // Apply to all node editing forms, but make sure we are not on the CCK field configuration form.
  if ($form['#id'] != 'node-form' || isset($form['#node']->cck_dummy_node_form)) {
    return;
  }
  cache_clear_all('domain_path', 'cache');

  // This lets CCK adjust the weight of our element using domain_content_extra_fields().
  $weight = module_exists('content') ? content_extra_field_weight($form['type']['#value'], 'domain_path') : 31;
  $form['domain_path'] = array(
    '#tree' => TRUE,
    '#title' => t('Domain-specific paths'),
    '#type' => 'fieldset',
    '#weight' => $weight,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#access' => user_access('edit domain paths'),
  );
  $paths = array();
  $domains = domain_domains();
  $default_domain = domain_default();
  $current = t('<none>');
  if (!empty($form['#node']->nid)) {
    $current = drupal_get_path_alias('node/' . $form['#node']->nid);
    $paths = domain_path_paths('nid', $form['#node']->nid);
  }
  $form['domain_path']['current'] = array(
    '#type' => 'item',
    '#title' => t('Current alias'),
    '#markup' => check_plain($current),
  );
  $form['domain_path']['domain_path_ignore'] = array(
    '#type' => 'checkbox',
    '#title' => t('Delete domain-specific aliases'),
    '#default_value' => FALSE,
  );
  foreach ($domains as $domain_id => $domain) {
    $default = '';

    // TODO: Only exposed checked domains?
    $form['domain_path'][$domain_id] = array(
      '#type' => 'textfield',
      '#title' => check_plain($domain['path']),
      '#default_value' => isset($paths[$domain_id]) ? $paths[$domain_id] : $default,
      '#access' => user_access('edit domain paths'),
    );
  }
}

/**
 * Implements hook_nodeapi().
*/
function domain_path_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'validate':
      $form = $a3;
      $ignore = $form['domain_path']['domain_path_ignore']['#value'];
      if (!empty($ignore)) {
        return;
      }
      $set_message = FALSE;
      $dids = array_keys(domain_domains());
      $paths = array();
      foreach ($dids as $did) {
        $paths[$did] = $form['domain_paths'][$did]['#value'];
      }
      $alias = $form['path']['path']['#value'];

      // Make sure we don't duplicate anything.
      foreach ($paths as $domain_id => $path) {
        $key = $domain_id == -1 ? 0 : $domain_id;
        if (!empty($path) && $path == $alias) {
          form_set_error("domain_path][{$key}", t('Domain path may not match default path alias. You may leave the element blank.'));
          $set_message = TRUE;
        }
        elseif (!empty($path)) {
          $query = db_query("SELECT COUNT(dpid) FROM {domain_path}\n            WHERE domain_id = %d\n            AND alias = %s\n            AND language = %s\n            AND source != %s", $key, $path, isset($node->language) ? $node->language : LANGUAGE_NONE, "node/{$node->nid}");
          if (db_result($query) > 0) {
            form_set_error("domain_path][{$key}", t('Domain path matches   an existing domain path alias.'));
          }
        }
      }

      // Check for duplicates.
      if (module_exists('pathauto') && !empty($node->pathauto_perform_alias)) {
        module_load_include('inc', 'pathauto');
        $placeholders = pathauto_get_placeholders('node', $node);
        $placeholders = array_combine($placeholders['tokens'], $placeholders['values']);
        $new_path = pathauto_create_alias('node', 'return', $placeholders, 'node/' . $node->nid, $node->nid, $node->type, $node->language);
      }
      else {
        $new_path = $node->path;
      }

      // Check to see if pathauto added a -0 to the alias.
      // In these cases, we try to notify the end user.
      $path = explode('-', $new_path);
      $end = array_pop($path);
      $num = intval($end);
      if (drupal_strlen($num) == drupal_strlen($end) && ($num == $end || $end === 0)) {
        $alias = implode('-', $path);
      }
      else {
        $alias = $new_path;
      }

      // Ensure that the submitted alias does not exist yet.
      $query = db_query_range("SELECT 1 FROM {url_alias} WHERE dst = '%s' AND language = '%s' AND src <> '%s'", $alias, $node->language, 'node/' . $node->nid, 0, 1);
      $count = db_result($query);
      if ($count) {

        // If there are no aliases for the active domains, we have to ensure
        // that this is not a duplicate alias.
        $domains = array_filter($node->domains);
        $set_paths = array_filter($paths);
        if (empty($domains)) {
          form_set_error('domain_path', t('The path alias is already in use. You may provide a domain-specific alias below.'));
          $set_message = TRUE;
        }
        elseif (empty($set_paths)) {
          foreach ($domains as $domain_id) {
            $key = $domain_id == -1 ? 0 : $domain_id;
            form_set_error("domain_path][{$key}", t('The path alias %alias is already in use. You should provide a domain-specific alias.', array(
              '%alias' => $alias,
            )));
            $set_message = TRUE;
          }
        }
      }
      if ($set_message) {
        drupal_set_message(t('If you choose to use the current alias, the path to this page will be: %alias', array(
          '%alias' => $new_path,
        )), 'error', FALSE);
      }
      break;
    case 'insert':
    case 'update':
      if (empty($node->domain_path)) {
        return;
      }

      // Delete existing aliases.
      domain_path_nodeapi($node, 'delete');

      // If not set to revert, then save changes.
      if (empty($node->domain_path['domain_path_ignore'])) {
        unset($node->domain_path['domain_path_ignore']);
        foreach ($node->domain_path as $domain_id => $path) {
          if (!empty($path)) {
            $record = array(
              'domain_id' => $domain_id,
              'source' => "node/{$node->nid}",
              'alias' => $path,
              'language' => isset($node->language) ? $node->language : LANGUAGE_NONE,
              'entity_type' => 'node',
              'entity_id' => $node->nid,
            );
            drupal_write_record('domain_path', $record);
          }
        }
      }

      // Rebuild the node alias.
      cache_clear_all('domain_path', 'cache');
      domain_path_paths('nid', NULL, TRUE);
      break;
    case 'delete':
      db_query("DELETE FROM {domain_path} where entity_type = 'node' AND entity_id = %d", $node->nid);
      cache_clear_all('domain_path', 'cache');
      break;
  }
}

/**
 * Implement hook_content_extra_fields()
 *
 * CCK hook to allow sorting of the domain settings field.
 */
function domain_path_content_extra_fields($type_name = NULL) {
  if (!empty($type_name)) {
    return array(
      'domain_path' => array(
        'label' => t('Domain path'),
        'description' => t('Domain-specific path settings.'),
        'weight' => 31,
      ),
    );
  }
}

Functions

Namesort descending Description
domain_path_boot Implements hook_boot
domain_path_content_extra_fields Implement hook_content_extra_fields()
domain_path_domainpath Implements hook_domainpath().
domain_path_form_alter Implements hook_form_alter().
domain_path_is_node_path Tell us if the given path is a node link.
domain_path_nodeapi Implements hook_nodeapi().
domain_path_paths Return an array of all paths.
domain_path_perm Implements hook_perm().
domain_path_url_inbound_alter Implements hook_url_inbound_alter().