/[drupal]/contributions/modules/helpdesk/helpdesk.php
ViewVC logotype

Contents of /contributions/modules/helpdesk/helpdesk.php

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


Revision 1.1 - (show annotations) (download) (as text)
Tue Jan 17 19:55:10 2006 UTC (3 years, 10 months ago) by fgm
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-4-6
File MIME type: text/x-php
First version under CVS control: not yet a working version: only performs a minimal subset of the functionality designed for the module.
1 <?php
2 /**
3 * Customer Support module.
4 * @package helpdesk
5 * @author Frederic G. MARAND <fgm@osinet.fr>
6 * Copyright OSI 2005. Licensed under GPL version 2.
7 * $Id$
8 *
9 * @todo make it work first
10 * @version $Id
11 * 20051005
12 * - Completed _helpdesk_user and affiliated functions
13 * 20050920
14 * - Added _helpdesk_block_view_CUSTOMEROPENTICKETS
15 * 20050919
16 * - Added _helpdesk_block_view_MYOPENTICKETS
17 * - Added access control to _helpdesk_block_view
18 * 20050918
19 * - Added _helpdek_block_view_ALLOPENTICKETS
20 */
21
22 $_helpdesk_saved_er = error_reporting (E_ALL || E_STRICT) ;
23
24 /**
25 * Import helpdesk-related classes and functions
26 */
27 require_once("misc.php") ;
28 require_once("contract.php") ;
29 require_once("customer.php") ;
30 require_once("event.php") ;
31 require_once("timeinfo.php") ;
32
33 define ('HELPDESKDEBUGALLFUNCTIONS', TRUE) ;
34
35 /**
36 * Constants for helpdesk node types
37 */
38 define ('HELPDESKNODECONTRACT', 'helpdesk-contra') ;
39 define ('HELPDESKNODETICKET', 'helpdesk-ticket') ;
40 define ('HELPDESKNODEFOLLOWUP', 'helpdesk-follow') ;
41
42 define ('HELPDESKTITLECONTRACT', 'Helpdesk > Contract') ;
43 define ('HELPDESKTITLETICKET', 'Helpdesk > Ticket') ;
44 define ('HELPDESKTITLEFOLLOWUP', 'Helpdesk > Followup') ;
45
46 /**
47 * Constants for HELPDESK perms
48 */
49 define ("HELPDESKPERMUSER", 'Helpdesk > User' ) ;
50 define ("HELPDESKPERMCUSTOMER", 'Helpdesk > Customer') ;
51 define ("HELPDESKPERMTECH", 'Helpdesk > Tech') ;
52 define ("HELPDESKPERMMAX", HELPDESKPERMTECH) ;
53
54 /**
55 * Constants for HELPDESK block deltas
56 */
57 define ("HELPDESKBLOCKMYOPENTICKETS", 0) ;
58 define ("HELPDESKBLOCKMYLATESTTICKETS", 1) ;
59 define ("HELPDESKBLOCKCUSTOMEROPENTICKETS", 2) ;
60 define ("HELPDESKBLOCKCUSTOMERBALANCE", 3) ;
61 define ("HELPDESKBLOCKALLOPENTICKETS", 4) ;
62 define ("HELPDESKBLOCKMAX", HELPDESKBLOCKALLOPENTICKETS) ;
63
64 /**
65 * Constants for Drupal variables
66 */
67 define ("HELPDESKVARSHOWROLES", 'helpdesk_show_roles') ;
68 define ("HELPDESKVARTICKETPREFIX", 'helpdesk_ticket_prefix') ; // Unused part of the ticket number
69 define ("HELPDESKVARTICKETOFFSET", 'helpdesk_ticket_base') ; // Number to be added to nid to build ticket number
70 define ('HELPDESKVARVIDSEVERITY', 'helpdesk_vid_severity') ; // Used to select the vocabulary used for severity terms
71 define ('HELPDESKVARVIDSTATUS', 'helpdesk_vid_status') ; // Used to select the vocabulary used for status terms
72
73 /**
74 * Constants for hook_access
75 */
76 define ("HELPDESKHOOKACCESSCREATE", "create") ;
77 define ("HELPDESKHOOKACCESSDELETE", "delete") ;
78 define ("HELPDESKHOOKACCESSUPDATE", "update") ;
79 define ("HELPDESKHOOKACCESSVIEW", "view") ;
80
81 /**
82 * Helpdesk access control
83 * User may create an issue, read and close his own issues, add followups to his issues
84 * Customer has User rights, extended to all users bound to him, and can perform some actions on his contracts
85 * Tech can do anything HELPDESK-related
86 * @param string $op create | delete | update | view
87 * @param object $node the node on which "op" is to be performed
88 * @return mixed boolean or NULL
89 * @link http://drupaldocs.org/api/head/function/hook_access Drupal API
90 */
91 function helpdesk_access ($op, $node)
92 {
93 global $user ;
94 $ret = FALSE ;
95
96 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
97 {
98 $log = "<pre>HELPDESK_ACCESS ($op, " . _helpdesk_get_node_property($node, 'nid') ;
99 }
100
101 /* By default, node_access is set to just one row :
102 nid == gid == 0
103 realm == "all"
104 grant_update == grant_delete == 0
105 grant_view == 1
106 gid appears to be unused in 4.6.*
107 */
108 switch ($op)
109 {
110 case HELPDESKHOOKACCESSCREATE:
111 {
112 // In this case, $node is a string containing the node type, not a node object
113 // Issue and Followup may be created from the HELPDESK User level, but only HELPDESK Techs can create contracts
114 switch ($node)
115 {
116 case HELPDESKNODECONTRACT :
117 $ret = user_access (HELPDESKPERMTECH) ;
118 // echo "<p>Create/Contract, ret = $ret</p>" ;
119 break ;
120 case HELPDESKNODETICKET :
121 case HELPDESKNODEFOLLOWUP :
122 $ret = user_access (HELPDESKPERMUSER) || user_access (HELPDESKPERMCUSTOMER) || user_access (HELPDESKPERMTECH) ;
123 // echo "<p>Create/Ticket of Followup, ret = $ret</p>" ;
124 break ;
125 default: // Don't worry about other types
126 echo "<pre>Anomalie dans helpdesk_access/create: node = " ; print_r ($node) ; echo "</pre>" ;
127 $ret = TRUE ;
128 break ;
129 }
130 break ;
131 }
132 case HELPDESKHOOKACCESSDELETE:
133 {
134 // For contract traceability, only techs may delete Issue or Followups
135 $ret = user_access (HELPDESKPERMTECH) ;
136 echo "<p>helpdesk_access/delete, ret = $ret</p>" ;
137 break ;
138 }
139 case HELPDESKHOOKACCESSUPDATE:
140 {
141 /* For traceability, only techs may update Issue or Followups
142 Users and customers wishing to update a ticket must issue a Followup
143 Modifiying the status of an issue is handled by creating a
144 followup with the new status */
145 $ret = user_access (HELPDESKPERMTECH) ;
146 //echo "<p>helpdesk_access/update, ret = $ret</p>" ;
147 break ;
148 }
149 case HELPDESKHOOKACCESSVIEW:
150 {
151 // For this op, node is supposed to be already assigned
152 $ret = FALSE ;
153 /* Helpdesk User may see his own events,
154 Helpdesk Customer may see the events of his users
155 Helpdesk tech may view anything */
156 $ret |= (user_access (HELPDESKPERMUSER) && ($user->uid == $node->uid)) ;
157 // TODO : HELPDESK Customer access will have to be computed from the HELPDESK users bound to him
158 $ret |= user_access (HELPDESKPERMCUSTOMER) ; // Will have to be restricted to the tickets of bound users.
159 $ret |= user_access (HELPDESKPERMTECH) ;
160 echo "<p>helpdesk_access/view, ret = $ret</p>" ;
161 break ;
162 }
163 default: die ('<p><code>helpdesk_access</code> invoked with an unauthorized value: $op. Aborting.</p>') ;
164 }
165 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
166 { echo "$log) = " . $ret . "</pre>" ; }
167 return $ret ;
168 }
169
170 /**
171 * Implementation of hook_help : provides and manages the helpdesk blocks.
172 * @param op the operation from the URL (Drupal: list, view, configure, save. ?)
173 * - 'list': A list of all blocks defined by the module
174 * - 'configure': A configuration form
175 * - 'view': Save the configuration options
176 * - save': Information about a particular block
177 * @param delta offset
178 * @return mixed type depends on $op.
179 * @link http://drupaldocs.org/api/head/function/hook_block Drupal API
180 * @see _helpdesk_block_list()
181 * @see _helpdesk_block_configure()
182 * @see _helpdesk_block_view()
183 * @see _helpdesk_block_save()
184 */
185 function helpdesk_block ($op = 'list', $delta = 0)
186 {
187 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
188 { echo "<pre>HELPDESK_BLOCK (op = $op, delta = $delta)</pre>" ; }
189
190 // listing of blocks, such as on the admin/block page
191 switch ($op)
192 {
193 case 'list': { return _helpdesk_block_list ($delta) ; }
194 case 'configure': { return _helpdesk_block_configure ($delta) ; }
195 case 'save': { return _helpdesk_block_save ($delta) ; }
196 case 'view': { return _helpdesk_block_view ($delta) ; } // Information about a particular block
197 default: die('helpdesk_block called with invalid op: $op') ;
198 }
199 } // end helpdesk_block
200
201 /**
202 * HELPDESK actions to be performed when a HELPDESK node is deleted
203 * @param object $node the node to be deleted after this function
204 * @return void
205 * @link http://drupaldocs.org/api/head/function/hook_delete
206 */
207 function helpdesk_delete ($node)
208 {
209 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
210 { echo "<pre>HELPDESK_DELETE (node = " ; print_r ($node) ; echo ")</pre>" ; }
211
212 /* This function must:
213 - either allow the db to become inconsistent (events without contracts, followups without tickets)
214 - or delete related nodes (followups for a ticket node, tickets and followups for a contract node), causing loss of traceability
215 In the first version, it will allow the db to become inconsistent: contract numbers are node, and as such
216 are not reused anyway, so there is no overload risk.
217 */
218 switch (_helpdesk_node_type($node))
219 {
220 case HELPDESKNODECONTRACT :
221 $q = 'DELETE FROM {hd_contract} WHERE nid = %d ';
222 $res = db_query($q, $node->nid);
223 unset ($q);
224 unset ($res);
225 break ;
226 case HELPDESKNODETICKET :
227 case HELPDESKNODEFOLLOWUP :
228 break; // Not yet implemented
229 }
230 }
231
232 /**
233 * Helpdesk data entry form. Used for both node add and edit
234 * testing for $node->nid allows the code to define whether the node is to be created of modified
235 * @param object $node the node to be entered
236 * @return string HTML
237 */
238 function helpdesk_form (&$node) //XXXwas helpdesk_form(&$node)
239 {
240 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
241 { echo "<pre>HELPDESK_FORM (node = " ; print_r ($node) ; echo ")</pre>" ; }
242
243 $output = '' ;
244 // In order to be able to attach taxonomy terms to this node, we need
245 // to display the appropriate form elements.
246 if (function_exists('taxonomy_node_form'))
247 {
248 $output .= implode('', taxonomy_node_form('helpdesk', $node));
249 }
250 else
251 { theme_error('helpdesk cannot find taxonomy_node_form. Have you activated taxonomy.module') ; }
252
253 $nodetype = _helpdesk_node_type($node) ;
254 switch ($nodetype)
255 {
256 case HELPDESKNODECONTRACT:
257 if (!isset($node->{$nodetype})) // Happens at the first step of node creation
258 {
259 $node->{$nodetype} = new helpdeskContract();
260 $node->{$nodetype}->init($node, FALSE); // $node is always set at this point, load from it, not from DB
261 }
262 $output = $node->{$nodetype}->form();
263 break;
264 case HELPDESKNODETICKET:
265 if (!isset($node->{$nodetype}))
266 {
267 $node->{$nodetype} = new helpdeskTicket();
268 $node->{$nodetype}->init($node, FALSE); // $node is always set at this point, load from it, not from DB
269 }
270 $output = $node->{$nodetype}->form();
271 break ;
272 case HELPDESKNODEFOLLOWUP:
273 $output = helpdeskFollowup::createForm () ;
274 break ;
275 default:
276 echo "<p>Anomaly: helpdesk_form called for type " . _helpdesk_node_type($node) . "</p>" ;
277 break;
278 }
279
280 // echo "<p>In helpdesk_form</p>" ;
281 return $output ;
282 } // helpdesk_form
283
284 /**
285 * Display help and module information
286 * Documented values as of 4.6.3 and HEAD on 2005/08/21
287 * @param string $section Drupal URL path (or: menu item) the help is being requested for, e.g. admin/node or user/edit. Recognizes special descriptors after a "#" sign
288 * @return help text for section
289 */
290 function helpdesk_help ($section = '')
291 {
292 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
293 { echo "<pre>HD HELP (section = $section), " ; }
294
295 $output = '' ;
296 switch ($section)
297 {
298 /* // The name of a module (unused, but there)
299 case "admin/modules#name" :
300 break; */
301 // The description found on the admin/system/modules page.
302 case "admin/modules#description":
303 $output = t ("Enable Helpdesk/ticketing functions") ;
304 break;
305
306 // The module's help text, displayed on the admin/help page and through the module's individual help link.
307 case "admin/help#helpdesk":
308 $output = t ("This module allows for the generation of tickets, and management of helpdesk calls. "
309 . "It enables tickets to be bound to support contracts and managed by a "
310 . "helpdesk contract administrator. Various types of charging are available, "
311 . "included unlimited, time spent, number of tickets, and date limit.") ;
312 break ;
313
314 /* // The help for a distributed authorization module (if applicable).
315 case "user/help#helpdesk":
316 break ;*/
317
318 // The description of a node type (if applicable).
319 case "node/add#" . HELPDESKNODECONTRACT:
320 $output = t("Define a new helpdesk contract for an existing helpdesk customer") ;
321 break ;
322 case "node/add#" . HELPDESKNODETICKET:
323 $output = t("Obtain a helpdesk ticket for a new helpdesk issue") ;
324 break ;
325 case "node/add#" . HELPDESKNODEFOLLOWUP:
326 $output = t("Add a followup to an existing helpdesk ticket") ;
327 break ;
328 }
329 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
330 echo "output : $output</pre>" ;
331 return $output;
332 } // function helpdesk_help
333
334 /**
335 * Upon creation of a helpdesk-related node, perform insertions on our private tables
336 * We're not supposed to test for access here, as it's already been done earlier in node_add (?)
337 * @param object $node the node being inserted
338 * @return void
339 */
340 function helpdesk_insert ($node)
341 {
342 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
343 { echo "<pre>HD INSERT (node = " ; print_r ($node) ; echo ")</pre>" ; }
344 switch ($node->type)
345 {
346 case HELPDESKNODECONTRACT:
347 $o = new helpdeskContract();
348 $o->init($node, FALSE); // Not yet in DB, load from $node
349 $o->insert();
350 break ;
351 case HELPDESKNODETICKET:
352 echo "<pre>Inserting ticket</pre>" ;
353 break ;
354 case HELPDESKNODEFOLLOWUP:
355 echo "<pre>Inserting followup</pre>" ;
356 break ;
357 default :
358 echo "<pre>helpdesk_insert: insertion d'un type non supporté: $node->type</pre>" ;
359 break ;
360 }
361 }
362
363 /**
364 * This hook enables modules to add links to many parts of Drupal.
365 * Links may be added in nodes or in the navigation block, for example.
366 * In our case, this will allow followups to be added to either issues or followups (threading)
367 * @param string $type An identifier declaring what kind of link is being requested. Possible values:
368 * - node: Links to be placed below a node being viewed.
369 * - comment: Links to be placed below a comment being viewed.
370 * @param int $node A node object passed in case of node links.
371 * @param int $teaser In case of node link: a 0/1 flag depending on whether the node is displayed with its teaser or its full form (on a node/nid page)
372 * @return array array of links
373 * @link http://drupaldocs.org/api/head/function/hook_link Drupal API
374 */
375 function helpdesk_link($type, $node = NULL, $teaser = FALSE)
376 {
377 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
378 { echo "<pre>HD LINK ($type, $node->nid, $teaser)</pre>" ; }
379
380 if ((!isset($type)) || ($type == 'comment'))
381 return NULL ;
382
383 if (!isset($node))
384 die("helpdesk_link('node', NULL, $teaser) invoked: invalid set of parameters") ;
385
386 /**
387 * @todo Access should be tested
388 * @todo It should be possibly to add a followup to the original issue from a followup
389 **/
390 switch ($node->type)
391 {
392 case HELPDESKNODETICKET:
393 $links[] = l(t('add followup'), ('helpdesk/followup/' . $node->nid),
394 array('title' => t('Add a followup to this ticket.')));
395 break;
396 case HELPDESKNODEFOLLOWUP:
397 $links[] = l(t('add followup'), 'helpdesk/followup/' . $node->nid,
398 array('title' => t('Add a followup to this followup (threaded answer).')));
399 break;
400 case HELPDESKNODECONTRACT:
401 $links[] = l(t('new ticket'), 'node/add/' . HELPDESKNODETICKET . '/' . $node->nid,
402 array('title' => t('Obtain a ticket for an issue covered by this contract.')));
403 break;
404 default:
405 $links = NULL ; // die("helpdesk_link('node', $node->nid, $teaser) invoked, but node is of type: $node->type");
406 }
407
408 return $links ;
409 }
410
411 /**
412 * load auxiliary data for HD nodes. We wrap the returned object in an array to prevent mixing with
413 * other modules and drupal core.
414 * @param object $node the node being loaded
415 * @return object the properties to be added to the passed node object
416 * @link http://drupaldocs.org/api/4.6/function/hook_load Drupal API
417 */
418 function helpdesk_load($node)
419 {
420 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
421 { echo "<pre>HD LOAD (" . _helpdesk_get_node_property($node, 'nid') . ")</pre>\r\n" ; }
422 $output = NULL ;
423 switch ($node->type) // Is supposed to be assigned and valid
424 {
425 case HELPDESKNODECONTRACT : // Load attributes from hd_contract/hd_timeinfo
426 $o = new helpdeskContract();
427 $o->init($node, TRUE); // Load from DB
428 break ;
429 case HELPDESKNODETICKET : // Load attributes and thread from hd_event/hd_timeinfo
430 break ;
431 case HELPDESKNODEFOLLOWUP : // Load attributes and thread from hd_event/hd_timeinfo
432 break ;
433 default :
434 die("helpdesk_load invoked for node $node->nid, incorrect type $node->type");
435 }
436
437 if (isset($o))
438 {
439 $output = array();
440 $output [$node->type] = $o ;
441 }
442 else
443 return NULL ;
444 return $output ; // Should contain the auxiliary data
445 }
446
447 /**
448 * HELPDESK menu is enabled for all users with HELPDESK
449 * @return array of menu definitions
450 */
451 function helpdesk_menu($may_cache) {
452 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
453 { echo '<pre>HD MENU</pre>' ; }
454 $items = array();
455
456 if ($may_cache)
457 {
458 $items[] = array('path' => 'node/add/' . HELPDESKNODECONTRACT,
459 'title' => t(HELPDESKTITLECONTRACT),
460 'access' => helpdesk_access('create', HELPDESKNODECONTRACT));
461 $items[] = array('path' => 'node/add/' . HELPDESKNODETICKET,
462 'title' => t(HELPDESKTITLETICKET),
463 'access' => helpdesk_access('create', HELPDESKNODETICKET));
464 $items[] = array('path' => 'node/add/' . HELPDESKNODEFOLLOWUP,
465 'title' => t(HELPDESKTITLEFOLLOWUP),
466 'access' => helpdesk_access('create', HELPDESKNODEFOLLOWUP));
467 $items[] = array('path' => 'helpdesk/followup/',
468 'title' => t(HELPDESKTITLEFOLLOWUP),
469 'access' => helpdesk_access('create', HELPDESKNODEFOLLOWUP),
470 'type' => MENU_CALLBACK); // This is to allow followups to a known node, so it must be called from a node, not from the menu
471 }
472
473 // echo "<pre>helpdesk_menu: " ; print_r ($items) ; echo ", may_cache: " . ($may_cache ? "TRUE" : "FALSE") . "</pre>" ;
474 return $items;
475 }
476
477
478 /**
479 * Implementation of hook_nodeapi, for tracing purposes only
480 *
481 * @param object $node
482 * @param string $op
483 * @param boolean $teaser
484 * @param boolean $page
485 */
486 function helpdesk_nodeapi(&$node, $op, $teaser = NULL, $page = NULL)
487 {
488 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
489 { echo "<pre>HD NODEAPI(node $node->nid, op = $op, teaser = $teaser, page = $page)</pre>\r\n" ; }
490 }
491
492 /**
493 * Name our node names. See also helpdesk_node_types
494 * @param mixed node either a string (node type ) or node object
495 * @return string the human-readable node name
496 */
497 function helpdesk_node_name ($node)
498 {
499 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
500 {
501 $ret = "<pre>HD NODE_NAME (" ;
502 if (is_object($node))
503 $ret .= "OBJ: nid = " . (isset($node->nid) ? $node->nid : 'new node') . ", type = $node->type" ;
504 else
505 $ret .= "Plain: $node" ;
506
507 $ret .= ")</pre>\r\n" ;
508 print ($ret);
509 }
510 switch (is_string ($node) ? $node : (is_array($node) ? $node['type'] : $node->type))
511 {
512 case HELPDESKNODECONTRACT: return t (HELPDESKTITLECONTRACT) ;
513 case HELPDESKNODETICKET: return t (HELPDESKTITLETICKET) ;
514 case HELPDESKNODEFOLLOWUP: return t (HELPDESKTITLEFOLLOWUP) ;
515 }
516 return NULL;
517 }
518
519 /**
520 * Define our node types
521 * @return array the array of our node types
522 */
523 function helpdesk_node_types ()
524 {
525 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
526 { echo '<pre>HD NODE_TYPES</pre>' ; }
527 return array (
528 HELPDESKNODECONTRACT,
529 HELPDESKNODETICKET,
530 HELPDESKNODEFOLLOWUP) ;
531 }
532
533 /**
534 * Valid permissions for this module
535 * @return array An array of valid permissions for the helpdesk module
536 */
537 function helpdesk_perm ()
538 {
539 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
540 { echo '<pre>HELPDESK_PERM</pre>' ; }
541 return array (
542 HELPDESKPERMUSER,
543 HELPDESKPERMCUSTOMER,
544 HELPDESKPERMTECH
545 ) ;
546 } // function helpdesk_perm()
547
548 /**
549 * Module configuration settings
550 * @return string settings HTML or deny access
551 */
552 function helpdesk_settings ()
553 {
554 $output = '' ;
555
556 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
557 { echo "<pre>HELPDESK_SETTINGS</pre>" ; }
558
559 // only HELPDESK Tech support can access this module
560 if (!user_access (HELPDESKPERMTECH))
561 {
562 return message_access () ;
563 }
564 $output .= form_checkbox // checked, description, attributes, required
565 (
566 t ("Show users their current roles"), // title
567 HELPDESKVARSHOWROLES, // name
568 TRUE, // value
569 variable_get (HELPDESKVARSHOWROLES, FALSE), // checked
570 t ("Allow users to see their Drupal roles on their \"My account/edit\" page, \"user roles\" local task."),
571 NULL, // attributes
572 FALSE
573 ) ;
574
575 $output .= form_textfield // checked, description, attributes, required
576 (
577 t ("Ticket prefix"), // title
578 HELPDESKVARTICKETPREFIX, // name
579 variable_get(HELPDESKVARTICKETPREFIX, ''), // initial value
580 8, // size of field
581 8, // max length
582 t ("The prefix to be prepended to the node number to build ticket numbers as seen by customers."), // description
583 NULL, // attributes
584 FALSE
585 ) ;
586
587 $output .= form_textfield // checked, description, attributes, required
588 (
589 t ("Ticket offset"), // title
590 HELPDESKVARTICKETOFFSET, // name
591 variable_get(HELPDESKVARTICKETOFFSET, 0), // initial value
592 8, // size of field
593 8, // max length
594 t ("The number to be added to the node number to build ticket numbers as seen by customers."), // description
595 NULL, // attributes
596 FALSE
597 ) ;
598
599 $q = '
600 SELECT
601 v.vid, v.name, v.description
602 FROM
603 {vocabulary} v
604 ORDER BY
605 2, 3, 1
606 ';
607 $arVids = array();
608 $res = db_query($q);
609 while ($o = db_fetch_object($res))
610 {
611 $arVids[$o->vid] = "$o->name: $o->description" ;
612 }
613 $output .= form_select(
614 t('Vocabulary used for severity levels'), // title
615 HELPDESKVARVIDSEVERITY, // name
616 variable_get(HELPDESKVARVIDSEVERITY, NULL), // current value
617 $arVids, // array of vocabularies
618 t('Choose the vocabulary to be used as the set of values allowed for severity values.'), // description
619 NULL, // extra
620 FALSE, // Only one vocabulary used
621 TRUE); // One vocabulary must be selected
622 unset($arVids);
623
624 $q = '
625 SELECT
626 v.vid, v.name, v.description
627 FROM
628 {vocabulary} v
629 ORDER BY
630 2, 3, 1
631 ';
632 $arVids = array();
633 $res = db_query($q);
634 while ($o = db_fetch_object($res))
635 {
636 $arVids[$o->vid] = "$o->name: $o->description" ;
637 }
638 $output .= form_select(
639 t('Vocabulary used for ticket status values'), // title
640 HELPDESKVARVIDSTATUS, // name
641 variable_get(HELPDESKVARVIDSTATUS, NULL), // current value
642 $arVids, // array of vocabularies
643 t('Choose the vocabulary to be used as the set of values allowed for ticket status.'), // description
644 NULL, // extra
645 FALSE, // Only one vocabulary used
646 TRUE); // One vocabulary must be selected
647 unset($arVids);
648
649 return $output;
650 }
651
652 /**
653 * Specs: Respond to node updating. This is a hook used by node modules. It is called to allow the module to take action when an edited node is being updated in the database by, for example, updating information in related tables.
654 * @param object $node The node being updated
655 * @return void
656 * @todo see source
657 */
658 function helpdesk_update($node)
659 {
660 /* For all our nodes:
661 - copy the node/created, node/changed timestaps to hd_timeinfo
662 - copy the additional properties to hd_contract, hd_event
663 */
664 return ;
665 }
666
667
668 /**
669 * Per the docs: This is a hook used by node modules.
670 * It allows a module to define a custom method of displaying its nodes,
671 * usually by displaying extra information particular to that node type.
672 * @param object $node
673 * @param string $teaser
674 * @param int $page
675 * @return void
676 */
677 function helpdesk_view(&$node, $teaser = FALSE, $page = FALSE)
678 {
679 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
680 { echo "<pre>HELPDESK_VIEW (node = " . _helpdesk_get_node_property($node, 'nid') . ", teaser = $teaser, page = $page)</pre>" ; }
681
682 $output = '' ;
683 $node = node_prepare ($node, $teaser) ; // Filter according to node filter settings
684
685 if ($teaser)
686 {
687 $output = 'We are working on the teaser' ;
688 $node->teaser = $output ;
689 $node->body = '' ;
690 unset ($output) ;
691 }
692 else
693 {
694 switch ($node->type)
695 {
696 case HELPDESKNODETICKET:
697 if (!isset($node->{$node->type})) // Not coming from a form (hence not a preview). Can come from DB
698 {
699 $node->{$node->type} = new helpdeskTicket();
700 $node->{$node->type}->init($node, TRUE);
701 }
702 $onode = $node->{$node->type};
703 $output = theme_placeholder($onode->getTicket ()) ;
704 $node->body = $onode->view() . $node->body ;
705 $node->body = theme_box (sprintf (t('Ticket number %s'), $output), $node->body, 'main') ;
706 break ;
707 case HELPDESKNODEFOLLOWUP:
708 // Same as above
709 break ;
710 case HELPDESKNODECONTRACT:
711 if (!isset($node->{$node->type}))
712 {
713 $node->{$node->type} = new helpdeskContract();
714 $node->{$node->type}->init($node, FALSE);
715 }
716 $output .= $node->{$node->type}->view();
717 $output = theme_box(t('Contract details'), $output, 'main');
718 $output .= theme_box(t('Contract description'), $node->body, 'main');
719 $node->body = $output ;
720 break ;
721 }
722 $node->body .= theme_placeholder (t('Notice: for traceability reasons, helpdesk-related nodes cannot be edited by users and customers. To modify, just add a followup.')) ;
723 unset($o) ;
724 $node->teaser = 'No teaser when \$teaser is not 1' ;
725 }
726
727 /* $themed_node = theme ('node', $node) ; */
728 }
729
730 /**
731 * Act on user account actions.
732 * This hook allows modules to react when operations are performed on user accounts.
733 * Sequence of calls for high-level functions:
734 * - creation: validate, load, insert, load. We don't care, yet.
735 * - prepare update: categories, load, form
736 * - perform update: load, validate, update, load
737 * - prepare deletion: categories, load
738 * - perform deletion: categories, load, delete(confirm=1). We should do something about tickets/issues.
739 * @param string $op Operation to be performed on user
740 * @param array $edit array of form values submitted by the user
741 * @param object $account The user object on which the operation is being performed.
742 * @param string $category The active category of user information being edited.
743 * @return mixed
744 * @see _helpdesk_user_load()
745 */
746 function helpdesk_user ($op, $edit, $account, $category = NULL) //XXX edit and author should be passed by ref
747 {
748 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
749 { echo "<pre>HD USER (op = $op, "
750 . (isset($edit)
751 ? (is_array($edit)
752 ? (array_key_exists('uid', $edit) ? ("edit[uid] = " . $edit['uid']) : print_r($edit, True))
753 : ("edit: string = [$edit]")
754 )
755 : 'edit not set')
756 . ", user name = "
757 . (is_object($account)
758 ? (isset($account->name)
759 ? $account->name
760 : 'name not set'
761 )
762 : 'not object'
763 )
764 .", category = $category)</pre>" ;
765 }
766
767 global $user ; // Masks the user parameter !
768
769 $output = NULL ;
770 switch ($op)
771 {
772 case 'view': // The user's account information is being displayed.
773 { $output = _helpdesk_user_view($user); break ; }
774 case 'categories': // A set of user information categories is requested.
775 { $output = _helpdesk_user_categories(); break ; }
776 case 'load': // The user account is being loaded. The module may respond to this and insert additional information into the user object.
777 /* in our case, this means loading the linked customer info if we need it later on */
778 {
779 if (isset($edit) && is_array($edit) && array_key_exists('uid', $edit))
780 _helpdesk_user_load($user, $edit['uid']);
781 $output = NULL ; // user_load is void
782 break;
783 }
784 case 'form': // The user account edit form is about to be displayed. The module should present the form elements it wishes to inject into the form.
785 { $output = _helpdesk_user_form($edit, $category); break; }
786 case 'delete': // The user account is being deleted.
787 /**
788 * @todo If this user has tickets, followups, or helpdesk contracts, they will be orphaned. The module should grant them to someone else or delete them
789 */
790 { $output = NULL; break; }
791 case "insert": // The user account is being added. As long as we don't store default user information, we needn't care
792 { $output = NULL; break; }
793 case "login": // The user just logged in. We don't care.
794 { $output = NULL; break; }
795 case "logout": // The user just logged out. We don't care. At some point, this could allow automatic timestamping of pending nodes
796 { $output = NULL; break; }
797 case "update": // The user account is being changed. Normally, we shouldn't care as long as we don't store user information
798 { $output = NULL; break; }
799 case "validate": // The user account is about to be modified. Normally, we shouldn't care as long as we don't store user information.
800 { $output = NULL; break; }
801 }
802 return $output;
803 }
804
805 /**
806 * Verify a node editing form. This is a hook used by node modules.
807 * It is called to allow the module to verify that the node is in a format valid to post
808 * to the site. It can also be used to make changes to the node before submission, such
809 * as node-type-specific formatting. Errors should be set with form_set_error().
810 *
811 * @param object $node The node to be validated.
812 */
813 function helpdesk_validate(&$node)
814 {
815 if (HELPDESKDEBUGALLFUNCTIONS == TRUE)
816 { echo "<pre>HD VALIDATE (node: " . print_r ($node, TRUE) . ")</pre>" ; }
817 /* Checks to be performed:
818 - date validity, absolute and relative
819 - status and severity having valid values
820 */
821 }
822
823 /* ----- Private functions ------------------------------------------------------------ */
824 /**
825 * Defines the name of the blocks attached to a delta
826 * @param int $delta the block number
827 * @return string the name of the block
828 * @see helpdesk_block()
829 */
830 function _helpdesk_block_list ($delta)
831 {
832 if ($delta > HELPDESKBLOCKMAX)
833 return NULL ;
834
835 // No need to test for HELPDESKPERMUSER as access won't be granted if if is absent
836 $block [HELPDESKBLOCKMYOPENTICKETS] ["info"] = t('Helpdesk &gt; My current tickets') ;
837 $block [HELPDESKBLOCKMYLATESTTICKETS] ["info"] = t('Helpdesk &gt; My latest tickets') ;
838 if (user_access (HELPDESKPERMCUSTOMER))
839 {
840 $block [HELPDESKBLOCKCUSTOMEROPENTICKETS]["info"] = t('Helpdesk &gt; Customer\'s current tickets') ;
841 $block [HELPDESKBLOCKCUSTOMERBALANCE] ["info"] = t('Helpdesk &gt; Customer\'s contracts balance') ;
842 }
843 if (user_access (HELPDESKPERMTECH))
844 {
845 $block [HELPDESKBLOCKALLOPENTICKETS] ["info"] = t('Helpdesk &gt; Oldest active tickets') ;
846 }
847 return $block ;
848 }
849
850 /**
851 * Subroutine for helpdesk_block/configure
852 * @param int $delta
853 * @return string HTML for the configuration form
854 * @see helpdesk_block()
855 */
856 function _helpdesk_block_configure ($delta)
857 {
858 $output = '' ;
859
860 $msg = t("This block (%d) doesn't have any configuration option") ;
861
862 switch ($delta)
863 {
864 case HELPDESKBLOCKMYOPENTICKETS: $output .= sprintf ($msg, $delta) ; break ;
865 case HELPDESKBLOCKMYLATESTTICKETS: $output .= sprintf ($msg, $delta) ; break ;
866 case HELPDESKBLOCKCUSTOMEROPENTICKETS: $output .= sprintf ($msg, $delta) ; break ;
867 case HELPDESKBLOCKCUSTOMERBALANCE: $output .= sprintf ($msg, $delta) ; break ;
868 case HELPDESKBLOCKALLOPENTICKETS: $output .= sprintf ($msg, $delta) ; break ;
869 default: t("You requested an unavailable block.") ;
870 }
871
872 return $output ;
873 }
874
875 /**
876 * Subroutine for helpdesk_block/save
877 * @param int $delta
878 * @return void
879 * @see helpdesk_block()
880 */
881 function _helpdesk_block_save ($delta)
882 {
883 // variable_set (HELPDESKCONFVAR, $_REQUEST ['edit'][HELPDESKCONFVAR]) ; // No longer used
884 /* $ret = "REQUEST: <pre>" . var_export ($_REQUEST ['edit'], True) . "</pre>" ;
885 echo $ret ; */
886 }
887
888 /**
889 * Checks whether or not the current user is a customer
890 * Does not depend on bound users or contracts
891 * @return boolean
892 */
893 function _helpdesk_is_customer ()
894 {
895 $s = HELPDESKPERMCUSTOMER ;
896 // echo "<pre>Perm requested: $s</pre>" ;
897 return (user_access ($s)) ;
898 }
899
900 /**
901 * Returns the contracts owned by a customer
902 * @param int $uidcustomer The UID of the customer being examined. Not necessarily the current user
903 * @return mixed NULL in case an error (presumably access limitation) happens, array of contracts otherwise, possibly empty
904 */
905 function _helpdesk_get_nid_contracts ($uidcustomer)
906 {
907 /* Can be checked only by tech for any uidcustomer, and by customer for own contracts
908 */
909 global $user;
910 if ((!user_access(HELPDESKPERMTECH)) && (!(user_access(HELPDESKPERMCUSTOMER) && ($user->uid == $uidcustomer))))
911 return NULL ;
912 else
913 {
914 $q = '
915 SELECT
916 n.nid, n.title
917 FROM {node} n
918 INNER JOIN {hd_contract} hdc on n.nid = hdc.nid
919 WHERE
920 hdc.uidcustomer = %d
921 ORDER BY
922 2
923 ' ;
924 $res = db_query($q, $uidcustomer);
925 while ($o = db_fetch_object($res))
926 {
927 $ret[] = $o ;
928 }
929 return $ret ;
930 }
931 }
932
933 /**
934 * Subroutine for helpdesk_block/view
935 * @param int $delta
936 * @return array array of HTML blocks
937 * @see helpdesk_block()
938 */
939 function _helpdesk_block_view ($delta)
940 {
941 $block = array() ;
942
943 if ($delta > HELPDESKBLOCKMAX)
944 return $block;
945
946 switch ($delta)
947 {
948 case HELPDESKBLOCKMYOPENTICKETS:
949 if (user_access(HELPDESKPERMUSER) || user_access(HELPDESKPERMCUSTOMER) || user_access(HELPDESKPERMTECH))
950 {
951 $block['subject'] = t('My open tickets');
952 $block['content'] = _helpdesk_block_view_MYOPENTICKETS();
953 }
954 break ;
955 case HELPDESKBLOCKMYLATESTTICKETS:
956 if (user_access(HELPDESKPERMUSER) || user_access(HELPDESKPERMCUSTOMER) || user_access(HELPDESKPERMTECH))
957 {
958 $block['subject'] = t('My latest tickets');
959 $block['content'] = _helpdesk_block_view_MYLATESTTICKETS();
960 }
961 break ;
962 case HELPDESKBLOCKCUSTOMEROPENTICKETS:
963 if (user_access(HELPDESKPERMCUSTOMER) || user_access(HELPDESKPERMTECH))
964 {
965 $block['subject'] = t('Customer\'s open tickets');
966 $block['content'] = _helpdesk_block_view_CUSTOMEROPENTICKETS();
967 }
968 break ;
969 case HELPDESKBLOCKCUSTOMERBALANCE:
970 if (user_access(HELPDESKPERMCUSTOMER) || user_access(HELPDESKPERMTECH))
971 {
972 $block['subject'] = t('Customer\'s contract balance');
973 $block['content'] = t('(none)') ;
974 }
975 break ;
976 case HELPDESKBLOCKALLOPENTICKETS:
977 if (user_access(HELPDESKPERMTECH))
978 {
979 $block['subject'] = t('All open tickets');
980 $block['content'] = _helpdesk_block_view_ALLOPENTICKETS();
981 }
982 break ;
983 }
984 return $block ;
985 }
986
987 /**
988 * Build a block returning a list of the current user's open tickets.
989 * - Open tickets are those for which tidstatus matches the first entry in the helpdesk_status vocabulary.
990 * - SECURITY: relies on _helpdesk_block_view to filter requests. Does not implement security on its own.
991 * @see _helpdesk_block_view()
992 * @return string HTML code for the list
993 */
994 function _helpdesk_block_view_MYOPENTICKETS()
995 {
996 global $user ;
997
998 $output = '' ;
999 $csq = "
1000 SELECT n.nid, n.title
1001 FROM {hd_event} hde
1002 INNER JOIN {node} n on hde.nid = n.nid
1003 WHERE
1004 (n.uid = %d)
1005 and (hde.tidstatus <>
1006 (
1007 SELECT min(td.tid)
1008 FROM term_data td
1009 INNER JOIN vocabulary v on td.vid = v.vid
1010 WHERE
1011 v.name = 'helpdesk_status'
1012 ))
1013 " ;
1014
1015 $q = db_query ($csq, array($user->uid)) ;
1016 while ($o = db_fetch_object ($q))
1017 {
1018 $output .= l($o->title, 'node/' . $o->nid) . '<br/>' ;
1019 }
1020 unset ($q);
1021 unset ($csq) ;
1022 return _helpdesk_notempty($output, t('none')) ;
1023 }
1024
1025 /**
1026 * Build a block returning a list of all open tickets.
1027 * - Open tickets are those for which tidstatus matches the first entry in the helpdesk_status vocabulary.
1028 * - SECURITY: relies on _helpdesk_block_view to filter requests. Does not implement security on its own. User is assumed to have HELPDESKPERMTECH perm checked by the caller
1029 * @see _helpdesk_block_view()
1030 * @return string HTML code for the list
1031 */
1032 function _helpdesk_block_view_ALLOPENTICKETS()
1033 {
1034 $output = '' ;
1035 $csq = "
1036 SELECT n.nid, n.title
1037 FROM {hd_event} hde
1038 INNER JOIN {node} n on hde.nid = n.nid
1039 WHERE
1040 hde.tidstatus <>
1041 (
1042 SELECT min(td.tid)
1043 FROM term_data td
1044 INNER JOIN {vocabulary} v on td.vid = v.vid
1045 WHERE
1046 v.name = 'helpdesk_status'
1047 )
1048 " ;
1049
1050 $q = db_query ($csq) ;
1051 while ($o = db_fetch_object ($q))
1052 {
1053 $output .= l($o->title, 'node/' . $o->nid) . '<br/>' ;
1054 }
1055 unset ($q);
1056 unset ($csq) ;
1057 return _helpdesk_notempty($output, t('none')) ;
1058 }
1059
1060 /**
1061 * Build a block returning a list of the latest tickets for the current user, be they open or not
1062 * - SECURITY: relies on _helpdesk_block_view to filter requests. Does not implement security on its own. User is assumed to have HELPDESKPERMCUSTOMER perm checked by caller
1063 * @see _helpdesk_block_view()
1064 * @return string HTML code for the list
1065 */
1066 function _helpdesk_block_view_MYLATESTTICKETS()
1067 {
1068 global $user ;
1069
1070 $output = '' ;
1071 $csq = "
1072 SELECT n.nid, n.title
1073 FROM {hd_event} hde
1074 INNER JOIN {node} n on hde.nid = n.nid
1075 WHERE
1076 (n.uid = %d)
1077 ORDER BY
1078 n.changed DESC, n.created DESC
1079 " ;
1080
1081 $q = db_query ($csq, array($user->uid)) ;
1082 while ($o = db_fetch_object ($q))
1083 {
1084 $output .= l($o->title, 'node/' . $o->nid) . '<br/>' ;
1085 }
1086 unset ($q);
1087 unset ($csq) ;
1088 return _helpdesk_notempty($output, t('none')) ;
1089 }
1090
1091 /**
1092 * Build a block returning a list of all open tickets for the users linked to this customer.
1093 * - Open tickets are those for which tidstatus matches the first entry in the helpdesk_status vocabulary.
1094 * - SECURITY: relies on _helpdesk_block_view to filter requests. Does not implement security on its own. User is assumed to have HELPDESKPERMCUSTOMER perm checked by caller
1095 * @see _helpdesk_block_view()
1096 * @return string HTML code for the list
1097 */
1098 function _helpdesk_block_view_CUSTOMEROPENTICKETS()
1099 {
1100 global $user ;
1101
1102 $output = '' ;
1103 $csq = "
1104 SELECT n.nid, n.title
1105 FROM {hd_event} hde
1106 INNER JOIN {node} n on hde.nid = n.nid
1107 INNER JOIN {hd_user} hdu on n.uid = hdu.uid
1108 WHERE
1109 (n.type = '%s')
1110 AND (hdu.uidcustomer = %d)
1111 AND hde.tidstatus <>
1112 (
1113 SELECT min(td.tid)
1114 FROM term_data td
1115 INNER JOIN {vocabulary} v on td.vid = v.vid
1116 WHERE
1117 v.name = 'helpdesk_status'
1118 )
1119 " ;
1120
1121 $q = db_query($csq, array(HELPDESKNODETICKET, $user->uid)) ;
1122 while ($o = db_fetch_object ($q))
1123 {
1124 $output .= l($o->title, 'node/' . $o->nid) . '<br/>' ;
1125 }
1126 unset ($q);
1127 unset ($csq) ;
1128 return _helpdesk_notempty($output, t('none')) ;
1129 }
1130
1131 /**
1132 * Build the public form of the node number from the actual nid
1133 *
1134 * @param int $nid The internal node number for the ticket
1135 * @return string The public form of the ticket number
1136 * @see _helpdesk_decode_nid()
1137 */
1138 function _helpdesk_encode_nid($nid)
1139 {
1140 $prefix = variable_get(HELPDESKVARTICKETPREFIX, '') ;
1141 $offset = variable_get(HELPDESKVARTICKETOFFSET, 0) ;
1142 $ticketnumber = $prefix . ($nid + $offset) ;
1143 unset($prefix);
1144 unset($offset);
1145 return $ticketnumber;
1146 }
1147
1148 /**
1149 * Extract the actual $node->nid from the public form of the ticket number
1150 * @param string $ticketnumber The public form of the ticket number
1151 * @return int The internal node number value for the ticket
1152 * @see _helpdesk_encode_nid()
1153 */
1154 function _helpdesk_decode_nid($ticketnumber)
1155 {
1156 $prefix = variable_get(HELPDESKVARTICKETPREFIX, '') ;
1157 $nid = substr($ticketnumber, strlen($prefix)) ;
1158 $offset = variable_get(HELPDESKVARTICKETOFFSET, 0) ;
1159 $nid -= $offset ;
1160
1161 unset($prefix);
1162 unset($offset);
1163 return $nid ;
1164 }
1165
1166 /**
1167 * Obtains the list of severity or status terms, in the proper order
1168 * @var string HD name for vocabulary to be queried
1169 * @return array of tid/name pairs
1170 * @see helpdesk_form()
1171 */
1172 function _helpdesk_get_terms($vocabulary)
1173 {
1174 /* $arTerms = array() ;
1175 $vid = variable_get($vocabulary, NULL) ;
1176 if (isset($vid))
1177 {
1178 $q = '
1179 SELECT
1180 td.tid, td.name
1181 FROM {term_data} td
1182 WHERE
1183 td.vid = %d
1184 ORDER BY 2, 1
1185 ' ;
1186 $res = db_query($q, $vid);
1187 while ($o = db_fetch_object($res))
1188 {
1189 $arTerms[$o->tid] = $o->name . "($o->tid)" ;
1190 }
1191 }
1192 return $arTerms ; */
1193 return taxonomy_get_tree(variable_get($vocabulary));
1194 }
1195
1196 /**
1197 * auxiliary function for helpdesk_user('view')
1198 * @param object $user
1199 * @return array An associative array of strings to display, keyed by category name
1200 * @see helpdesk_user
1201 * @todo display global account balance, pointer to the list of contracts (for customers),
1202 * @todo display global ticket starts, pointer to the list of tickets, followups (for users)
1203 */
1204 function _helpdesk_user_view($user)
1205 {
1206 $ret = NULL;
1207 $output = NULL;
1208
1209 if (isset($user->uidCustomer)) // Can't use user_access(HELPDESKPERMUSER): admin will always get info even if he is not a HD user.
1210 {
1211 $ret .= t('<p>Helpdesk access managed by %customer-link</p>',
1212 array('%customer-link' => l($user->customerName, 'user/' . $user->uidCustomer)));
1213 }
1214 if ($user->uidCustomer == $user->uid) // we are a customer
1215 {
1216 $ret .= "<p></p>";
1217 $oc = new helpdeskCustomer();
1218 $oc->uid = $user->uid ;
1219 $oc->uidCustomer = $user->uidCustomer ;
1220 $arUsers = $oc->uidUsers();
1221 foreach($arUsers as $ou)
1222 {
1223 $arItems[] = l($ou->name, "user/$ou->uid", NULL) ;
1224 }
1225 $ret .= theme_item_list ($arItems, t('Managing helpdesk access for users:')) ;
1226 unset($arItems);
1227 unset($arUsers);
1228
1229 $arContracts = _helpdesk_get_nid_contracts($user->uidCustomer); // User has already been checked as a customer: there must be a result
1230 foreach($arContracts as $oc)
1231 {
1232 $arItems[] = l($oc->title, "node/$oc->nid", NULL) ;
1233 }
1234 $ret .= theme_item_list ($arItems, t('Holder of contracts:')) ;
1235 }
1236
1237 if (isset($ret))
1238 {
1239 $ret .= t('Future versions will display more information, like '
1240 . 'users\' stats: account balance, #tickets, and so on.') ;
1241 $output = array ('Helpdesk account' => $ret) ;
1242 }
1243
1244 return $output;
1245 }
1246
1247 /**
1248 * auxiliary function for helpdesk_user('categorie'). Currently, this displays the user roles and admin status if the module has been set up to do so.
1249 * @return array
1250 * @see helpdesk_user
1251 */
1252 function _helpdesk_user_categories()
1253 {
1254 if (variable_get (HELPDESKVARSHOWROLES, FALSE))
1255 {
1256 return array (
1257 array (
1258 "name" => "helpdeskroles",
1259 "title" => t("user roles"),
1260 "weight" => 1
1261 )
1262 ) ;
1263 }
1264 else
1265 return NULL;
1266 }
1267
1268 /**
1269 * auxiliary function for helpdeks_user('form'), to be displayed when user tries to display/edit his own data:
1270 * @param array $edit array of form values submitted by the user
1271 * @param string $category The category of personal information to be displayed/edited
1272 * @return array
1273 * @see helpdesk_user
1274 */
1275 function _helpdesk_user_form($edit, $category)
1276 {
1277 global $user;
1278
1279 if (($category == 'helpdeskroles') && variable_get (HELPDESKVARSHOWROLES, FALSE)) // default category: account
1280 {
1281 $output = array
1282