You are here

nodejs_subscribe.module in Node.js integration 6

Same filename and directory in other branches
  1. 7 nodejs_subscribe/nodejs_subscribe.module

File

nodejs_subscribe/nodejs_subscribe.module
View source
<?php

/**
 * Implements hook_nodeapi().
 */
function nodejs_subscribe_nodeapi(&$node, $op, $teaser, $page) {
  switch ($op) {
    case 'load':
      $result = db_fetch_object(db_query('SELECT nid, subscribe FROM {nodejs_subscribe_node} WHERE nid = "%d"', $node->nid));
      $node->nodejs_subscribe = $result->subscribe;
      break;
    case 'delete':
      db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
      if (nodejs_subscribe_is_node_subscribed_to($node->nid)) {
        nodejs_subscribe_send_notification($node, 'deleted');
      }
      break;
    case 'insert':
      if (isset($node->nodejs_subscribe)) {
        if ($node->nodejs_subscribe['nodejs_subscriptions_allowed']) {
          db_query('INSERT INTO {nodejs_subscribe_node} (nid, subscribe) VALUES (%d, %d)', $node->nid, 1);
        }
      }
      break;
    case 'update':
      global $user;
      if (isset($node->nodejs_subscribe)) {
        if ($node->nodejs_subscribe['nodejs_subscriptions_allowed']) {
          $transaction = db_transaction();
          try {
            db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
            db_query('INSERT INTO {nodejs_subscribe_node} (nid, subscribe) VALUES (%d, %d)', $node->nid, $node->nodejs_subscribe['nodejs_subscriptions_allowed']);
          } catch (Exception $e) {
            $transaction
              ->rollback();
            watchdog('nodejs_subscribe', t('Error processing node subscription for nid %nid', array(
              ':nid' => $node->nid,
            )));
          }
        }
        else {
          db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
        }
      }
      if (nodejs_subscribe_is_node_subscribed_to($node->nid)) {
        nodejs_subscribe_send_notification($node, 'update');
      }
      break;
    case 'view':
      global $user;

      //var_dump($node);

      // If node allows nodejs subscriptions and user has permission to subscribe,
      // then provide "Subscribe" or "Unsubscribe" links.
      if (isset($node->nodejs_subscribe) && $node->nodejs_subscribe && user_access('Subscribe to realtime content updates')) {
        $links = array();
        $node_title_stripped = strip_tags($node->title);
        if (nodejs_subscribe_is_user_subscribed_to_node($user->uid, $node->nid)) {
          $links['nodejs-subscribe-unsubscribe-node'] = array(
            'title' => t('Unsubscribe'),
            'href' => "nodejs/unsubscribe/{$node->nid}",
            'attributes' => array(
              'class' => array(
                'nodejs-subscribe-node-link',
              ),
              'title' => t('Unsubscribe to @title', array(
                '@title' => $node_title_stripped,
              )),
            ),
          );
        }
        else {
          $links['nodejs-subscribe-subscribe-node'] = array(
            'title' => t('Subscribe'),
            'href' => "nodejs/subscribe/{$node->nid}",
            'attributes' => array(
              'class' => array(
                'nodejs-subscribe-node-link',
              ),
              'title' => t('Subscribe to @title', array(
                '@title' => $node_title_stripped,
              )),
            ),
          );
        }
        $node->content['links']['nodejs_subscribe'] = array(
          '#theme' => 'links__node__nodejs_subscribe',
          '#links' => $links,
          '#attributes' => array(
            'class' => array(
              'links',
              'inline',
            ),
          ),
        );
      }
      break;
  }
}

/**
 * Implements hook_menu().
 */
function nodejs_subscribe_menu() {
  return array(
    'nodejs/subscribe/%node' => array(
      'title' => t('Subscribe to a node'),
      'page callback' => 'nodejs_subscribe_subscribe_node',
      'page arguments' => array(
        2,
      ),
      'access arguments' => array(
        'Subscribe to realtime content updates',
      ),
      'type' => MENU_CALLBACK,
    ),
    'nodejs/unsubscribe/%node' => array(
      'title' => t('Subscribe to a node'),
      'page callback' => 'nodejs_subscribe_unsubscribe_node',
      'page arguments' => array(
        2,
      ),
      'access arguments' => array(
        'Subscribe to realtime content updates',
      ),
      'type' => MENU_CALLBACK,
    ),
  );
}

/**
 * Implements hook_perm().
 */
function nodejs_subscribe_perm() {

  /*return array(
      'nodejs subscribe to node' => array(
        'title' => t('Subscribe to realtime content updates'),
        'description' => t('Allows users to subscribe to content and receive realtime notifications.'),
      ),
    );*/
  return array(
    'Subscribe to realtime content updates',
  );
}

/**
 * Implements hook_comment_insert().
 */
function nodejs_subscribe_comment_insert($comment) {
  if (nodejs_subscribe_is_node_subscribed_to($comment->nid)) {
    nodejs_subscribe_send_notification(node_load($comment->nid), 'commented on', array(
      'fragment' => 'comment-' . $comment->cid,
    ));
  }
}

/**
 * Implements hook_nodejs_user_channels().
 */
function nodejs_subscribe_nodejs_user_channels($account) {
  $channels = array();
  foreach (nodejs_subscribe_get_user_channels($account->uid) as $subscription) {
    $channels[] = 'nodejs_subscribe_node_' . $subscription->nid;
  }
  return $channels;
}

/**
 * Check to see if anyone is subscribed to this node.
 * 
 * @param mixed $nid 
 * @return boolean
 */
function nodejs_subscribe_is_node_subscribed_to($nid) {
  return db_query('SELECT COUNT(*) subscription_count FROM {nodejs_subscribe_subscription} WHERE nid = %d', $nid);
}

/**
 * Check to see if the given uid is subscribed to the given node.
 * 
 * @param mixed $uid 
 * @param mixed $nid 
 * @return boolean
 */
function nodejs_subscribe_is_user_subscribed_to_node($uid, $nid) {
  return db_fetch_object(db_query('SELECT nid FROM {nodejs_subscribe_subscription} WHERE uid = %d AND nid = %d', $uid, $nid));
}

/**
 * Get a list of channels this user is subscribed to.
 *
 * @param mixed $uid
 * @return array
 */
function nodejs_subscribe_get_user_channels($uid) {
  return db_fetch_object(db_query('SELECT nid FROM {nodejs_subscribe_subscription} WHERE uid = %d', $uid));
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function nodejs_subscribe_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['#node']) && $form['#node']->type . '_node_form' == $form_id) {
    $subscriptions_allowed = FALSE;
    if (!empty($form['#node']->nid)) {
      if (isset($form['#node']->nodejs_subscribe)) {
        $subscriptions_allowed = $form['#node']->nodejs_subscribe ? '1' : '0';
      }
    }
    $form['nodejs_subscribe'] = array(
      '#type' => 'fieldset',
      '#title' => t('Realtime notifications'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#group' => 'additional_settings',
      '#attributes' => array(
        'class' => array(
          'nodejs-subscribe-form',
        ),
      ),
      '#access' => TRUE,
      '#weight' => 30,
      '#tree' => TRUE,
    );
    $form['nodejs_subscribe']['nodejs_subscriptions_allowed'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow users to subscribe'),
      '#description' => t('Allow users to subscribe for realtime notifications'),
      '#default_value' => $subscriptions_allowed,
    );
  }
}

/**
 * Page callback for unsubscribing to a node.
 */
function nodejs_subscribe_unsubscribe_node($node) {
  global $user;
  nodejs_subscribe_delete($node, $user->uid);
  drupal_set_message(t("You have been unsubscribed from '%node_title'.", array(
    '%node_title' => $node->title,
  )));
  drupal_goto('node/' . $node->nid);
}

/**
 * Page callback for subscribing/unsubscribing to a node.
 */
function nodejs_subscribe_subscribe_node($node) {
  global $user;
  if (!nodejs_subscribe_is_user_subscribed_to_node($user->uid, $node->nid)) {
    nodejs_subscribe_insert($node, $user->uid);
    drupal_set_message(t("You have subscribed to '%node_title'.", array(
      '%node_title' => $node->title,
    )));
  }
  drupal_goto('node/' . $node->nid);
}

/**
 * Implements hook_node_load().
 */
function nodejs_subscribe_node_load($nodes, $types) {
  $result = db_query('SELECT nid, subscribe FROM {nodejs_subscribe_node} WHERE nid IN (:nids)', array(
    ':nids' => array_keys($nodes),
  ));
  foreach ($result as $record) {
    $nodes[$record->nid]->nodejs_subscribe = $record->subscribe;
  }
}

/**
 * Implements hook_node_insert().
 */
function nodejs_subscribe_node_insert($node) {
  if (isset($node->nodejs_subscribe)) {
    if ($node->nodejs_subscribe['nodejs_subscriptions_allowed']) {
      db_query('INSERT INTO {nodejs_subscribe_node} (nid, subscribe) VALUES (%d, %d)', $node->nid, 1);
    }
  }
}

/**
 * Implements hook_node_update().
 *
 * TODO: When disabling subscriptions for users on a node, delete all active subscriptions
 */
function nodejs_subscribe_node_update($node) {
  global $user;
  if (isset($node->nodejs_subscribe)) {
    if ($node->nodejs_subscribe['nodejs_subscriptions_allowed']) {
      $transaction = db_transaction();
      try {
        db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
        db_query('INSERT INTO {nodejs_subscribe_node} (nid, subscribe) VALUES (%d, %d)', $node->nid, $node->nodejs_subscribe['nodejs_subscriptions_allowed']);
      } catch (Exception $e) {
        $transaction
          ->rollback();
        watchdog('nodejs_subscribe', t('Error processing node subscription for nid %nid', array(
          ':nid' => $node->nid,
        )));
      }
    }
    else {
      db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
    }
  }
  if (nodejs_subscribe_is_node_subscribed_to($node->nid)) {
    nodejs_subscribe_send_notification($node, 'update');
  }
}

/**
 * Implements hook_node_delete().
 *
 * TODO: When a node is deleted, delete subscriptions of all users on this node.
 */
function nodejs_subscribe_node_delete($node) {
  db_query('DELETE FROM {nodejs_subscribe_node} WHERE nid = %d', $node->nid);
  if (nodejs_subscribe_is_node_subscribed_to($node->nid)) {
    nodejs_subscribe_send_notification($node, 'deleted');
  }
}

/**
 * Implements hook_node_view().
 */
function nodejs_subscribe_node_view($node, $view_mode) {
  global $user;

  // If node allows nodejs subscriptions and user has permission to subscribe,
  // then provide "Subscribe" or "Unsubscribe" links.
  if (isset($node->nodejs_subscribe) && $node->nodejs_subscribe && user_access('nodejs subscribe to node') && in_array($view_mode, array(
    'full',
    'teaser',
  ))) {
    $links = array();
    $node_title_stripped = strip_tags($node->title);
    if (nodejs_subscribe_is_user_subscribed_to_node($user->uid, $node->nid)) {
      $links['nodejs-subscribe-unsubscribe-node'] = array(
        'title' => t('Unsubscribe'),
        'href' => "nodejs/unsubscribe/{$node->nid}",
        'attributes' => array(
          'class' => array(
            'nodejs-subscribe-node-link',
          ),
          'title' => t('Unsubscribe to @title', array(
            '@title' => $node_title_stripped,
          )),
        ),
      );
    }
    else {
      $links['nodejs-subscribe-subscribe-node'] = array(
        'title' => t('Subscribe'),
        'href' => "nodejs/subscribe/{$node->nid}",
        'attributes' => array(
          'class' => array(
            'nodejs-subscribe-node-link',
          ),
          'title' => t('Subscribe to @title', array(
            '@title' => $node_title_stripped,
          )),
        ),
      );
    }
    $node->content['links']['nodejs_subscribe'] = array(
      '#theme' => 'links__node__nodejs_subscribe',
      '#links' => $links,
      '#attributes' => array(
        'class' => array(
          'links',
          'inline',
        ),
      ),
    );
  }
}

/**
 * Delete a subscription to a node.
 * 
 * @param mixed $node
 * @param mixed $uid
 * @return boolean
 */
function nodejs_subscribe_delete($node, $uid) {
  nodejs_remove_user_from_channel($uid, 'nodejs_subscribe_node_' . $node->nid);
  return db_query('DELETE FROM {nodejs_subscribe_subscription} WHERE nid = %d AND uid = %d', $node->nid, $uid);
}

/**
 * Create subscription to a node for a given user.
 * 
 * @param mixed $node
 * @param mixed $uid
 * @return boolean
 */
function nodejs_subscribe_insert($node, $uid) {
  nodejs_add_user_to_channel($uid, 'nodejs_subscribe_node_' . $node->nid);
  return db_query('INSERT INTO {nodejs_subscribe_subscription} (nid, uid) VALUES (%d, %d)', $node->nid, $uid);
}

/**
 * Send a message that the given node was updated.
 * 
 * @param mixed $node
 * @param mixed $action
 * @param array $link_options
 */
function nodejs_subscribe_send_notification($node, $action, $link_options = array()) {
  $subject = t('Node %action.', array(
    '%action' => $action,
  ));
  $link = l($node->title, 'node/' . $node->nid);
  $body = t('The node !link was %action.', array(
    '!link' => $link,
    '%action' => $action,
  ));
  $message = (object) array(
    'broadcast' => FALSE,
    'channel' => 'nodejs_subscribe_node_' . $node->nid,
    'data' => (object) array(
      'subject' => $subject,
      'body' => $body,
    ),
  );
  nodejs_enqueue_message($message);
}

Functions

Namesort descending Description
nodejs_subscribe_comment_insert Implements hook_comment_insert().
nodejs_subscribe_delete Delete a subscription to a node.
nodejs_subscribe_form_alter Implements hook_form_BASE_FORM_ID_alter().
nodejs_subscribe_get_user_channels Get a list of channels this user is subscribed to.
nodejs_subscribe_insert Create subscription to a node for a given user.
nodejs_subscribe_is_node_subscribed_to Check to see if anyone is subscribed to this node.
nodejs_subscribe_is_user_subscribed_to_node Check to see if the given uid is subscribed to the given node.
nodejs_subscribe_menu Implements hook_menu().
nodejs_subscribe_nodeapi Implements hook_nodeapi().
nodejs_subscribe_nodejs_user_channels Implements hook_nodejs_user_channels().
nodejs_subscribe_node_delete Implements hook_node_delete().
nodejs_subscribe_node_insert Implements hook_node_insert().
nodejs_subscribe_node_load Implements hook_node_load().
nodejs_subscribe_node_update Implements hook_node_update().
nodejs_subscribe_node_view Implements hook_node_view().
nodejs_subscribe_perm Implements hook_perm().
nodejs_subscribe_send_notification Send a message that the given node was updated.
nodejs_subscribe_subscribe_node Page callback for subscribing/unsubscribing to a node.
nodejs_subscribe_unsubscribe_node Page callback for unsubscribing to a node.