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'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_case_state_edit'), 'title' => 'Edit case state', 'type' => MENU_CALLBACK, ); $items['admin/settings/casetracker/states/delete'] = array( 'file' => 'casetracker_admin.inc', 'access arguments' => array('administer case tracker'), 'page callback' => 'drupal_get_form', 'page arguments' => array('casetracker_case_state_confirm_delete'), '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': // cases: generate a case ID and send it along. $record = (object) $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': // used in the breadcrumb and our theme function, mostly for nid and project number display. $project = node_load($node->casetracker->pid); $trail = array( l(t('Home'), NULL), l(t('Case Tracker projects'), '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': $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': $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) { // We can't make a link to a project here because the admin may have assigned more than one node type as project usable. // @TODO of course we can... ever heard of multiple links? drupal_set_message(t('You must create a project before adding cases.'), 'error'); return; } else { casetracker_case_form_common($form); } } } } /** * 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 (ie., no select box). * @return $form * A modified Forms API $form. */ function casetracker_case_form_common(&$form, $default_project = NULL) { global $user; $node = $form['#node']; // project to set as the default is based on how the user got here. if (isset($default_project)) { $default_project = $default_project; } else if (!empty($node->casetracker->pid)) { $default_project = $node->casetracker->pid; } else { $default_project = 0; } $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), ); } $options = casetracker_user_options(); $form['casetracker']['assign_to'] = array( '#type' => 'textfield', '#title' => t('Assign to'), '#autocomplete_path' => 'casetracker_autocomplete', '#required' => TRUE, '#size' => 12, ); if (count($options) < 20) { $normalized = array(); foreach ($options as $name) { $normalized[$name] = $name; } $form['casetracker']['assign_to'] = array( '#type' => 'radios', '#title' => t('Assign to'), '#required' => TRUE, '#options' => $normalized, ); } if (isset($node->casetracker->assign_to)) { $form['casetracker']['assign_to']['#default_value'] = is_numeric($node->casetracker->assign_to) ? casetracker_get_name($node->casetracker->assign_to) : $node->casetracker->assign_to; } else { $form['casetracker']['assign_to']['#default_value'] = variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous'))); } $case_status_options = casetracker_case_state_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_case_state_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_case_state_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; } /** * CASE STATE CRUD ==================================================== */ /** * Returns information about the various case states and their options. * The number of parameters passed will determine the return value. * * @param $realm * Optional; the name of the realm ('status', 'priority', or 'type'). * @param $csid * Optional; the state ID to return from the passed $realm. * @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($realm = NULL, $csid = NULL) { static $states_lookup = array(); if (!$states_lookup) { $results = db_query("SELECT csid, case_state_name, case_state_realm, weight FROM {casetracker_case_states} ORDER BY weight"); while ($result = db_fetch_object($results)) { // offer cached csid and realm lookups from a one-time query. $states_lookup[$result->case_state_realm][$result->csid] = array( 'name' => $result->case_state_name, 'realm' => $result->case_state_realm, 'weight' => (int)$result->weight, 'csid' => (int)$result->csid ); $states_lookup[$result->csid] = $states_lookup[$result->case_state_realm][$result->csid]; } } if ($csid && $realm) { return $states_lookup[$csid]['name']; } elseif ($csid && !$realm) { return $states_lookup[$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['name']; } } return $options; } } /** * 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); } 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 a pipe delimited string of autocomplete suggestions for existing * users. Stolen from user_autocomplete. Eventually this will be expanded to * include OG specific users subscribed to a project. */ function casetracker_autocomplete($string) { $matches = array(); $group = module_exists('og') ? og_get_group_context() : NULL; if ($group) { $gid = $group->nid; $result = db_query_range("SELECT u.name FROM {users} u LEFT JOIN {og_uid} ou ON u.uid = ou.uid WHERE LOWER(name) LIKE LOWER('%s%%') AND u.status > 0 AND ou.nid = %d", $string, $gid, 0, 10); } else { $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10); } while ($user = db_fetch_object($result)) { $matches[$user->name] = check_plain($user->name); } 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} = casetracker_case_state_load('status', $old->{$field}); $new->{$field} = casetracker_case_state_load('status', $new->{$field}); break; case 'assign_to': $old->{$field} = casetracker_get_name($old->{$field}); $new->{$field} = casetracker_get_name($new->{$field}); break; case 'case_priority_id': $old->{$field} = casetracker_case_state_load('priority', $old->{$field}); $new->{$field} = casetracker_case_state_load('priority', $new->{$field}); break; case 'case_type_id': $old->{$field} = casetracker_case_state_load('type', $old->{$field}); $new->{$field} = casetracker_case_state_load('type', $new->{$field}); break; } $rows[] = array(t('!label: !old » !new', array('!label' => $label, '!old' => $old->{$field}, '!new' => $new->{$field}))); } } 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') { $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(); $rows[] = array( t('Assigned to:'), theme('username', user_load(array('uid' => $case->casetracker->assign_to))), ); $rows[] = array( t('Created:'), theme_username($case) ." ". t('at') ." ". format_date($case->created, 'medium'), ); $rows[] = array( t('Status:'), "". casetracker_case_state_load('status', $case->casetracker->case_status_id) ." (" . casetracker_case_state_load('type', $case->casetracker->case_type_id) .' / '. t("Priority") ." ". casetracker_case_state_load('priority', $case->casetracker->case_priority_id) . ")", ); $rows[] = array( t('Case ID:'), l($project->title, 'node/'. $case->casetracker->pid) .': '. $project->nid .'-'. $case->nid, ); 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('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() { $group = module_exists('og') ? og_get_group_context() : NULL; $options = array(0 => variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous')))); if ($group) { $gid = $group->nid; $results = db_query('SELECT u.uid, u.name FROM {users} u INNER JOIN {og_uid} ou ON u.uid = ou.uid WHERE u.status > 0 AND u.uid > 0 AND ou.nid = %d ORDER BY u.name ASC', $gid); } else { $results = db_query('SELECT u.uid, u.name FROM {users} u WHERE u.status > 0 AND u.uid > 0 ORDER BY u.name ASC'); } while ($result = db_fetch_object($results)) { $options[$result->uid] = check_plain($result->name); } 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) { $result = db_result(db_query("SELECT name FROM {users} WHERE uid = %d", $uid)); $users[$uid] = $result ? $result : ''; } return !empty($users[$uid]) ? $users[$uid] : variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous'))); }