2); } /** * Implementation of hook_help(). */ function casetracker_help($path, $arg) { switch ($path) { case 'admin/settings/casetracker/states': return '
'. t('Current Case Tracker case states are listed below.') .'
'; case 'admin/settings/casetracker/states/add': return ''. t('You may add a new case state below.') .'
'; case 'admin/settings/casetracker/states/edit/'. arg(4): return ''. t('You may edit an existing case state below.') .'
'; case 'admin/settings/casetracker': return ''. t('Configure the various Case Tracker options with these settings.') .'
'; } } /** * Implementation of hook_perm(). */ function casetracker_perm() { return array( 'access case tracker', 'administer case tracker', ); } /** * Implementation of hook_menu(). */ function casetracker_menu() { /* casetracker main settings */ $items['admin/settings/casetracker'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_settings'), 'description' => 'Configure the various Case Tracker options with these settings.', 'title' => 'Case Tracker', 'type' => MENU_NORMAL_ITEM, ); $items['admin/settings/casetracker/settings'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_settings'), 'title' => 'Settings', 'weight' => -10, 'type' => MENU_DEFAULT_LOCAL_TASK, ); /* casetracker state handling */ $items['admin/settings/casetracker/states'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'casetracker_case_state_overview', 'type' => MENU_LOCAL_TASK, 'title' => 'Case states', 'description' => 'Add, edit and delete Case States, Types and Priorities', ); $items['admin/settings/casetracker/states/list'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'casetracker_case_state_overview', 'type' => MENU_DEFAULT_LOCAL_TASK, 'title' => 'Overview', 'weight' => -10, 'description' => 'Add, edit and delete Case States, Types and Priorities', ); $items['admin/settings/casetracker/states/add'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_case_state_edit'), 'title' => 'Add case state', 'type' => MENU_LOCAL_TASK, ); $items['admin/settings/casetracker/states/edit/%casetracker_case_state'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_case_state_edit', 5), 'title' => 'Edit case state', 'type' => MENU_CALLBACK, ); $items['admin/settings/casetracker/states/delete/%casetracker_case_state'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_case_state_confirm_delete', 5), 'title' => 'Delete case state', 'type' => MENU_CALLBACK, ); /* casetracker autocomplete */ $items['casetracker_autocomplete'] = array( 'title' => 'Case Tracker autocomplete', 'page callback' => 'casetracker_autocomplete', 'access callback' => 'user_access', 'access arguments' => array('access case tracker'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implementation of hook_nodeapi(). */ function casetracker_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { // CASES if (casetracker_is_case($node->type)) { switch ($op) { case 'delete': // delete case and its comments. $comment_results = db_query("SELECT cid FROM {comments} WHERE nid = %d", $node->nid); while ($comment_result = db_fetch_object($comment_results)) { db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment_result->cid); } db_query('DELETE FROM {casetracker_case} WHERE nid = %d', $node->nid); break; case 'insert': // $node->casetracker is an Array and we wanna it to be an object. I // guess it's a nasty workaround. $node->casetracker = (object) $node->casetracker; // cases: generate a case ID and send it along. $record = $node->casetracker; $record->assign_to = casetracker_get_uid($record->assign_to); $record->nid = $node->nid; $record->vid = $node->vid; drupal_write_record('casetracker_case', $record); break; case 'load': $casetracker = db_fetch_object(db_query('SELECT pid, case_priority_id, case_type_id, assign_to, case_status_id FROM {casetracker_case} WHERE nid = %d AND vid = %d', $node->nid, $node->vid)); if ($casetracker) { return array('casetracker' => $casetracker); } break; case 'update': $record = (object) $node->casetracker; $record->assign_to = casetracker_get_uid($record->assign_to); $record->nid = $node->nid; $record->vid = $node->vid; $primary = $node->revision ? array('nid') : array('nid', 'vid'); drupal_write_record('casetracker_case', $record, $primary); break; case 'view': // On preview the case will be an array, we want an object. if (isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW) { $node->casetracker = (object)$node->casetracker; } // used in the breadcrumb and our theme function, mostly for nid and project number display. $project = node_load($node->casetracker->pid); if ($page) { $trail = array( l(t('Home'), NULL), l(t('Case Tracker'), 'casetracker/projects'), l($project->title, "node/{$node->casetracker->pid}"), l(t('All cases'), "casetracker/cases/{$node->casetracker->pid}/all"), ); drupal_set_breadcrumb($trail); } $node->content['casetracker_case_summary'] = array( '#value' => theme('casetracker_case_summary', $node, $project), '#weight' => -10 ); break; } } // PROJECTS else if (casetracker_is_project($node->type)) { switch ($op) { case 'delete': // projects: delete all the cases under the project and all the comments under each case. $case_results = db_query("SELECT nid from {casetracker_case} WHERE pid = %d", $node->nid); while ($case_result = db_fetch_object($case_results)) { db_query("DELETE FROM {casetracker_case} WHERE nid = %d", $case_result->nid); $comment_results = db_query("SELECT cid FROM {comments} WHERE nid = %d", $case_result->nid); while ($comment_result = db_fetch_object($comment_results)) { db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment_result->cid); } node_delete($case_result->nid); // this'll handle comment deletion too. } break; case 'view': if ($page) { $trail = array( l(t('Home'), NULL), l(t('Case Tracker'), 'casetracker/projects'), ); drupal_set_breadcrumb($trail); } $node->content['casetracker_project_summary'] = array('#value' => theme('casetracker_project_summary', $node), '#weight' => -10); break; } } } /** * Implementation of hook_comment(). */ function casetracker_comment(&$comment, $op) { // Load the node here anyway -- it is almost certainly static cached already. $node = is_array($comment) ? node_load($comment['nid']) : node_load($comment->nid); // Bail if this is not a casetracker node. if (!casetracker_is_case($node->type)) { return; } if ($op == 'insert' || $op == 'update') { $new = (object) $comment['casetracker']; $new->cid = $comment['cid']; $new->nid = $comment['nid']; $new->vid = $comment['revision_id']; $new->state = 1; $new->assign_to = casetracker_get_uid($new->assign_to); // Populate old state values from node $old = $node->casetracker; $old->cid = $comment['cid']; $old->state = 0; drupal_write_record('casetracker_case', $new, array('nid', 'vid')); } switch ($op) { case 'insert': drupal_write_record('casetracker_comment_status', $old); drupal_write_record('casetracker_comment_status', $new); break; case 'update': drupal_write_record('casetracker_comment_status', $old, array('cid', 'state')); drupal_write_record('casetracker_comment_status', $new, array('cid', 'state')); break; case 'delete': // @todo theoretically, if you delete a comment, we should reset all the values // to what they were before the comment was submitted. this doesn't happen yet. db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment->cid); break; case 'view': // If this is a preview we won't have a cid yet. if (empty($comment->cid)) { $case_data['new'] = (object)$comment->casetracker; $case_data['new']->assign_to = casetracker_get_uid($case_data['new']->assign_to); $case = node_load($comment->nid); $case_data['old'] = drupal_clone($case->casetracker); } else { $results = db_query("SELECT * FROM {casetracker_comment_status} WHERE cid = %d", $comment->cid); while ($result = db_fetch_object($results)) { $state = $result->state ? 'new' : 'old'; $case_data[$state] = $result; } } $comment->comment = theme('casetracker_comment_changes', $case_data['old'], $case_data['new']) . $comment->comment; break; } } /** * Implementation of hook_form_alter(). */ function casetracker_form_alter(&$form, &$form_state, $form_id) { if (!empty($form['#node'])) { $node = $form['#node']; // Add case options to our basic case type. if (casetracker_is_case($node->type)) { $count = count(casetracker_project_options()); if ($count == 0) { drupal_set_message(t('You must create a project before adding cases.'), 'error'); return; } else { $default_project = null; if (!isset($form['#node']->nid) && is_numeric(arg(3))) { $default_project = arg(3); } casetracker_case_form_common($form, $default_project); } } } } /** * Implementation of hook_form_comment_form_alter(). */ function casetracker_form_comment_form_alter(&$form, &$form_state) { $node = isset($form['nid']['#value']) ? node_load($form['nid']['#value']) : NULL; if (casetracker_is_case($node->type)) { $form['#node'] = $node; // add case options to the comment form. casetracker_case_form_common($form); // necessary for our casetracker_comment() callback. $form['revision_id'] = array('#type' => 'hidden', '#value' => $node->vid); } } /** * Common form elements for cases, generic enough for use either in * a full node display, or in comment displays and updating. Default * values are calculated based on an existing $form['nid']['#value']. * * @param $form * A Forms API $form, as received from a hook_form_alter(). * @param $default_project * The project ID that should be pre-selected. * @return $form * A modified Forms API $form. */ function casetracker_case_form_common(&$form, $default_project = NULL) { global $user; $node = $form['#node']; // On preview the case will be an array, we want an object. if (isset($node->build_mode) && $node->build_mode == NODE_BUILD_PREVIEW) { $node->casetracker = (object)$node->casetracker; } // project to set as the default is based on how the user got here. if (empty($default_project) && !empty($node->casetracker->pid)) { $default_project = $node->casetracker->pid; } $project_options = casetracker_project_options(); $form['casetracker'] = array( '#type' => 'fieldset', '#title' => t('Case information'), '#weight' => -10, '#collapsible' => TRUE, '#collapsed' => FALSE, '#tree' => TRUE, '#theme' => 'casetracker_case_form_common', ); // if there's no project ID from the URL, or more than one project, // we'll create a select menu for the user; otherwise, we'll save // the passed (or only) project ID into a hidden field. if (count($project_options) > 1) { $form['casetracker']['pid'] = array( '#title' => t('Project'), '#type' => 'select', '#default_value' => $default_project, '#options' => $project_options, ); } else { $form['casetracker']['pid'] = array( '#type' => 'value', // default value, or the only the project ID in the project_options array. '#value' => !empty($default_project) ? $default_project : key($project_options), ); } // Retrieve the assign_to default value. if (isset($node->casetracker->assign_to)) { $default_assign_to = is_numeric($node->casetracker->assign_to) ? casetracker_get_name($node->casetracker->assign_to) : $node->casetracker->assign_to; } else { $default_assign_to = variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous'))); } $form['casetracker']['assign_to'] = array( '#title' => t('Assign to'), '#required' => TRUE, ); // Use different widgets based on the potential assignees. $options = drupal_map_assoc(casetracker_user_options()); if (count($options) < 25) { $form['casetracker']['assign_to']['#type'] = 'radios'; $form['casetracker']['assign_to']['#options'] = $options; } else if (count($options) < 50) { $form['casetracker']['assign_to']['#type'] = 'select'; $form['casetracker']['assign_to']['#options'] = $options; } else { $form['casetracker']['assign_to']['#type'] = 'textfield'; $form['casetracker']['assign_to']['#autocomplete_path'] = 'casetracker_autocomplete'; $form['casetracker']['assign_to']['#size'] = 12; } // Set the default value if it is valid. $form['casetracker']['assign_to']['#default_value'] = in_array($default_assign_to, $options, TRUE) ? $default_assign_to : NULL; $case_status_options = casetracker_realm_load('status'); $default_status = !empty($node->casetracker->case_status_id) ? $node->casetracker->case_status_id : variable_get('casetracker_default_case_status', key($case_status_options)); $form['casetracker']['case_status_id'] = array( '#type' => 'select', '#title' => t('Status'), '#options' => $case_status_options, '#default_value' => $default_status, ); $case_priority_options = casetracker_realm_load('priority'); $default_priority = !empty($node->casetracker->case_priority_id) ? $node->casetracker->case_priority_id : variable_get('casetracker_default_case_priority', key($case_priority_options)); $form['casetracker']['case_priority_id'] = array( '#type' => 'select', '#title' => t('Priority'), '#options' => $case_priority_options, '#default_value' => $default_priority, ); $case_type_options = casetracker_realm_load('type'); $default_type = !empty($node->casetracker->case_type_id) ? $node->casetracker->case_type_id : variable_get('casetracker_default_case_type', key($case_type_options)); $form['casetracker']['case_type_id'] = array( '#type' => 'select', '#title' => t('Type'), '#options' => $case_type_options, '#default_value' => $default_type, ); return $form; } /** * Implementation of hook_block */ function casetracker_block($op = 'list', $delta = 0, $edit = array()) { switch ($op) { case 'list': $blocks[0] = array( 'info' => t('Jump to case'), ); return $blocks; case 'configure': return array(); case 'save': return; case 'view': switch ($delta) { case 0: if (user_access('access case tracker')) { $block['subject'] = t('Jump to case'); $block['content'] = drupal_get_form('casetracker_block_jump_to_case_number'); } break; } return $block; } } /** * Form for "Jump to case number" block. */ function casetracker_block_jump_to_case_number() { $form = array(); $form['case_number'] = array( '#maxlength' => 60, '#required' => TRUE, '#size' => 15, '#title' => t('Case number'), '#type' => 'textfield', '#prefix' => '