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

Contents of /contributions/modules/uts/uts.module

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


Revision 1.56 - (show annotations) (download) (as text)
Thu Jun 4 01:28:36 2009 UTC (5 months, 3 weeks ago) by boombatower
Branch: MAIN
CVS Tags: HEAD
Changes since 1.55: +20 -1 lines
File MIME type: text/x-php
#475846: create color scheme for analysis graphs.
1 <?php
2 // $Id: uts.module,v 1.55 2009/06/04 01:01:28 boombatower Exp $
3 /**
4 * @file
5 * Provide general Usability Testing Suite functionality and module implementation.
6 *
7 * Copyright 2008 by Jimmy Berry ("boombatower", http://drupal.org/user/214218)
8 */
9
10 /**
11 * The content type for a UTS Study.
12 */
13 define('UTS_STUDY', 'uts_study');
14
15 /**
16 * The content type for a UTS Task.
17 */
18 define('UTS_TASK', 'uts_task');
19
20 /**
21 * The content type for a UTS Environment.
22 */
23 define('UTS_ENVIRONMENT', 'uts_environment');
24
25 /**
26 * Study status: in development.
27 */
28 define('UTS_STUDY_STATUS_IN_DEVELOPMENT', 1);
29
30 /**
31 * Study status: active.
32 */
33 define('UTS_STUDY_STATUS_ACTIVE', 2);
34
35 /**
36 * Study status: closed.
37 */
38 define('UTS_STUDY_STATUS_CLOSED', 3);
39
40 /**
41 * Task Completion.
42 */
43 define('UTS_STUDY_TYPE_TASK', 1);
44
45 /**
46 * Audience role: end user.
47 */
48 define('UTS_STUDY_AUDIENCE_ROLE_USER', 1);
49
50 /**
51 * Audience role: designer.
52 */
53 define('UTS_STUDY_AUDIENCE_ROLE_DESIGNER', 2);
54
55 /**
56 * Audience role: programer.
57 */
58 define('UTS_STUDY_AUDIENCE_ROLE_PROGRAMER', 3);
59
60 /**
61 * Audience experience level: beginner.
62 */
63 define('UTS_STUDY_AUDIENCE_LEVEL_BEGINNER', 1);
64
65 /**
66 * Audience experience level: intermediate.
67 */
68 define('UTS_STUDY_AUDIENCE_LEVEL_INTERMEDIATE', 2);
69
70 /**
71 * Audience experience level: advanced.
72 */
73 define('UTS_STUDY_AUDIENCE_LEVEL_ADVANCED', 3);
74
75 require_once drupal_get_path('module', 'uts') . '/uts.data.inc';
76 require_once drupal_get_path('module', 'uts') . '/uts.environment.inc';
77 require_once drupal_get_path('module', 'uts') . '/uts.node.inc';
78 require_once drupal_get_path('module', 'uts') . '/uts.participate.inc';
79 require_once drupal_get_path('module', 'uts') . '/uts.session.inc';
80 require_once drupal_get_path('module', 'uts') . '/uts.help.inc';
81
82 /**
83 * Implementation of hook_menu().
84 */
85 function uts_menu() {
86 $items = array();
87
88 // Participant items.
89 $items['uts'] = array(
90 'title' => '1 - Choose a study',
91 'description' => 'Description of usability testing and study selection.',
92 'page callback' => 'uts_participate_list',
93 'access arguments' => array('participate in study'),
94 'file' => 'uts.pages.inc',
95 'type' => MENU_CALLBACK
96 );
97 $items['uts/environment/%'] = array(
98 'title' => '2 - Create environment',
99 'page callback' => 'drupal_get_form',
100 'page arguments' => array('uts_participate_create_environment_form', 2),
101 'access arguments' => array('participate in study'),
102 'file' => 'uts.pages.inc',
103 'type' => MENU_CALLBACK
104 );
105 $items['uts/session/%'] = array(
106 'title' => '3 - Start session',
107 'page callback' => 'drupal_get_form',
108 'page arguments' => array('uts_participate_start_session_form', 2),
109 'access arguments' => array('participate in study'),
110 'file' => 'uts.pages.inc',
111 'type' => MENU_CALLBACK
112 );
113 $items['uts/thanks'] = array(
114 'title' => 'Thanks for participating',
115 'page callback' => 'uts_participate_thanks',
116 'access arguments' => array('access content'),
117 'file' => 'uts.pages.inc',
118 'type' => MENU_CALLBACK
119 );
120 $items['uts/thanks/return'] = array(
121 'title' => 'Thanks for participating',
122 'page callback' => 'uts_participate_thanks',
123 'page arguments' => array(TRUE),
124 'access arguments' => array('access content'),
125 'file' => 'uts.pages.inc',
126 'type' => MENU_CALLBACK
127 );
128
129 // Internal environmental callback.
130 $items['uts/environment/%/%'] = array(
131 'title' => 'Environment',
132 'description' => 'Perform environment processes.',
133 'page callback' => 'uts_environment_callback',
134 'page arguments' => array(2, 3),
135 'access callback' => TRUE,
136 'type' => MENU_CALLBACK
137 );
138 $items['uts/environment/%/%/%'] = array(
139 'title' => 'Environment',
140 'description' => 'Perform environment processes.',
141 'page callback' => 'uts_environment_callback',
142 'page arguments' => array(2, 3, 4),
143 'access callback' => TRUE,
144 'type' => MENU_CALLBACK
145 );
146
147 // General items.
148 $items['admin/uts'] = array(
149 'title' => 'Usability testing suite',
150 'description' => 'Configure suite, create studies, manage data, and analyze results.',
151 'page callback' => 'uts_dashboard',
152 'access arguments' => array('access administration pages'),
153 'file' => 'uts.pages.inc'
154 );
155 $items['admin/uts/configuration'] = array(
156 'title' => 'Configuration',
157 'description' => 'Configure usability testing suite.',
158 'page callback' => 'drupal_get_form',
159 'page arguments' => array('uts_settings'),
160 'access arguments' => array('access administration pages')
161 );
162 $items['admin/uts/invite'] = array(
163 'title' => 'Invite',
164 'description' => 'Send e-mails inviting people to participate in a study.',
165 'page callback' => 'drupal_get_form',
166 'page arguments' => array('uts_invite'),
167 'access arguments' => array('access administration pages'),
168 'file' => 'uts.pages.inc'
169 );
170
171 // Study related items.
172 $items['admin/uts/studies'] = array(
173 'title' => 'Studies',
174 'description' => 'Manage studies: create, edit, copy, and delete studies.',
175 'page callback' => 'uts_studies',
176 'access arguments' => array('manage studies')
177 );
178 $items['admin/uts/studies/list'] = array(
179 'title' => 'List',
180 'type' => MENU_DEFAULT_LOCAL_TASK,
181 'weight' => -10
182 );
183 $items['admin/uts/studies/add'] = array(
184 'title' => 'Add',
185 'page callback' => 'node_add',
186 'page arguments' => array('uts-study'),
187 'access callback' => 'node_access',
188 'access arguments' => array('create', 'uts-study'),
189 'type' => MENU_LOCAL_TASK,
190 'file' => 'node.pages.inc',
191 'file path' => drupal_get_path('module', 'node'),
192 'weight' => -9
193 );
194 $items['admin/uts/studies/%node/edit'] = array(
195 'title' => 'Edit',
196 'page callback' => 'node_page_edit',
197 'page arguments' => array(3),
198 'access callback' => 'node_access',
199 'access arguments' => array('update', 'uts-study'),
200 'type' => MENU_CALLBACK,
201 'file' => 'node.pages.inc',
202 'file path' => drupal_get_path('module', 'node'),
203 'weight' => -8
204 );
205 $items['admin/uts/studies/%node/delete'] = array(
206 'title' => 'Delete',
207 'page callback' => 'drupal_get_form',
208 'page arguments' => array('uts_delete_confirm', 3),
209 'access callback' => 'node_access',
210 'access arguments' => array('delete', 'uts-study'),
211 'type' => MENU_CALLBACK,
212 'file' => 'uts.pages.inc',
213 'weight' => -7
214 );
215
216 // General task management.
217 $items['admin/uts/tasks'] = array(
218 'title' => 'Tasks',
219 'description' => 'Manage tasks: create, edit, copy, and delete tasks.',
220 'page callback' => 'drupal_get_form',
221 'page arguments' => array('uts_tasks'),
222 'access arguments' => array('manage studies'),
223 'type' => MENU_NORMAL_ITEM
224 );
225 $items['admin/uts/tasks/list'] = array(
226 'title' => 'List',
227 'type' => MENU_DEFAULT_LOCAL_TASK,
228 'weight' => -10
229 );
230 $items['admin/uts/tasks/add'] = array(
231 'title' => 'Add',
232 'page callback' => 'node_add',
233 'page arguments' => array('uts-task'),
234 'access callback' => 'node_access',
235 'access arguments' => array('create', 'uts-task'),
236 'type' => MENU_LOCAL_TASK,
237 'file' => 'node.pages.inc',
238 'file path' => drupal_get_path('module', 'node'),
239 'weight' => -9
240 );
241 $items['admin/uts/tasks/import'] = array(
242 'title' => 'Import',
243 'page callback' => 'drupal_get_form',
244 'page arguments' => array('uts_import_tasks'),
245 'access arguments' => array('manage studies'),
246 'type' => MENU_LOCAL_TASK,
247 'file' => 'uts.pages.inc',
248 'weight' => -8
249 );
250
251 // Tasks related to a study.
252 $items['admin/uts/tasks/%'] = array(
253 'title' => 'Tasks',
254 'description' => 'View tasks.',
255 'page callback' => 'drupal_get_form',
256 'page arguments' => array('uts_tasks', 3),
257 'access arguments' => array('manage studies'),
258 'type' => MENU_CALLBACK
259 );
260 $items['admin/uts/tasks/%/list'] = array(
261 'title' => 'List',
262 'type' => MENU_DEFAULT_LOCAL_TASK,
263 'weight' => -10
264 );
265 $items['admin/uts/tasks/%/add'] = array(
266 'title' => 'Add',
267 'page callback' => 'node_add',
268 'page arguments' => array('uts-task'),
269 'access callback' => 'node_access',
270 'access arguments' => array('create', 'uts-task'),
271 'type' => MENU_LOCAL_TASK,
272 'file' => 'node.pages.inc',
273 'file path' => drupal_get_path('module', 'node'),
274 'weight' => -9
275 );
276 $items['admin/uts/tasks/%/import'] = array(
277 'title' => 'Import',
278 'page callback' => 'drupal_get_form',
279 'page arguments' => array('uts_import_tasks', 3),
280 'access arguments' => array('manage studies'),
281 'type' => MENU_LOCAL_TASK,
282 'file' => 'uts.pages.inc',
283 'weight' => -8
284 );
285
286 // General task wrappers.
287 $items['admin/uts/tasks/%node/edit'] = array(
288 'title' => 'Edit',
289 'page callback' => 'node_page_edit',
290 'page arguments' => array(3),
291 'access callback' => 'node_access',
292 'access arguments' => array('update', 'uts-task'),
293 'type' => MENU_CALLBACK,
294 'file' => 'node.pages.inc',
295 'file path' => drupal_get_path('module', 'node'),
296 'weight' => -8
297 );
298 $items['admin/uts/tasks/%node/detach'] = array(
299 'title' => 'Detach',
300 'page callback' => 'drupal_get_form',
301 'page arguments' => array('uts_task_detach_confirm', 3),
302 'access arguments' => array('manage studies'),
303 'type' => MENU_CALLBACK,
304 'file' => 'uts.pages.inc',
305 'weight' => -7
306 );
307 $items['admin/uts/tasks/%node/delete'] = array(
308 'title' => 'Delete',
309 'page callback' => 'drupal_get_form',
310 'page arguments' => array('uts_delete_confirm', 3),
311 'access callback' => 'node_access',
312 'access arguments' => array('delete', 'uts-task'),
313 'type' => MENU_CALLBACK,
314 'file' => 'uts.pages.inc',
315 'weight' => -6
316 );
317
318 // Analysis related items.
319 $items['admin/uts/analyze'] = array(
320 'title' => 'Analyze',
321 'description' => 'Analyze data collected from studies.',
322 'page callback' => 'uts_analysis_list',
323 'access arguments' => array('manage studies'),
324 'file' => 'uts.analysis.inc',
325 'type' => MENU_NORMAL_ITEM
326 );
327 $items['admin/uts/analyze/%'] = array(
328 'title' => 'Analyze',
329 'description' => 'Analyze data collected from studies.',
330 'page callback' => 'uts_analysis_list_sessions',
331 'page arguments' => array(3),
332 'access arguments' => array('manage studies'),
333 'file' => 'uts.analysis.inc',
334 'type' => MENU_CALLBACK
335 );
336 $items['admin/uts/analyze/%/sessions'] = array(
337 'title' => 'Sessions',
338 'description' => 'Manage sessions',
339 'type' => MENU_DEFAULT_LOCAL_TASK,
340 'weight' => -10
341 );
342
343 $items['admin/uts/analyze/%/%'] = array(
344 'title' => 'Analyze',
345 'description' => 'Analyze data collected from studies.',
346 'page callback' => 'uts_analysis_session_details',
347 'page arguments' => array(3, 4),
348 'access arguments' => array('manage studies'),
349 'file' => 'uts.analysis.inc',
350 'type' => MENU_CALLBACK
351 );
352 $items['admin/uts/analyze/%/%/sessions'] = array(
353 'title' => 'Sessions',
354 'description' => 'Manage sessions',
355 'page callback' => 'uts_analysis_sessions_goto',
356 'page arguments' => array(3),
357 'access arguments' => array('manage studies'),
358 'file' => 'uts.analysis.inc',
359 'type' => MENU_LOCAL_TASK,
360 'weight' => -10
361 );
362 $items['admin/uts/analyze/%/%/details'] = array(
363 'title' => 'Details',
364 'description' => 'Manage sessions',
365 'type' => MENU_DEFAULT_LOCAL_TASK,
366 'weight' => -9
367 );
368
369 $items['admin/uts/analyze/%/%/destroy'] = array(
370 'title' => 'Destroy session',
371 'description' => 'Remove session and related data.',
372 'page callback' => 'drupal_get_form',
373 'page arguments' => array('uts_analysis_destroy_confirm', 4),
374 'access arguments' => array('manage studies'),
375 'file' => 'uts.analysis.inc',
376 'type' => MENU_CALLBACK
377 );
378
379 // Generate local tasks for plug-ins.
380 $bases = array('admin/uts/analyze/%' => FALSE, 'admin/uts/analyze/%/%' => TRUE);
381 $analysis_plugins = uts_data_analysis_list();
382 $collection_plugins = uts_data_collection_list();
383 foreach ($bases as $base => $session_id) {
384 foreach ($analysis_plugins as $module => $modes) {
385 // Create task for data collection module.
386 $items["$base/$module"] = array(
387 'title' => $collection_plugins[$module]['name'],
388 'description' => 'Analyze data for ' . $collection_plugins[$module]['name'],
389 'page callback' => 'uts_analysis',
390 'page arguments' => array(3, 4, 5), // Althought arg[5] will never be set it serves as a placeholder.
391 'access arguments' => array('manage studies'),
392 'file' => 'uts.analysis.inc',
393 'type' => MENU_LOCAL_TASK
394 );
395 if ($session_id) {
396 // Shift arguements to make room for session ID.
397 $items["$base/$module"]['page arguments'][1]++;
398 $items["$base/$module"]['page arguments'][2]++;
399 $items["$base/$module"]['page arguments'][] = 4;
400 }
401
402 // Create sub-task for each analysis mode.
403 $first = TRUE;
404 $i = 0;
405 foreach ($modes as $mode) {
406 $items["$base/$module/$mode"] = array(
407 'title' => $mode,
408 'description' => $mode,
409 'page callback' => 'uts_analysis',
410 'page arguments' => array(3, 4, 5),
411 'access arguments' => array('manage studies'),
412 'file' => 'uts.analysis.inc',
413 'type' => MENU_LOCAL_TASK,
414 'weight' => $i
415 );
416 // Action callback.
417 $items["$base/$module/$mode/%"] = array(
418 'title' => $mode,
419 'description' => $mode,
420 'page callback' => 'uts_analysis_action',
421 'page arguments' => array(3, 4, 5, 6),
422 'access arguments' => array('manage studies'),
423 'file' => 'uts.analysis.inc',
424 'type' => MENU_CALLBACK
425 );
426 if ($session_id) {
427 // Shift arguements to make room for session ID.
428 $items["$base/$module/$mode"]['page arguments'][1]++;
429 $items["$base/$module/$mode"]['page arguments'][2]++;
430 $items["$base/$module/$mode"]['page arguments'][] = 4;
431
432 $items["$base/$module/$mode/%"]['page arguments'][1]++;
433 $items["$base/$module/$mode/%"]['page arguments'][2]++;
434 $items["$base/$module/$mode/%"]['page arguments'][3]++;
435 $items["$base/$module/$mode/%"]['page arguments'][] = 4;
436 }
437 if ($first) {
438 $items["$base/$module/$mode"]['type'] = MENU_DEFAULT_LOCAL_TASK;
439 $first = FALSE;
440 }
441 $i++;
442 }
443 }
444 }
445
446 // Base environment items.
447 $items['admin/uts/environments'] = array(
448 'title' => 'Environments',
449 'description' => 'Setup base environments to be used as the starting point for studies.',
450 'page callback' => 'uts_environments',
451 'access arguments' => array('manage studies'),
452 'file' => 'uts.pages.inc'
453 );
454 $items['admin/uts/environments/list'] = array(
455 'title' => 'List',
456 'type' => MENU_DEFAULT_LOCAL_TASK,
457 'weight' => -10
458 );
459 $items['admin/uts/environments/add'] = array(
460 'title' => 'Add',
461 'page callback' => 'node_add',
462 'page arguments' => array('uts-environment'),
463 'access callback' => 'node_access',
464 'access arguments' => array('create', 'uts-environment'),
465 'type' => MENU_LOCAL_TASK,
466 'file' => 'node.pages.inc',
467 'file path' => drupal_get_path('module', 'node'),
468 'weight' => -9
469 );
470 $items['admin/uts/environments/%node/edit'] = array(
471 'title' => 'Edit',
472 'page callback' => 'node_page_edit',
473 'page arguments' => array(3),
474 'access callback' => 'node_access',
475 'access arguments' => array('update', 'uts-environment'),
476 'type' => MENU_CALLBACK,
477 'file' => 'node.pages.inc',
478 'file path' => drupal_get_path('module', 'node'),
479 'weight' => -7
480 );
481 $items['admin/uts/environments/%node/open'] = array(
482 'title' => 'Open',
483 'page callback' => 'uts_environment_open',
484 'page arguments' => array(3),
485 'access arguments' => array('manage studies'),
486 'type' => MENU_CALLBACK,
487 'weight' => -6
488 );
489 $items['admin/uts/environments/%node/delete'] = array(
490 'title' => 'Delete',
491 'page callback' => 'drupal_get_form',
492 'page arguments' => array('uts_delete_confirm', 3),
493 'access callback' => 'node_access',
494 'access arguments' => array('delete', 'uts-environment'),
495 'type' => MENU_CALLBACK,
496 'file' => 'uts.pages.inc',
497 'weight' => -5
498 );
499
500 return $items;
501 }
502
503 /**
504 * Implementation of hook_menu_alter().
505 */
506 function uts_menu_alter(&$callbacks) {
507 // Disable node/add links.
508 $callbacks['node/add/uts-study']['access callback'] = FALSE;
509 $callbacks['node/add/uts-task']['access callback'] = FALSE;
510 $callbacks['node/add/uts-environment']['access callback'] = FALSE;
511 }
512
513 /**
514 * Implementation of hook_perm().
515 */
516 function uts_perm() {
517 return array('manage studies', 'participate in study');
518 }
519
520 /**
521 * Implementation of hook_theme().
522 */
523 function uts_theme() {
524 return array(
525 'uts_tasks' => array(
526 'arguments' => array('form' => NULL)
527 ),
528 'uts_form_data_collection' => array(
529 'arguments' => array('form' => NULL)
530 ),
531 'uts_participate_start_form_data_collection' => array(
532 'arguments' => array('form' => NULL)
533 ),
534 'uts_dashboard_studies' => array(
535 'arguments' => array('header' => NULL, 'rows' => NULL),
536 'file' => 'uts.pages.inc'
537 ),
538 'uts_progress' => array(
539 'arguments' => array('progress' => 0, 'total' => 100),
540 'file' => 'uts.pages.inc'
541 )
542 );
543 }
544
545 /**
546 * UTS settings form.
547 */
548 function uts_settings(&$form_state) {
549 $form = array();
550 $form['admin_login'] = array(
551 '#type' => 'fieldset',
552 '#title' => t('Admin login'),
553 '#description' => t('The admin login information used to populate the first user when an environment
554 is created. If a study uses a base environment than this will not take effect,
555 but when creating a base environment or a study with no base environment specified
556 then the admin user will have the following information.')
557 );
558 $form['admin_login']['uts_environment_admin_name'] = array(
559 '#type' => 'textfield',
560 '#title' => t('Username'),
561 '#default_value' => variable_get('uts_environment_admin_name', 'admin')
562 );
563 $form['admin_login']['uts_environment_admin_pass'] = array(
564 '#type' => 'textfield',
565 '#title' => t('Password'),
566 '#default_value' => variable_get('uts_environment_admin_pass', 'utsadmin')
567 );
568
569 $form['email'] = array(
570 '#type' => 'fieldset',
571 '#title' => t('E-mail text'),
572 '#description' => t('Customize various e-mail texts. Users will only receive e-mails if they are logged in
573 as a registered user. You can set the <i>participate in study</i> permission to allow
574 only registered users to participate.')
575 );
576
577 // Describe the available variables.
578 $header = array(t('Variable'), t('Description'));
579 $rows = array();
580 $rows[] = array('!username', t('Username of the current user.'));
581 $rows[] = array('!name', t('The name specified through the format on the <a href="@invite">invite</a> page.
582 If only the e-mail address is found than the name will be set to the e-mail address.',
583 array('@invite' => url('admin/uts/invite'))));
584 $rows[] = array('!site', t('Title of the base site. The title used in the site you are currently viewing.'));
585 $rows[] = array('!mailto', t('The e-mail address of the user account at the time the e-mail is sent. For invites
586 this will be the user you run the invite page as. For session info it will be
587 the user that starts the session.'));
588 $rows[] = array('!date', t('Current date using the <em>medium</em> format.'));
589 $rows[] = array('!register', t('Registration page url.'));
590 $rows[] = array('!participate', t('URL to participation page. Will specify a study if in the context of the e-mail.'));
591 $rows[] = array('!session_id', t('The ID of the generated session.'));
592
593 $form['email']['variables'] = array(
594 '#type' => 'item',
595 '#value' => theme('table', $header, $rows)
596 );
597
598 // Generate base email form items for each key.
599 $keys = array('invite', 'session_info');
600 foreach ($keys as $key) {
601 $form['email'][$key] = array(
602 '#type' => 'fieldset',
603 '#collapsible' => TRUE,
604 '#collapsed' => TRUE
605 );
606 $form['email'][$key]['uts_mail_' . $key . '_subject'] = array(
607 '#type' => 'textfield',
608 '#title' => t('Subject'),
609 '#default_value' => uts_mail_text($key . '_subject'),
610 '#maxlength' => 180
611 );
612 $form['email'][$key]['uts_mail_' . $key . '_body'] = array(
613 '#type' => 'textarea',
614 '#title' => t('Body'),
615 '#default_value' => uts_mail_text($key . '_body'),
616 '#rows' => 15
617 );
618 }
619
620 // Set title and description for each email key.
621 $form['email']['invite']['#title'] = t('Invite');
622 $form['email']['invite']['#description'] = t('Customize the invite message.
623 Available varibles: !name, !site, !mailto, !date, !register,
624 !participate');
625
626 $form['email']['session_info']['#title'] = t('Session info');
627 $form['email']['session_info']['#description'] = t('Customize the message sent when participant creates a session.
628 Available varibles: !username, !site, !mailto, !date, !register,
629 !participate, !session_id.');
630
631 return system_settings_form($form);
632 }
633
634 /**
635 * Create a table to list all the studies.
636 *
637 * @return string HTML output.
638 */
639 function uts_studies() {
640 $header = array(t('Title'), t('Status'), t('Task count'), t('Completed sessions'), t('Operations'));
641 $rows = array();
642
643 $studies = uts_studies_load();
644 foreach ($studies as $study) {
645 $row = array();
646 $row[] = l($study->title, 'node/' . $study->nid);
647 $row[] = uts_get_study_status($study->study_status);
648 $row[] = count(uts_tasks_load($study->nid));
649 $row[] = $study->complete_session_count = count(uts_session_load_all($study->nid, TRUE));
650
651 $operations = uts_study_operations($study);
652 $row[] = uts_render_operations($operations);
653
654 $rows[] = $row;
655 }
656
657 if (empty($rows)) {
658 return t('No studies to display.');
659 }
660 return theme('table', $header, $rows);
661 }
662
663 /**
664 * Get an array containing the study operation links.
665 *
666 * @param $study Study object.
667 * @return Array of links.
668 */
669 function uts_study_operations($study) {
670 $links = array();
671 $links['study_edit'] = array(
672 'title' => t('edit'),
673 'href' => "admin/uts/studies/$study->nid/edit"
674 );
675 $links['study_manage_tasks'] = array(
676 'title' => t('manage tasks'),
677 'href' => "admin/uts/tasks/$study->nid"
678 );
679 if ($study->complete_session_count > 0) {
680 $links['study_analyze'] = array(
681 'title' => t('analyze'),
682 'href' => "admin/uts/analyze/$study->nid"
683 );
684 }
685 $links['study_delete'] = array(
686 'title' => t('delete'),
687 'href' => "admin/uts/studies/$study->nid/delete"
688 );
689 return $links;
690 }
691
692 /**
693 * Load all the studies.
694 *
695 * @param boolean $status Require the study to be a specific status. NULL for any status.
696 * @return array List of study node objects.
697 */
698 function uts_studies_load($status = NULL) {
699 if ($status !== NULL) {
700 $result = db_query('SELECT nid
701 FROM {uts_study}
702 WHERE study_status = %d', $status);
703 }
704 else {
705 $result = db_query('SELECT nid
706 FROM {uts_study}');
707 }
708 $studies = array();
709 while ($nid = db_result($result)) {
710 $studies[] = node_load($nid);
711 }
712 return $studies;
713 }
714
715 /**
716 * Create a form to list all the tasks related to a study and their weights.
717 *
718 * @param int $study_nid Study NID tasks are related to.
719 */
720 function uts_tasks(&$form_state, $study_nid = NULL) {
721 $form = array();
722 if ($study_nid) {
723 uts_set_title($study_nid);
724
725 $form['study_nid'] = array(
726 '#type' => 'value',
727 '#value' => $study_nid
728 );
729 }
730
731 $tasks = uts_tasks_load($study_nid);
732 foreach ($tasks as $task) {
733 $row = array();
734 $row['title'] = array(
735 '#type' => 'item',
736 '#title' => t('Title'),
737 '#value' => l($task->title, 'node/' . $task->nid),
738 );
739 $row['description'] = array(
740 '#type' => 'item',
741 '#title' => t('Description'),
742 '#value' => $task->body
743 );
744 $row['study_title'] = array(
745 '#type' => 'item',
746 '#title' => t('Parent study'),
747 '#value' => ''
748 );
749 if ($task->study_nid) {
750 $study = node_load($task->study_nid);
751 $row['study_title']['#value'] = l($study->title, 'node/' . $study->nid);
752 }
753
754 $operations = uts_task_operations($task);
755 $row['operations'] = array(
756 '#type' => 'item',
757 '#title' => t('Operations'),
758 '#value' => uts_render_operations($operations)
759 );
760
761 $row['weight'] = array(
762 '#type' => 'textfield',
763 '#name' => 'weight[' . $task->nid . ']',
764 '#title' => t('Weight'),
765 '#default_value' => $task->weight
766 );
767
768 $form[] = $row;
769 }
770
771 $form['draggable'] = array(
772 '#type' => 'value',
773 '#value' => ($study_nid !== NULL)
774 );
775 $form['save'] = array(
776 '#type' => 'submit',
777 '#value' => t('Save')
778 );
779 return $form;
780 }
781
782 /**
783 * Theme the task overview form to include the draggable components.
784 *
785 * @return string HTML output.
786 */
787 function theme_uts_tasks($form) {
788 $draggable = $form['draggable']['#value'];
789 $header = array(t('Title'), t('Description'), t('Parent study'), t('Operations'), t('Weight'));
790 $rows = array();
791 foreach (element_children($form) as $key) {
792 // Make sure element is task.
793 if (!is_numeric($key)) {
794 continue;
795 }
796 $task = &$form[$key];
797
798 $row = array();
799 $row[] = $task['title']['#value'];
800 $row[] = $task['description']['#value'];
801 $row[] = $task['study_title']['#value'];
802 $row[] = $task['operations']['#value'];
803
804 if ($draggable) {
805 $task['weight']['#attributes']['class'] = 'task-weight';
806 $row[] = drupal_render($task['weight']);
807 }
808
809 $rows[] = array(
810 'data' => $row,
811 'class' => 'draggable'
812 );
813 unset($form[$key]); // Remove already rendered item.
814 }
815
816 $output = '';
817 if ($draggable) {
818 drupal_add_tabledrag('uts-tasks-table', 'order', 'sibling', 'task-weight');
819 $output = drupal_render($form);
820 }
821 else {
822 array_pop($header);
823 }
824
825 if (empty($rows)) {
826 return t('No tasks to display.');
827 }
828 $output = theme('table', $header, $rows, array('id' => 'uts-tasks-table')) . $output;
829
830 if (isset($form['study_nid'])) {
831 $study = node_load($form['study_nid']['#value']);
832 $output = t('<p><b>Description:</b> @body</p>', array('@body' => $study->body)) . $output;
833 }
834 else {
835 $studies = uts_studies_load();
836 $list = array();
837 $list[] = t('--');
838 foreach ($studies as $study) {
839 $list[$study->nid] = $study->title;
840 }
841
842 $form = array();
843 $form['filter'] = array(
844 '#type' => 'fieldset',
845 '#title' => t('Filter'),
846 '#attributes' => array('class' => 'container-inline'),
847 );
848 $form['filter']['study_nid'] = array(
849 '#type' => 'select',
850 '#title' => t('Study'),
851 '#options' => $list,
852 '#attributes' => array('onchange' => 'window.location.href = "/admin/uts/tasks/" + $(this).val();'),
853 );
854 $output = drupal_render($form) . $output;
855 }
856 return $output;
857 }
858
859 /**
860 * Save task weights.
861 */
862 function uts_tasks_submit($form, &$form_state) {
863 foreach ($form_state['values']['weight'] as $task_nid => $weight) {
864 db_query('UPDATE {uts_task}
865 SET weight = %d
866 WHERE nid = %d', $weight, $task_nid);
867 }
868 drupal_set_message(t('Task order saved.'));
869 }
870
871 /**
872 * Get an array containing the task operation links.
873 *
874 * @param $task Task object.
875 * @return Array of links.
876 */
877 function uts_task_operations($task) {
878 $links = array();
879 $links['task_edit'] = array(
880 'title' => t('edit'),
881 'href' => "admin/uts/tasks/$task->nid/edit"
882 );
883 if ($task->study_nid) {
884 $links['task_detach'] = array(
885 'title' => t('detach'),
886 'href' => "admin/uts/tasks/$task->nid/detach"
887 );
888 }
889 $links['task_delete'] = array(
890 'title' => t('delete'),
891 'href' => "admin/uts/tasks/$task->nid/delete"
892 );
893 return $links;
894 }
895
896 /**
897 * Load the tasks for a particular study. If none is specified then load
898 * all tasks.
899 *
900 * @param integer $study_nid NID of the study to load the tasks for.
901 * @param boolean $free Not attached to a study.
902 * @return array List of task node objects.
903 */
904 function uts_tasks_load($study_nid = NULL, $free = FALSE) {
905 if ($study_nid) {
906 $result = db_query('SELECT nid
907 FROM {uts_task}
908 WHERE study_nid = %d
909 ORDER BY weight ASC', $study_nid);
910 }
911 else if ($free) {
912 $result = db_query('SELECT nid
913 FROM {uts_task}
914 WHERE study_nid IS NULL');
915 }
916 else {
917 $result = db_query('SELECT nid
918 FROM {uts_task}');
919 }
920
921 // Load the node objects for each task.
922 $tasks = array();
923 while ($nid = db_result($result)) {
924 $tasks[] = node_load($nid);
925 }
926 return $tasks;
927 }
928
929 /**
930 * Import a list of tasks to the specified study.
931 *
932 * @param integer $study_nid Study NID to related tasks to.
933 * @param array $tasks List of task NIDs to import.
934 */
935 function uts_tasks_import($study_nid, array $tasks) {
936 // Tasks selected for import into current study.
937 $study = node_load($study_nid);
938
939 // Get largest weight for tasks in study.
940 $max_weight = db_result(db_query('SELECT MAX(weight) FROM {uts_task} WHERE study_nid = %d', $study->nid));
941 if (!$max_weight) {
942 $max_weight = 0;
943 }
944
945 // Always start with a weight one larger than the previous.
946 $weight = $max_weight + 1;
947 foreach ($tasks as $task) {
948 db_query('UPDATE {uts_task}
949 SET study_nid = %d,
950 weight = %d
951 WHERE nid = %d', $study->nid, $weight, $task);
952 $weight++;
953 }
954 drupal_set_message(t('%count task(s) imported to %study', array('%count' => count($tasks), '%study' => $study->title)));
955 }
956
957 /**
958 * Render a set of operations as links.
959 *
960 * @param array $operations Operations to render.
961 * @return string HTML output.
962 */
963 function uts_render_operations(array $operations) {
964 $out = '';
965 foreach ($operations as $operation) {
966 $out .= l($operation['title'], $operation['href']) . ' | ';
967 }
968 return substr($out, 0, strlen($out) - 3); // Remove last task pipe.
969 }
970
971 /**
972 * Set the page title in for in operation related to a study.
973 *
974 * @param integer $study_nid Study NID that operation is related to.
975 * @param string $title_prefix Page title prefix or operation.
976 */
977 function uts_set_title($study_nid, $title_prefix = NULL) {
978 if ($title_prefix === NULL) {
979 $title_prefix = drupal_get_title();
980 }
981 $study = node_load($study_nid);
982 drupal_set_title(t('@prefix for %name', array('@prefix' => $title_prefix, '%name' => $study->title)));
983 }
984
985 /**
986 * Implementation of hook_mail().
987 */
988 function uts_mail($key, &$message, $params) {
989 $language = $message['language'];
990 $variables = uts_mail_tokens($params, $language);
991 $message['subject'] .= uts_mail_text($key .'_subject', $language, $variables);
992 $message['body'][] = uts_mail_text($key .'_body', $language, $variables);
993 }
994
995 /**
996 * Get the tokens used in uts e-mails.
997 *
998 * @param array $params Associative array of parameters.
999 * @param object $language Language object.
1000 * @return array Associative array of tokens.
1001 */
1002 function uts_mail_tokens($params, $language) {
1003 $account = $params['account'];
1004
1005 $tokens = array(
1006 '!username' => $account->name,
1007 '!site' => variable_get('site_name', 'Drupal'),
1008 '!mailto' => $account->mail,
1009 '!date' => format_date(time(), 'medium', '', NULL, $language->language),
1010 '!register' => url('user/register', array('absolute' => TRUE))
1011 );
1012
1013 if (!empty($params['session_id'])) {
1014 $tokens['!participate'] = url('uts/session/' . $params['session_id'], array('absolute' => TRUE));
1015 }
1016 elseif (!empty($params['study_nid'])) {
1017 $tokens['!participate'] = url('uts/environment/' . $params['study_nid'], array('absolute' => TRUE));
1018 }
1019 else {
1020 $tokens['!participate'] = url('uts', array('absolute' => TRUE));
1021 }
1022
1023 if (!empty($params['session_id'])) {
1024 $tokens['!session_id'] = check_plain($params['session_id']);
1025 }
1026
1027 if (!empty($params['name'])) {
1028 $tokens['!name'] = check_plain($params['name']);
1029 }
1030
1031 return $tokens;
1032 }
1033
1034 /**
1035 * Get the text of an e-mail with the specified key. Translate the text and
1036 * merge the tokens.
1037 *
1038 * @param string $key Mail key.
1039 * @param object $language Language object.
1040 * @param array $tokens Associative array of tokens.
1041 * @return string Mail text.
1042 */
1043 function uts_mail_text($key, $language = NULL, $tokens = array()) {
1044 $langcode = isset($language) ? $language->language : NULL;
1045
1046 if ($admin_setting = variable_get('uts_mail_'. $key, FALSE)) {
1047 // An admin setting overrides the default string.
1048 return strtr($admin_setting, $tokens);
1049 }
1050 else {
1051 // No override, return default string.
1052 switch ($key) {
1053 case 'session_info_subject':
1054 return t('Usability testing session started', $tokens, $langcode);
1055 case 'session_info_body':
1056 return t("!username,\n\n" .
1057 "Your testing session code is: !session_id.\n\n" .
1058 "If you decided to quit during the session you may return to resume your session by visiting " .
1059 "!participate.\n\n" .
1060 "You may also change computers when you resume, but the data collection plug-in requirements " .
1061 "will be re-evaluated so make sure you meet any of the requirements on your new computer.\n\n" .
1062 "Thanks for participating!", $tokens, $langcode);
1063 case 'invite_subject':
1064 return t('Your invited to participate in a usability study!', $tokens, $langcode);
1065 case 'invite_body':
1066 return t("!name,\n\n" .
1067 "Your invited to take part in a usability study. The data collected from the study will be " .
1068 "used to improve the usability of the interfaces tested.\n\n" .
1069 "If you are interested you can find out more by visiting !participate.\n\n" .
1070 "You may be required to register an account on the site. If so visit !register and login " .
1071 "before visiting the above link.\n\n" .
1072 "Thanks for your consideration.", $tokens, $langcode);
1073 }
1074 }
1075 }
1076
1077 /**
1078 * Get the study status from a integer code.
1079 *
1080 * @param integer $status Study status code.
1081 * @return string Representation of study status.
1082 */
1083 function uts_get_study_status($status) {
1084 switch ($status) {
1085 case UTS_STUDY_STATUS_IN_DEVELOPMENT:
1086 return t('In development');
1087 case UTS_STUDY_STATUS_ACTIVE:
1088 return t('Active');
1089 case UTS_STUDY_STATUS_CLOSED:
1090 return t('Closed');
1091 default:
1092 return 'Unknown';
1093 }
1094 }
1095
1096 /**
1097 * Get the study type from a integer code.
1098 *
1099 * @param integer $type Study type code.
1100 * @return string Representation of study type.
1101 */
1102 function uts_get_study_type($type) {
1103 switch ($type) {
1104 case UTS_STUDY_TYPE_TASK:
1105 return t('Task Completion');
1106 default:
1107 return 'Unknown';
1108 }
1109 }
1110
1111 /**
1112 * Get the study audience role from a integer code.
1113 *
1114 * @param integer $type Study audience role code.
1115 * @return string Representation of study audience role.
1116 */
1117 function uts_get_study_audience_role($type) {
1118 switch ($type) {
1119 case UTS_STUDY_AUDIENCE_ROLE_USER:
1120 return t('End user');
1121 case UTS_STUDY_AUDIENCE_ROLE_DESIGNER:
1122 return t('Designer');
1123 case UTS_STUDY_AUDIENCE_ROLE_PROGRAMER:
1124 return t('Programer');
1125 default:
1126 return 'Unknown';
1127 }
1128 }
1129
1130 /**
1131 * Get the study audience level from a integer code.
1132 *
1133 * @param integer $type Study audience level code.
1134 * @return string Representation of study audience level.
1135 */
1136 function uts_get_study_audience_level($type) {
1137 switch ($type) {
1138 case UTS_STUDY_AUDIENCE_LEVEL_BEGINNER:
1139 return t('Beginner');
1140 case UTS_STUDY_AUDIENCE_LEVEL_INTERMEDIATE:
1141 return t('Intermediate');
1142 case UTS_STUDY_AUDIENCE_LEVEL_ADVANCED:
1143 return t('Advanced');
1144 default:
1145 return 'Unknown';
1146 }
1147 }
1148
1149 /**
1150 * Implementation of hook_chart_color_schemes().
1151 */
1152 function uts_chart_color_schemes(&$colors) {
1153 $colors['uts'] = array(
1154 'fdbb6d',
1155 '7dd186',
1156 '6f7dc4',
1157 '5e95d6',
1158 'c1a283',
1159 'a5a5a5',