<?php
// $Id: domain_source.module,v 1.13 2009/05/31 18:16:41 agentken Exp $

/**
 * @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
 */

/**
 * 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;
    $options = array();
    $domains = domain_domains();
    $show = FALSE;
    if (user_access('set domain access')) {
      $show = TRUE;
      foreach ($domains as $domain) {
        $options[$domain['domain_id']] = $domain['sitename'];
      }
    }
    // In the case of users with limited permissions, option 3 is the "show options" value.
    else if (user_access('publish to any assigned domain')) {
      global $user;
      // Get the user's allowed domains.
      foreach ($domains as $domain) {
        if ($user->domain_user[$domain['domain_id']] != 0 && $domain['domain_id'] == $user->domain_user[$domain['domain_id']]) {
          $options[$domain['domain_id']] = $domain['sitename'];
        }
      }
      // Is this node assigned to a source that the user can control?
      $source = $form['#node']->domain_source;
      if (isset($source)) {
        if ($user->domain_user[$domain['domain_id']] == $source) {
          $show = TRUE;
        }
        else {
          $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' => $domains[$source]['sitename'])) .'</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' => ($form['#node']->domain_source) ? $form['#node']->domain_source : $_domain['domain_id'],
        '#description' => t('This affiliate will be used to write links to this content from other affiliates, as needed.')
      );
    }
    // Non-privileged users just have the current domain assigned.
    else {
      $form['domain']['domain_source'] = array(
        '#type' => 'value',
        '#value' => (isset($form['#node']->domain_source)) ? $form['#node']->domain_source : $_domain['domain_id'],
      );
    }
  }
  // Integration with Domain Content
  else if ($form_id == 'domain_content_form') {
    global $_domain;
    $options = array();
    $domains = domain_domains();
    if (user_access('set domain access')) {
      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('This affiliate will be linked to from other affiliates, as needed.')
      );
      $form['#validate'][] = 'domain_source_validate';
      $form['#submit'][] = 'domain_source_update_nodes';
    }
  }
}

/**
 * Implement hook_nodeapi()
 */
function domain_source_nodeapi(&$node, $op, $a3, $a4) {
  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;
      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.
      }
      // Here we account for both the 'domains_raw' and 'domains' options.
      // If selected, these clauses will not be zero.
      else if ((!empty($node->domains) && !$node->domains[$key]) || (!empty($node->domains_raw) && !in_array($key, $node->domains_raw))) {
        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'];
      }
      db_query("DELETE FROM {domain_source} WHERE nid = %d", $node->nid);
      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 = array();
        $source = db_fetch_array(db_query("SELECT domain_id FROM {domain_source} WHERE nid = %d", $node->nid));
      }
      if (empty($source)) {
        $node->domain_source = variable_get('domain_default_source', 0);
      }
      else {
        $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_lookup($node->domain_source);
        $node->content['domain_source'] = array('#value' => '<p>'. t('<b>Source domain</b>: %source', array('%source' => $source['sitename'])) .'</b></p>', '#weight' => 25);
        }
      }
      break;
  }
}

/**
 * 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
  // {node_access} 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'];
    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) {
      // This case is acceptable, so we let it pass.
      // I find this code easier to read than a compound IF statement.
    }
    // Here we account for both the 'domains_raw' and 'domains' options.
    // If selected, these clauses will not be zero.
    else if (!$form_state['values']['domains'][$key] && (!empty($form_state['values']['domains_raw']) && !in_array($key, $form_state['values']['domains_raw']))) {
      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);
  }
}
