You are here

notifications.manage.inc in Notifications 6.4

Common functions for bulk management of subscriptions

File

notifications.manage.inc
View source
<?php

/**
 * @file
 *   Common functions for bulk management of subscriptions
 */

/**
 * Menu callback: user subscriptions management
 */
function notifications_manage_user_subscriptions($form_state, $account) {
  module_load_include('inc', 'notifications', 'notifications.pages');
  if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
    $form = notifications_multiple_delete_confirm($form_state, array_filter($form_state['values']['subscriptions']));
    return $form;
  }
  $form = notifications_subscriptions_filter_form();
  $form['filters']['#title'] = t('Filter');

  // Display collapsed only when no filters set
  $form['filters'] += array(
    '#collapsible' => TRUE,
    '#collapsed' => empty($_SESSION['subscriptions_overview_filter']),
  );
  $form['#theme'] = 'notifications_subscriptions_filter_form';
  $form['admin'] = notifications_manage_subscriptions_form($account);
  return $form;
}

/**
 * Check access for current user to manage subscriptions
 * 
 * @param $sids
 *   Array of subscription ids
 */
function notifications_manage_subscriptions_access($sids) {
  global $user;
  if (user_access('administer notifications') || user_access('manage all subscriptions')) {
    return TRUE;
  }
  else {
    $params = array_merge(array(
      $user->uid,
    ), array_values($sids));
    $count = db_result(db_query("SELECT COUNT(*) FROM {notifications} WHERE uid = %d AND sid IN (" . db_placeholders($sids) . ')', $params));
    return $count == count($sids);
  }
}

/**
 * Administer user subscriptions
 * 
 * @param $account
 *   User account or destination
 */
function notifications_manage_subscriptions_form($account = NULL, $full = TRUE) {
  $filter = notifications_subscriptions_build_filter_query($account);
  if ($account) {
    $result = pager_query('SELECT n.*, d.address FROM {notifications} n INNER JOIN {messaging_destination} d ON n.mdid = d.mdid ' . $filter['join'] . $filter['where'] . ' ORDER BY n.sid DESC', 50, 0, NULL, $filter['args']);
  }
  else {
    $result = pager_query('SELECT n.*, d.address, u.name AS user_name FROM {notifications} n INNER JOIN {messaging_destination} d ON n.mdid = d.mdid ' . $filter['join'] . ' INNER JOIN {users} u ON n.uid = u.uid ' . $filter['where'] . ' ORDER BY n.sid DESC', 50, 0, NULL, $filter['args']);
  }
  $form = notifications_manage_subscriptions_form_options($account);
  $form_destination = drupal_get_destination();
  $subscriptions = array();
  $status = Notifications_Subscription::status_list();
  $send_methods = messaging_method_info(NULL, 'name');
  $send_intervals = notifications_send_intervals();
  while ($object = db_fetch_object($result)) {
    $sub = notifications_load_subscription($object);
    $subscriptions[$sub->sid] = '';

    // Naming for this specific subscription, formatted strings
    $form['type'][$sub->sid] = array(
      '#value' => $sub
        ->get_type('title'),
    );

    // If full loading, load full subscription and add description
    if ($full) {
      $form['description'][$sub->sid] = array(
        '#value' => $sub
          ->get_name(),
      );
    }

    // If not account, this is an admin form for multiple users, print full account and address
    if (!$account) {
      if ($sub->uid) {
        $username = $sub
          ->get_user_name();
      }
      else {

        // Anonymous subscription, print destination instead
        $dest = $sub
          ->get_destination();
        $username = $dest
          ->address_name() . ' ' . l($dest
          ->format_address(FALSE), 'notifications/destination/' . $sub->mdid . '/manage');
      }
      $form['username'][$sub->sid] = array(
        '#value' => $username,
      );
    }
    $form['send_method'][$sub->sid] = array(
      '#value' => !empty($send_methods[$sub->send_method]) ? $send_methods[$sub->send_method] : $sub->send_method,
    );
    $form['send_interval'][$sub->sid] = array(
      '#value' => !empty($send_intervals[$sub->send_interval]) ? $send_intervals[$sub->send_interval] : $sub->send_interval,
    );
    $form['status'][$sub->sid] = array(
      '#value' => $status[$sub->status],
    );

    // These links will be different depending on whether we are under admin or user account
    if ($account) {
      $operations = array(
        l(t('edit'), 'user/' . $account->uid . '/notifications/subscriptions/edit/' . $sub->sid, array(
          'query' => $form_destination,
        )),
        l(t('drop'), 'user/' . $account->uid . '/notifications/subscriptions/delete/' . $sub->sid, array(
          'query' => $form_destination,
        )),
      );
    }
    else {
      $operations = array(
        l(t('edit'), 'notifications/subscription/' . $sub->sid, array(
          'query' => $form_destination,
        )),
        l(t('drop'), 'notifications/unsubscribe/sid/' . $sub->sid, array(
          'query' => $form_destination,
        )),
      );
    }
    $form['operations'][$sub->sid] = array(
      '#value' => implode(', ', $operations),
    );
  }
  $form['subscriptions'] = array(
    '#type' => 'checkboxes',
    '#options' => $subscriptions,
  );
  $form['pager'] = array(
    '#value' => theme('pager', NULL, 50, 0),
  );
  $form['#theme'] = 'notifications_manage_subscriptions';
  return $form;
}

/**
 * Form options
 */
function notifications_manage_subscriptions_form_options($account) {
  $form['options'] = array(
    '#type' => 'fieldset',
    '#title' => t('Update options'),
    '#prefix' => '<div class="container-inline">',
    '#suffix' => '</div>',
  );
  $options = array();
  foreach (notifications_subscriptions_operations($account) as $operation => $array) {
    if (!empty($array['parent'])) {
      $options[$array['parent']][$operation] = $array['label'];
    }
    else {
      $options[$operation] = $array['label'];
    }
  }
  $form['options']['operation'] = array(
    '#type' => 'select',
    '#options' => $options,
    '#default_value' => 'approve',
  );
  $form['options']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Update'),
    '#validate' => array(
      'notifications_manage_subscriptions_form_validate',
    ),
    '#submit' => array(
      'notifications_manage_subscriptions_form_submit',
    ),
  );
  return $form;
}

/**
 * Validate notifications_admin_subscriptions form submissions.
 * 
 * Check if any items have been selected to perform the chosen
 * 'Update option' on.
 */
function notifications_manage_subscriptions_form_validate($form, &$form_state) {
  $items = array_filter($form_state['values']['subscriptions']);
  if (count($items) == 0) {
    form_set_error('', t('No items selected.'));
  }
  else {
    if (!notifications_manage_subscriptions_access(array_keys($items))) {
      form_set_error('', t('You don\'t have permissions to manage these subscriptions'));
    }
  }
}

/**
 * Handle manage form submissions, run batch operations
 */
function notifications_manage_subscriptions_form_submit($form, &$form_state) {
  $operations = notifications_subscriptions_operations();
  $operation = $operations[$form_state['values']['operation']];

  // Filter out unchecked subscriptions
  $items = array_filter($form_state['values']['subscriptions']);
  if ($function = $operation['callback']) {

    // Add in callback arguments if present.
    if (isset($operation['callback arguments'])) {
      $args = array_merge(array(
        $items,
      ), $operation['callback arguments']);
    }
    else {
      $args = array(
        $items,
      );
    }
    call_user_func_array($function, $args);
  }
  else {

    // We need to rebuild the form to go to a second step.  For example, to
    // show the confirmation form for the deletion of subscriptions.
    $form_state['rebuild'] = TRUE;
  }
}

/**
 * Manage destination form. Edit subscriptions for a destination
 */
function notifications_manage_destination_form($form_state, $destination) {
  module_load_include('inc', 'notifications', 'notifications.pages');
  notifications_include('destination.inc');
  if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
    $form = notifications_multiple_delete_confirm($form_state, array_filter($form_state['values']['subscriptions']));
    return $form;
  }

  //$form = notifications_destination_view_subform($destination);
  $form['description'] = notifications_destination_subform($destination);
  $form['admin'] = notifications_destination_manage_subform($destination);
  $form['admin'] += notifications_manage_subscriptions_form_options($destination);
  $form['extra'] = notifications_manage_destination_extra($destination);
  return $form;
}

/**
 * Manage destination extra options for administrators
 */
function notifications_manage_destination_extra($destination) {
  if (user_access('administer notifications') && function_exists('notifications_anonymous_manage_links')) {
    foreach (_notifications_anonymous_manage_links('destination', $destination) as $link) {
      $url = url($link['href'], $link['options']);
      $rows[] = array(
        $link['title'],
        l($url, $url),
      );
    }
    $form['links'] = array(
      '#type' => 'item',
      '#title' => t('Anonymous links for this destination'),
      '#value' => theme('table', array(), $rows),
    );
    return $form;
  }
  else {
    return array();
  }
}

/**
 * Build query for node administration filters based on session.
 */
function notifications_subscriptions_build_filter_query($account = NULL) {
  $filters = notifications_subscriptions_filters();

  // Build query
  $where = $args = array();
  $join = '';

  // If account passed, will be the first condition
  if ($account) {
    $where[] = "n.uid = %d";
    $args[] = $account->uid;
  }
  foreach ($_SESSION['subscriptions_overview_filter'] as $index => $filter) {
    list($key, $value) = $filter;
    switch ($key) {
      case 'status':
      case 'send_interval':
        $where[] = "n.{$key} = %d";
        $args[] = $value;
        break;
      case 'send_method':
      case 'type':
        $where[] = "n.{$key} = '%s'";
        $args[] = $value;
        break;
    }
    $args[] = $value;
  }
  $where = count($where) ? 'WHERE ' . implode(' AND ', $where) : '';
  return array(
    'where' => $where,
    'join' => $join,
    'args' => $args,
  );
}

/**
 * List node administration filters that can be applied.
 * 
 * @param $admin
 *   Whether this is for the site admin page, will display more options
 */
function notifications_subscriptions_filters($admin = FALSE) {
  global $user;
  $filters['status'] = array(
    'title' => t('status'),
    'options' => Notifications_Subscription::status_list(),
  );
  $filters['type'] = array(
    'title' => t('type'),
    // If not admin page, check access to each type
    'options' => notifications_subscription_types(NULL, 'title', !$admin),
  );
  $filters['send_method'] = array(
    'title' => t('method'),
    // If not admin mode, filter for current user
    'options' => _notifications_send_methods($admin ? NULL : $user),
  );
  $filters['send_interval'] = array(
    'title' => t('interval'),
    'options' => notifications_send_intervals(),
  );

  // Take out the filters when only one option
  foreach ($filters as $key => $data) {
    if (empty($data['options']) || count($data['options']) == 1) {
      unset($filters[$key]);
    }
  }
  return $filters;
}

/**
 * Subscription mass operations.
 * 
 * @param $account
 *   User account if we are administering subscriptions for this user
 */
function notifications_subscriptions_operations($account = NULL) {
  $operations = array(
    'activate' => array(
      'label' => t('Activate'),
      'callback' => 'notifications_subscriptions_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'status' => Notifications_Subscription::STATUS_ACTIVE,
        ),
      ),
    ),
    'deactivate' => array(
      'label' => t('Deactivate'),
      'callback' => 'notifications_subscriptions_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'status' => Notifications_Subscription::STATUS_INACTIVE,
        ),
      ),
    ),
    'delete' => array(
      'label' => t('Delete'),
      'callback' => NULL,
    ),
  );

  // Block option only for administrators
  if (user_access('administer notifications') || user_access('manage all subscriptions')) {
    $operations['block'] = array(
      'label' => t('Block'),
      'callback' => 'notifications_subscriptions_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'status' => Notifications_Subscription::STATUS_BLOCKED,
        ),
      ),
    );
  }

  // Sending methods, not for destination
  if (!empty($account->mdid)) {
    $parent = t('Change send method to');
    foreach (_notifications_send_methods($account) as $key => $name) {
      $operations['send_method-' . $key] = array(
        'label' => $name,
        'parent' => $parent,
        'callback' => 'notifications_subscriptions_mass_update',
        'callback arguments' => array(
          'updates' => array(
            'send_method' => $key,
          ),
        ),
      );
    }
  }
  $parent = t('Change send interval to');
  foreach (notifications_send_intervals() as $key => $name) {
    $operations['send_method-' . $key] = array(
      'label' => $name,
      'parent' => $parent,
      'callback' => 'notifications_subscriptions_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'send_interval' => $key,
        ),
      ),
    );
  }

  // Intervals
  return $operations;
}

/**
 * Make mass update of subscriptions, changing all nodes in the $nodes array
 * to update them with the field values in $updates.
 *
 * IMPORTANT NOTE: This function is intended to work when called
 * from a form submit handler. Calling it outside of the form submission
 * process may not work correctly.
 *
 * @param array $subscriptions
 *   Array of subscriptions nid to update.
 * @param array $updates
 *   Array of key/value pairs with node field names and the
 *   value to update that field to.
 */
function notifications_subscriptions_mass_update($subscriptions, $updates) {
  foreach ($subscriptions as $id) {
    _notifications_subscriptions_mass_update_helper($id, $updates);
  }
  drupal_set_message(t('The update has been performed.'));
}
function _notifications_subscriptions_mass_update_helper($sid, $updates) {
  $subs = notifications_load_subscription($sid);
  foreach ($updates as $name => $value) {
    $subs->{$name} = $value;
  }
  notifications_save_subscription($subs);
  return $subs;
}

/**
 * Form for multiple delete. When account passed check that all subscriptions belong to the user account
 */
function notifications_multiple_delete_confirm(&$form_state, $items, $destination = NULL) {
  $destination = $destination ? $destination : $_GET['q'];
  if (notifications_manage_subscriptions_access(array_keys($items))) {
    $form['items'] = array(
      '#prefix' => '<ul>',
      '#suffix' => '</ul>',
      '#tree' => TRUE,
    );

    // array_filter returns only elements with TRUE values
    foreach ($items as $id => $value) {

      // Load the subscription to display a friendly name
      $subscription = notifications_load_subscription($id);
      $form['items'][$id] = array(
        '#type' => 'hidden',
        '#value' => $id,
        '#prefix' => '<li>',
        '#suffix' => $subscription
          ->format_long() . "</li>\n",
      );
    }
    $form['operation'] = array(
      '#type' => 'hidden',
      '#value' => 'delete',
    );
    $form['#submit'][] = 'notifications_multiple_delete_confirm_submit';
    $form['#validate'][] = 'notifications_multiple_delete_confirm_validate';
    $form['#redirect'] = $destination;
    return confirm_form($form, t('Are you sure you want to delete these items?'), $destination, t('This action cannot be undone.'), t('Delete all'), t('Cancel'));
  }
  else {
    drupal_set_message(t('Validation error. You don\'t have permission to delete some of these subscriptions'), 'error');
    drupal_access_denied();
  }
}

/**
 * Validate permissions to delete all the subscriptions
 */
function notifications_multiple_delete_confirm_validate($form, &$form_state) {
  if (!notifications_manage_subscriptions_access(array_keys($form_state['values']['items']))) {
    form_set_error('', t('You don\'t have permission to manage all these subscriptions'));
  }
}

/**
 * Submit multiple delete from
 */
function notifications_multiple_delete_confirm_submit($form, &$form_state) {
  if ($form_state['values']['confirm']) {
    notifications_subscription_delete(array_keys($form_state['values']['items']));
    drupal_set_message(t('The subscriptions have been deleted.'));
  }
  return;
}

/**
 * Return form for node administration filters.
 * 
 * @param $admin
 *   Whether this is for the site admin page, will display more options
 */
function notifications_subscriptions_filter_form($admin = FALSE) {
  $session =& $_SESSION['subscriptions_overview_filter'];
  $session = is_array($session) ? $session : array();
  $filters = notifications_subscriptions_filters($admin);
  $i = 0;
  $form['filters'] = array(
    '#type' => 'fieldset',
    '#title' => t('Show only items where'),
    '#theme' => 'node_filters',
  );
  $form['#submit'][] = 'notifications_subscriptions_filter_form_submit';
  foreach ($session as $filter) {
    list($type, $value) = $filter;
    $value = $filters[$type]['options'][$value];
    $form['filters']['current'][] = array(
      '#value' => t('<strong>%a</strong> is <strong>%b</strong>', array(
        '%a' => $filters[$type]['title'],
        '%b' => $value,
      )),
    );
  }
  foreach ($filters as $key => $filter) {
    $names[$key] = $filter['title'];
    $form['filters']['status'][$key] = array(
      '#type' => 'select',
      '#options' => $filter['options'],
    );
  }
  $form['filters']['filter'] = array(
    '#type' => 'radios',
    '#options' => $names,
    '#default_value' => 'status',
  );
  $form['filters']['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => count($session) ? t('Refine') : t('Filter'),
  );
  if (count($session)) {
    $form['filters']['buttons']['undo'] = array(
      '#type' => 'submit',
      '#value' => t('Undo'),
    );
    $form['filters']['buttons']['reset'] = array(
      '#type' => 'submit',
      '#value' => t('Reset'),
    );
  }
  drupal_add_js('misc/form.js', 'core');
  return $form;
}

/**
 * Process result from node administration filter form.
 */
function notifications_subscriptions_filter_form_submit($form, &$form_state) {
  $filters = notifications_subscriptions_filters();
  switch ($form_state['values']['op']) {
    case t('Filter'):
    case t('Refine'):
      if (isset($form_state['values']['filter'])) {
        $filter = $form_state['values']['filter'];

        // Flatten the options array to accommodate hierarchical/nested options.
        $flat_options = form_options_flatten($filters[$filter]['options']);
        if (isset($flat_options[$form_state['values'][$filter]])) {
          $_SESSION['subscriptions_overview_filter'][] = array(
            $filter,
            $form_state['values'][$filter],
          );
        }
      }
      break;
    case t('Undo'):
      array_pop($_SESSION['subscriptions_overview_filter']);
      break;
    case t('Reset'):
      $_SESSION['subscriptions_overview_filter'] = array();
      break;
  }
}

/**
 * Theme subscriptions management form
 *
 * @ingroup themeable
 */
function theme_notifications_manage_subscriptions($form) {

  // If there are rows in this form, then $form['title'] contains a list of
  // the title form elements.
  $has_posts = isset($form['type']) && is_array($form['type']);
  $select_header = $has_posts ? theme('table_select_header_cell') : '';
  $header = array(
    $select_header,
  );
  $header[] = t('Type');
  if (!empty($form['description'])) {
    $header[] = t('Description');
  }
  if (!empty($form['username'])) {
    $header[] = t('User');
  }
  if (!empty($form['send_method'])) {
    $header[] = t('Send method');
  }
  if (!empty($form['send_interval'])) {
    $header[] = t('Send interval');
  }
  $header[] = t('Status');
  $header[] = t('Operations');
  $output = '';
  $output .= drupal_render($form['options']);
  if ($has_posts) {
    foreach (element_children($form['type']) as $key) {
      $row = array();
      $row[] = drupal_render($form['subscriptions'][$key]);
      $row[] = drupal_render($form['type'][$key]);
      if (isset($form['description'])) {
        $row[] = drupal_render($form['description'][$key]);
      }
      if (isset($form['username'])) {
        $row[] = drupal_render($form['username'][$key]);
      }
      if (isset($form['send_method'])) {
        $row[] = drupal_render($form['send_method'][$key]);
      }
      if (isset($form['send_interval'])) {
        $row[] = drupal_render($form['send_interval'][$key]);
      }
      $row[] = drupal_render($form['status'][$key]);
      $row[] = drupal_render($form['operations'][$key]);
      $rows[] = $row;
    }
  }
  else {
    $rows[] = array(
      array(
        'data' => t('No subscriptions available.'),
        'colspan' => '6',
      ),
    );
  }
  $output .= theme('table', $header, $rows);
  if ($form['pager']['#value']) {
    $output .= drupal_render($form['pager']);
  }
  $output .= drupal_render($form);
  return $output;
}

/**
 * Theme node administration filter form.
 *
 * @ingroup themeable
 */
function theme_notifications_subscriptions_filter_form($form) {
  $output = '';
  $output .= '<div id="notifications-admin-filter">';
  $output .= drupal_render($form['filters']);
  $output .= '</div>';
  $output .= drupal_render($form);
  return $output;
}

Functions

Namesort descending Description
notifications_manage_destination_extra Manage destination extra options for administrators
notifications_manage_destination_form Manage destination form. Edit subscriptions for a destination
notifications_manage_subscriptions_access Check access for current user to manage subscriptions
notifications_manage_subscriptions_form Administer user subscriptions
notifications_manage_subscriptions_form_options Form options
notifications_manage_subscriptions_form_submit Handle manage form submissions, run batch operations
notifications_manage_subscriptions_form_validate Validate notifications_admin_subscriptions form submissions.
notifications_manage_user_subscriptions Menu callback: user subscriptions management
notifications_multiple_delete_confirm Form for multiple delete. When account passed check that all subscriptions belong to the user account
notifications_multiple_delete_confirm_submit Submit multiple delete from
notifications_multiple_delete_confirm_validate Validate permissions to delete all the subscriptions
notifications_subscriptions_build_filter_query Build query for node administration filters based on session.
notifications_subscriptions_filters List node administration filters that can be applied.
notifications_subscriptions_filter_form Return form for node administration filters.
notifications_subscriptions_filter_form_submit Process result from node administration filter form.
notifications_subscriptions_mass_update Make mass update of subscriptions, changing all nodes in the $nodes array to update them with the field values in $updates.
notifications_subscriptions_operations Subscription mass operations.
theme_notifications_manage_subscriptions Theme subscriptions management form
theme_notifications_subscriptions_filter_form Theme node administration filter form.
_notifications_subscriptions_mass_update_helper