From 5503f4f6f7931e098b97ac91cf54736fe68a9d47 Mon Sep 17 00:00:00 2001
From: Mikkel Hoegh <mikkel@hoegh.org>
Date: Wed, 25 Apr 2012 16:54:50 +0200
Subject: [PATCH] Added Rules integration.

---
 includes/nodequeue.admin.inc |    6 ++
 includes/nodequeue.rules.inc |  176 ++++++++++++++++++++++++++++++++++++++++++
 includes/nodequeue.token.inc |   37 +++++++++
 nodequeue.module             |   24 +++++-
 4 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 includes/nodequeue.rules.inc
 create mode 100644 includes/nodequeue.token.inc

diff --git a/includes/nodequeue.admin.inc b/includes/nodequeue.admin.inc
index 2f483c1..86df3af 100644
--- a/includes/nodequeue.admin.inc
+++ b/includes/nodequeue.admin.inc
@@ -999,6 +999,12 @@ function nodequeue_save_subqueue_order($nodes, $qid, $sqid) {
     nodequeue_check_subqueue_size($queue, $subqueue);
   }
 
+  // As there's no API for saving a subqueue, we have to trigger the nodequeue save event here.
+  // There might be some other places where we have to add these lines.
+  if (module_exists('rules')) {
+    rules_invoke_event('nodequeue_saved', $subqueue, NULL);
+  }
+
   return array(NODEQUEUE_OK, 'The queue has been updated.');
 }
 
diff --git a/includes/nodequeue.rules.inc b/includes/nodequeue.rules.inc
new file mode 100644
index 0000000..48db68a
--- /dev/null
+++ b/includes/nodequeue.rules.inc
@@ -0,0 +1,176 @@
+<?php
+/**
+ * @file
+ * Provides nodequeue (subqueue) rules integration.
+ */
+
+/**
+ * Implementation of hook_rules_event_info().
+ * 
+ * Events are triggered by invokations of rules_invoke_event('EVENT_NAME', $nodequeue, $node);
+ */
+function nodequeue_rules_event_info() {
+  $items = array();
+  
+  // arguments provided by all events
+  $args = array(
+    'nodequeue' => array(
+      'type' => 'nodequeue',
+      'label' => t('Changed nodequeue'),
+    ),
+    'node' => array(
+      'type' => 'node',
+      'label' => t('Queued node'),
+    ),    
+  );
+ 
+  $items['nodequeue_added'] = array(
+    'label' => t('Node has been added to a nodequeue'),
+    'module' => 'Nodequeue',
+    'arguments' => $args,
+  );
+  
+  $items['nodequeue_removed'] = array(
+    'label' => t('Node has been removed from a nodequeue'),
+    'module' => 'Nodequeue',
+    'arguments' => $args,
+  );
+  
+  $items['nodequeue_saved'] = array(
+    'label' => t('Nodequeue has been updated'),
+    'module' => 'Nodequeue',
+    'arguments' => $args,
+  );
+  
+  $items['nodequeue_node_changed'] = array(
+    'label' => t("A nodequeue's node has been updated"),
+    'module' => 'Nodequeue',
+    'arguments' => $args,
+  );  
+ 
+  return $items;
+}
+
+/**
+ * Implementation of hook_rules_data_type_info().
+ * 
+ * We define a nodequeue data type to be used as a ruleset argument.
+ */
+function nodequeue_rules_data_type_info() {
+  return array(
+    'nodequeue' => array(
+      'label' => t('Nodequeue'),
+      'class' => 'nodequeue_rules_data_type_nodequeue',
+      'savable' => FALSE,
+      'identifiable' => TRUE,
+      'module' => 'Nodequeue',
+    ),      
+  );
+}
+
+// Load rules, so we can extend its classes.
+rules_include();
+
+/**
+ * Defines the nodequeue type
+ */
+class nodequeue_rules_data_type_nodequeue extends rules_data_type {
+  function load($sqid) {
+    return nodequeue_load_subqueue($sqid);
+  }
+  function get_identifier() {
+    $nodequeue = &$this->get();
+    return $nodequeue->sqid;
+  }
+}
+
+/**
+ * Implementation of hook_rules_condition_info().
+ * 
+ * As we have generic events, e. g. node added to nodequeue, 
+ * we might also want to identify and filter by certain nodequeues.
+ */
+function nodequeue_rules_condition_info() {
+  $items = array();
+  
+  $items['nodequeue_rules_condition_belongs_to_nodequeue'] = array(
+    'label' => t("Belongs to Nodequeue(s)"),
+    'help' => t('Evaluates to TRUE, if the given nodequeue is one of the selected nodequeues.'),
+    'module' => 'Nodequeue',
+    'arguments' => array(
+      'nodequeue' => array(
+        'type' => 'nodequeue',
+        'label' => t('Nodequeue'),
+      ),
+    ),
+  );
+  
+  return $items;
+}
+
+/**
+ * The condition verifies if the provided nodequeue argument is contained within the configured nodequeues.
+ * 
+ * @param $nodequeue
+ *   nodequeue (subqueue) object
+ * @param $settings
+ *   form settings
+ * @return boolean
+ *   boolean indicating whether the conditions applies
+ */
+function nodequeue_rules_condition_belongs_to_nodequeue($nodequeue, $settings) {
+  if (in_array($nodequeue->qid, $settings['queues'])) {
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**
+ * Configurable condition form for nodequeue matching.
+ * 
+ * @param $settings
+ *   form settings
+ * @param $form
+ *   form items
+ * @param $form_state
+ *   form values
+ */
+function nodequeue_rules_condition_belongs_to_nodequeue_form($settings, &$form, &$form_state) {
+  $settings += array('queues' => '');
+  $form['settings']['queues'] = array(
+    '#type' => 'select',
+    '#multiple' => TRUE,
+    '#title' => t('Nodequeues'),
+    '#default_value' => $settings['queues'],
+    '#description' => t('Select one or more nodequeues which should be matched.'),
+    '#required' => TRUE,
+  );
+  
+  // Fetch all of the queues.
+  $queues = nodequeue_load_queues(nodequeue_get_all_qids());
+  foreach ($queues as $queue) {
+    $form['settings']['queues']['#options'][$queue->qid] = $queue->title;
+  }
+}
+
+/**
+ * Implementation of hook_nodequeue_add().
+ */
+function nodequeue_nodequeue_add($sqid, $nid) {
+  // When a node is added to a nodequeue invoke the corresponding rules event
+  $subqueue = nodequeue_load_subqueue($sqid);
+  rules_invoke_event('nodequeue_added', array('nodequeue' => $subqueue, 'node' => $nid));
+  rules_invoke_event('nodequeue_saved', array('nodequeue' => $subqueue, 'node' => $nid));
+}
+
+/**
+ * Implementation of hook_nodequeue_remove().
+ */
+function nodequeue_nodequeue_remove($sqid, $nid) {
+  // When a node is added to a nodequeue invoke the corresponding rules event
+  $subqueue = nodequeue_load_subqueue($sqid);
+  rules_invoke_event('nodequeue_removed', array('nodequeue' => $subqueue, 'node' => $nid));
+  rules_invoke_event('nodequeue_saved', array('nodequeue' => $subqueue, 'node' => $nid));
+}
diff --git a/includes/nodequeue.token.inc b/includes/nodequeue.token.inc
new file mode 100644
index 0000000..c83d144
--- /dev/null
+++ b/includes/nodequeue.token.inc
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @file
+ * Tokens for a nodequeue (subqueue).
+ */
+
+/**
+ * Implementation of hook_token_values().
+ */
+function nodequeue_token_values($type, $object = NULL, $options = array()) {
+  $values = array();
+  if ($type == 'nodequeue' && !empty($object)) {
+    $nodequeue = $object;
+    $values['sqid'] = $nodequeue->sqid;
+    $values['qid'] = $nodequeue->qid;
+    $values['reference'] = $nodequeue->reference;
+    $values['title'] = $nodequeue->title;
+  }
+
+  return $values;
+}
+
+/**
+ * Implementation of hook_token_list().
+ */
+function nodequeue_token_list($type = 'all') {
+  $tokens = array();
+
+  if ($type == 'nodequeue' || $type == 'all') {
+    $tokens['nodequeue']['sqid'] = t('Subqueue ID');
+    $tokens['nodequeue']['qid'] = t('Nodequeue ID');
+    $tokens['nodequeue']['reference'] = t('Subqueue reference');
+    $tokens['nodequeue']['title'] = t('Subqueue title');
+  }
+
+  return $tokens;
+}
diff --git a/nodequeue.module b/nodequeue.module
index 20a749a..e393360 100644
--- a/nodequeue.module
+++ b/nodequeue.module
@@ -13,6 +13,18 @@ define('NODEQUEUE_DUPLICATE_POSITION', 3);
 /* --- HOOKS ---------------------------------------------------------------- */
 
 /**
+ * Implementation of hook_init().
+ */
+function nodequeue_init() {
+  if (module_exists('rules')) { // rules support, e. g. events, conditions
+    module_load_include('inc', 'nodequeue', 'includes/nodequeue.rules');
+  }
+  if (module_exists('token')) { // nodequeue tokens support
+    module_load_include('inc', 'nodequeue', 'includes/nodequeue.token');
+  }
+}
+
+/**
  * Implementation of hook_perm
  */
 function nodequeue_perm() {
@@ -164,7 +176,17 @@ function nodequeue_menu() {
  */
 function nodequeue_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
   switch ($op) {
-    case 'delete':
+    case 'insert':
+    case 'update':
+      if (module_exists('rules')) {
+        // We check here if the changed node is member of a nodequeue and trigger separate events for each assignment.
+        $result = db_query("SELECT qid, sqid FROM {nodequeue_nodes} WHERE nid = %d", $node->nid);
+        while ($obj = db_fetch_object($result)) { // pass on the corresponding subqueue
+          rules_invoke_event('nodequeue_node_changed', array('nodequeue' => nodequeue_load_subqueue($obj->sqid), 'node' => $node));
+        }
+      }
+      break;
+   case 'delete':
       // 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 = %d", $node->nid);
       while ($obj = db_fetch_object($result)) {
-- 
1.7.9.6

