From 4add29d83b034639857893ab6f9ffc4ea7c0f4f0 Mon Sep 17 00:00:00 2001
From: Mark Carver <mark.carver@me.com>
Date: Wed, 2 Jan 2013 13:02:48 -0600
Subject: [PATCH] [#371328] - Views integration for userqueue.

---
 includes/views/userqueue.views.inc                 | 174 +++++++++++++++++++++
 includes/views/userqueue_handler_argument_uqid.inc |  17 ++
 .../views/userqueue_handler_filter_in_queue.inc    |  11 ++
 .../userqueue_handler_relationship_userqueue.inc   |  76 +++++++++
 userqueue.info                                     |   8 +
 userqueue.module                                   |  99 +++++++++++-
 userqueue.pages.inc                                |   2 +-
 7 files changed, 381 insertions(+), 6 deletions(-)
 create mode 100644 includes/views/userqueue.views.inc
 create mode 100644 includes/views/userqueue_handler_argument_uqid.inc
 create mode 100644 includes/views/userqueue_handler_filter_in_queue.inc
 create mode 100644 includes/views/userqueue_handler_relationship_userqueue.inc

diff --git a/includes/views/userqueue.views.inc b/includes/views/userqueue.views.inc
new file mode 100644
index 0000000..71c7d04
--- /dev/null
+++ b/includes/views/userqueue.views.inc
@@ -0,0 +1,174 @@
+<?php
+// $Id: $
+
+/**
+ * @file userqueue.views.inc
+ * Provides support for the Views module.
+ */
+
+
+
+function userqueue_views_handlers() {
+  return array(
+  'info' => array(
+    'path' => drupal_get_path('module', 'userqueue') .'/includes/views',
+    ),
+    'handlers' => array(
+      'userqueue_handler_argument_uqid' => array(
+         'parent' => 'views_handler_argument_numeric',
+       ),
+      'userqueue_handler_field_queue_tab' => array(
+        'parent' => 'views_handler_field_node_link',
+      ),
+      'userqueue_handler_filter_in_queue' => array(
+        'parent' => 'views_handler_filter_boolean_operator',
+      ),
+      'userqueue_handler_relationship_userqueue' => array(
+        'parent' => 'views_handler_relationship',
+      ),
+    ),
+  );
+}
+/**
+ * Implementation of hook_views_data()
+ */
+function userqueue_views_data() {
+  $data = array();
+
+  // ----------------------------------------------------------------
+  // userqueue_user table
+  $data['userqueue_user']['table']['group'] = t('Userqueue');
+
+  // The nodequeue_nodes table is how nodequeue connects to the
+  // rest of the world, but we will only join it in via relationship.
+
+  // position
+  $data['userqueue_user']['position'] = array(
+    'title' => t('Position'),
+    'help' => t('The position of the user within a queue.'),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+     ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+  );
+
+  $data['userqueue_user']['uqid'] = array(
+    'title' => t('Queue ID'),
+    'help' => t('The ID of the queue the user belongs to.'),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+     ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'userqueue_handler_argument_uqid',
+      'name field' => 'title',
+      'name table' => 'userqueue',
+      'empty field name' => t('No queue'),
+    ),
+  );
+
+  // specialized is null/is not null filter
+  $data['userqueue_user']['in_queue'] = array(
+    'title' => t('In queue'),
+    'help' => t('Filter to ensure a user IS or IS NOT in the related queue'),
+    'filter' => array(
+      'handler' => 'userqueue_handler_filter_in_queue',
+      'label' => t('In queue'),
+    ),
+  );
+
+  // ----------------------------------------------------------------
+  // nodequeue_queue table
+  $data['userqueue']['table']['group'] = t('Userqueue');
+
+  // For use with the relationship.
+  $data['userqueue']['table']['join'] = array(
+    'userqueue_user' => array(
+      'left_field' => 'uqid',
+      'field' => 'uqid',
+    ),
+  );
+
+  $data['userqueue']['title'] = array(
+    'title' => t('Queue title'),
+    'help' => t('The title of the userqueue.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+     ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+
+  return $data;
+}
+
+/**
+ * Implementation of hook_views_data_alter().
+ */
+function userqueue_views_data_alter(&$data) {
+  // queue relationship
+  $data['users']['userqueue_rel'] = array(
+    'group' => t('Userqueue'),
+    'title' => t('Queue'),
+    'help' => t('Create a relationship to a userqueue.'),
+    'real field' => 'uid',
+    'relationship' => array(
+      'handler' => 'userqueue_handler_relationship_userqueue',
+      'base' => 'userqueue_user',
+      'field' => 'uid',
+      'label' => t('queue'),
+    ),
+  );
+
+  // links
+  $data['users']['userqueue_links'] = array(
+    'group' => t('Userqueue'),
+    'title' => t('Add/remove links'),
+    'help' => t('Display add/remove links for all eligible userqueues. Note that this performs a user_load so could add many extra queries to a view.'),
+    'real field' => 'uid',
+    'field' => array(
+      'handler' => 'userqueue_handler_field_links',
+    ),
+  );
+
+  $data['users']['userqueue_queue_tab'] = array(
+    'group' => t('Userqueue'),
+    'title' => t('Link to tab'),
+    'help' => t('Display add/remove links for all eligible userqueues. Note that this performs a user_load so could add many extra queries to a view.'),
+    'real field' => 'uid',
+    'field' => array(
+      'handler' => 'userqueue_handler_field_queue_tab',
+    ),
+  );
+
+  // all queues
+  $data['users']['userqueue_all_queues'] = array(
+    'group' => t('Userqueue'),
+    'title' => t('All queues'),
+    'help' => t('Display all queues a user is a member of.'),
+    'real field' => 'uid',
+    'field' => array(
+      'handler' => 'userqueue_handler_field_all_queues',
+    ),
+  );
+}
diff --git a/includes/views/userqueue_handler_argument_uqid.inc b/includes/views/userqueue_handler_argument_uqid.inc
new file mode 100644
index 0000000..8e97423
--- /dev/null
+++ b/includes/views/userqueue_handler_argument_uqid.inc
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Argument handler for subqueues.
+ *
+ * Subqueues have titles that are determined by doing substitution from
+ * the subqueue_title on the queue using the title on the subqueue, which
+ * takes a little extra work to do here.
+ */
+class userqueue_handler_argument_uqid extends views_handler_argument_numeric {
+  function title_query() {
+    foreach ($this->value as &$uqid) {
+      $queue = userqueue_load($this->value[0]);
+      $uqid = $queue ? $queue->title : $this->value;
+    }
+    return $this->value;
+  }
+}
diff --git a/includes/views/userqueue_handler_filter_in_queue.inc b/includes/views/userqueue_handler_filter_in_queue.inc
new file mode 100644
index 0000000..7ca39de
--- /dev/null
+++ b/includes/views/userqueue_handler_filter_in_queue.inc
@@ -0,0 +1,11 @@
+<?php
+//$Id: $
+/**
+ * Handler to filter for users that are not in a queue.
+ */
+class userqueue_handler_filter_in_queue extends views_handler_filter_boolean_operator {
+  function query() {
+    $this->ensure_my_table();
+    $this->query->add_where($this->options['group'], "$this->table_alias.uid", $this->value, ($this->value ? 'IS NOT NULL' : 'IS NULL'));
+  }
+}
diff --git a/includes/views/userqueue_handler_relationship_userqueue.inc b/includes/views/userqueue_handler_relationship_userqueue.inc
new file mode 100644
index 0000000..b27168c
--- /dev/null
+++ b/includes/views/userqueue_handler_relationship_userqueue.inc
@@ -0,0 +1,76 @@
+<?php
+//$Id$
+/**
+ * Specialized relationship handler to add userqueues.
+ */
+class userqueue_handler_relationship_userqueue extends views_handler_relationship {
+  function options(&$options) {
+    parent::options($options);
+
+    $options['limit'] = FALSE;
+    $options['uqids'] = array();
+  }
+
+  /**
+   * Default options form that provides the label widget that all fields
+   * should have.
+   */
+  function options_form(&$form, &$form_state) {
+    parent::options_form($form, $form_state);
+
+
+    $form['limit'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Limit to one or more queues (recommended)'),
+      '#default_value'=> $this->options['limit'],
+    );
+
+    $options = array();
+    $queues = userqueue_load_queues();
+    foreach ($queues as $queue) {
+      $options[$queue->uqid] = $queue->title;
+    }
+    $form['uqids'] = array(
+      '#prefix' => '<div><div id="edit-options-uqids">',
+      '#suffix' => '</div></div>',
+      '#type' => 'checkboxes',
+      '#title' => t('Queues'),
+      '#options' => $options,
+      '#default_value' => $this->options['uqids'],
+      '#process' => array('form_process_checkboxes', 'ctools_dependent_process'),
+      '#dependency' => array('edit-options-limit' => array(TRUE)),
+    );
+  }
+
+  /**
+   * Called to implement a relationship in a query.
+   */
+  function query() {
+    // Figure out what base table this relationship brings to the party.
+    $join = new views_join();
+    $join->definition = array(
+      'table' => 'userqueue_user',
+      'field' => 'uid',
+      'left_table' => 'users',
+      'left_field' => 'uid',
+    );
+
+    if (!empty($this->options['required'])) {
+      $join->definition['type'] = 'INNER';
+    }
+
+    if (!empty($this->options['limit'])) {
+      $join->definition['extra'] = array(array(
+        'field' => 'uqid',
+        'value' => array_filter($this->options['uqids']),
+        'numeric' => TRUE,
+      ));
+    }
+
+    $join->construct();
+
+    $alias = $join->definition['table'] . '_' . $join->definition['left_table'];
+
+    $this->alias = $this->query->add_relationship($alias, $join, 'userqueue_user', $this->relationship);
+  }
+}
diff --git a/userqueue.info b/userqueue.info
index ffc5422..3430442 100644
--- a/userqueue.info
+++ b/userqueue.info
@@ -5,3 +5,11 @@ core = 7.x
 configure = admin/structure/userqueue/settings
 core = "7.x"
 project = "userqueue"
+
+; Includes
+files[] = includes/views/userqueue.views.inc
+
+; Views Handlers
+files[] = includes/views/userqueue_handler_argument_uqid.inc
+files[] = includes/views/userqueue_handler_filter_in_queue.inc
+files[] = includes/views/userqueue_handler_relationship_userqueue.inc
diff --git a/userqueue.module b/userqueue.module
index d2c0790..f8e5576 100644
--- a/userqueue.module
+++ b/userqueue.module
@@ -55,13 +55,29 @@ function userqueue_menu() {
     'file' => 'userqueue.admin.inc',
     'type' => MENU_CALLBACK,
   );
-  $items['userqueue/%userqueue/remove-user/%user'] = array(
+  $items['userqueue/%userqueue/remove/%user'] = array(
     'page callback' => 'userqueue_admin_remove_user',
     'page arguments' => array(1, 3),
     'access arguments' => array('administer user queues'),
     'file' => 'userqueue.pages.inc',
     'type' => MENU_CALLBACK
   );
+  $items['userqueue/%userqueue/add/%user'] = array(
+    'title' => 'Add user to queue',
+    'page callback' => 'userqueue_add_user_callback',
+    'page arguments' => array(1, 3),
+    'access arguments' => array('administer user queues'),
+    'type' => MENU_CALLBACK,
+  );
+  $items['user/%user/userqueue'] = array(
+    'title' => '@tab',
+    'title arguments' => array('@tab' => variable_get('userqueue_tab_name', 'Userqueue')),
+    'access arguments' => array('administer user queues'),
+    'page callback' => 'userqueue_user_tab',
+    'page arguments' => array(1),
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 5
+  );
   return $items;
 }
 
@@ -99,14 +115,14 @@ function userqueue_load($uqid) {
 function userqueue_get_users($queue) {
   $result = db_select('userqueue_user', 'uu')
       -> fields('uu', array('uid', 'position'))
-      -> condition('uqid', $queue -> uqid)
+      -> condition('uqid', $queue->uqid)
       -> orderBy('position', 'ASC')
       -> execute();
   $users = array();
   foreach ($result as $row) {
-    $account = user_load($row -> uid);
-    $account -> position = $row -> position;
-    $users[$row -> uid] = $account;
+    $account = user_load($row->uid);
+    $account->position = $row->position;
+    $users[$row->uid] = $account;
   }
   return $users;
 }
@@ -211,3 +227,76 @@ function userqueue_create_queue($queue) {
     return $queue;
   }
 }
+
+ /**
+ * Callback to add a user to a queue
+ */
+function userqueue_add_user_callback($queue, $user) {
+  // Get the max weight (+1) for the queue. If there is nothing in the queue, $weight should be null...
+  $weight = db_select('userqueue_user', 'uq')
+      ->fields('uq', array('position'))
+      ->condition('uqid', $queue->uqid)
+      ->orderBy('position', 'DESC')
+      ->range(0,1)
+      ->execute()
+      ->fetchField();
+  // ... so if $weight is not set, make it zero.
+  if (!$weight) {
+    $weight = 0;
+  }
+
+  // Add the user to the userqueue
+  $record = array(
+    'uqid' => $queue->uqid,
+    'uid' => $user->uid,
+    'weight' => $weight,
+  );
+
+  drupal_write_record('userqueue_user', $record);
+
+  if (isset($_REQUEST['destination'])) {
+    drupal_goto($_REQUEST['destination']);
+  }
+  else {
+    drupal_goto("admin/user/userqueue/{$queue->uqid}/view");
+  }
+}
+
+/**
+ * Implementation of hook_views_api()
+ */
+function userqueue_views_api() {
+  return array(
+    'api' => 2,
+    'path' => drupal_get_path('module', 'userqueue') .'/includes/views',
+  );
+}
+
+function userqueue_user_tab($user) {
+  $output = '';
+  $queues = userqueue_load_queues();
+  if (!empty($queues)) {
+    $headers = array(
+      array('data' => t('Title'), 'class' => 'userqueue-title'),
+      array('data' => t('Max Queue Size'), 'class' => 'userqueue-max-queue-size'),
+      array('data' => t('In Queue'), 'class' => 'userqueue-in-queue'),
+      array('data' => t('Operation'), 'class' => 'userqueue-operation'),
+    );
+    $rows = array();
+    foreach ($queues as $uqid => $queue) {
+      $users = userqueue_get_users($queue);
+      $op = l('Add to queue', "userqueue/{$uqid}/add/{$user->uid}", array('query' => array('destination' => "user/{$user->uid}/userqueue")));
+      if (isset($users[$user->uid])) {
+        $op = l('Remove from queue', "userqueue/{$uqid}/remove/{$user->uid}", array('query' => array('destination' => "user/{$user->uid}/userqueue")));
+      }
+      $rows[] = array(
+        array('class' => 'userqueue-title',          'data' => l($queue->title, "userqueue/{$uqid}")),
+        array('class' => 'userqueue-max-queue-size', 'data' => ($queue->size == 0 ? t('Infinite') : $queue->size)),
+        array('class' => 'userqueue-in-queue',       'data' => count($users)),
+        array('class' => 'userqueue-operations',     'data' => $op),
+      );
+    }
+    $output = theme('table', array('header' => $headers, 'rows' => $rows));
+  }
+  return $output;
+}
diff --git a/userqueue.pages.inc b/userqueue.pages.inc
index 18b99ad..a852f98 100644
--- a/userqueue.pages.inc
+++ b/userqueue.pages.inc
@@ -55,7 +55,7 @@ function userqueue_arrange_subqueue_form($form, $form_state, $queue, $users) {
       ),
       'query' => drupal_get_destination(),
     );
-    $form['users'][$account->uid]['remove'] = array('#markup' => l(t('remove'), 'userqueue/' . $queue->uqid . '/remove-user/' . $account->uid, $attr));
+    $form['users'][$account->uid]['remove'] = array('#markup' => l(t('remove'), 'userqueue/' . $queue->uqid . '/remove/' . $account->uid, $attr));
   }
 
   // Textfield for adding users to the queue.
-- 
1.7.11.5

