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( 'administer case tracker', 'assign cases', ); } /** * 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('assign cases'), '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 'presave': // $node->casetracker is an Array and we wanna it to be an object. $node->casetracker = (object) $node->casetracker; break; case 'insert': // cases: generate a case ID and send it along. $record = $node->casetracker; $record->assign_to = is_numeric($record->assign_to) ? $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 = is_numeric($record->assign_to) ? $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 = casetracker_default_assign_to(); } // Only show this element if the user has access. $form['casetracker']['assign_to'] = array( '#title' => t('Assign to'), '#required' => TRUE, '#access' => user_access('assign cases'), ); // Use different widgets based on the potential assignees. $options = drupal_map_assoc(casetracker_user_options()); $assign_to_widget = variable_get('casetracker_assign_to_widget', 'flexible'); if (($assign_to_widget == 'flexible' && count($options) < 25) || $assign_to_widget == 'radios') { $form['casetracker']['assign_to']['#type'] = 'radios'; $form['casetracker']['assign_to']['#options'] = $options; } else if (($assign_to_widget == 'flexible' && count($options) < 50) || $assign_to_widget == 'select') { $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 content')) { $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' => '
', ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Go'), '#suffix' => '
', ); return $form; } /** * Submit function for our "Jump to case number" block. */ function casetracker_block_jump_to_case_number_submit($form, $form_state) { list($pid, $nid) = explode('-', $form_state['values']['case_number']); $case_nid = db_result(db_query("SELECT nid FROM {casetracker_case} WHERE pid = %d AND nid = %d", $pid, $nid)); if (!$case_nid) { drupal_set_message(t('Your case number was not found.'), 'error'); return; } drupal_goto('node/'. $case_nid); } /** * CASE STATE CRUD ==================================================== */ /** * Returns information about the various case states and their options. * The number of parameters passed will determine the return value. * * @param $csid * Optional; the state ID to return from the passed $realm. * @param $realm * Optional; the name of the realm ('status', 'priority', or 'type'). * @param $reset * Optional; set to TRUE to reset the static cache. * * @return $values * If only $realm is passed, you'll receive an array with the keys * being the state ID and the values being their names. If a $csid * is also passed, you'll receive just a string of the state name. * If ONLY a $csid is passed, we'll return a list of 'name', 'realm'. */ function casetracker_case_state_load($csid = NULL, $realm = NULL, $reset = FALSE) { static $states_lookup; if (!$states_lookup || $reset) { $results = db_query("SELECT csid, case_state_name AS name, case_state_realm AS realm, weight FROM {casetracker_case_states} ORDER BY weight"); $states_lookup = array(); while ($row = db_fetch_object($results)) { $row->display = casetracker_tt("case_states:$row->csid:name", $row->name); $states_lookup[$row->realm][$row->csid] = $states_lookup['all'][$row->csid] = $row; } } if ($csid && $realm) { return $states_lookup['all'][$csid]->display; } elseif ($csid && !$realm) { return $states_lookup['all'][$csid]; } elseif (!$csid && $realm) { $options = array(); // suitable for form api. if (!empty($states_lookup[$realm])) { foreach ($states_lookup[$realm] as $state) { $options[$state->csid] = $state->display; } } return $options; } } /** * Translate user defined string. Wrapper function for tt() if i18nstrings enabled. * * The string id for case states will be: case:[realm]#[csid]:name * * @param $name * String id without 'casetracker', which will be prepended automatically */ function casetracker_tt($name, $string, $langcode = NULL) { return function_exists('i18nstrings') ? i18nstrings('casetracker:' . $name, $string, $langcode) : $string; } /** * Implementation of hook_locale(). */ function casetracker_locale($op = 'groups', $group = NULL) { switch ($op) { case 'groups': return array('casetracker' => t('Case Tracker')); case 'info': $info['casetracker']['refresh callback'] = 'casetracker_locale_refresh'; $info['casetracker']['format'] = FALSE; return $info; } } /** * Refresh locale strings. */ function casetracker_locale_refresh() { $results = db_query("SELECT csid, case_state_name AS name, case_state_realm AS realm FROM {casetracker_case_states}"); while ($row = db_fetch_object($results)) { i18nstrings_update("casetracker:case_states:$row->csid:name", $row->name); } // Meaning it completed with no issues. @see i18nmenu_locale_refresh(). return TRUE; } /** * Load states for a particular realm. Wrapper around casetracker_case_state_load() * * @param $realm * Name of the realm ('status', 'priority', or 'type'). * * @return * array with the keys being the state ID and the values being their names. */ function casetracker_realm_load($realm) { return casetracker_case_state_load(null, $realm); } /** * Saves a case state. * * @param $case_state * An array containing 'name' and 'realm' keys. If no 'csid' * is passed, a new state is created, otherwise, we'll update * the record that corresponds to that ID. */ function casetracker_case_state_save($case_state = NULL) { if (!$case_state['name'] || !$case_state['realm']) { return NULL; } // Need to collect information into another array since the db columns have different names : ( $record = array( 'case_state_name' => $case_state['name'], 'case_state_realm' => $case_state['realm'], 'weight' => $case_state['weight'], ); if (isset($case_state['csid'])) { $record['csid'] = $case_state['csid']; drupal_write_record('casetracker_case_states', $record, array('csid')); } else { drupal_write_record('casetracker_case_states', $record); } // Update translations if (function_exists('i18nstrings_update')) { i18nstrings_update('casetracker:case_states:'. $record['csid'] .':name', $case_state['name']); } return $result; } /** * Deletes a case state. * * @todo There is currently no attempt to do anything with cases which * have been assigned the $csid that is about to be deleted. We should * reset them to the default per our settings (and warn the user on our * confirmation page), or something else entirely. * * @param $csid * The case state ID to delete. */ function casetracker_case_state_delete($csid = NULL) { if (!empty($csid)) { db_query('DELETE FROM {casetracker_case_states} WHERE csid = %d', $csid); } } /** * COMMENT DISPLAY ==================================================== */ /** * Retrieve autocomplete suggestions for assign to user options. * * @TODO: In order to get this down to 1 query and respect any custom * views selected for use as user option filters, we need to: * - Submit a patch to the Views user name filter/argument handler to support LIKE filtering. * - Ensure that the custom view uses this handler or add it if does not. * - Generate the query & result set using this modified View. */ function casetracker_autocomplete($string) { $matches = array(); $options = casetracker_user_options(); $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10); while ($user = db_fetch_object($result)) { if (in_array($user->name, $options, TRUE)) { $matches[$user->name] = check_plain($user->name); } } // Special case for 'Unassigned' $unassigned = t('Unassigned'); if (strpos(strtolower($unassigned), strtolower($string)) !== FALSE) { $matches[$unassigned] = $unassigned; } drupal_json($matches); } /** * Returns an query string needed in case of Organic Groups * providing preselected audience checkboxes for projects as groups (og) * * @param object CT project * @return string */ function _casetracker_get_og_query_string(&$project) { $querystring = array(); // checking if project is group if ($project->type == 'group') { $querystring[] = 'gids[]='. $project->nid; //checking if group-project is part of another group if (isset($project->og_groups) && is_array($project->og_groups) ) { foreach ($project->og_groups as $group) { $querystring[] = 'gids[]='. $group; } } } //checking if project is part of a group elseif (isset($project->og_groups) && is_array($project->og_groups) && $project->type !== 'group' ) { foreach ($project->og_groups as $group) { $querystring[] = 'gids[]='. $group; } } return (0 < count($querystring)) ? implode('&', $querystring) : NULL; } /** * THEME ============================================================== */ /** * Implementation of hook_theme */ function casetracker_theme() { return array( 'casetracker_comment_changes' => array(), 'casetracker_case_form_common' => array(), 'casetracker_case_summary' => array(), 'casetracker_project_summary' => array(), ); } /** * Displays the changes a comment has made to the case fields. * * @param $case_data * An array of both 'old' and 'new' objects that contains * the before and after values this comment has changed. */ function theme_casetracker_comment_changes($old, $new) { $rows = array(); $fields = array( 'pid' => t('Project'), 'title' => t('Title'), 'case_status_id' => t('Status'), 'assign_to' => t('Assigned'), 'case_priority_id' => t('Priority'), 'case_type_id' => t('Type'), ); foreach ($fields as $field => $label) { if ($new->{$field} != $old->{$field}) { switch ($field) { case 'pid': $old_title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", $old->pid)); $new_title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", $new->pid)); $old->{$field} = l($old_title, "node/{$old->pid}"); $new->{$field} = l($new_title, "node/{$new->pid}"); break; case 'case_status_id': $old->{$field} = check_plain(casetracker_case_state_load($old->{$field}, 'status')); $new->{$field} = check_plain(casetracker_case_state_load($new->{$field}, 'status')); break; case 'assign_to': $old->{$field} = check_plain(casetracker_get_name($old->{$field})); $new->{$field} = check_plain(casetracker_get_name($new->{$field})); break; case 'case_priority_id': $old->{$field} = check_plain(casetracker_case_state_load($old->{$field}, 'priority')); $new->{$field} = check_plain(casetracker_case_state_load($new->{$field}, 'priority')); break; case 'case_type_id': $old->{$field} = check_plain(casetracker_case_state_load($old->{$field}, 'type')); $new->{$field} = check_plain(casetracker_case_state_load($new->{$field}, 'type')); break; } $rows[] = array(t('@label: !old » !new', array('@label' => $label, '!old' => $old->{$field}, '!new' => $new->{$field}))); } } if (!empty($rows)) { return theme('table', NULL, $rows, array('class' => 'case_changes')); } } /** * Theme function for cleaning up the casetracker common form. */ function theme_casetracker_case_form_common($form) { drupal_add_css(drupal_get_path('module', 'casetracker') .'/casetracker.css'); $output = ''; $output .= drupal_render($form['pid']); $output .= drupal_render($form['case_title']); if ($form['assign_to']['#type'] == 'radios') { if ($form['assign_to']['#access']) { $header = array_fill(0, 5, array()); $header[0] = $form['assign_to']['#title']; $radios = array(); foreach (element_children($form['assign_to']) as $id) { $radios[] = drupal_render($form['assign_to'][$id]); } $radios = array_chunk($radios, 5); $output .= theme('table', $header, $radios, array('class' => 'casetracker-assign-to')); } drupal_render($form['assign_to']); } else { $output .= drupal_render($form['assign_to']); } $row = array(); foreach (element_children($form) as $id) { if (!in_array($id, array('pid', 'case_title', 'assign_to'))) { $row[] = drupal_render($form[$id]); } } $rows = array($row); $output .= theme('table', array(), $rows); $output .= drupal_render($form); return $output; } /** * Theme the case summary shown at the beginning of a case's node. * * @param $case * The node object of the case being viewed. * @param $project * The node object of the project this case belongs to. */ function theme_casetracker_case_summary($case, $project) { $last_comment = db_result(db_query('SELECT last_comment_timestamp FROM {node_comment_statistics} WHERE nid = %d', $case->nid)); $rows = array(); // On node preview the form logic can't translate assign_to back to a uid for // us so we need to be able handle it either way. if (is_numeric($case->casetracker->assign_to)) { $assign_to = user_load(array('uid' => $case->casetracker->assign_to)); } else { $assign_to = user_load(array('name' => $case->casetracker->assign_to)); } if (empty($assign_to) || $assign_to->uid == 0) { $rows[] = array( t('Assigned to:'), '' . t('Unassigned') . '', ); } else { $rows[] = array( t('Assigned to:'), theme('username', $assign_to), ); } $rows[] = array( t('Created:'), t('!username at !date', array('!username' => theme('username', $case), '!date' => format_date($case->created, 'medium'))), ); $rows[] = array( t('Status:'), t('@status (@type / Priority @priority)', array( '@status' => casetracker_case_state_load($case->casetracker->case_status_id, 'status'), '@type' => casetracker_case_state_load($case->casetracker->case_type_id, 'type'), '@priority' => casetracker_case_state_load($case->casetracker->case_priority_id, 'priority'), )), ); // On node preview a case may not have a nid, so we use some placeholder text. $case_id = isset($case->nid) ? $case->nid : t("NEW"); $rows[] = array( t('Case ID:'), l($project->title, 'node/'. $case->casetracker->pid) .': '. $project->nid .'-'. $case_id, ); if ($last_comment != $case->created) { $rows[] = array( t('Last modified:'), format_date($last_comment, 'medium') ); } $output = '
'; $output .= theme('table', NULL, $rows, array('class' => 'summary')); $output .= '
'; return $output; } /** * Theme the project summary shown at the beginning of a project's node. * * @param $project * The node object of the project being viewed. */ function theme_casetracker_project_summary($project) { $rows = array(); $rows[] = array(t('Project number:'), $project->nid); $rows[] = array(t('Opened by:'), theme('username', $project)); $rows[] = array(t('Opened on:'), format_date($project->created, 'large')); $rows[] = array(t('Last modified:'), format_date($project->changed, 'large')); $querystring = _casetracker_get_og_query_string($project); $operations = array(); $node_types = node_get_types('names'); foreach (array_filter(variable_get('casetracker_case_node_types', array('casetracker_basic_case'))) as $type) { $operations[] = l( t('add !name', array('!name' => $node_types[$type])), 'node/add/'. str_replace('_', '-', $type) .'/'. $project->nid, array('query' => $querystring) ); } $operations = implode(' | ', $operations); // ready for printing in our Operations table cell - delimited by a pipe. nonstandard. $rows[] = array(t('Operations:'), $operations .' | '. l(t('view all project cases'), 'casetracker', array('query' => 'keys=&pid='. $project->nid))); $output = '
'; $output .= theme('table', NULL, $rows, array('class' => 'summary')); $output .= '
'; return $output; } /** * API FUNCTIONS ====================================================== */ /** * API function that returns valid project options. */ function casetracker_project_options() { $projects = array(); // Fetch the views list of projects, which is space-aware. if ($view = views_get_view(variable_get('casetracker_view_project_options', 'casetracker_project_options'))) { $view->set_display(); $view->set_items_per_page(0); $view->execute(); foreach ($view->result as $row) { $projects[$row->nid] = $row->node_title; } } return $projects; } /** * API function that returns valid user options. */ function casetracker_user_options() { $users = array(); $options = array(); if ($view = views_get_view(variable_get('casetracker_view_assignee_options', 'casetracker_assignee_options'))) { $view->set_display(); $view->set_items_per_page(0); $view->execute(); foreach ($view->result as $row) { $options[$row->uid] = $row->users_name; } } $anon_user = casetracker_default_assign_to(); // fill in "Unassigned" value because view is not rendered and the redundant option in views is irrelevant // @TODO render the view before display so this isn't needed. if (isset($options[0])) { $options[0] = $anon_user; } // if "Unassigned" is the default assignee, we graft it onto the view results here as most views // that do any substantive filtering will exclude the anonymous user. elseif (in_array(variable_get('casetracker_default_assign_to', $anon_user), array($anon_user, variable_get('anonymous', t('Anonymous'))))) { $options = array($anon_user) + $options; } return $options; } /** * API function for checking whether a node type is a casetracker case. */ function casetracker_is_case($node) { if (is_object($node) && !empty($node->type)) { $type = $node->type; } else if (is_string($node)) { $type = $node; } if ($type) { return in_array($type, variable_get('casetracker_case_node_types', array('casetracker_basic_case')), TRUE); } return FALSE; } /** * API function for checking whether a node type is a casetracker project. */ function casetracker_is_project($node) { if (is_object($node) && !empty($node->type)) { $type = $node->type; } else if (is_string($node)) { $type = $node; } if ($type) { return in_array($type, variable_get('casetracker_project_node_types', array('casetracker_basic_project')), TRUE); } return FALSE; } /** * Given a user name, returns the uid of that account. * If the passed name is not found, returns 0. * See also casetracker_get_name(). */ function casetracker_get_uid($name = NULL, $reset = FALSE) { static $users = array(); if (!isset($users[$name]) || $reset) { $result = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $name)); $users[$name] = $result ? $result : 0; } return $users[$name]; } /** * Given a uid, returns the name of that account. If the passed uid is * not found, returns the default "assign to" name as specified in the * settings. @todo This may not always be desired, but is how we use it. * See also casetracker_get_uid(). */ function casetracker_get_name($uid = NULL, $reset = FALSE) { static $users = array(); if (!isset($users[$uid]) || $reset) { if ($uid == 0) { $users[0] = t('Unassigned'); } else { $result = db_result(db_query("SELECT name FROM {users} WHERE uid = %d", $uid)); $users[$uid] = $result ? $result : ''; } } return !empty($users[$uid]) ? $users[$uid] : casetracker_default_assign_to(); } /** * Fetch the proper default assignee. */ function casetracker_default_assign_to() { $assign_to = variable_get('casetracker_default_assign_to', t('Unassigned')); if ($assign_to == variable_get('anonymous', t('Anonymous'))) { return t('Unassigned'); } return $assign_to; } /** * Implementation of hook_token_values(). */ function casetracker_token_values($type, $object = NULL) { module_load_include('inc', 'casetracker', 'casetracker.token'); return _casetracker_token_values($type, $object); } /** * Implementation of hook_token_list(). */ function casetracker_token_list($type = 'all') { module_load_include('inc', 'casetracker', 'casetracker.token'); return _casetracker_token_list($type); }