Skip to content
nodequeue.module 61 KiB
Newer Older
Earl Miles's avatar
Earl Miles committed
<?php

/**
 *  NOTES
 *  Here are various notes I've taken about notable changes and/or ommissions
 *
 *  - Everything has been moved to admin/structure/nodequeue which seemed the
 *    most appropriate destination now that admin/content is out of the picture.
 *
 *  - None of the PagerQueries are working, they're all just normal queries for
 *    the time being.
 */

/**
 * @file
 * Maintains queues of nodes in arbitrary order.
 */

define('NODEQUEUE_OK', 0);
define('NODEQUEUE_INVALID_POSITION', 1);
define('NODEQUEUE_INVALID_NID', 2);
define('NODEQUEUE_DUPLICATE_POSITION', 3);

/* --- HOOKS ---------------------------------------------------------------- */
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
/**
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_permission() {
  return array(
    'administer nodequeue' => array(
      'title' => t('Administer nodequeue'),
      'description' => t('Administer the nodequeue module.'),
    ),
   'manipulate queues' => array(
      'title' => t('Manipulate queues'),
      'description' => t('Manipulate queues.'),
    ),
      'title' => t('Manipulate all queues'),
      'description' => t('Manipulate all queues.'),
Earl Miles's avatar
Earl Miles committed
}

Earl Miles's avatar
Earl Miles committed
/**
Earl Miles's avatar
Earl Miles committed
 *
 * Loads subsidiary includes for other modules.
 */
function nodequeue_init() {
  include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'nodequeue') . '/includes/nodequeue.actions.inc';
Earl Miles's avatar
Earl Miles committed
/**
Earl Miles's avatar
Earl Miles committed
 */
Earl Miles's avatar
Earl Miles committed
  $items = array();
  $admin_access = array('administer nodequeue');

  // administrative items
  $items['admin/structure/nodequeue'] = array(
    'title' => 'Nodequeues',
    'page callback' => 'nodequeue_view_queues',
    'access callback' => '_nodequeue_access_admin_or_manipulate',
    'description' => 'Create and maintain simple nodequeues.',
    'file' => 'includes/nodequeue.admin.inc',
  $items['admin/structure/nodequeue/list'] = array(
    'page callback' => 'nodequeue_view_queues',
    'access callback' => '_nodequeue_access_admin_or_manipulate',
    'file' => 'includes/nodequeue.admin.inc',
    'weight' => -1,
    'type' => MENU_DEFAULT_LOCAL_TASK
  );
  $items['admin/structure/nodequeue/settings'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('nodequeue_admin_settings'),
    'file' => 'includes/nodequeue.admin.inc',
    'type' => MENU_LOCAL_TASK
  );
  $items['nodequeue/autocomplete'] = array(
    'page callback' => 'nodequeue_autocomplete',
    'access callback' => '_nodequeue_access_admin_or_manipulate',
    'file' => 'includes/nodequeue.admin.inc',
    'type' => MENU_CALLBACK
  );
  $info = nodequeue_api_info();
  foreach ($info as $key => $data) {
    $items['admin/structure/nodequeue/add/' . $key] = array(
      'title' => 'Add @type',
      'title arguments' => array('@type' => strtolower($data['title'])),
      'page callback' => 'drupal_get_form',
      'page arguments' => array('nodequeue_edit_queue_form', $key),
      'file' => 'includes/nodequeue.admin.inc',
      'type' => MENU_LOCAL_ACTION
Earl Miles's avatar
Earl Miles committed
  }
    'title' => '@tab',
    'title arguments' => array('@tab' => variable_get('nodequeue_tab_name', 'Nodequeue')),
    'page callback' => 'nodequeue_node_tab',
    'page arguments' => array(1),
    'access callback' => 'nodequeue_node_tab_access',
    'access arguments' => array(1),
    'file' => 'includes/nodequeue.admin.inc',
    'weight' => 5,
    'type' => MENU_LOCAL_TASK
  );

  // Administrative items for an individual queue.
  $items['admin/structure/nodequeue/%nodequeue'] = array(
    'page callback' => 'nodequeue_admin_view',
    'page arguments' => array(3),
    'access callback' => 'nodequeue_queue_access',
    'access arguments' => array(3),
    'file' => 'includes/nodequeue.admin.inc',
  $items['admin/structure/nodequeue/%nodequeue/view'] = array(
    'title' => 'View',
    'page callback' => 'nodequeue_admin_view',
    'page arguments' => array(3),
    'access callback' => 'nodequeue_queue_access',
    'access arguments' => array(3),
    'file' => 'includes/nodequeue.admin.inc',
    'weight' => -10,
    'type' => MENU_DEFAULT_LOCAL_TASK
  );
  $items['admin/structure/nodequeue/%nodequeue/view/%subqueue'] = array(
    'title' => 'View',
    'page callback' => 'nodequeue_admin_view',
    'page arguments' => array(3, 5),
    'access callback' => 'nodequeue_queue_access',
    'access arguments' => array(3, 5),
    'file' => 'includes/nodequeue.admin.inc',
    'tab parent' => 'admin/structure/nodequeue/%',
  $items['admin/structure/nodequeue/%nodequeue/edit'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('nodequeue_edit_queue_form', 3),
    'file' => 'includes/nodequeue.admin.inc',
  $items['admin/structure/nodequeue/%nodequeue/delete'] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('nodequeue_admin_delete', 3),
    'file' => 'includes/nodequeue.admin.inc',
  $items['nodequeue/%nodequeue/add-node/%subqueue/%node'] = array(
    'page callback' => 'nodequeue_admin_add_node',
    'access callback' => 'nodequeue_node_and_queue_access',
    'access arguments' => array(4, 1, 3),
    'file' => 'includes/nodequeue.admin.inc',
  $items['nodequeue/%nodequeue/remove-node/%subqueue/%node'] = array(
    'page callback' => 'nodequeue_admin_remove_node',
    'access callback' => 'nodequeue_node_and_queue_access',
    'access arguments' => array(4, 1, 3),
    'file' => 'includes/nodequeue.admin.inc',
  $items["admin/structure/nodequeue/%nodequeue/clear/%subqueue"] = array(
    'page callback' => 'drupal_get_form',
    'page arguments' => array('nodequeue_clear_confirm', 3, 5),
    'access callback' => 'nodequeue_queue_access',
    'access arguments' => array(3, 5),
    'file' => 'includes/nodequeue.admin.inc',
Earl Miles's avatar
Earl Miles committed
  return $items;
}
/**
 * Helper function for a _menu_translate() bug.
 */
function subqueue_to_arg() {
  return '';
}

/**
 * Implements hook_admin_paths().
 */
function nodequeue_admin_paths() {
  if (variable_get('node_admin_theme')) {
    $paths = array(
      'node/*/nodequeue' => TRUE,
    );
    return $paths;
  }
}

Earl Miles's avatar
Earl Miles committed
/**
 * Implements hook_node_delete.
 */
function nodequeue_node_delete($node) {
  // If a node is being deleted, ensure it's also removed from any queues.
  $result = db_query("SELECT qid, sqid FROM {nodequeue_nodes} WHERE nid =:nid", array(
    ':nid' => $node->nid,
  ));
  foreach ($result as $obj) {
    // If the queue is being tracked by translation set and the node is part
    // of a translation set, don't delete the queue record.
    // Instead, data will be updated in the 'translation_change' op, below.
    $queues = nodequeue_load_queues(array($obj->qid));
    $queue = array_shift($queues);
    if (!$queue->i18n || (isset($node->tnid) && empty($node->tnid))) {
      // This removes by nid, not position, because if we happen to have a
      // node in a queue twice, the 2nd position would be wrong.
      nodequeue_subqueue_remove_node($obj->sqid, $node->nid);
    }
Earl Miles's avatar
Earl Miles committed
  }
}
function nodequeue_node_view($node, $view_mode) {
  $links = nodequeue_node_links($node);
  if (!empty($links)) {
    $node->content['links']['nodequeue'] = array(
      '#links' => $links,
      '#theme' => 'links__node__nodequeue',
    );
  }
Earl Miles's avatar
Earl Miles committed

/**
 * Implementats hook_forms().
 */
function nodequeue_forms($form_id) {
  $forms = array();
  if (strpos($form_id, 'nodequeue_arrange_subqueue_form_') === 0) {
    $forms[$form_id] = array(
      'callback' => 'nodequeue_arrange_subqueue_form',
    );
  }
  return $forms;
}

 */
function nodequeue_theme() {
  return array(
    'nodequeue_arrange_subqueue_form_table' => array(
      'render element' => 'form',
    ),
    'nodequeue_subqueue_empty_text' => array(
    ),
    'nodequeue_subqueue_full_text' => array(
    ),
    'nodequeue_subqueue_count_text' => array(
      'variables' => array('count' => 0),
  $type = array();

  $type['position'] = array(
    '#input'         => TRUE,
    '#delta'         => 10,
    '#default_value' => 0,
    '#process'       => array('process_position', 'ajax_process_form'),
  );

  return $type;
}

/**
 * Expand position elements into selects. Works like the weight element, except
 * only positive values are allowed.
 */
function process_position($element) {
  for ($n = 1; $n <= $element['#delta']; $n++) {
    $positions[$n] = $n;
  }

  $element['#options']      = $positions;
  $element['#options']['r'] = t('Remove');
  $element['#type']         = 'select';

  // add default properties for the select element

  return $element;
}

/**
 * If no default value is set for position select boxes, use 1.
 */
function position_value(&$form) {
  if (isset($form['#default_value'])) {
    $form['#value'] = $form['#default_value'];
  }
  else {
    $form['#value'] = 1;
  }
}

 */
function nodequeue_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'nodequeue') . '/includes/views',
// --------------------------------------------------------------------------
// Nodequeue Apache Solr Search Integration

 * Implements hook_form_FORM_ID_alter().
function nodequeue_form_apachesolr_search_bias_form_alter(&$form, &$form_state, $form_id) {
  // Setup for the form building.
  $weights = drupal_map_assoc(array('21.0', '13.0', '8.0', '5.0', '3.0', '2.0', '1.0', '0.8', '0.5', '0.3', '0.2', '0.1'));
  $weights['0'] = t('Normal');
  $queues = nodequeue_load_subqueues_by_queue(array_keys(nodequeue_get_all_qids()));
  $form['biasing']['nodequeue_boost'] = array(
    '#type' => 'fieldset',
    '#title' => t('Nodequeue Biasing'),
    '#weight' => -5,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['biasing']['nodequeue_boost']['nodequeue_apachesolr_boost'] = array(
    '#type' => 'item',
    '#description' => t("Specify to bias the search result when a node is in a queue. Any value except <em>Normal</em> will increase the socre for the given queue in the search results"),
  );
  foreach ($queues as $sqid => $queue) {
    $boost = variable_get("nodequeue_apachesolr_boost_$sqid", 0);
    $form['biasing']['nodequeue_boost']['nodequeue_apachesolr_boost']["nodequeue_apachesolr_boost_$sqid"] = array(
      '#type' => 'select',
      '#title' => t('Weight for %title nodequeue', array('%title' => $queue->title)),
      '#options' => $weights,
      '#default_value' => $boost,
    );
  }
}

/**
 * Implements hook_apachesolr_index_document_ENTITY_TYPE().
function nodequeue_apachesolr_index_document_node($document, $node, $env_id) {
Ezra Barnett Gildesgame's avatar
Ezra Barnett Gildesgame committed
  if (empty($document)) {
    return;
  }

  $queues = nodequeue_load_queues(array_keys(nodequeue_get_all_qids()));
  $subqueues = nodequeue_get_subqueues_by_node($queues, $node);

  nodequeue_set_subqueue_positions($subqueues, $node->nid);
  if (is_array($subqueues)) {
    foreach ($subqueues as $sqid => $subqueue) {
      if (!empty($subqueue->position)) {
        $key = _nodequeue_solr_qid_key();
        $document->setMultiValue($key, $sqid);
 * Returns the apachesolr index key for group id.
 */
function _nodequeue_solr_qid_key() {
  $qid_key = array(
    'index_type' => 'sint',
    'multiple' => TRUE,
    'name' => "nodequeue",
  );
  return apachesolr_index_key($qid_key);
/**
 * Implements hook_apachesolr_query_alter().
 */
function nodequeue_apachesolr_query_alter(DrupalSolrQueryInterface $query) {
  $queues = nodequeue_load_subqueues_by_queue(array_keys(nodequeue_get_all_qids()));
  $added = FALSE;
  foreach ($queues as $sqid => $queue) {
    $boost = variable_get("nodequeue_apachesolr_boost_$sqid", 0);
    if (!empty($boost)) {
      $query->params['bq'][] = _nodequeue_solr_qid_key() . ":$sqid^$boost";
      if (!$added) {
        // Only want to add the facet.field once. no need to repeat it.
        $query->params['facet.field'][] = _nodequeue_solr_qid_key();
        $added = TRUE;
      }
    }
Earl Miles's avatar
Earl Miles committed
// --------------------------------------------------------------------------
// Nodequeue manipulation API.

/**
 * @defgroup nodequeue_api
 * @{
 * Access to the internals of nodequeues are handled primarily through these
 * API functions. They allow easy loading of queues for manipulation.
 */

/**
 * The nodequeue queue class; the constructor makes it so we don't have to
 * always check to see if our variables are empty or not.
 */
class nodequeue_queue {
Earl Miles's avatar
Earl Miles committed
  var $title = '';
  var $size = 0;
  var $link = '';
Earl Miles's avatar
Earl Miles committed
  var $roles = array();
  var $types = array();
  var $show_in_links = TRUE;
  var $show_in_tab = TRUE;
  var $show_in_ui = TRUE;
  var $reference = 0;
Earl Miles's avatar
Earl Miles committed


  // runtime
  var $subqueues = array();
  var $subqueue = NULL;

  var $current = NULL;

Earl Miles's avatar
Earl Miles committed
  function nodequeue_queue($type) {
    $this->owner = $type;
  }
}

/**
 * Fetch a list of available queues for a given location. These queues
 * will be fully loaded and ready to go.
 */
function nodequeue_load_queues_by_type($type, $location = NULL, $account = NULL, $bypass_cache = FALSE) {
  $qids = nodequeue_get_qids($type, $account, $bypass_cache);
Earl Miles's avatar
Earl Miles committed
  if ($location) {
    nodequeue_filter_qids($qids, $location);
  }
  return nodequeue_load_queues(array_keys($qids), $bypass_cache);
Earl Miles's avatar
Earl Miles committed
}

/**
 * Filter a list of qids returned by nodequeue_get_qids to a location.
 *
 * @param $qids
 *   An array of $qids from @see nodequeue_get_qids()
 * @param $location
 *   One of:
 *   - 'links': Only check for queues that have node links.
 *   - 'tab': Only check for queues that appear on the node tab.
 *   - 'ui': Only check for queues that appear in the UI.
 */
function nodequeue_filter_qids(&$qids, $location) {
  $var = "show_in_$location";
  foreach ($qids as $qid => $info) {
    if (empty($info->$var)) {
      unset($qids[$qid]);
    }
  }
}

/**
 * Get an array of qids applicable to this node type.
 *
 * @param $type
 *   The node type.
 * @param $account
 *   The account to test against. Defaults to the currently logged in user.
 *
 * @return $qids
 *   An array in the format: @code { array($qid => array('qid' => $qid, 'show_in_tab' '
 *   => true/false, 'show_in_links' => true/false }
 * @param $bypass_cache
 *  Boolean value indicating whether to bypass the cache or not.
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_get_qids($type, $account = NULL, $bypass_cache = FALSE) {
Earl Miles's avatar
Earl Miles committed
  if (!isset($account)) {
    global $user;
    $account = $user;
  }

  static $cache = array();
  if ($bypass_cache || !isset($cache[$type])) {
Earl Miles's avatar
Earl Miles committed
    $roles_join = $roles_where = '';
    $roles = array();
Earl Miles's avatar
Earl Miles committed

    // superuser always has access.
    if (!user_access('manipulate all queues', $account)) {
Earl Miles's avatar
Earl Miles committed
      $roles_join = "INNER JOIN {nodequeue_roles} nr ON nr.qid = nq.qid ";
Earl Miles's avatar
Earl Miles committed
      $roles = array_keys((array) $account->roles) + array(DRUPAL_AUTHENTICATED_RID);
    $sql = 'SELECT nq.qid, nq.show_in_tab, nq.show_in_links, nq.show_in_ui, nq.i18n ' .
      'FROM {nodequeue_queue} nq ' .
      'INNER JOIN {nodequeue_types} nt ON nt.qid = nq.qid ' . $roles_join .
      "WHERE nt.type = :type " . $roles_where;
    $result = db_query($sql, array(':type' => $type, ':roles' => $roles));
Earl Miles's avatar
Earl Miles committed
    $qids = array();
Earl Miles's avatar
Earl Miles committed
      $qids[$qid->qid] = $qid;
Earl Miles's avatar
Earl Miles committed
    }
Earl Miles's avatar
Earl Miles committed
    $cache[$type] = $qids;
Earl Miles's avatar
Earl Miles committed
  }
Earl Miles's avatar
Earl Miles committed
  return $cache[$type];
Earl Miles's avatar
Earl Miles committed
/**
 * Get an array of qids using the pager query. This administrative list
Earl Miles's avatar
Earl Miles committed
 * does no permission checking, so should only be available to users who
 * have passed the 'administer queues' check.
 *
 * @param $page_size
 *   The page size to use. If this is 0 or NULL, all queues will be returned.
 *   Defaults to 0.
Earl Miles's avatar
Earl Miles committed
 * @param $pager_element
 *   In the rare event this should use another pager element, set this..
 * @param $bypass_cache
 *   Boolean value indicating whether to bypass the cache or not.
 *
 * @return $qids
 *   An array in the format: @code { array($qid => $qid) }
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_get_all_qids($page_size = 0, $pager_element = 0, $bypass_cache = FALSE) {
  $cache = &drupal_static(__FUNCTION__, array());
  if ($bypass_cache || empty($cache[$page_size])) {
    $query = db_select('nodequeue_queue', 'nq')
      ->fields('nq', array('qid'));

    if (!empty($page_size)) {
      $query->extend('PagerDefault')
        ->extend('TableSort')
        ->limit($page_size)
        ->element($pager_element);
Earl Miles's avatar
Earl Miles committed
    }

    $qids = $query->execute()->fetchAllKeyed(0, 0);

    $cache[$page_size] = $qids;
Earl Miles's avatar
Earl Miles committed
  }
Earl Miles's avatar
Earl Miles committed
}
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
 * Load an array of $qids.
 *
 * This exists to provide a way of loading a bunch of queues with
 * the fewest queries. Loading 5 queues results in only 4 queries,
 * not 20. This also caches queues so that they don't get loaded
 * repeatedly.
 *
 * @param $qids
 *   An array of queue IDs to load.
 * @param $bypass_cache
 *   Boolean value indicating whether to bypass the cache or not.
function nodequeue_load_queues($qids = array(), $bypass_cache = FALSE) {
Earl Miles's avatar
Earl Miles committed
  static $cache = array();
  $to_load = $loaded = array();
Earl Miles's avatar
Earl Miles committed

  foreach ($qids as $qid) {
    if ($bypass_cache || !isset($cache[$qid])) {
Earl Miles's avatar
Earl Miles committed
      $to_load[] = $qid;
    }
  }

  if (!empty($to_load)) {
    $result = db_query("SELECT q.*, (SELECT count(*) FROM {nodequeue_subqueue} s WHERE q.qid = s.qid) AS subqueues FROM {nodequeue_queue} q WHERE q.qid IN (:to_load)", array(':to_load' => $to_load));
      $loaded[$queue->qid] = $queue;
      $loaded[$queue->qid]->types = array();
      $loaded[$queue->qid]->roles = array();
      $loaded[$queue->qid]->count = 0;
Earl Miles's avatar
Earl Miles committed
    }
    $result = db_query("SELECT qid, rid FROM {nodequeue_roles} WHERE qid IN (:to_load)", array(':to_load' => $to_load));
      $loaded[$obj->qid]->roles[] = $obj->rid;
Earl Miles's avatar
Earl Miles committed
    }
    $result = db_query("SELECT qid, type FROM {nodequeue_types} WHERE qid IN (:to_load)", array(':to_load' => $to_load));
      $loaded[$obj->qid]->types[] = $obj->type;
Earl Miles's avatar
Earl Miles committed
    }
    $context = 'load_queues';
    drupal_alter('nodequeue', $loaded, $context);
Earl Miles's avatar
Earl Miles committed
  }
  if ($bypass_cache) {
    return $loaded;
  }
  else {
    if (!empty($loaded)) {
      $cache += $loaded;
    }
    $queues = array();
    foreach ($qids as $qid) {
      if (isset($cache[$qid])) {
        $queues[$qid] = $cache[$qid];
      }
Earl Miles's avatar
Earl Miles committed
    }
    return $queues;
Earl Miles's avatar
Earl Miles committed
  }
}
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
/**
 * Load a nodequeue.
 *
 * @param $qid
 *   The qid of the queue to load.
 */
function nodequeue_load($qid) {
  $queues = nodequeue_load_queues(array($qid));
  return !empty($queues) ? array_shift($queues) : array();
Earl Miles's avatar
Earl Miles committed
}

/**
 * This function exists so that %subqueue will work in hook_menu.
 */
function subqueue_load($sqid) {
  if (!$sqid) {
    return NULL;
  }
  $queues = nodequeue_load_subqueues(array($sqid));
  return !empty($queues) ? array_shift($queues) : array();
Earl Miles's avatar
Earl Miles committed
/**
 * Load a list of subqueues
 *
 * This exists to provide a way of loading a bunch of queues with
 * the fewest queries. Loading 5 queues results in only 4 queries,
 * not 20. This also caches queues so that they don't get loaded
 * repeatedly.
 *
 * @param $sqids
 *   An array of subqueue IDs to load.
 * @param $bypass_cache
 *   Boolean value indicating whether to bypass the cache or not.
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_load_subqueues($sqids, $bypass_cache = FALSE) {
Earl Miles's avatar
Earl Miles committed
  static $cache = array();
  $to_load = array();

  foreach ($sqids as $sqid) {
    if ($bypass_cache || !isset($cache[$sqid])) {
Earl Miles's avatar
Earl Miles committed
      $to_load[] = $sqid;
    }
  }

  if (!empty($to_load)) {
    $result = db_query("SELECT s.*, (SELECT count(*) FROM {nodequeue_nodes} n WHERE n.sqid = s.sqid) AS count FROM {nodequeue_subqueue} s WHERE s.sqid IN (:to_load)", array(':to_load' => $to_load));
Earl Miles's avatar
Earl Miles committed
      // Sometimes we want to get to subqueues by reference, sometimes by sqid.
      // sqid is always unique, but reference is sometimes more readily available.
      $cache[$obj->sqid] = $obj;
    }
  }

  foreach ($sqids as $sqid) {
    if (isset($cache[$sqid])) {
      $subqueues[$sqid] = $cache[$sqid];
    }
  }
  return $subqueues;
Earl Miles's avatar
Earl Miles committed
/**
 * Load a single subqueue.
 *
 * @param $sqid
 *   The subqueue ID to load.
 * @param $bypass_cache
 *   Boolean value indicating whether to bypass the cache or not.
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_load_subqueue($sqid, $bypass_cache = FALSE) {
  $subqueues = nodequeue_load_subqueues(array($sqid), $bypass_cache);
Earl Miles's avatar
Earl Miles committed
  if ($subqueues) {
    return array_shift($subqueues);
  }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
}

/**
 * Load the entire set of subqueues for a queue.
 *
 * This will load the entire set of subqueues for a given queue (and can
 * respect the pager, if desired). It does NOT cache the subqueues like
 * nodequeue_load_subqueues does, so beware of this mixed caching.
 *
 * @param $qids
 *   A $qid or array of $qids
 * @param $page_size
 *   If non-zero, use the pager_query and limit the page-size to the parameter.
 */
function nodequeue_load_subqueues_by_queue($qids, $page_size = 0) {
  if (is_numeric($qids)) {
    $qids = array($qids);
  }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
  if (empty($qids)) {
    return array();
  }
Earl Miles's avatar
Earl Miles committed

  $query = "SELECT s.*, (SELECT count(*) FROM {nodequeue_nodes} n WHERE n.sqid = s.sqid) AS count FROM {nodequeue_subqueue} s WHERE s.qid IN (:qids)";
  $result = db_query($query, array(':qids' => $qids));
Earl Miles's avatar
Earl Miles committed

  $subqueues = array();

Earl Miles's avatar
Earl Miles committed
    $subqueues[$subqueue->sqid] = $subqueue;
  }

  return $subqueues;
}

/**
 * Load a set of subqueues by reference.
 *
 * This can be used to load a set of subqueues by reference; it will primarily
 * be used by plugins that are managing subqueues.
 *
 * @param $references
 *   A keyed array of references to load. The key is the $qid and each value
 *   is another array of references.
 */
function nodequeue_load_subqueues_by_reference($references, $bypass_cache = FALSE) {
Earl Miles's avatar
Earl Miles committed
  static $cache = array();
  $subqueues = array();
Earl Miles's avatar
Earl Miles committed

  if (!empty($references)) {
    $query = db_select('nodequeue_subqueue', 's')
      ->groupBy('s.sqid')
      ->fields('s');
    $query->leftJoin('nodequeue_nodes', 'n', 'n.sqid = s.sqid');
    $query->addExpression('COUNT(n.position)', 'count');
    foreach ($references as $qid => $reference) {
      $where->condition(db_and()->condition('s.qid', $qid)->condition('s.reference', $reference));
Earl Miles's avatar
Earl Miles committed
    }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
      $cache[$subqueue->qid][$subqueue->reference] = $subqueues[$subqueue->sqid] = $subqueue;
    }
  }

  return $subqueues;
/**
 * Return a queue by its machine name. This is obviously not ideal due to the
 * extra queries, but probably preferable to changing current API calls.
 *
 * @param $name
 *   The queue machine name
 *
 * @return
 *   The queue definition, or an empty array if no queue was found with the
 *   given machine name.
 */
function nodequeue_load_queue_by_name($name) {
  $map = nodequeue_get_qid_map();
  if (isset($map[$name])) {
    $queues = nodequeue_load_queues(array($map[$name]));
    if ($queues) {
      return current($queues);
    }
  }

  return array();
}

/**
 * Return a map of queue name to qid values to aid in various lookups.
 *
 * @return array
 *   A array of qids, keyed by machine name.
 */
function nodequeue_get_qid_map() {
  static $map = array();
  if (!$map) {
    $result = db_query("SELECT qid, name FROM {nodequeue_queue}");
    while ($get = $result->fetchObject()) {
      $map[$get->name] = $get->qid;
    }
  }
  return $map;
}

Earl Miles's avatar
Earl Miles committed
/**
 * Save a nodequeue. This does not save subqueues; those must be added separately.
 */
function nodequeue_save(&$queue) {
    'title' => $queue->title,
    'subqueue_title' => $queue->subqueue_title,
    'size' => $queue->size,
    'link' => $queue->link,
    'link_remove' => $queue->link_remove,
    'owner' => $queue->owner,
    'show_in_links' => ($queue->show_in_links) ? 1 : 0,
    'show_in_tab' => $queue->show_in_tab,
    'show_in_ui' => $queue->show_in_ui,
    'i18n' => $queue->i18n,
    'reverse' => $queue->reverse,
    'reference' => $queue->reference,
  );
Earl Miles's avatar
Earl Miles committed
  if (!isset($queue->qid)) {
    $queue->qid = db_insert('nodequeue_queue')
      ->fields($nodequeue_queue_fields)
      ->execute();
Earl Miles's avatar
Earl Miles committed
    if (function_exists('views_invalidate_cache')) {
      views_invalidate_cache();
    }
Earl Miles's avatar
Earl Miles committed
  }
  else {
    db_update('nodequeue_queue')
      ->fields($nodequeue_queue_fields)
      ->condition('qid', $queue->qid)
      ->execute();

    db_delete('nodequeue_roles')
      ->condition('qid', $queue->qid)
      ->execute();
    db_delete('nodequeue_types')
      ->condition('qid', $queue->qid)
      ->execute();
Earl Miles's avatar
Earl Miles committed
  }

Earl Miles's avatar
Earl Miles committed
  if (is_array($queue->roles)) {
    foreach ($queue->roles as $rid) {
      db_insert('nodequeue_roles')
        ->fields(array(
          'qid' => $queue->qid,
          'rid' => $rid,
        ))
        ->execute();
    }
Earl Miles's avatar
Earl Miles committed
  }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
  if (is_array($queue->types)) {
    foreach ($queue->types as $type) {
      db_insert('nodequeue_types')
        ->fields(array(
          'qid' => $queue->qid,
          'type' => $type,
        ))
        ->execute();
    }
Earl Miles's avatar
Earl Miles committed
  }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
  // set our global that tells us whether or not we need to activate hook_link
  if (db_query("SELECT COUNT(*) FROM {nodequeue_queue} WHERE link <> ''")->fetchField()) {
Earl Miles's avatar
Earl Miles committed
    variable_set('nodequeue_links', TRUE);
  }
  else {
    variable_set('nodequeue_links', FALSE);
  }
Earl Miles's avatar
Earl Miles committed

Earl Miles's avatar
Earl Miles committed
  if (isset($queue->add_subqueue) && is_array($queue->add_subqueue)) {
    foreach ($queue->add_subqueue as $reference => $title) {
      // If reference is unset it should be set to the qid; this is generally
      // used for a single subqueue; setting the reference to the qid makes
      // it easy to find that one subqueue.
      if ($reference == 0) {
        $reference = $queue->qid;
      }
      nodequeue_add_subqueue($queue, $title, $reference);
    }
  }
  return $queue->qid;
Earl Miles's avatar
Earl Miles committed
/**
 * Delete a nodequeue.
 */
Earl Miles's avatar
Earl Miles committed
function nodequeue_delete($qid) {
  db_delete('nodequeue_roles')
    ->condition('qid', $qid)
    ->execute();
  db_delete('nodequeue_types')
    ->condition('qid', $qid)
    ->execute();

  db_delete('nodequeue_queue')
    ->condition('qid', $qid)
    ->execute();

  db_delete('nodequeue_nodes')
    ->condition('qid', $qid)
    ->execute();

  db_delete('nodequeue_subqueue')
    ->condition('qid', $qid)
    ->execute();

  // Invoke a hook to notify other modules that a nodequeue has been deleted.
  module_invoke_all('nodequeue_delete', $qid);
Earl Miles's avatar
Earl Miles committed
}

Earl Miles's avatar
Earl Miles committed
/**
 * Add a new subqueue to a queue.
 *
 * @param $queue
 *   The queue object that is the parent of this subqueue.
 * @param $title
 *   The title of the subqueue.
Earl Miles's avatar
Earl Miles committed
 * @param $reference
 *   A reference that uniquely identifies this subqueue. If NULL it will
Earl Miles's avatar
Earl Miles committed
 */
function nodequeue_add_subqueue(&$queue, $title, $reference = NULL) {
  if (empty($reference)) {
    $insert_reference = "";
  }
  else {
    $insert_reference = $reference;
Earl Miles's avatar
Earl Miles committed
  $subqueue->reference = $reference;
  $subqueue->qid = $queue->qid;
  $subqueue->title = $title;

  $subqueue->sqid = db_insert('nodequeue_subqueue')
    ->fields(array(
      'qid' => $queue->qid,
      'reference' => $insert_reference,
      'title' => $title,
    ))
    ->execute();

  // If somehow the $reference is null, here we set it to the sqid.
  // We have to do it here, because before the insert we don't know what the sqid will be.
  if (empty($reference)) {
    db_update('nodequeue_subqueue')
      ->fields(array('reference' => $subqueue->sqid))
      ->condition('sqid', $subqueue->sqid)
      ->execute();