You are here

support_reference.module in Support Ticketing System 7

Same filename and directory in other branches
  1. 6 support_reference/support_reference.module

Support ticket references.

File

support_reference/support_reference.module
View source
<?php

/**
 * @file
 * Support ticket references.
 */

/**
 * Implements hook_menu().
 */
function support_reference_menu() {
  $items = array();
  $items['support_reference/autocomplete/%support_client/%'] = array(
    'title' => 'Autocomplete ticket reference',
    'page callback' => 'support_reference_autocomplete',
    'page arguments' => array(
      2,
      3,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'edit support ticket references',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_permission().
 */
function support_reference_permission() {
  return array(
    'edit support ticket references' => array(
      'title' => t('Edit support ticket references'),
    ),
    'view support ticket references' => array(
      'title' => t('View support ticket references'),
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function support_reference_block_info() {
  return array(
    'support_reference_references' => array(
      'info' => t('Support ticket references'),
      // Turn off caching because the user MIGHT have access to the form.
      // We don't have sufficient control over things to do any better.
      // If we want to be more agressive, we could turn off
      // XSRF protection by setting $form['#token'] = FALSE in the
      // builder, but it's probably a bad idea for this form, which doesn't
      // have confirm page protection.
      'cache' => DRUPAL_NO_CACHE,
    ),
  );
}

/**
 * Implements hook_block_view().
 */
function support_reference_block_view($delta = '') {
  global $user;
  $block = array();
  if ($delta == 'support_reference_references' && arg(0) == 'node' && is_numeric(arg(1))) {
    if ($node = node_load(arg(1))) {
      if ($node->type == 'support_ticket') {
        $view = $edit = '';
        if (user_access('view support ticket references')) {
          $result = db_query('SELECT rnid FROM {support_reference} WHERE nid = :nid ORDER BY rnid DESC', array(
            ':nid' => $node->nid,
          ))
            ->fetchCol();
          $nodes = node_load_multiple($result);
          $references = array();
          foreach ($nodes as $reference) {

            // Only list reference if user viewing page has access.
            $client = support_client_load($reference->client);
            if (support_access_clients($client, $user)) {
              $state = _support_state($reference->state);
              $priority = _support_priorities($reference->priority);
              $class = "support-reference state-{$state} priority-{$priority}";
              if ($node->client != $reference->client) {
                $class .= ' crossclient';
              }
              $references[$reference->nid] = '<span class="' . check_plain($class) . '">' . l(t('#!nid: !title', array(
                '!nid' => $reference->nid,
                '!title' => $reference->title,
              )), "node/{$reference->nid}", array(
                'attributes' => array(
                  'title' => t('!state !priority priority ticket.', array(
                    '!state' => ucfirst($state),
                    '!priority' => $priority,
                  )),
                ),
              )) . '</span>';
            }
          }
          $view = theme('item_list', array(
            'items' => $references,
          ));
        }
        if (user_access('edit support ticket references')) {
          $edit = drupal_get_form('support_reference_block_form', $node->client, $node);
        }
        $block['content'][] = array(
          '#markup' => $view,
        );
        $block['content'][] = $edit;
        $block['subject'] = t('Support ticket references');
      }
    }
  }
  return $block;
}
function support_reference_block_form($form, &$form_state, $client, $node) {
  $path = drupal_get_path('module', 'support_reference');
  $form['#attached']['library'][] = array(
    'system',
    'ui.autocomplete',
  );
  $form['#attached']['css'][] = "{$path}/support_reference.css";
  $form['#attached']['js'][] = "{$path}/support_reference.js";
  $form['#attached']['js'][] = array(
    'data' => array(
      'supportReferenceAutoCompletePath' => base_path() . "support_reference/autocomplete/{$client}/{$node->nid}",
    ),
    'type' => 'setting',
  );
  $form['#nid'] = $node->nid;
  $form['reference'] = array(
    '#type' => 'textfield',
    '#title' => t('Add / Remove Reference'),
    '#default_value' => '',
    '#required' => TRUE,
  );

  // This gets hidden by the css.
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Change'),
  );
  return $form;
}
function support_reference_block_form_submit($form, &$form_state) {
  $nid = $form['#nid'];
  $node = node_load($nid);
  $client = support_client_load($node->client);

  // Make sure the user is allowed to do this.
  if (user_access('edit support ticket references') && support_access_clients($client)) {
    $match = array();
    if (preg_match_all('/\\[#(\\d+)\\]/', $form_state['values']['reference'], $match)) {
      foreach ($match[1] as $rnid) {
        $rnode = node_load($rnid);
        $rclient = support_client_load($rnode->client);

        // Additional access control check to ignore messing with any references
        // to tickets belonging to clients that the user doesn't have access to.
        if (support_access_clients($rclient)) {

          // If it already exists, delete instead.
          if (db_query('SELECT 1 FROM {support_reference} WHERE nid = :nid AND rnid = :rnid', array(
            ':nid' => $nid,
            ':rnid' => $rnid,
          ))
            ->fetchField()) {
            db_delete('support_reference')
              ->condition('nid', $nid)
              ->condition('rnid', $rnid)
              ->execute();
            db_delete('support_reference')
              ->condition('nid', $rnid)
              ->condition('rnid', $nid)
              ->execute();
          }
          else {
            db_insert('support_reference')
              ->fields(array(
              'nid' => $nid,
              'rnid' => $rnid,
            ))
              ->execute();
            db_insert('support_reference')
              ->fields(array(
              'nid' => $rnid,
              'rnid' => $nid,
            ))
              ->execute();
          }
        }
      }
    }
  }
}

/**
 * @todo: should we allow cross-client references?
 */
function support_reference_autocomplete($client = NULL, $skipnid = 0) {
  $matches = array();
  if (is_object($client) && isset($client->clid) && support_access_clients($client)) {
    $result = db_query('SELECT n.nid, n.title, r.rnid FROM {support_ticket} s INNER JOIN {node} n ON s.nid = n.nid LEFT JOIN {support_reference} r ON (r.nid = :skipnid AND r.rnid = s.nid) WHERE s.client = :client AND s.nid <> :skipnid ORDER BY n.nid DESC', array(
      ':skipnid' => $skipnid,
      ':client' => $client->clid,
    ));
    foreach ($result as $ticket) {

      // We are using the titles directly from the database instead of using node_load() for speed / memory reasons.
      if (!empty($ticket->rnid)) {

        // If rnid is non null, there's a reference already, so indicate that choosing it will cause removal.
        // NOTE: check_plain() here causes double escaping on Drupal 7. (But not Drupal 6!)
        $matches[] = t('[#!nid]: !title (remove)', array(
          '!nid' => $ticket->nid,
          '!title' => $ticket->title,
        ));
      }
      else {

        // NOTE: check_plain() here causes double escaping on Drupal 7. (But not Drupal 6!)
        $matches[] = t('[#!nid]: !title', array(
          '!nid' => $ticket->nid,
          '!title' => $ticket->title,
        ));
      }
    }
  }
  drupal_json_output($matches);
}