You are here

domain_source.module in Domain Access 6.2

Creates a source domain for linking to content from other domains.

File

domain_source/domain_source.module
View source
<?php

/**
 * @defgroup domain_source Domain Source: editor-defined links.
 *
 * Creates a source domain for linking to content from other domains.
 */

/**
 * @file
 * Creates a source domain for linking to content from other domains.
 *
 * @ingroup domain_source
 */
define('DOMAIN_SOURCE_USE_ACTIVE', -5);
define('DOMAIN_SOURCE_IGNORE', -10);

/**
 * Implement hook_form_alter()
 */
function domain_source_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.
  // See http://drupal.org/node/186624.
  if ($form['#id'] == 'node-form' && !isset($form['#node']->cck_dummy_node_form)) {
    global $_domain, $user;
    if (!empty($form['#node']->nid)) {
      $default_source = db_result(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $form['#node']->nid));
    }
    if (!isset($default_source)) {
      $default_source = $_domain['domain_id'];
    }

    // Prevent invalid domains from being used.
    $lookup = domain_lookup($default_source);
    if ($default_source != DOMAIN_SOURCE_USE_ACTIVE && empty($lookup['valid'])) {
      $default_source = NULL;
    }
    $account = $user;
    domain_get_user_domains($account);

    // Only uses with 'set domain access' can assign content to all affilaites, so they get a new option.
    // This option allows domain source to be ignored on a per-node basis.
    $options = array();
    $domains = domain_domains();
    $show = FALSE;
    if (user_access('set domain access')) {
      $options[DOMAIN_SOURCE_USE_ACTIVE] = t('Use active domain');
      $show = TRUE;
      foreach ($domains as $domain) {
        if ($domain['valid'] || user_access('access inactive domains')) {
          $options[$domain['domain_id']] = $domain['sitename'];
        }
      }
    }
    else {
      if (user_access('publish to any assigned domain') && !empty($account->domain_user)) {
        $show = FALSE;
        $options[DOMAIN_SOURCE_USE_ACTIVE] = t('Use active domain');

        // Get the user's allowed domains.
        foreach ($domains as $domain) {
          $key = $domain['domain_id'];
          if ($domain['domain_id'] == 0) {
            $key = -1;
          }
          if (!empty($user->domain_user[$key]) && ($domain['valid'] || user_access('access inactive domains'))) {
            $options[$key] = $domain['sitename'];
          }
        }

        // Is this node assigned to a source that the user can control?
        if (isset($form['#node']->domain_source)) {

          // Transform the 0 to -1 for lookups.
          $source = $form['#node']->domain_source == 0 ? -1 : $form['#node']->domain_source;
        }
        else {
          $source = NULL;
          $show = TRUE;
        }
        if (!is_null($source) && isset($account->domain_user[$source])) {
          if ($account->domain_user[$source] == $source) {
            $show = TRUE;
          }
          else {
            $name = $source != -5 ? $domains[$source]['sitename'] : t('the active domain');
            $form['domain']['domain_source_notes'] = array(
              '#value' => '<label><b>' . t('Source domain:') . '</b></label><div class="description">' . t('This content is assigned to %domain and cannot be reassigned.', array(
                '%domain' => $name,
              )) . '</div>',
            );
          }
        }
      }
    }

    // Determine how to show the form element.
    if ($show) {
      $form['domain']['domain_source'] = array(
        '#type' => 'select',
        '#title' => t('Source domain'),
        '#options' => $options,
        '#default_value' => $default_source,
        '#description' => t('The canonical domain for this content.'),
      );
    }
    else {
      $form['domain']['domain_source'] = array(
        '#type' => 'value',
        '#value' => $default_source,
      );
    }
  }
}

/**
 * Form integration with Domain Content.
 */
function domain_source_form_domain_content_form_alter(&$form, &$form_state) {
  global $_domain;
  if (!user_access('set domain access')) {
    return;
  }
  $options = array();
  $domains = domain_domains();

  // Options.
  $options[DOMAIN_SOURCE_IGNORE] = t('Do not change');
  $options[DOMAIN_SOURCE_USE_ACTIVE] = t('Use active domain');
  foreach ($domains as $domain) {
    $options[$domain['domain_id']] = $domain['sitename'];
  }
  $form['domain']['domain_source'] = array(
    '#type' => 'select',
    '#title' => t('Source domain'),
    '#options' => $options,
    '#default_value' => $_domain['domain_id'],
    '#description' => t('The canonical domain for the selected content. This element replaces existing settings for all selections.'),
  );
  $form['#validate'][] = 'domain_source_validate';
  $form['#submit'][] = 'domain_source_update_nodes';
}

/**
 * Form integration with Administer nodes.
 */
function domain_source_form_node_admin_content_alter(&$form, &$form_state) {

  // Do nothing on the delete screen.
  if (isset($form['operation']['#value']) && $form['operation']['#value'] == 'delete') {
    return;
  }
  domain_source_form_domain_content_form_alter($form, $form_state);
  $form['admin']['options']['submit']['#validate'][] = 'domain_source_validate';
  $form['admin']['options']['submit']['#submit'][] = 'domain_source_update_nodes';
}

/**
 * Implement hook_nodeapi()
 */
function domain_source_nodeapi(&$node, $op, $a3, $a4) {
  global $_domain;
  switch ($op) {
    case 'validate':

      // If not set, we ignore.
      if (!isset($node->domain_source)) {
        return;
      }

      // Cast the key from zero to -1 to match the data coming from the input.
      $node->domain_source == 0 ? $key = -1 : ($key = $node->domain_source);

      // Check the domain and domains_raw variables to set up the allowed source list.
      $allowed = array();
      if (!empty($node->domains)) {
        $allowed = $node->domains;
      }
      if (!empty($node->domains_raw)) {
        $allowed = array_merge($allowed, $node->domains_raw);
      }
      if ($node->domain_site && $key == -1) {

        // This case is acceptable, so we let it pass.
        // I find this code easier to read than a compound IF statement.
      }
      else {
        if ($node->domain_source != DOMAIN_SOURCE_USE_ACTIVE && !in_array($key, $allowed)) {
          form_set_error('domain_source', t('The source affiliate must be selected as a publishing option.'));
        }
      }
      break;
    case 'insert':
    case 'update':
      global $_domain;

      // If not set, we came from a drupal_execute() or other external call, so use the current domain.
      if (!isset($node->domain_source)) {
        $node->domain_source = $_domain['domain_id'];
      }

      // Prevent invalid domains from being used.
      $lookup = domain_lookup($node->domain_source);
      if ($node->domain_source != DOMAIN_SOURCE_USE_ACTIVE && empty($lookup['valid'])) {
        $node->domain_source = NULL;
      }
      db_query("DELETE FROM {domain_source} WHERE nid = %d", $node->nid);
      if (!is_null($node->domain_source)) {
        db_query("INSERT INTO {domain_source} (nid, domain_id) VALUES (%d, %d)", $node->nid, $node->domain_source);
      }
      break;
    case 'delete':
      db_query("DELETE FROM {domain_source} WHERE nid = %d", $node->nid);
      break;
    case 'load':
      if ($node->nid) {
        $source = domain_source_lookup($node->nid, $node->domains, $node->domain_site);
        $node->domain_source = $source['domain_id'];
      }
      break;
    case 'view':

      // Search module casts both $a3 and $a4 as FALSE, not NULL.
      // We check that to hide this data from search and other nodeapi
      // 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_get_node_match($node->nid);
          $extra = ' ';
          $use_active = db_result(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $node->nid));
          if ($use_active === FALSE) {
            $extra .= t('(determined automatically)');
          }
          else {
            if ($use_active == DOMAIN_SOURCE_USE_ACTIVE) {
              $extra .= t('(using active domain)');
            }
          }
          $node->content['domain_source'] = array(
            '#value' => '<p>' . t('<strong>Source domain</strong>: %source', array(
              '%source' => $source['sitename'],
            )) . $extra . '</p>',
            '#weight' => 25,
          );
        }
      }
      break;
  }
}

/**
 * Find the proper source domain for a node.
 *
 * @param $nid
 *   The node id.
 * @param $domains
 *   An optional array of domain ids, which is present when this function is called from hook_nodeapi().
 * @param $domain_site
 *   Optional flag indicating that the node is assigned to all domains.
 * @param $reset
 *   Force a reset of the static data lookup.
 * @return
 *   The active source domain to use; an array returned by domain_lookup().
 */
function domain_source_lookup($nid, $domains = array(), $domain_site = FALSE, $reset = FALSE) {
  global $_domain;
  static $lookups;

  // Static cache.
  if (!$reset && isset($lookups[$nid])) {
    return $lookups[$nid];
  }
  $source = db_result(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $nid));

  // Default source for nodes with no setting.
  if ($source === FALSE) {
    $source = variable_get('domain_default_source', 0);
  }

  // Global setting for 'do not change domain.'
  if ($source == -1) {
    $source = $_domain['domain_id'];
  }
  else {
    if ($source == DOMAIN_SOURCE_USE_ACTIVE) {
      $source = $_domain['domain_id'];
    }
  }

  // When called from url_rewrite_outbound(), we have no data.
  if (empty($domains)) {
    $lookup = domain_get_node_domains($nid);
    $domain_site = $lookup['domain_site'];
    $domains = $lookup['domain_id'];
  }

  // domain_get_node_domains() returns the default (0) domain as -1, so we
  // must transform it here before running a check.
  $source = $source == 0 ? -1 : $source;

  // If no valid source is found, take the first match from the $domains array.
  if (empty($domain_site) && !empty($domains) && !in_array($source, $domains)) {
    $source = current($domains);
  }

  // Convert the source id from -1 to 0 and run the lookup.
  $domain_id = $source == -1 ? 0 : $source;
  $lookups[$nid] = domain_lookup($domain_id);
  return $lookups[$nid];
}

/**
 * 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) {

  // If our operation is flagged, then we have to manually change the
  // {domain_source} table.  The rest of the process will clear the cache,
  // so this should be a safe operation.
  if ($form_state['values']['operation'] == 'domain') {
    $source = $form_state['values']['domain_source'];
    if ($source == DOMAIN_SOURCE_IGNORE) {
      return;
    }
    foreach ($form_state['values']['nodes'] as $key => $value) {
      if ($key == $value) {
        db_query("DELETE FROM {domain_source} WHERE nid = %d", $key);
        db_query("INSERT INTO {domain_source} (nid, domain_id) VALUES (%d, %d)", $key, $source);
      }
    }
  }
}

/**
 * Form validation step
 */
function domain_source_validate($form, &$form_state) {
  if ($form_state['values']['operation'] == 'domain') {
    $form_state['values']['domain_source'] == 0 ? $key = -1 : ($key = $form_state['values']['domain_source']);
    if ($form_state['values']['domain_site'] && $key == -1 || $key == DOMAIN_SOURCE_USE_ACTIVE) {

      // These cases are acceptable, so we let them pass.
      // I find this code easier to read than a compound negative IF statement.
    }
    else {
      if ($key == DOMAIN_SOURCE_IGNORE) {

        // In this case, we need to check all the selected nodes, which is resource intensive.
        $nodes = array_filter($form_state['values']['nodes']);
        foreach ($nodes as $nid) {
          $source = domain_source_lookup($nid, array(), $form_state['values']['domain_site'], TRUE);
          $key = $source['domain_id'] == 0 ? -1 : $source['domain_id'];

          // Test for the first two behaviors, which add domains to the node.
          $behavior = $form_state['values']['behavior'];
          if ($behavior < 2) {
            if (empty($form_state['values']['domains'][$key])) {
              $node = node_load($nid);
              form_set_error('domain_source', t('The source affiliate must be selected as a publishing option. %title is assigned to %domain.', array(
                '%title' => $node->title,
                '%domain' => $source['sitename'],
              )));
            }
          }
          else {
            if (!empty($form_state['values']['domains'][$key])) {
              $node = node_load($nid);
              form_set_error('domain_source', t('The source affiliate must be selected as a publishing option. %title is assigned to %domain.', array(
                '%title' => $node->title,
                '%domain' => $source['sitename'],
              )));
            }
          }
        }
      }
      else {
        if (empty($form_state['values']['domains'][$key])) {
          form_set_error('domain_source', t('The source affiliate must be selected as a publishing option.'));
        }
      }
    }
  }
}

/**
 * Implement hook_domainupdate()
 *
 * When deleting domain records, we remove all traces from the {domain_source} table.
 */
function domain_source_domainupdate($op, $domain, $form_state = array()) {
  if ($op == 'delete' && $domain['domain_id'] > 0) {
    db_query("DELETE FROM {domain_source} WHERE domain_id = %d", $domain['domain_id']);
  }
}

/**
 * Implement hook_views_api().
 */
function domain_source_views_api() {
  if (module_exists('domain_views')) {
    return array(
      'api' => 2.0,
    );
  }
}

Related topics

Functions

Namesort descending Description
domain_source_domainupdate Implement hook_domainupdate()
domain_source_domain_source_alter Implement hook_domain_source_node_alter().
domain_source_form_alter Implement hook_form_alter()
domain_source_form_domain_content_form_alter Form integration with Domain Content.
domain_source_form_node_admin_content_alter Form integration with Administer nodes.
domain_source_lookup Find the proper source domain for a node.
domain_source_nodeapi Implement hook_nodeapi()
domain_source_update_nodes FormAPI function that lets us update access rules.
domain_source_validate Form validation step
domain_source_views_api Implement hook_views_api().

Constants

Namesort descending Description
DOMAIN_SOURCE_IGNORE
DOMAIN_SOURCE_USE_ACTIVE @file Creates a source domain for linking to content from other domains.