Index: nodequeue.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/nodequeue/nodequeue.module,v
retrieving revision 1.52
diff -u -p -r1.52 nodequeue.module
--- nodequeue.module	9 Jun 2008 18:00:59 -0000	1.52
+++ nodequeue.module	17 Jul 2008 19:17:38 -0000
@@ -103,12 +103,12 @@ function nodequeue_menu() {
     'page arguments' => array(3),
     'type' => MENU_CALLBACK
   );
-  $items['admin/content/nodequeue/%nodequeue/view'] = array(
+  $items['admin/content/nodequeue/%nodequeue/view/%subqueue'] = array(
     'title' => t('View'),
-    'access arguments' => array(3),
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_view',
-    'page arguments' => array(3),
+    'page arguments' => array(3, 5),
     'weight' => -10,
     'type' => MENU_DEFAULT_LOCAL_TASK
   );
@@ -138,62 +138,58 @@ function nodequeue_menu() {
           $node = node_load($nid);
         }*/
 
-
-  $items["admin/content/nodequeue/%nodequeue/add/%/%node"] = array(
-    'access arguments' => array(6, 3),
+  $items["admin/content/nodequeue/%nodequeue/add/%subqueue/%node"] = array(
+    'access arguments' => array(6, 3, 5),
     'access callback' => 'nodequeue_node_and_queue_access',
     'page callback' => 'nodequeue_admin_add_node',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-  $items["admin/content/nodequeue/%nodequeue/remove-node/%/%node"] = array(
-    'access arguments' => array(6, 3),
+  $items["admin/content/nodequeue/%nodequeue/remove-node/%subqueue/%node"] = array(
+    'access arguments' => array(6, 3, 5),
     'access callback' => 'nodequeue_node_and_queue_access',
     'page callback' => 'nodequeue_admin_remove_node',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-
-  // NB: For the following menu paths, the value in spot 6 is the position, not the nid.
-  $items["admin/content/nodequeue/%nodequeue/up/%/%"] = array(
-    'access arguments' => array(3),
+  $items["admin/content/nodequeue/%nodequeue/up/%subqueue/%"] = array(
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_up',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-  $items["admin/content/nodequeue/%nodequeue/down/%/%"] = array(
-    'access arguments' => array(3),
+  $items["admin/content/nodequeue/%nodequeue/down/%subqueue/%"] = array(
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_down',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-  $items["admin/content/nodequeue/%nodequeue/front/%/%"] = array(
-    'access arguments' => array(3),
+  $items["admin/content/nodequeue/%nodequeue/front/%subqueue/%"] = array(
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_front',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-  $items["admin/content/nodequeue/%nodequeue/back/%/%"] = array(
-    'access arguments' => array(3),
+  $items["admin/content/nodequeue/%nodequeue/back/%subqueue/%"] = array(
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_back',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-  $items["admin/content/nodequeue/%nodequeue/remove/%/%"] = array(
-    'access arguments' => array(3),
+  $items["admin/content/nodequeue/%nodequeue/remove/%subqueue/%"] = array(
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'nodequeue_admin_remove',
     'page arguments' => array(3, 5, 6),
     'type' => MENU_CALLBACK
   );
-
-  $items["admin/content/nodequeue/%nodequeue/clear/%"] = array(
+  $items["admin/content/nodequeue/%nodequeue/clear/%subqueue"] = array(
     'title' => t('Clear'),
-    'access arguments' => array(3),
+    'access arguments' => array(3, 5),
     'access callback' => 'nodequeue_queue_access',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('nodequeue_clear_confirm', 3, 5),
@@ -245,7 +241,6 @@ function nodequeue_link($type, $node = N
     }
 
     nodequeue_set_subqueue_positions($subqueues, $node->nid);
-    //drupal_set_message(dprint_r($subqueues, true));
 
     foreach ($subqueues as $subqueue) {
       $queue = $queues[$subqueue->qid];
@@ -297,10 +292,9 @@ function nodequeue_js_output($label, $hr
  * Page callback to add a node to a queue.
  */
 function nodequeue_admin_add_node($queue, $subqueue, $node) {
-  if (!is_numeric($subqueue) || !nodequeue_check_token($node->nid)) {
+  if (!nodequeue_check_token($node->nid)) {
     return drupal_goto();
   }
-  $subqueue = nodequeue_load_subqueue($subqueue);
   nodequeue_subqueue_add($queue, $subqueue, $node->nid);
 
   // Provide a response if this is javascript.
@@ -325,10 +319,11 @@ function nodequeue_admin_add_node($queue
  * Page callback to remove a node from a queue.
  */
 function nodequeue_admin_remove_node($queue, $subqueue, $node) {
-  if (!is_numeric($subqueue) || !nodequeue_check_token($node->nid)) {
+  if (!nodequeue_check_token($node->nid)) {
+    drupal_set_message("token failed");
     return drupal_goto();
   }
-  $subqueue = nodequeue_load_subqueue($subqueue);
+
   nodequeue_subqueue_remove_node($subqueue->sqid, $node->nid);
 
   // Provide a response if this is javascript.
@@ -413,7 +408,6 @@ function nodequeue_node_tab($node) {
   $output .= theme('table', $header, $rows, array('class' => 'nodequeue-table'));
   drupal_add_js(drupal_get_path('module', 'nodequeue') .'/nodequeue.js');
   drupal_add_css(drupal_get_path('module', 'nodequeue') .'/nodequeue.css');
-
   return $output;
 }
 
@@ -424,6 +418,12 @@ function nodequeue_view_queues() {
   $output = theme('advanced_help_topic', 'nodequeue', 'about', 'icon') . '&nbsp;' . theme('advanced_help_topic', 'nodequeue', 'about', t('Click here for information about this module'));
   // Fetch all of the queues.
   $queues = nodequeue_load_queues(nodequeue_get_all_qids(25));
+  foreach ($queues as $queue) {
+    if (!nodequeue_queue_access($queue)) {
+      unset($queues[$queue->qid]);
+    }
+  }
+
   if (empty($queues)) {
     return $output . t('No nodequeues exist.');
   }
@@ -439,7 +439,9 @@ function nodequeue_view_queues() {
   $subqueues = nodequeue_load_subqueues_by_queue($qids);
   // Relate all the subqueues we loaded back to our queues.
   foreach ($subqueues as $subqueue) {
-    $queues[$subqueue->qid]->subqueue = $subqueue;
+     if (nodequeue_api_subqueue_access($subqueue, NULL, $queues[$subqueue->qid])) {
+       $queues[$subqueue->qid]->subqueue = $subqueue;
+     }
   }
 
   $header = array(t('Title'), t('Max nodes'), t('Subqueues'), t('Operation'));
@@ -1370,6 +1372,10 @@ function _nodequeue_ajax_add($sqid, $pos
     return array('error' => t('Invalid sqid'));
   }
 
+  if (!nodequeue_api_subqueue_access($subqueue)) {
+    return array('error' => t('Access denied'));
+  }
+ 
   $nodes = nodequeue_api_autocomplete($queue, $subqueue, $string);
   if (empty($nodes) || !is_array($nodes)) {
     return array('error' => t('Invalid node'));
@@ -1438,7 +1444,7 @@ class nodequeue_queue {
 /**
  * Return TRUE If the specified account has access to manipulate this queue.
  */
-function nodequeue_queue_access($queue, $account = NULL) {
+function nodequeue_queue_access($queue, $account = NULL, $subqueue = NULL) {
   if (!$account) {
     global $user;
     $account = $user;
@@ -1450,10 +1456,18 @@ function nodequeue_queue_access($queue, 
   }
 
   // Automatically false if they can't manipulate queues at all.
-  if (!user_access('manipulate queues')) {
+  if (!user_access('manipulate queues') || empty($queue->roles)) {
+    return FALSE;
+  }
+
+  if (!nodequeue_api_queue_access($queue, $account)) {
     return FALSE;
   }
 
+  if ($subqueue) {
+    return nodequeue_api_subqueue_access($subqueue, $account);
+  }
+
   $roles = array_keys((array) $account->roles) + array(DRUPAL_AUTHENTICATED_RID);
   return (bool) array_intersect($roles, $queue->roles);
 }
@@ -1479,8 +1493,8 @@ function nodequeue_load_queues_by_type($
  * @param unknown_type $queue
  * @return unknown
  */
-function nodequeue_node_and_queue_access($node, $queue) {
-  return nodequeue_node_access($node->type) && nodequeue_queue_access($queue);
+function nodequeue_node_and_queue_access($node, $queue, $subqueue = NULL) { 
+  return nodequeue_node_access($node->type) && nodequeue_queue_access($queue, NULL, $subqueue);
 }
 
 /**
@@ -1549,18 +1563,15 @@ function nodequeue_get_qids($type, $acco
     // superuser always has access.
     if (!user_access('manipulate all queues', $account)) {
       $roles_join = "INNER JOIN {nodequeue_roles} nr ON nr.qid = nq.qid ";
-      $roles = array_keys((array) $account->roles) + array(DRUPAL_AUTHENTICATED_RID);
-
-      $roles_where .= "AND nr.rid IN (". db_placeholders($role_args, 'int') .")";
+      $role_args = array_keys((array) $account->roles) + array(DRUPAL_AUTHENTICATED_RID);
+      $roles_where .= "AND nr.rid IN (". implode(',', $role_args) .")";
     }
 
     $sql = 'SELECT nq.qid, nq.show_in_tab, nq.show_in_links, show_in_ui '.
       'FROM {nodequeue_queue} nq '.
       'INNER JOIN {nodequeue_types} nt ON nt.qid = nq.qid '. $roles_join .
       "WHERE nt.type = '%s' ". $roles_where;
-    $result = db_query($sql, array_merge(array($type), $roles));
-
-    $qids = array();
+    $result = db_query($sql, array_merge(array($type), $roles));;
     while ($qid = db_fetch_object($result)) {
       $qids[$qid->qid] = $qid;
     }
@@ -1669,6 +1680,16 @@ function nodequeue_load($qid) {
 }
 
 /**
+ * This function exists so that %subqueue will work in hook_menu.
+ */
+function subqueue_load($sqid) {
+  if (!$sqid) {
+    return NULL;
+  }
+  return array_shift(nodequeue_load_subqueues(array($sqid)));
+}
+
+/**
  * Load a list of subqueues
  *
  * This exists to provide a way of loading a bunch of queues with
@@ -1974,7 +1995,6 @@ function nodequeue_subqueue_remove_node(
     nodequeue_subqueue_remove($sqid, $pos);
   }
 }
-
 /**
  * Remove a node or node(s) from a nodequeue by position.
  *
@@ -2473,6 +2493,49 @@ function nodequeue_api_info() {
   return module_invoke_all('nodequeue_info');
 }
 
+function nodequeue_api_queue_access($queue, $account = NULL) {
+  if (!$account) {
+    global $user;
+    $account = $user;
+  }
+
+  if ($queue->owner != 'nodequeue') { // Avoids an infinite loop.
+    $function = $queue->owner . '_queue_access';
+    if (function_exists($function)) {
+      $access = $function($queue, $account);
+    }
+  }
+
+  if (!isset($access)) {
+    $access = TRUE;
+  }
+  return $access;
+}
+
+/**
+ * Allows the owning module of a subqueue to restrict access to viewing and
+ * manipulating the queue.
+ */
+function nodequeue_api_subqueue_access($subqueue, $account = NULL, $queue = NULL) {
+  if (!$account) {
+    global $user;
+    $account = $user;
+  }
+  
+  if (!$queue) {
+    $queue = nodequeue_load($subqueue->qid);
+  }
+
+  $function = $queue->owner . '_subqueue_access';
+  if (function_exists($function)) {
+    $access = $function($subqueue, $account, $queue);
+  }
+
+  if (!isset($access)) {
+    $access = TRUE;
+  }
+  return $access;
+}
 /**
  * Form builder for the nodequeue settings tab.
  */
