/[drupal]/contributions/modules/casetracker/casetracker.module
ViewVC logotype

Contents of /contributions/modules/casetracker/casetracker.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.123 - (show annotations) (download) (as text)
Wed Feb 11 21:18:58 2009 UTC (9 months, 2 weeks ago) by jmiccolis
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.122: +2 -2 lines
File MIME type: text/x-php
Adding more sensible views, case and project filters, and cleaning up whitespace
1 <?php
2 // $Id: casetracker.module,v 1.122 2009/02/10 22:33:33 jmiccolis Exp $
3
4 /**
5 * @file
6 * Enables the handling of projects and their cases.
7 */
8
9 /**
10 * Implementation of hook_views_api().
11 */
12 function casetracker_views_api() {
13 return array('api' => 2);
14 }
15
16 /**
17 * Implementation of hook_help().
18 */
19 function casetracker_help($path, $arg) {
20 switch ($path) {
21 case 'admin/settings/casetracker/states':
22 return '<p>'. t('Current Case Tracker case states are listed below.') .'</p>';
23 case 'admin/settings/casetracker/states/add':
24 return '<p>'. t('You may add a new case state below.') .'</p>';
25 case 'admin/settings/casetracker/states/edit/'. arg(4):
26 return '<p>'. t('You may edit an existing case state below.') .'</p>';
27 case 'admin/settings/casetracker':
28 return '<p>'. t('Configure the various Case Tracker options with these settings.') .'</p>';
29 }
30 }
31
32 /**
33 * Implementation of hook_perm().
34 */
35 function casetracker_perm() {
36 return array(
37 'access case tracker',
38 'administer case tracker',
39 );
40 }
41
42 /**
43 * Implementation of hook_menu().
44 */
45 function casetracker_menu() {
46 /* casetracker main settings */
47 $items['admin/settings/casetracker'] = array(
48 'file' => 'casetracker_admin.inc',
49 'access arguments' => array('administer case tracker'),
50 'page callback' => 'drupal_get_form',
51 'page arguments' => array('casetracker_settings'),
52 'description' => 'Configure the various Case Tracker options with these settings.',
53 'title' => 'Case Tracker',
54 'type' => MENU_NORMAL_ITEM,
55 );
56 $items['admin/settings/casetracker/settings'] = array(
57 'file' => 'casetracker_admin.inc',
58 'access arguments' => array('administer case tracker'),
59 'page callback' => 'drupal_get_form',
60 'page arguments' => array('casetracker_settings'),
61 'title' => 'Settings',
62 'weight' => -10,
63 'type' => MENU_DEFAULT_LOCAL_TASK,
64 );
65 /* casetracker state handling */
66 $items['admin/settings/casetracker/states'] = array(
67 'file' => 'casetracker_admin.inc',
68 'access arguments' => array('administer case tracker'),
69 'page callback' => 'casetracker_case_state_overview',
70 'type' => MENU_LOCAL_TASK,
71 'title' => 'Case states',
72 'description' => 'Add, edit and delete Case States, Types and Priorities',
73 );
74 $items['admin/settings/casetracker/states/list'] = array(
75 'file' => 'casetracker_admin.inc',
76 'access arguments' => array('administer case tracker'),
77 'page callback' => 'casetracker_case_state_overview',
78 'type' => MENU_DEFAULT_LOCAL_TASK,
79 'title' => 'Overview',
80 'weight' => -10,
81 'description' => 'Add, edit and delete Case States, Types and Priorities',
82 );
83 $items['admin/settings/casetracker/states/add'] = array(
84 'file' => 'casetracker_admin.inc',
85 'access arguments' => array('administer case tracker'),
86 'page callback' => 'drupal_get_form',
87 'page arguments' => array('casetracker_case_state_edit'),
88 'title' => 'Add case state',
89 'type' => MENU_LOCAL_TASK,
90 );
91 $items['admin/settings/casetracker/states/edit'] = array(
92 'file' => 'casetracker_admin.inc',
93 'access arguments' => array('administer case tracker'),
94 'page callback' => 'drupal_get_form',
95 'page arguments' => array('casetracker_case_state_edit'),
96 'title' => 'Edit case state',
97 'type' => MENU_CALLBACK,
98 );
99 $items['admin/settings/casetracker/states/delete'] = array(
100 'file' => 'casetracker_admin.inc',
101 'access arguments' => array('administer case tracker'),
102 'page callback' => 'drupal_get_form',
103 'page arguments' => array('casetracker_case_state_confirm_delete'),
104 'title' => 'Delete case state',
105 'type' => MENU_CALLBACK,
106 );
107 /* casetracker autocomplete */
108 $items['casetracker_autocomplete'] = array(
109 'title' => 'Case Tracker autocomplete',
110 'page callback' => 'casetracker_autocomplete',
111 'access callback' => 'user_access',
112 'access arguments' => array('access case tracker'),
113 'type' => MENU_CALLBACK,
114 );
115 return $items;
116 }
117
118 /**
119 * Implementation of hook_nodeapi().
120 */
121 function casetracker_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
122 // CASES
123 if (casetracker_is_case($node->type)) {
124 switch ($op) {
125
126 case 'delete':
127 // delete case and its comments.
128 $comment_results = db_query("SELECT cid FROM {comments} WHERE nid = %d", $node->nid);
129 while ($comment_result = db_fetch_object($comment_results)) {
130 db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment_result->cid);
131 }
132 db_query('DELETE FROM {casetracker_case} WHERE nid = %d', $node->nid);
133 break;
134
135 case 'insert':
136 // cases: generate a case ID and send it along.
137 $record = (object) $node->casetracker;
138 $record->assign_to = casetracker_get_uid($record->assign_to);
139 $record->nid = $node->nid;
140 $record->vid = $node->vid;
141
142 drupal_write_record('casetracker_case', $record);
143 break;
144
145 case 'load':
146 $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));
147 if ($casetracker) {
148 return array('casetracker' => $casetracker);
149 }
150 break;
151
152 case 'update':
153 $record = (object) $node->casetracker;
154 $record->assign_to = casetracker_get_uid($record->assign_to);
155 $record->nid = $node->nid;
156 $record->vid = $node->vid;
157
158 $primary = $node->revision ? array('nid') : array('nid', 'vid');
159 drupal_write_record('casetracker_case', $record, $primary);
160 break;
161
162 case 'view':
163 // used in the breadcrumb and our theme function, mostly for nid and project number display.
164 $project = node_load($node->casetracker->pid);
165 $trail = array(
166 l(t('Home'), NULL),
167 l(t('Case Tracker projects'), 'casetracker/projects'),
168 l($project->title, "node/{$node->casetracker->pid}"),
169 l(t('All cases'), "casetracker/cases/{$node->casetracker->pid}/all"),
170 );
171 drupal_set_breadcrumb($trail);
172 $node->content['casetracker_case_summary'] = array(
173 '#value' => theme('casetracker_case_summary', $node, $project),
174 '#weight' => -10
175 );
176 break;
177
178 }
179 }
180 // PROJECTS
181 else if (casetracker_is_project($node->type)) {
182 switch ($op) {
183
184 case 'delete':
185 // projects: delete all the cases under the project and all the comments under each case.
186 $case_results = db_query("SELECT nid from {casetracker_case} WHERE pid = %d", $node->nid);
187 while ($case_result = db_fetch_object($case_results)) {
188 db_query("DELETE FROM {casetracker_case} WHERE nid = %d", $case_result->nid);
189 $comment_results = db_query("SELECT cid FROM {comments} WHERE nid = %d", $case_result->nid);
190 while ($comment_result = db_fetch_object($comment_results)) {
191 db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment_result->cid);
192 }
193 node_delete($case_result->nid); // this'll handle comment deletion too.
194 }
195 break;
196
197 case 'view':
198 $node->content['casetracker_project_summary'] = array('#value' => theme('casetracker_project_summary', $node), '#weight' => -10);
199 break;
200 }
201 }
202 }
203
204 /**
205 * Implementation of hook_comment().
206 */
207 function casetracker_comment(&$comment, $op) {
208 // Load the node here anyway -- it is almost certainly static cached already.
209 $node = is_array($comment) ? node_load($comment['nid']) : node_load($comment->nid);
210
211 // Bail if this is not a casetracker node.
212 if (!casetracker_is_case($node->type)) {
213 return;
214 }
215
216 if ($op == 'insert' || $op == 'update') {
217 $new = (object) $comment['casetracker'];
218 $new->cid = $comment['cid'];
219 $new->nid = $comment['nid'];
220 $new->vid = $comment['revision_id'];
221 $new->state = 1;
222 $new->assign_to = casetracker_get_uid($new->assign_to);
223
224 // Populate old state values from node
225 $old = $node->casetracker;
226 $old->cid = $comment['cid'];
227 $old->state = 0;
228
229 drupal_write_record('casetracker_case', $new, array('nid', 'vid'));
230 }
231
232 switch ($op) {
233 case 'insert':
234 drupal_write_record('casetracker_comment_status', $old);
235 drupal_write_record('casetracker_comment_status', $new);
236 break;
237 case 'update':
238 drupal_write_record('casetracker_comment_status', $old, array('cid', 'state'));
239 drupal_write_record('casetracker_comment_status', $new, array('cid', 'state'));
240 break;
241 case 'delete':
242 // @todo theoretically, if you delete a comment, we should reset all the values
243 // to what they were before the comment was submitted. this doesn't happen yet.
244 db_query("DELETE FROM {casetracker_comment_status} WHERE cid = %d", $comment->cid);
245 break;
246 case 'view':
247 $results = db_query("SELECT * FROM {casetracker_comment_status} WHERE cid = %d", $comment->cid);
248 while ($result = db_fetch_object($results)) {
249 $state = $result->state ? 'new' : 'old';
250 $case_data[$state] = $result;
251 }
252 $comment->comment = theme('casetracker_comment_changes', $case_data['old'], $case_data['new']) . $comment->comment;
253 break;
254 }
255 }
256
257 /**
258 * Implementation of hook_form_alter().
259 */
260 function casetracker_form_alter(&$form, &$form_state, $form_id) {
261 if (!empty($form['#node'])) {
262 $node = $form['#node'];
263
264 // Add case options to our basic case type.
265 if (casetracker_is_case($node->type)) {
266 $count = count(casetracker_project_options());
267 if ($count == 0) {
268 // We can't make a link to a project here because the admin may have assigned more than one node type as project usable.
269 // @TODO of course we can... ever heard of multiple links?
270 drupal_set_message(t('You must create a project before adding cases.'), 'error');
271 return;
272 }
273 else {
274 casetracker_case_form_common($form);
275 }
276 }
277 }
278 }
279
280 /**
281 * Implementation of hook_form_comment_form_alter().
282 */
283 function casetracker_form_comment_form_alter(&$form, &$form_state) {
284 $node = isset($form['nid']['#value']) ? node_load($form['nid']['#value']) : NULL;
285 if (casetracker_is_case($node->type)) {
286 $form['#node'] = $node;
287
288 // add case options to the comment form.
289 casetracker_case_form_common($form);
290
291 // necessary for our casetracker_comment() callback.
292 $form['revision_id'] = array('#type' => 'hidden', '#value' => $node->vid);
293 }
294 }
295
296 /**
297 * Common form elements for cases, generic enough for use either in
298 * a full node display, or in comment displays and updating. Default
299 * values are calculated based on an existing $form['nid']['#value'].
300 *
301 * @param $form
302 * A Forms API $form, as received from a hook_form_alter().
303 * @param $default_project
304 * The project ID that should be pre-selected (ie., no select box).
305 * @return $form
306 * A modified Forms API $form.
307 */
308 function casetracker_case_form_common(&$form, $default_project = NULL) {
309 global $user;
310
311 $node = $form['#node'];
312
313 // project to set as the default is based on how the user got here.
314 if (isset($default_project)) {
315 $default_project = $default_project;
316 }
317 else if (!empty($node->casetracker->pid)) {
318 $default_project = $node->casetracker->pid;
319 }
320 else {
321 $default_project = 0;
322 }
323 $project_options = casetracker_project_options();
324
325 $form['casetracker'] = array(
326 '#type' => 'fieldset',
327 '#title' => t('Case information'),
328 '#weight' => -10,
329 '#collapsible' => TRUE,
330 '#collapsed' => FALSE,
331 '#tree' => TRUE,
332 '#theme' => 'casetracker_case_form_common',
333 );
334
335 // if there's no project ID from the URL, or more than one project,
336 // we'll create a select menu for the user; otherwise, we'll save
337 // the passed (or only) project ID into a hidden field.
338 if (count($project_options) > 1) {
339 $form['casetracker']['pid'] = array(
340 '#title' => t('Project'),
341 '#type' => 'select',
342 '#default_value' => $default_project,
343 '#options' => $project_options,
344 );
345 }
346 else {
347 $form['casetracker']['pid'] = array(
348 '#type' => 'value', // default value, or the only the project ID in the project_options array.
349 '#value' => !empty($default_project) ? $default_project : key($project_options),
350 );
351 }
352
353 $options = casetracker_user_options();
354
355 $form['casetracker']['assign_to'] = array(
356 '#type' => 'textfield',
357 '#title' => t('Assign to'),
358 '#autocomplete_path' => 'casetracker_autocomplete',
359 '#required' => TRUE,
360 '#size' => 12,
361 );
362 if (count($options) < 20) {
363 $normalized = array();
364 foreach ($options as $name) {
365 $normalized[$name] = $name;
366 }
367 $form['casetracker']['assign_to'] = array(
368 '#type' => 'radios',
369 '#title' => t('Assign to'),
370 '#required' => TRUE,
371 '#options' => $normalized,
372 );
373 }
374
375 if (isset($node->casetracker->assign_to)) {
376 $form['casetracker']['assign_to']['#default_value'] = is_numeric($node->casetracker->assign_to) ? casetracker_get_name($node->casetracker->assign_to) : $node->casetracker->assign_to;
377 }
378 else {
379 $form['casetracker']['assign_to']['#default_value'] = variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous')));
380 }
381
382 $case_status_options = casetracker_case_state_load('status');
383 $default_status = !empty($node->casetracker->case_status_id) ? $node->casetracker->case_status_id : variable_get('casetracker_default_case_status', key($case_status_options));
384 $form['casetracker']['case_status_id'] = array(
385 '#type' => 'select',
386 '#title' => t('Status'),
387 '#options' => $case_status_options,
388 '#default_value' => $default_status,
389 );
390
391 $case_priority_options = casetracker_case_state_load('priority');
392 $default_priority = !empty($node->casetracker->case_priority_id) ? $node->casetracker->case_priority_id : variable_get('casetracker_default_case_priority', key($case_priority_options));
393 $form['casetracker']['case_priority_id'] = array(
394 '#type' => 'select',
395 '#title' => t('Priority'),
396 '#options' => $case_priority_options,
397 '#default_value' => $default_priority,
398 );
399
400 $case_type_options = casetracker_case_state_load('type');
401 $default_type = !empty($node->casetracker->case_type_id) ? $node->casetracker->case_type_id : variable_get('casetracker_default_case_type', key($case_type_options));
402 $form['casetracker']['case_type_id'] = array(
403 '#type' => 'select',
404 '#title' => t('Type'),
405 '#options' => $case_type_options,
406 '#default_value' => $default_type,
407 );
408
409 return $form;
410 }
411
412 /**
413 * CASE STATE CRUD ====================================================
414 */
415
416 /**
417 * Returns information about the various case states and their options.
418 * The number of parameters passed will determine the return value.
419 *
420 * @param $realm
421 * Optional; the name of the realm ('status', 'priority', or 'type').
422 * @param $csid
423 * Optional; the state ID to return from the passed $realm.
424 * @return $values
425 * If only $realm is passed, you'll receive an array with the keys
426 * being the state ID and the values being their names. If a $csid
427 * is also passed, you'll receive just a string of the state name.
428 * If ONLY a $csid is passed, we'll return a list of 'name', 'realm'.
429 */
430 function casetracker_case_state_load($realm = NULL, $csid = NULL) {
431 static $states_lookup = array();
432
433 if (!$states_lookup) {
434 $results = db_query("SELECT csid, case_state_name, case_state_realm, weight FROM {casetracker_case_states} ORDER BY weight");
435 while ($result = db_fetch_object($results)) { // offer cached csid and realm lookups from a one-time query.
436 $states_lookup[$result->case_state_realm][$result->csid] = array(
437 'name' => $result->case_state_name,
438 'realm' => $result->case_state_realm,
439 'weight' => (int)$result->weight,
440 'csid' => (int)$result->csid
441 );
442 $states_lookup[$result->csid] = $states_lookup[$result->case_state_realm][$result->csid];
443 }
444 }
445
446 if ($csid && $realm) {
447 return $states_lookup[$csid]['name'];
448 }
449 elseif ($csid && !$realm) {
450 return $states_lookup[$csid];
451 }
452 elseif (!$csid && $realm) {
453 $options = array(); // suitable for form api.
454 if (!empty($states_lookup[$realm])) {
455 foreach ($states_lookup[$realm] as $state) {
456 $options[$state['csid']] = $state['name'];
457 }
458 }
459 return $options;
460 }
461 }
462
463 /**
464 * Saves a case state.
465 *
466 * @param $case_state
467 * An array containing 'name' and 'realm' keys. If no 'csid'
468 * is passed, a new state is created, otherwise, we'll update
469 * the record that corresponds to that ID.
470 */
471 function casetracker_case_state_save($case_state = NULL) {
472 if (!$case_state['name'] || !$case_state['realm']) {
473 return NULL;
474 }
475 // Need to collect information into another array since the db columns have different names : (
476 $record = array(
477 'case_state_name' => $case_state['name'],
478 'case_state_realm' => $case_state['realm'],
479 'weight' => $case_state['weight'],
480 );
481 if (isset($case_state['csid'])) {
482 $record['csid'] = $case_state['csid'];
483 drupal_write_record('casetracker_case_states', $record, array('csid'));
484 }
485 else {
486 drupal_write_record('casetracker_case_states', $record);
487 }
488 return $result;
489 }
490
491 /**
492 * Deletes a case state.
493 *
494 * @todo There is currently no attempt to do anything with cases which
495 * have been assigned the $csid that is about to be deleted. We should
496 * reset them to the default per our settings (and warn the user on our
497 * confirmation page), or something else entirely.
498 *
499 * @param $csid
500 * The case state ID to delete.
501 */
502 function casetracker_case_state_delete($csid = NULL) {
503 if (!empty($csid)) {
504 db_query('DELETE FROM {casetracker_case_states} WHERE csid = %d', $csid);
505 }
506 }
507
508 /**
509 * COMMENT DISPLAY ====================================================
510 */
511
512 /**
513 * Retrieve a pipe delimited string of autocomplete suggestions for existing
514 * users. Stolen from user_autocomplete. Eventually this will be expanded to
515 * include OG specific users subscribed to a project.
516 */
517 function casetracker_autocomplete($string) {
518 $matches = array();
519 $group = module_exists('og') ? og_get_group_context() : NULL;
520 if ($group) {
521 $gid = $group->nid;
522 $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);
523 }
524 else {
525 $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
526 }
527 while ($user = db_fetch_object($result)) {
528 $matches[$user->name] = check_plain($user->name);
529 }
530 drupal_json($matches);
531 }
532
533 /**
534 * Returns an query string needed in case of Organic Groups
535 * providing preselected audience checkboxes for projects as groups (og)
536 *
537 * @param object CT project
538 * @return string
539 */
540 function _casetracker_get_og_query_string(&$project) {
541 $querystring = array();
542 // checking if project is group
543 if ($project->type == 'group') {
544 $querystring[] = 'gids[]='. $project->nid;
545 //checking if group-project is part of another group
546 if (isset($project->og_groups)
547 && is_array($project->og_groups)
548 ) {
549 foreach ($project->og_groups as $group) {
550 $querystring[] = 'gids[]='. $group;
551 }
552 }
553 }
554 //checking if project is part of a group
555 elseif (isset($project->og_groups)
556 && is_array($project->og_groups)
557 && $project->type !== 'group'
558 ) {
559 foreach ($project->og_groups as $group) {
560 $querystring[] = 'gids[]='. $group;
561 }
562 }
563
564 return (0 < count($querystring))
565 ? implode('&', $querystring)
566 : NULL;
567 }
568
569 /**
570 * THEME ==============================================================
571 */
572
573 /**
574 * Implementation of hook_theme
575 */
576 function casetracker_theme() {
577 return array(
578 'casetracker_comment_changes' => array(),
579 'casetracker_case_form_common' => array(),
580 'casetracker_case_summary' => array(),
581 'casetracker_project_summary' => array(),
582 );
583 }
584
585 /**
586 * Displays the changes a comment has made to the case fields.
587 *
588 * @param $case_data
589 * An array of both 'old' and 'new' objects that contains
590 * the before and after values this comment has changed.
591 */
592 function theme_casetracker_comment_changes($old, $new) {
593 $rows = array();
594
595 $fields = array(
596 'pid' => t('Project'),
597 'title' => t('Title'),
598 'case_status_id' => t('Status'),
599 'assign_to' => t('Assigned'),
600 'case_priority_id' => t('Priority'),
601 'case_type_id' => t('Type'),
602 );
603 foreach ($fields as $field => $label) {
604 if ($new->{$field} != $old->{$field}) {
605 switch ($field) {
606 case 'pid':
607 $old_title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", $old->pid));
608 $new_title = db_result(db_query("SELECT title FROM {node} WHERE nid = %d", $new->pid));
609 $old->{$field} = l($old_title, "node/{$old->pid}");
610 $new->{$field} = l($new_title, "node/{$new->pid}");
611 break;
612 case 'case_status_id':
613 $old->{$field} = casetracker_case_state_load('status', $old->{$field});
614 $new->{$field} = casetracker_case_state_load('status', $new->{$field});
615 break;
616 case 'assign_to':
617 $old->{$field} = casetracker_get_name($old->{$field});
618 $new->{$field} = casetracker_get_name($new->{$field});
619 break;
620 case 'case_priority_id':
621 $old->{$field} = casetracker_case_state_load('priority', $old->{$field});
622 $new->{$field} = casetracker_case_state_load('priority', $new->{$field});
623 break;
624 case 'case_type_id':
625 $old->{$field} = casetracker_case_state_load('type', $old->{$field});
626 $new->{$field} = casetracker_case_state_load('type', $new->{$field});
627 break;
628 }
629 $rows[] = array(t('!label: !old &raquo; !new', array('!label' => $label, '!old' => $old->{$field}, '!new' => $new->{$field})));
630 }
631 }
632
633 return theme('table', NULL, $rows, array('class' => 'case_changes'));
634 }
635
636 /**
637 * Theme function for cleaning up the casetracker common form.
638 */
639 function theme_casetracker_case_form_common($form) {
640 drupal_add_css(drupal_get_path('module', 'casetracker') .'/casetracker.css');
641 $output = '';
642 $output .= drupal_render($form['pid']);
643 $output .= drupal_render($form['case_title']);
644
645 if ($form['assign_to']['#type'] == 'radios') {
646 $header = array_fill(0, 5, array());
647 $header[0] = $form['assign_to']['#title'];
648 $radios = array();
649 foreach (element_children($form['assign_to']) as $id) {
650 $radios[] = drupal_render($form['assign_to'][$id]);
651 }
652 $radios = array_chunk($radios, 5);
653 $output .= theme('table', $header, $radios, array('class' => 'casetracker-assign-to'));
654 drupal_render($form['assign_to']);
655 }
656 else {
657 $output .= drupal_render($form['assign_to']);
658 }
659
660 $row = array();
661 foreach (element_children($form) as $id) {
662 if (!in_array($id, array('pid', 'case_title', 'assign_to'))) {
663 $row[] = drupal_render($form[$id]);
664 }
665 }
666 $rows = array($row);
667 $output .= theme('table', array(), $rows);
668 $output .= drupal_render($form);
669 return $output;
670 }
671
672 /**
673 * Theme the case summary shown at the beginning of a case's node.
674 *
675 * @param $case
676 * The node object of the case being viewed.
677 * @param $project
678 * The node object of the project this case belongs to.
679 */
680 function theme_casetracker_case_summary($case, $project) {
681 $last_comment = db_result(db_query('SELECT last_comment_timestamp FROM {node_comment_statistics} WHERE nid = %d', $case->nid));
682 $rows = array();
683
684 $rows[] = array(
685 t('Assigned to:'),
686 theme('username', user_load(array('uid' => $case->casetracker->assign_to))),
687 );
688 $rows[] = array(
689 t('Created:'),
690 theme_username($case) ." ". t('at') ." ". format_date($case->created, 'medium'),
691 );
692 $rows[] = array(
693 t('Status:'),
694 "<strong>". casetracker_case_state_load('status', $case->casetracker->case_status_id) ."</strong> (" .
695 casetracker_case_state_load('type', $case->casetracker->case_type_id) .' / '.
696 t("Priority") ." ".
697 casetracker_case_state_load('priority', $case->casetracker->case_priority_id) .
698 ")",
699 );
700 $rows[] = array(
701 t('Case ID:'),
702 l($project->title, 'node/'. $case->casetracker->pid) .': '. $project->nid .'-'. $case->nid,
703 );
704 if ($last_comment != $case->created) {
705 $rows[] = array(
706 t('Last modified:'),
707 format_date($last_comment, 'medium')
708 );
709 }
710
711 $output = '<div class="case">';
712 $output .= theme('table', NULL, $rows, array('class' => 'summary'));
713 $output .= '</div>';
714 return $output;
715 }
716
717 /**
718 * Theme the project summary shown at the beginning of a project's node.
719 *
720 * @param $project
721 * The node object of the project being viewed.
722 */
723 function theme_casetracker_project_summary($project) {
724 $rows = array();
725 $rows[] = array(t('Project number:'), $project->nid);
726 $rows[] = array(t('Opened by:'), theme_username($project));
727 $rows[] = array(t('Opened on:'), format_date($project->created, 'large'));
728 $rows[] = array(t('Last modified:'), format_date($project->changed, 'large'));
729
730 $querystring = _casetracker_get_og_query_string($project);
731 $operations = array(); $node_types = node_get_types('names');
732 foreach (array_filter(variable_get('casetracker_case_node_types', array('casetracker_basic_case'))) as $type) {
733 $operations[] = l(
734 t('add !name', array('!name' => $node_types[$type])),
735 'node/add/'. str_replace('_', '-', $type) .'/'. $project->nid,
736 array('query' => $querystring)
737 );
738 }
739 $operations = implode(' | ', $operations); // ready for printing in our Operations table cell - delimited by a pipe. nonstandard.
740 $rows[] = array(t('Operations:'), $operations .' | '. l(t('view all project cases'), 'casetracker', array('query' => 'keys=&pid='. $project->nid)));
741
742 $output = '<div class="project">';
743 $output .= theme('table', NULL, $rows, array('class' => 'summary'));
744 $output .= '</div>';
745 return $output;
746 }
747
748 /**
749 * API FUNCTIONS ======================================================
750 */
751
752 /**
753 * API function that returns valid project options.
754 */
755 function casetracker_project_options() {
756 $projects = array();
757 // Fetch the views list of projects, which is space-aware.
758 if ($view = views_get_view('casetracker_project_options')) {
759 $view->set_display();
760 $view->set_items_per_page(0);
761 $view->execute();
762 foreach ($view->result as $row) {
763 $projects[$row->nid] = $row->node_title;
764 }
765 }
766 return $projects;
767 }
768
769 /**
770 * API function that returns valid user options.
771 */
772 function casetracker_user_options() {
773 $group = module_exists('og') ? og_get_group_context() : NULL;
774 $options = array(0 => variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous'))));
775 if ($group) {
776 $gid = $group->nid;
777 $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);
778 }
779 else {
780 $results = db_query('SELECT u.uid, u.name FROM {users} u WHERE u.status > 0 AND u.uid > 0 ORDER BY u.name ASC');
781 }
782 while ($result = db_fetch_object($results)) {
783 $options[$result->uid] = check_plain($result->name);
784 }
785 return $options;
786 }
787
788 /**
789 * API function for checking whether a node type is a casetracker case.
790 */
791 function casetracker_is_case($node) {
792 if (is_object($node) && !empty($node->type)) {
793 $type = $node->type;
794 }
795 else if (is_string($node)) {
796 $type = $node;
797 }
798 if ($type) {
799 return in_array($type, variable_get('casetracker_case_node_types', array('casetracker_basic_case')), TRUE);
800 }
801 return FALSE;
802 }
803
804 /**
805 * API function for checking whether a node type is a casetracker project.
806 */
807 function casetracker_is_project($node) {
808 if (is_object($node) && !empty($node->type)) {
809 $type = $node->type;
810 }
811 else if (is_string($node)) {
812 $type = $node;
813 }
814 if ($type) {
815 return in_array($type, variable_get('casetracker_project_node_types', array('casetracker_basic_project')), TRUE);
816 }
817 return FALSE;
818 }
819
820 /**
821 * Given a user name, returns the uid of that account.
822 * If the passed name is not found, returns 0.
823 * See also casetracker_get_name().
824 */
825 function casetracker_get_uid($name = NULL, $reset = FALSE) {
826 static $users = array();
827 if (!isset($users[$name]) || $reset) {
828 $result = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $name));
829 $users[$name] = $result ? $result : 0;
830 }
831 return $users[$name];
832 }
833
834 /**
835 * Given a uid, returns the name of that account. If the passed uid is
836 * not found, returns the default "assign to" name as specified in the
837 * settings. @todo This may not always be desired, but is how we use it.
838 * See also casetracker_get_uid().
839 */
840 function casetracker_get_name($uid = NULL, $reset = FALSE) {
841 static $users = array();
842 if (!isset($users[$uid]) || $reset) {
843 $result = db_result(db_query("SELECT name FROM {users} WHERE uid = %d", $uid));
844 $users[$uid] = $result ? $result : '';
845 }
846 return !empty($users[$uid]) ? $users[$uid] : variable_get('casetracker_default_assign_to', variable_get('anonymous', t('Anonymous')));
847 }

  ViewVC Help
Powered by ViewVC 1.1.2