You are here

notifications_ui.module in Notifications 5

User Interface for subscriptions modules

File

notifications_ui/notifications_ui.module
View source
<?php

/**
 * @file
 * User Interface for subscriptions modules
 */

/**
 * Implementation of hook_help()
 */
function notifications_ui_help($section) {
  switch ($section) {
    case 'admin/messaging/notifications/ui':
      $output = '<p>' . t('These are UI settings only. They will be combined with other settings and permissions to determine which subscription options will be finally available for each page.') . '</p>';
      if (module_exists('notifications_content')) {
        $output .= '<p>' . t('To enable different subscription options for each content type visit the !content-type-settings', array(
          '!content-type-settings' => l(t('content types settings page'), 'admin/content/types'),
        )) . '</p>';
      }
      return $output;
  }
}

/**
 * Implementation of hook_menu
 */
function notifications_ui_menu($may_cache) {
  $items = array();
  if (!$may_cache) {
    $items[] = array(
      'path' => 'admin/messaging/notifications/ui',
      'title' => t('User Interface'),
      'description' => t('Enables site settings for user subscriptions.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => 'notifications_ui_settings_form',
      'access' => user_access('administer site configuration'),
      'type' => MENU_LOCAL_TASK,
    );
  }
  return $items;
}

/**
 * Implementation of hook_notifications.
 */
function notifications_ui_notifications($op, $arg0, $arg1 = NULL, $arg2 = NULL) {
  if ($op == 'event trigger') {
    $event = $arg0;
    if ($event->type == 'node' && isset($event->node->subscriptions)) {
      if ($event->action == 'insert') {

        // On insert some field information will be missing, we need to recreate it.
        foreach ($event->node->subscriptions['params'] as $i => $subscriptions) {
          foreach ($subscriptions['fields'] as $key => $value) {
            if (!$value && isset($event->params[$key])) {
              $event->node->subscriptions['params'][$i]['fields'][$key] = $event->params[$key];
            }
          }
        }
      }
      notifications_ui_node_form_submit('', array(
        'subscriptions' => $event->node->subscriptions,
      ));
    }
    elseif ($event->type == 'node' && isset($event->comment->subscriptions)) {
      notifications_ui_node_form_submit('', array(
        'subscriptions' => $event->comment->subscriptions,
      ));
    }
  }
}

/**
 *  Site-wide settings form.
 */
function notifications_ui_settings_form() {
  $form['notifications_ui_types'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Enabled subscription types'),
    '#options' => notifications_subscription_types(NULL, 'title'),
    '#default_value' => variable_get('notifications_ui_types', array()),
    '#description' => t('Check the subscription types the UI module should show.'),
  );
  $form['notifications_link_teaser'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show subscribe link with teaser'),
    '#default_value' => variable_get('notifications_link_teaser', 1),
    '#description' => t('Uncheck to show links only in full node view. This will work only for content types that have subscription links enabled.'),
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_form_alter()
 * 
 */
function notifications_ui_form_alter($form_id, &$form) {
  global $user;

  // Content type settings
  if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {

    // Just in case we want to add more settings here
    $form['workflow']['notifications_node_ui'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Subscriptions UI'),
      '#default_value' => notifications_ui_type_options($form['#node_type']->type),
      '#options' => _notifications_ui_type_options(),
      '#description' => t('Enable different display options for subscriptions to this content type'),
    );
  }
  elseif (isset($form['type']) && $form['type']['#value'] . '_node_form' == $form_id && notifications_ui_type_options($form['#node']->type, 'form')) {

    //  Add node forms.
    $node = $form['#node'];
    $form[] = notifications_ui_node_form($node);
  }
  elseif ($form_id == 'comment_form') {

    // Add to comment forms.
    $node = node_load($form['nid']['#value']);
    if ($user->uid && notifications_ui_type_options($node->type, 'comment')) {
      $form[] = notifications_ui_node_form($node);
    }
  }
}

/**
 * Form for node subscriptions
 * @ TODO: offer the same form in a block to be put in the contents region.
 *
 * @param $node
 *   a node object
 * @param $subform
 *   Optional produce subform instead of full form with buttons
 * @return 
 *   Partial subscription form, just missing submit button.
 */
function notifications_ui_node_form($node, $subform = TRUE) {
  global $user;
  $form = array();
  $node_options = notifications_ui_user_node($user, $node);
  if (count($node_options)) {

    // Process all options building the array of indexed params for each
    $options = $params = $defaults = array();
    $index = 1;

    // If we start with zero, get some value sent as 0 => 0
    $number = 0;

    // Number of subscriptions
    foreach ($node_options as $option) {
      $options[$index] = $option['name'];

      // Check wether user is subscribed
      if (!empty($option['subscription'])) {
        $params[$index] = (array) $option['subscription'];
        $defaults[] = $index;
        $number++;
      }
      else {
        $params[$index] = $option;
      }
      $index++;
    }

    // Now we have compiled the data, build the form. Note that we are passing the parameters
    // in the 'params' value as an array, while the checkboxes are in 'options' fieldset
    if ($subform) {
      $form['subscriptions'] = array(
        '#type' => 'fieldset',
        '#title' => t('Subscriptions (%number)', array(
          '%number' => $number,
        )),
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
        '#tree' => TRUE,
      );
    }
    else {
      $form['subscriptions'] = array(
        '#tree' => TRUE,
      );
    }
    $form['subscriptions']['params'] = array(
      '#type' => 'value',
      '#value' => $params,
    );
    $form['subscriptions']['options'] = array(
      '#type' => 'checkboxes',
      '#default_value' => $defaults,
      '#options' => $options,
    );
    $form['subscriptions']['account'] = array(
      '#type' => 'value',
      '#value' => $user,
    );
    if (!$subform) {
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Update'),
      );
    }
  }

  // Allow other modules, i.e. autosubscribe to change this form
  notifications_alter('node_form', $form);
  return $form;
}

/**
 * Form submission, node subscriptions form
 */
function notifications_ui_node_form_submit($form_id, $form_values) {
  $uid = $form_values['subscriptions']['account']->uid;
  foreach ($form_values['subscriptions']['options'] as $index => $value) {
    $subscription = $form_values['subscriptions']['params'][$index] + array(
      'uid' => $uid,
      'event_type' => 'node',
    );
    if ($value) {
      notifications_save_subscription($subscription);
    }
    elseif (!empty($subscription['sid'])) {
      notifications_delete_subscription($subscription['sid']);
    }
  }
  drupal_set_message(t('Your subscriptions have been updated.'));
}

/**
 * Implementation of hook_link()
 * 
 * Add subscriptions links to nodes
 */
function notifications_ui_link($type, $node = NULL, $teaser = FALSE) {
  global $user;
  $links = array();
  if ($type == 'node' && $user->uid && (variable_get('notifications_link_teaser', 1) || !$teaser) && notifications_ui_type_options($node->type, 'links')) {

    // Now we have the array of allowed options ready, build links
    foreach (notifications_ui_user_node($user, $node) as $index => $option) {
      if (!empty($option['subscription'])) {

        // Unsubscribe link
        $title = t('Unsubscribe from: !name', array(
          '!name' => $option['name'],
        ));
        $props = notifications_get_link('unsubscribe', array(
          'sid' => $option['subscription']->sid,
        ));
      }
      else {

        // Subscribe link
        $title = t('Subscribe to: !name', array(
          '!name' => $option['name'],
        ));
        $props = notifications_get_link('subscribe', array(
          'type' => $option['type'],
          'confirm' => TRUE,
          'fields' => $option['fields'],
        ));
      }
      $links['notifications_' . $index] = array(
        'title' => $title,
        'html' => TRUE,
      ) + $props;
    }
  }
  return $links;
}

/**
 * Get list of allowed subscriptions types
 * 
 * Checks permissions and settings
 * 
 * @return
 *   Subscription types allowed for this user
 */
function notifications_ui_allowed_types() {
  $enabled = variable_get('notifications_ui_types', array());
  $allowed = array();
  foreach (notifications_subscription_types() as $type => $info) {
    if (isset($enabled[$type]) && $enabled[$type] && !empty($info['access']) && user_access($info['access'])) {
      $allowed[$type] = $info;
    }
  }
  return $allowed;
}

/**
 * Get list of possible and existing subscriptions for user/node
 * 
 * @return
 *   Array of subscription options
 *   The enabled ones will have a 'subscriptions' element loaded
 */
function notifications_ui_user_node($account, $node) {

  // Get allowed node options and current subscriptions
  $node_options = notifications_module_information('node options', $account, $node);
  $allowed_types = notifications_ui_allowed_types();
  $allowed_options = array();

  // We also keep track of event types for each subscription type
  $event_types = array(
    'node' => TRUE,
  );
  foreach ($node_options as $index => $option) {
    if (isset($allowed_types[$option['type']])) {
      $allowed_options[] = $option;

      // We add the event type to our list
      $event_types[$allowed_types[$option['type']]['event_type']] = TRUE;
    }
  }

  // Check if user is subscribed to show 'subscribe'/'unsubscribe' links
  $subscriptions = array();
  foreach (array_keys($event_types) as $type) {
    if ($more = notifications_user_get_subscriptions($account->uid, $type, $node->nid, $node)) {
      $subscriptions += $more;
    }
  }

  // Populate subscriptions when they exist
  foreach ($allowed_options as $index => $option) {
    foreach ($subscriptions as $sub) {
      if ($sub->type == $option['type'] && !array_diff_key($option['fields'], $sub->fields)) {
        $allowed_options[$index]['subscription'] = $sub;
      }
    }
  }

  // Finally check permissions for all of them
  foreach ($allowed_options as $index => $option) {
    if (!notifications_user_allowed('subscription', $account, (object) $option)) {
      unset($allowed_options[$index]);
    }
  }
  return $allowed_options;
}

/**
 * Implementation of hook_block()
 */
function notifications_ui_block($op = 'list', $delta = 0) {
  if ($op == 'list') {
    $blocks[0]['info'] = t('Subscriptions');
    return $blocks;
  }
  else {
    if ($op == 'view') {
      if (arg(0) == 'node' && is_numeric(arg(1)) && ($node = node_load(arg(1))) && notifications_ui_type_options($node->type, 'block')) {
        $block['subject'] = t('Subscriptions');
        $block['content'] = drupal_get_form('notifications_ui_node_form', $node, FALSE);
        return $block;
      }
    }
  }
}

/**
 * Implementation of hook node_type
 */
function notifications_ui_node_type($op, $info) {
  if ($op == 'delete') {

    // Remove settings for this node type
    variable_del('notifications_node_ui_' . $info->type);
  }
}

/**
 * Get settings value for content types
 * 
 * @param $type
 *   Content type
 * @param $option
 *   Optional option to check
 */
function notifications_ui_type_options($type, $option = NULL, $default = NULL) {

  // The default setting will be 'links' = 1
  $settings = variable_get('notifications_node_ui_' . $type, array(
    'links',
  ));
  if ($option) {
    return is_array($settings) && in_array($option, $settings) ? TRUE : $default;
  }
  else {
    return $settings;
  }
}

/**
 * Allowed options for content types
 */
function _notifications_ui_type_options() {
  return array(
    'form' => t('Display in node form'),
    'comment' => t('Display in comment form'),
    'links' => t('Display as node links'),
    'block' => t('Display in block'),
  );
}

Functions

Namesort descending Description
notifications_ui_allowed_types Get list of allowed subscriptions types
notifications_ui_block Implementation of hook_block()
notifications_ui_form_alter Implementation of hook_form_alter()
notifications_ui_help Implementation of hook_help()
notifications_ui_link Implementation of hook_link()
notifications_ui_menu Implementation of hook_menu
notifications_ui_node_form Form for node subscriptions @ TODO: offer the same form in a block to be put in the contents region.
notifications_ui_node_form_submit Form submission, node subscriptions form
notifications_ui_node_type Implementation of hook node_type
notifications_ui_notifications Implementation of hook_notifications.
notifications_ui_settings_form Site-wide settings form.
notifications_ui_type_options Get settings value for content types
notifications_ui_user_node Get list of possible and existing subscriptions for user/node
_notifications_ui_type_options Allowed options for content types