Index: plugins/uts_live_feedback/uts_live_feedback.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/plugins/uts_live_feedback/uts_live_feedback.module,v
retrieving revision 1.7
diff -u -r1.7 uts_live_feedback.module
--- plugins/uts_live_feedback/uts_live_feedback.module	8 Aug 2008 19:29:22 -0000	1.7
+++ plugins/uts_live_feedback/uts_live_feedback.module	30 Dec 2008 07:15:13 -0000
@@ -18,7 +18,8 @@
     'uts_live_feedback' => array(
       'name' => t('Live feedback'),
       'description' => t('Collect user comments through an AJAX dialog while running a test.'),
-      'software_require' => FALSE
+      'software_require' => FALSE,
+      'javascript' => TRUE
     )
   );
 }
@@ -29,11 +30,9 @@
 function uts_live_feedback_uts_client_requirements() {
   return array(
     'uts_live_feedback' => array(
-      'status' => 'warning',
+      'status' => 'ok',
       'name' => t('Live feedback'),
-      'description' => t('Please make sure you have JavaScript enabled. To confirm that it is working
-                          !link and a message should pop-up saying "Success."',
-                          array('!link' => '<a href="javascript: alert(\'Success!\');">click here</a> '))
+      'description' => t('All requirements met, data collection enabled.')
     )
   );
 }
Index: uts.hooks.data.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/uts.hooks.data.php,v
retrieving revision 1.1
diff -u -r1.1 uts.hooks.data.php
--- uts.hooks.data.php	16 Aug 2008 22:04:38 -0000	1.1
+++ uts.hooks.data.php	30 Dec 2008 07:15:12 -0000
@@ -21,13 +21,15 @@
  *   - "description": Short description of the module that can be easily
  *     understood by both the test creator and the participant.
  *   - "software_require": Client side software requirements.
+ *   - "javascript": Boolean javascript required.
  */
 function hook_uts_data_collection() {
   return array(
     'uts_plugin' => array(
       'name' => t('Plug-in name'),
       'description' => t('Plug-in description.'),
-      'software_require' => FALSE
+      'software_require' => FALSE,
+      'javascript' => FALSE
     )
   );
 }
Index: uts.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/uts.pages.inc,v
retrieving revision 1.35
diff -u -r1.35 uts.pages.inc
--- uts.pages.inc	28 Dec 2008 07:02:42 -0000	1.35
+++ uts.pages.inc	30 Dec 2008 07:15:13 -0000
@@ -8,283 +8,192 @@
  */
 
 /**
- * Page that displays the active studies.
+ * Display list of active studies to choose from.
  *
- * @param integer $study_nid Study NID to display.
  * @return string HTML output.
  */
-function uts_participate($study_nid = NULL) {
-  if ($study_nid) {
-    // Display information describing the process before user begins study.
-    $study = node_load($study_nid);
-
-    // Make sure study is valid and active.
-    if ($study->type != UTS_STUDY) {
-      drupal_set_message(t('Not a valid study.'), 'error');
-      return '';
-    }
-    else if ($study->study_status == UTS_STUDY_STATUS_IN_DEVELOPMENT) {
-      drupal_set_message(t('Study is not active.'), 'error');
-      return '';
-    }
-
-    $tasks = uts_tasks_load($study_nid);
-    $max_time = 0;
-    foreach ($tasks as $task) {
-      $max_time += $task->max_time;
-    }
-    drupal_set_title(t('Participate in @study', array('@study' => $study->title)));
+function uts_participate_list() {
+  $out .= '<p>' . t('Thanks for participating in our studies for making Drupal better. Please follow the steps.') . '</p>';
 
-    return t('<p>You have selected %title which is for <i>@role (@level)</i>. The maximum
-              time allotted for this study is %time for %count tasks. If you do not finish
-              a task in the time allotted that is perfectly fine, or if you would like to
-              skip a task you may do so by pressing <i>Done</i>. Once you complete a task
-              press the <i>Done</i> button which will present you with the option to
-              move on to the next task or come back later.</p>
-              <p>You may stop after any idividual task or complete the entire study in one
-              sitting, but make sure you have un-interupted time availabe before starting.
-              Please do not use reference material for help during the study unless
-              instructed to do so.</p>
-              <p>To begin read the scenario carefully and press the start button.</p>
-              <p><b>Scenario:</b><br />@scenario</p>
-              !form',
-      array('%title' => $study->title,
-            '@role' => uts_get_study_audience_role($study->audience_role),
-            '@level' => uts_get_study_audience_level($study->audience_level),
-            '%time' => format_interval($max_time),
-            '%count' => count($tasks),
-            '@scenario' => $study->body,
-            '!form' => drupal_get_form('uts_participate_start_form', $study_nid)));
-  }
-
-  // Add warning to users who can manage studies since this page may be confusing.
-  if (user_access('manage studies')) {
-    drupal_set_message(t('This page allows participants to take part in a study. To administer the
-                          Usability Testing Suite please goto the <a href="@admin">administration pages</a>.',
-                          array('@admin' => url('admin/uts'))), 'warning');
-  }
-
-  // Display list of active studies.
-  $list = array();
-  $studies = array_merge(uts_studies_load(UTS_STUDY_STATUS_ACTIVE), uts_studies_load(UTS_STUDY_STATUS_CLOSED));
+  $studies = array_merge(uts_studies_load(UTS_STUDY_STATUS_ACTIVE));
   foreach ($studies as $study) {
-    // Set status message.
-    if ($study->study_status == UTS_STUDY_STATUS_CLOSED) {
-      // Make sure open sessions.
-      $session_ids = uts_session_load_all($study->nid);
-      $incomplete = FALSE;
-      foreach ($session_ids as $session_id) {
-        $session = uts_session_load($session_id);
-        if (!$session->complete) {
-          $incomplete = TRUE;
-          break;
-        }
-      }
-      if (!$incomplete) {
-        // No need to display study if no incomplete sessions.
-        continue;
-      }
-      $status = t(' - resume session only');
-    }
-    else {
-      $status = t(' - open to new participants');
-    }
-
-    $list[] = t('<b>!title</b><i>@status</i><br />@body',
-      array('!title' => l($study->title, 'uts/participate/' . $study->nid),
-            '@status' => $status,
-            '@body' => $study->body));
+    $out .= '<div class="uts-choose-study">';
+    $out .= l($study->title, 'uts/environment/' . $study->nid);
+    $teaser = node_teaser($study->body, NULL, 300);
+    $out .= '<p>' . $study->body . '</p>';
+    $out .= '</div>';
   }
 
-  if (empty($list)) {
-    $list[] = t('No active studies.');
+  if (!$studies) {
+    $out .= '<p>' . t('No active studies.') . '</p>';
   }
-  return theme('item_list', $list);
+
+  return $out;
 }
 
 /**
- * Participation form.
+ * Create an environment for the session.
+ *
+ * @param integer $study_nid Study NID to display.
  */
-function uts_participate_start_form(&$form_state, $study_nid) {
+function uts_participate_create_environment_form(&$form_state, $study_nid) {
+  $study = node_load($study_nid);
+
   $form = array();
+  $form['#validate'][] = 'uts_participate_create_environment_form_validate';
   $form['study_nid'] = array(
     '#type' => 'value',
     '#value' => $study_nid
   );
-  $form['participate'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Participate'),
-    '#description' => t('Take part in the current study.')
-  );
-  $form['participate']['code'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Code',
-    '#description' => t('Enter the code you were given to resume a previous testing session, otherwise leave this field blank.'),
-    '#size' => '20',
-    '#default_value' => (isset($_COOKIE['uts_session']) ? $_COOKIE['uts_session'] : '')
+  $form['instructions'] = array(
+    '#type' => 'item',
+    '#value' => t('In order to participate you must create an environment for your session.')
   );
-  $form['participate']['data_collection'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Data collection'),
-    '#description' => t('Check data collection requirements and rosolve any issues.'),
-    '#tree' => TRUE,
-    '#theme' => 'uts_participate_start_form_data_collection'
-  );
-  $study = node_load($study_nid);
-  $requirements = uts_data_client_requirements();
-  foreach ($requirements as $module => $requirement) {
-    if (array_key_exists($module, $study->data_collection)) {
-      $row = array();
-      $row['status'] = array(
-        '#type' => 'value',
-        '#value' => $requirement['status']
-      );
-      $row['required'] = array(
-        '#type' => 'value',
-        '#value' => $study->data_collection[$module]['required']
-      );
-      $row['name'] = array(
-        '#type' => 'value',
-        '#value' => $requirement['name']
-      );
-      $row['description'] = array(
-        '#type' => 'item',
-        '#value' => $requirement['description']
-      );
 
-      $form['participate']['data_collection'][$module] = $row;
-    }
-  }
+  $form += uts_participate_requirements($study);
 
-  $form['participate']['start'] = array(
+  $form['op'] = array(
     '#type' => 'submit',
-    '#value' => t('Start')
+    '#value' => t('Create')
   );
+
   return $form;
 }
 
 /**
- * Theme data collection requirements into a table.
- *
- * @param array $requirements Fieldset with array of requirements.
- * @return string HTML output.
+ * Make sure that there is still room in the study for another paritipant.
  */
-function theme_uts_participate_start_form_data_collection($requirements) {
-  $header = array(t('Status'), t('Name'), t('Description'));
-  $rows = array();
-  foreach (element_children($requirements) as $module) {
-    $requirement = &$requirements[$module];
-    $row = array();
-    $row[] = theme('image', "misc/watchdog-{$requirement['status']['#value']}.png");
-    $row[] = $requirement['name']['#value'];
-    $row[] = drupal_render($requirement['description']);
-
-    $rows[] = $row;
+function uts_participate_create_environment_form_validate($form, &$form_state) {
+  // Check the number of existing sessions against the maximum participant count.
+  $study = node_load($form_state['values']['study_nid']);
+  $sessions = uts_session_load_all($study->nid);
+  if (count($sessions) >= $study->participant_count) {
+    form_set_error('study_nid', t('The study is no longer open to new participants. Please try a different study.'));
+    drupal_goto('uts');
   }
-  return theme('table', $header, $rows);
 }
 
 /**
- * Ensure that code entered is valid.
+ * Start the batch process to create the session environment.
  */
-function uts_participate_start_form_validate($form, &$form_state) {
-  if (!empty($form_state['values']['code'])) {
-    $session = uts_session_load($form_state['values']['code']);
-    if (!$session) {
-      form_set_error('code', t('Invalid code.'));
-    }
-    else if ($session->study_nid != $form_state['values']['study_nid']) {
-      form_set_error('code', t('The code is not for this study.'));
-      drupal_set_message(t('Please try a different code or go to the related !link.',
-                            array('!link' => l('study page', 'uts/participate/' . $study_nid))));
-    }
-    else if ($session->complete) {
-      form_set_error('code', t('This code is for an already completed session.'));
-    }
-  }
+function uts_participate_create_environment_form_submit($form, &$form_state) {
+  uts_participate_environment_batch($form_state['values']['study_nid']);
+}
 
-  // Check data collection requirements.
-  foreach ($form_state['values']['data_collection'] as $module => $requirement) {
-    if ($requirement['status'] == 'error' && $requirement['required']) {
-      form_set_error('', t('Data collection plug-in %name is required and has issues that
-                            need to be resolved.', array('%name' => $requirement['name'])));
-    }
+/**
+ * Start a session.
+ *
+ * @param string $session_id UTS session ID.
+ */
+function uts_participate_start_session_form(&$form_state, $session_id) {
+  $session = uts_session_load($session_id);
+
+  if (!$session) {
+    drupal_set_message(t('Invalid session ID.'), 'error');
+    drupal_goto('uts');
   }
+
+  $study = node_load($session->study_nid);
+
+  $form = array();
+  $form['session_id'] = array(
+    '#type' => 'value',
+    '#value' => $session->session_id
+  );
+  $form['instructions'] = array(
+    '#type' => 'item',
+    '#value' => t('Start/Restore your session in which you are participating in %study.', array('%study' => $study->title))
+  );
+
+  $form += uts_participate_requirements($study);
+
+  $form['op'] = array(
+    '#type' => 'submit',
+    '#value' => t('Start')
+  );
+
+  return $form;
 }
 
 /**
- * Create session or resume already open one.
+ * Start the batch process to configure the session.
  */
-function uts_participate_start_form_submit($form, &$form_state) {
-  global $db_prefix;
+function uts_participate_start_session_form_submit($form, &$form_state) {
+  uts_participate_session_batch($form_state['values']['session_id'], $form_state['values']['data_collection']);
+}
 
-  if (!empty($form_state['values']['code'])) {
-    // Initialize testing session.
-    uts_session_restore($form_state['values']['code']);
+/**
+ * Create form elements for the data plug-in requirements.
+ *
+ * @param object $study Study object.
+ * @return array Addition to root of form definition array.
+ */
+function uts_participate_requirements($study) {
+  $form = array();
+  $plugins = uts_data_collection_list();
+  $requirements = uts_data_client_requirements();
 
-    // Update data collection plug-ins in testing environment.
-    $enable = array();
-    $disable = array();
-    foreach ($form_state['values']['data_collection'] as $module => $requirement) {
-      if ($requirement['status'] != 'error') {
-        $enable[] = $module;
-      }
-      else {
-        $disable[] = $module;
-      }
-    }
-    // Enable to proctor to ensure that menu hooks are added appropriately.
-    $disable[] = 'uts_proctor'; // TODO If not disabled then menu hooks are not picked up for some reason.
-    $enable[] = 'uts_proctor';
+  $form['#validate'][] = 'uts_participate_requirements_validate';
 
-    if (!empty($disable)) {
-      uts_environment_invoke_callback('disable_modules', $form_state['values']['code'], implode(',', $disable));
-    }
-    if (!empty($enable)) {
-      uts_environment_invoke_callback('enable_modules', $form_state['values']['code'], implode(',', $enable));
+  // Check for javascript requirement.
+  foreach ($plugins as $module => $plugin) {
+    if ($plugin['javascript'] && $study->data_collection[$module]['required']) {
+      $form['requirements']['javascript_status'] = array(
+        '#type' => 'hidden',
+        '#default_value' => 'not-found'
+      );
+      $form['requirements'][] = array(
+        '#type' => 'markup',
+        '#value' => '<div class="uts-requirement error" id="uts-javascript">' .
+                      t('Javascript is not enabled. Please turn it on.') .
+                    '</div>'
+      );
+      drupal_add_js('$("div#uts-javascript").hide(); $("input#edit-javascript-status").attr("value", "found");', 'inline', 'footer');
+      break;
     }
   }
-  else {
-    // Check the number of existing sessions against the maximum participant count.
-    $study = node_load($form_state['values']['study_nid']);
-    $sessions = uts_session_load_all($study->nid);
-    if (count($sessions) >= $study->participant_count) {
-      drupal_set_message(t('This study is no longer open to new participants. Please enter a code or try a
-                            different study.'), 'error');
-      return;
-    }
-
-    $session_id = uts_session_create($form_state['values']['study_nid']);
-
-    if ($session_id) {
-      drupal_set_message(t('A test environment has been created for you. Please store the following code
-                            so that if you choose to stop part way and continue later you may do so.
-                            Once you are ready press that <i>Start</i> button again.'));
-      drupal_set_message(t('Code: @code', array('@code' => $session_id)));
-
-      // Send e-mail containing session information.
-      global $user;
-      if (!user_is_anonymous()) {
-        $params = array();
-        $params['account'] = $user;
-        $params['study_nid'] = $study->nid;
-        $params['session_id'] = $session_id;
-        drupal_mail('uts', 'session_info', $user->mail, user_preferred_language($user), $params);
+
+  $form['data_collection'] = array(
+    '#type' => 'value',
+    '#tree' => TRUE
+  );
+  foreach ($requirements as $module => $requirement) {
+    if (array_key_exists($module, $study->data_collection)) {
+      if ($study->data_collection[$module]['required'] &&
+          $requirement['status'] != 'ok') {
+        $form['requirements'][] = array(
+          '#type' => 'markup',
+          '#value' => '<div class="uts-requirement ' . $requirement['status'] . '" id="' . $module . '">' .
+                        $requirement['description'] .
+                      '</div>'
+        );
       }
+      $form['data_collection'][$module] = array(
+        '#type' => 'value',
+        '#value' => $requirement['status']
+      );
     }
-    else {
-      drupal_set_message(t('Failed creating environment, please try again.
-                            If this issue continue to persist contact the administrator.'), 'error');
-    }
+  }
+
+  return $form;
+}
 
-    // Check the number of existing sessions against the maximum participant count. If maximum count reached
-    // then close study.
-    $sessions = uts_session_load_all($study->nid); // Reload.
-    if (count($sessions) >= $study->participant_count) {
-      $study->study_status = UTS_STUDY_STATUS_CLOSED;
-      $study->revision = FALSE;
-      $study = node_submit($study);
-      node_save($study);
+/**
+ * Ensure that all the requirements have been met.
+ */
+function uts_participate_requirements_validate($form, &$form_state) {
+  // Check JavaScript requirement.
+  if (isset($form_state['values']['javascript_status']) && $form_state['values']['javascript_status'] != 'found') {
+    form_set_error('javascript_status', t('Javascript must be enabled.'));
+  }
+
+  // Check data plug-in requirements.
+  $requirements = uts_data_client_requirements();
+  foreach ($requirements as $module => $requirement) {
+    foreach ($form_state['values']['data_collection'] as $module => $status) {
+      if ($status != 'ok') {
+        form_set_error($module . '_status', $requirement['description']);
+      }
     }
   }
 }
Index: uts.help.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/uts.help.inc,v
retrieving revision 1.9
diff -u -r1.9 uts.help.inc
--- uts.help.inc	13 Oct 2008 01:27:35 -0000	1.9
+++ uts.help.inc	30 Dec 2008 07:15:12 -0000
@@ -46,16 +46,5 @@
                   The message to be sent can be modified on the <a href="@configuration">configuration</a> page.
                 </p>',
                 array('@configuration' => url('admin/uts/configuration')));
-    case 'uts':
-      return t('<p>
-                  The usability testing suite provides a way for a user experience to be
-                  recorded and analysed. This is done with the help of participants who take
-                  part in studies by completing tasks. The results of which are recorded
-                  and analysed for usability isues that need fixing.
-                </p>
-                <p>
-                  If you are willing to participate and/or have been contacted to take part
-                  in a study please procede in selecting a study.
-                </p>');
   }
 }
Index: uts.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/uts.module,v
retrieving revision 1.49
diff -u -r1.49 uts.module
--- uts.module	28 Dec 2008 07:02:42 -0000	1.49
+++ uts.module	30 Dec 2008 07:15:13 -0000
@@ -75,6 +75,7 @@
 require_once drupal_get_path('module', 'uts') . '/uts.data.inc';
 require_once drupal_get_path('module', 'uts') . '/uts.environment.inc';
 require_once drupal_get_path('module', 'uts') . '/uts.node.inc';
+require_once drupal_get_path('module', 'uts') . '/uts.participate.inc';
 require_once drupal_get_path('module', 'uts') . '/uts.session.inc';
 require_once drupal_get_path('module', 'uts') . '/uts.help.inc';
 
@@ -86,17 +87,25 @@
 
   // Participant items.
   $items['uts'] = array(
-    'title' => 'Usability testing',
+    'title' => '1 - Choose a study',
     'description' => 'Description of usability testing and study selection.',
-    'page callback' => 'uts_participate',
+    'page callback' => 'uts_participate_list',
     'access arguments' => array('participate in study'),
-    'file' => 'uts.pages.inc'
+    'file' => 'uts.pages.inc',
+    'type' => MENU_CALLBACK
   );
-  $items['uts/%'] = array(
-    'title' => 'Participate',
-    'description' => 'Participate in a usability study.',
-    'page callback' => 'uts_participate',
-    'page arguments' => array(2),
+  $items['uts/environment/%'] = array(
+    'title' => '2 - Create test environment',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('uts_participate_create_environment_form', 2),
+    'access arguments' => array('participate in study'),
+    'file' => 'uts.pages.inc',
+    'type' => MENU_CALLBACK
+  );
+  $items['uts/session/%'] = array(
+    'title' => '3 - Start session',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('uts_participate_start_session_form', 2),
     'access arguments' => array('participate in study'),
     'file' => 'uts.pages.inc',
     'type' => MENU_CALLBACK
Index: plugins/uts_path/uts_path.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/plugins/uts_path/uts_path.module,v
retrieving revision 1.14
diff -u -r1.14 uts_path.module
--- plugins/uts_path/uts_path.module	17 Aug 2008 00:59:11 -0000	1.14
+++ plugins/uts_path/uts_path.module	30 Dec 2008 07:15:13 -0000
@@ -33,7 +33,8 @@
     'uts_path' => array(
       'name' => t('User path'),
       'description' => t('Collect the user path taken to complete a task and compare to defined ideal path.'),
-      'software_require' => FALSE
+      'software_require' => FALSE,
+      'javascript' => FALSE
     )
   );
 }
Index: plugins/uts_form/uts_form.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uts/plugins/uts_form/uts_form.module,v
retrieving revision 1.2
diff -u -r1.2 uts_form.module
--- plugins/uts_form/uts_form.module	8 Aug 2008 00:07:58 -0000	1.2
+++ plugins/uts_form/uts_form.module	30 Dec 2008 07:15:13 -0000
@@ -18,7 +18,8 @@
     'uts_form' => array(
       'name' => t('Form submission'),
       'description' => t('Collect the user input.'),
-      'software_require' => FALSE
+      'software_require' => FALSE,
+      'javascript' => FALSE
     )
   );
 }
Index: uts.participate.inc
===================================================================
RCS file: uts.participate.inc
diff -N uts.participate.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ uts.participate.inc	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,167 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Provide particpation batch definitions.
+ *
+ * Copyright 2008 by Jimmy Berry ("boombatower", http://drupal.org/user/214218)
+ */
+
+/**
+ * Batch to create an environment.
+ *
+ * @param integer $study_nid Study NID.
+ */
+function uts_participate_environment_batch($study_nid) {
+  // Validate, create, e-mail, enable modules load session.
+  $batch = array(
+    'operations' => array(
+      array('uts_participate_environment_batch_session', array($study_nid)),
+      array('uts_participate_environment_batch_notify', array($study_nid)),
+      array('uts_participate_environment_batch_close', array($study_nid)),
+    ),
+    'finished' => 'uts_participate_environment_batch_finished',
+    'title' => t('Create a session and an environment'),
+    'init_message' => t('Creating environment...'),
+    'error_message' => t('An error occured during environment setup.'),
+  );
+
+  batch_set($batch);
+}
+
+/**
+ * Create a session and an environment.
+ *
+ * @param integer $study_nid Study NID.
+ */
+function uts_participate_environment_batch_session($study_nid, &$context) {
+  $session_id = uts_session_create($study_nid);
+
+  $context['message'] = t('Environment created.');
+  $context['results']['session_id'] = $session_id;
+}
+
+/**
+ * Send e-mail containing session information.
+ *
+ * @param integer $study_nid Study NID.
+ */
+function uts_participate_environment_batch_notify($study_nid, &$context) {
+  $session_id = $context['results']['session_id'];
+
+  if ($session_id) {
+    global $user;
+    $params = array();
+    $params['account'] = $user;
+    $params['study_nid'] = $study_nid;
+    $params['session_id'] = $session_id;
+    drupal_mail('uts', 'session_info', $user->mail, user_preferred_language($user), $params);
+
+    $context['message'] = t('E-mail sent reguarding environment information.');
+  }
+}
+
+/**
+ * Check the number of existing sessions against the maximum participant count.
+ * If maximum count reached then close study.
+ *
+ * @param integer $study_nid Study NID.
+ */
+function uts_participate_environment_batch_close($study_nid, &$context) {
+  $study = node_load($study_nid);
+  $sessions = uts_session_load_all($study->nid);
+  if (count($sessions) >= $study->participant_count) {
+    $study->study_status = UTS_STUDY_STATUS_CLOSED;
+    $study->revision = FALSE;
+    $study = node_submit($study);
+    node_save($study);
+    $context['message'] = t('Maximum number of sessions reached, study closed.');
+  }
+}
+
+/**
+ * Batch 'finished' callback.
+ */
+function uts_participate_environment_batch_finished($success, $results, $operations) {
+  if ($success) {
+    if ($results['session_id']) {
+      drupal_set_message(t('Environment created successfully.'));
+      drupal_goto('uts/session/' . $results['session_id']);
+    }
+    else {
+      drupal_set_message(t('Failed to setup environment. Please contact the administrator.'), 'error');
+    }
+  }
+  else {
+    $error_operation = reset($operations);
+    drupal_set_message('An error occurred while processing ' . $error_operation[0] . ' with arguments :' .
+                        print_r($error_operation[0], TRUE));
+  }
+}
+
+/**
+ * Setup session.
+ *
+ * @param string $session_id UTS session ID.
+ * @param array $modules Associative array of data collection module and status.
+ */
+function uts_participate_session_batch($session_id, $modules) {
+  $batch = array(
+    'operations' => array(
+      array('uts_participate_session_batch_modules', array($session_id, $modules)),
+    ),
+    'finished' => 'uts_participate_session_batch_finished',
+    'title' => t('Start session'),
+    'init_message' => t('Configuring data plug-ins...'),
+    'error_message' => t('An error occured during session setup.'),
+  );
+
+  batch_set($batch);
+}
+
+/**
+ * Update data collection plug-ins in testing environment.
+ *
+ * @param string $session_id UTS session ID.
+ * @param array $modules Associative array of data collection module and status.
+ */
+function uts_participate_session_batch_modules($session_id, $modules, &$context) {
+  $enable = array();
+  $disable = array();
+  foreach ($modules as $module => $status) {
+    if ($status != 'error') {
+      $enable[] = $module;
+    }
+    else {
+      $disable[] = $module;
+    }
+  }
+  // Enable to proctor to ensure that menu hooks are added appropriately.
+  $disable[] = 'uts_proctor'; // TODO If not disabled then menu hooks are not picked up for some reason.
+  $enable[] = 'uts_proctor';
+
+  if (!empty($disable)) {
+    uts_environment_invoke_callback('disable_modules', $session_id, implode(',', $disable));
+  }
+  if (!empty($enable)) {
+    uts_environment_invoke_callback('enable_modules', $session_id, implode(',', $enable));
+  }
+  $context['results']['session_id'] = $session_id;
+  $context['message'] = t('Data collection plug-ins configured.');
+}
+
+/**
+ * Batch 'finished' callback.
+ */
+function uts_participate_session_batch_finished($success, $results, $operations) {
+  if ($success) {
+    // Should be inside session and will not see messages anyway.
+    uts_session_restore($results['session_id']);
+    drupal_goto('');
+  }
+  else {
+    $error_operation = reset($operations);
+    drupal_set_message('An error occurred while processing ' . $error_operation[0] . ' with arguments :' .
+                        print_r($error_operation[0], TRUE));
+  }
+}
