You are here

opigno_scorm_ui.module in Opigno 7

Opigno SCORM UI.

File

modules/scorm/ui/opigno_scorm_ui.module
View source
<?php

/**
 * @file
 * Opigno SCORM UI.
 */

/**
 * Implements hook_menu().
 */
function opigno_scorm_ui_menu() {
  return array(
    'opigno-scorm/ui/player/sco/%opigno_scorm_sco' => array(
      'page callback' => 'opigno_scorm_ui_player_integrate_sco',
      'page arguments' => array(
        4,
      ),
      'access callback' => TRUE,
      // @todo
      'file' => 'includes/opigno_scorm_ui.player.inc',
      'type' => MENU_CALLBACK,
    ),
    'opigno-scorm/ui/scorm/%opigno_scorm_scorm/%/ajax/commit' => array(
      'page callback' => 'opigno_scorm_ui_ajax_commit',
      'page arguments' => array(
        3,
        4,
      ),
      'access callback' => 'opigno_scorm_access',
      'access arguments' => array(
        3,
      ),
      'file' => 'includes/opigno_scorm_ui.ajax.inc',
      'type' => MENU_CALLBACK,
    ),
  );
}

/**
 * Implements hook_theme().
 */
function opigno_scorm_ui_theme() {
  return array(
    'opigno_scorm_ui__player' => array(
      'variables' => array(
        'scorm_id' => NULL,
        'tree' => array(),
        'start_sco' => NULL,
      ),
      'template' => 'theme/opigno-scorm-ui--player',
    ),
    'opigno_scorm_ui__player_tree' => array(
      'variables' => array(
        'tree' => array(),
      ),
      'template' => 'theme/opigno-scorm-ui--player-tree',
    ),
    'opigno_scorm_ui__player_tree_item' => array(
      'variables' => array(
        'sco' => NULL,
      ),
      'template' => 'theme/opigno-scorm-ui--player-tree-item',
    ),
  );
}

/**
 * Implements hook_field_info().
 */
function opigno_scorm_ui_field_info() {
  return array(
    'opigno_scorm_package' => array(
      'label' => t('SCORM package'),
      'description' => t("This field allows users to upload SCORM packages"),
      'settings' => array(
        'display_field' => 0,
        'display_default' => 0,
        'uri_scheme' => variable_get('file_default_scheme', 'public'),
      ),
      'instance_settings' => array(
        'file_extensions' => 'zip',
        'file_directory' => 'opigno_scorm',
        'max_filesize' => '',
        'description_field' => 0,
      ),
      'default_widget' => 'file_generic',
      'default_formatter' => 'opigno_scorm_player',
    ),
  );
}

/**
 * Implements hook_field_widget_info_alter().
 */
function opigno_scorm_ui_field_widget_info_alter(&$info) {
  $info['file_generic']['field types'] = array_merge($info['file_generic']['field types'], array(
    'opigno_scorm_package',
  ));
}

/**
 * Implements hook_field_formatter_info().
 */
function opigno_scorm_ui_field_formatter_info() {
  return array(
    'opigno_scorm_player' => array(
      'label' => t('SCORM player'),
      'field types' => array(
        'opigno_scorm_package',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_info_alter().
 */
function opigno_scorm_ui_field_formatter_info_alter(&$info) {
  foreach (array(
    'file_default',
    'file_url_plain',
  ) as $formatter) {
    $info[$formatter]['field types'][] = 'opigno_scorm_package';
  }
}

/**
 * Implements hook_field_is_empty().
 */
function opigno_scorm_ui_field_is_empty($item, $field) {
  return file_field_is_empty($item, $field);
}

/**
 * Implements hook_field_load().
 */
function opigno_scorm_ui_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
  file_field_load($entity_type, $entities, $field, $instances, $langcode, $items, $age);
}

/**
 * Implements hook_field_presave().
 */
function opigno_scorm_ui_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  file_field_presave($entity_type, $entity, $field, $instance, $langcode, $items);
}

/**
 * Implements hook_field_insert().
 */
function opigno_scorm_ui_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
  module_load_include('inc', 'opigno_scorm', 'includes/opigno_scorm.manifest');
  file_field_insert($entity_type, $entity, $field, $instance, $langcode, $items);
  foreach ($items as $item) {
    opigno_scorm_extract($item['fid']);
  }
}

/**
 * Implements hook_field_update().
 */
function opigno_scorm_ui_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
  module_load_include('inc', 'opigno_scorm', 'includes/opigno_scorm.manifest');
  file_field_update($entity_type, $entity, $field, $instance, $langcode, $items);
  foreach ($items as $item) {
    $scorm = opigno_scorm_scorm_load_by_fid($item['fid']);
    if (empty($scorm->id)) {
      opigno_scorm_extract($item['fid']);
    }
  }
}

/**
 * Implements hook_field_delete().
 */
function opigno_scorm_ui_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) {
  file_field_delete($entity_type, $entity, $field, $instance, $langcode, $items);
}

/**
 * Implements hook_field_delete_revision().
 */
function opigno_scorm_ui_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) {
  file_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, $items);
}

/**
 * Implements hook_field_formatter_view().
 */
function opigno_scorm_ui_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  switch ($display['type']) {
    case 'opigno_scorm_player':
      $first = TRUE;
      foreach ($items as $delta => $item) {
        if ($first) {
          $scorm = opigno_scorm_scorm_load_by_fid($item['fid']);
          $element[$delta] = array(
            '#markup' => opigno_scorm_ui_render_player($scorm),
          );
          $first = FALSE;
        }
        else {
          $element[$delta] = array(
            '#markup' => t("As per <a href='!link' target='_blank'>SCORM.2004.3ED.ConfReq.v1.0</a>, only <em>only one SCO can be launched at a time.</em> To enforce this, only one SCORM package is loaded inside the player on this page at a time.", array(
              '!link' => 'http://www.adlnet.gov/wp-content/uploads/2011/07/SCORM.2004.3ED.ConfReq.v1.0.pdf',
            )),
          );
        }
      }
      break;
  }
  return $element;
}

/**
 * Implements hook_opigno_scorm_ui_register_cmi_paths().
 */
function opigno_scorm_ui_opigno_scorm_ui_register_cmi_paths($scorm_version) {
  switch ($scorm_version) {
    case '2004':
      $data = array(
        'cmi.location' => array(),
        'cmi.completion_status' => array(),
        'cmi.exit' => array(),
        'cmi.learner_id' => array(),
        'cmi.learner_name' => array(),
        'cmi.learner_preference._children' => array(),
        'cmi.learner_preference.audio_level' => array(),
        'cmi.learner_preference.language' => array(),
        'cmi.learner_preference.delivery_speed' => array(),
        'cmi.learner_preference.audio_captioning' => array(),
      );
      break;
    case '1.2':
      $data = array(
        'cmi.core.lesson_location' => array(),
        'cmi.core.lesson_status' => array(),
        'cmi.core.exit' => array(),
        'cmi.core.student_name' => array(),
        'cmi.core.student_id' => array(),
        'cmi.student_preference._children' => array(),
        'cmi.student_preference.audio' => array(),
        'cmi.student_preference.language' => array(),
        'cmi.student_preference.speed' => array(),
        'cmi.student_preference.text' => array(),
      );
      break;
  }
  return $data;
}

/**
 * Implements hook_opigno_scorm_ui_register_cmi_data().
 */
function opigno_scorm_ui_opigno_scorm_ui_register_cmi_data($scorm, $scos, $scorm_version) {
  global $user;
  if (!$user->uid) {
    $learner_name = "anonymous";
  }
  else {
    $learner_name = $user->name;
  }
  switch ($scorm_version) {
    case '2004':
      $data = array(
        'cmi.location' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.location', ''),
        'cmi.completion_status' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.completion_status', 'unknown'),
        'cmi.exit' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.exit', ''),
        'cmi.learner_id' => $user->uid,
        'cmi.learner_name' => $learner_name,
        'cmi.learner_preference._children' => "audio_level,language,delivery_speed,audio_captioning",
        'cmi.learner_preference.audio_level' => 1,
        'cmi.learner_preference.language' => '',
        'cmi.learner_preference.delivery_speed' => 1,
        'cmi.learner_preference.audio_captioning' => 0,
      );
      break;
    case '1.2':
      $data = array(
        'cmi.core.lesson_location' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.lesson_location', ''),
        'cmi.core.exit' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.exit', ''),
        'cmi.core.student_id' => $user->uid,
        'cmi.core.student_name' => $learner_name,
        'cmi.student_preference._children' => "audio,language,speed,text",
        'cmi.student_preference.audio' => array(),
        'cmi.student_preference.language' => '',
        'cmi.student_preference.speed' => array(),
        'cmi.student_preference.text' => array(),
      );
      break;
  }
  return $data;
}

/**
 * Implements hook_opigno_scorm_ui_commit().
 */
function opigno_scorm_ui_opigno_scorm_ui_commit($scorm, $sco_id, $data) {
  global $user;
  if (!empty($data->scorm_version)) {
    switch ($data->scorm_version) {
      case '2004':

        // Store the last visited SCO id.
        opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'user.sco', $sco_id);

        // Store the last position.
        if (!empty($data->cmi->location)) {
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.location', $data->cmi->location);
        }

        // Store suspend data value.
        if (!empty($data->cmi->suspend_data)) {
          if (!is_null($sco_id)) {
            opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.suspend_data.' . $sco_id, $data->cmi->suspend_data);
          }
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.suspend_data', $data->cmi->suspend_data);
        }

        // Store the completion status.
        if (!empty($data->cmi->completion_status)) {
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.completion_status', $data->cmi->completion_status);
        }
        break;
      case '1.2':

        // Store the last position.
        if (!empty($data->cmi->core->lesson_location)) {
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.core.lesson_location', $data->cmi->core->lesson_location);
        }

        // Store suspend data value.
        if (!empty($data->cmi->suspend_data)) {
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.suspend_data', $data->cmi->suspend_data);
        }

        // Store the completion status.
        if (!empty($data->cmi->core->lesson_status)) {
          opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, 'cmi.core.lesson_status', $data->cmi->core->lesson_status);
        }
        break;
    }
  }
}

/**
 * Render a SCORM player for the given SCORM object.
 *
 * @param object $scorm
 *
 * @return string
 */
function opigno_scorm_ui_render_player($scorm) {
  global $user;
  module_load_include('inc', 'opigno_scorm_ui', 'includes/opigno_scorm_ui.player');

  // Get SCORM API version.
  $metadata = unserialize($scorm->metadata);
  if (strpos($metadata['schemaversion'], '1.2') !== FALSE) {
    $scorm_version = '1.2';
  }
  else {
    $scorm_version = '2004';
  }

  // Get the SCO tree.
  $tree = opigno_scorm_ui_player_scorm_tree($scorm);
  $flat_tree = opigno_scorm_ui_player_scorm_flatten_tree($tree);

  // Get the start SCO.
  $start_sco = opigno_scorm_ui_player_start_sco($flat_tree);

  // Add assets.
  opigno_scorm_ui_add_assets();

  // Get implemented CMI paths.
  $paths = opigno_scorm_ui_add_cmi_paths($scorm_version);

  // Get CMI data for each SCO.
  $data = opigno_scorm_ui_add_cmi_data($scorm, $flat_tree, $scorm_version);
  $sco_identifiers = array();
  foreach ($flat_tree as $delta => $item) {
    if ($item->scorm_type == 'sco') {
      $sco_identifiers[$item->identifier] = $item->id;
    }
  }
  $scos_suspend_data = array();

  // Check for quiz and user result id.
  if (is_numeric(arg(1)) && arg(2) == 'take') {
    $quiz_nid = arg(1);
    if (isset($_SESSION['quiz_' . $quiz_nid]['quiz_vid']) && $quiz_nid != $_SESSION['quiz_' . $quiz_nid]['quiz_vid'] && variable_get('quiz_auto_revisioning')) {
      $quiz = node_load($quiz_nid, $_SESSION['quiz_' . $quiz_nid]['quiz_vid']);
    }
    else {
      $quiz = node_load($quiz_nid);
    }

    // Load user results id.
    $rid = $user->uid > 0 ? _quiz_active_result_id($user->uid, $quiz->nid, $quiz->vid) : 0;

    // Are we resuming an in-progress quiz?
    if ($quiz->allow_resume && $rid > 0) {

      // Resume.
      foreach ($flat_tree as $sco) {
        if ($sco->scorm_type == 'sco') {
          $scos_suspend_data[$sco->id] = opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.suspend_data.' . $sco->id, '');
        }
      }
      $last_user_sco = opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'user.sco', '');
      if ($last_user_sco != '') {
        foreach ($flat_tree as $sco) {
          if ($last_user_sco == $sco->id && !empty($sco->launch)) {
            $start_sco = $sco;
          }
        }
      }
    }
    else {

      // Not resume.
      $data['cmi.suspend_data'] = '';
    }
  }

  // Pass it to JS.
  drupal_add_js(array(
    'opignoScormUIPlayer' => array(
      'cmiPaths' => $paths,
      'cmiData' => $data,
      'scoIdentifiers' => $sco_identifiers,
      'cmiSuspendItems' => $scos_suspend_data,
    ),
    'scormVersion' => $scorm_version,
  ), 'setting');
  return theme('opigno_scorm_ui__player', array(
    'scorm_id' => $scorm->id,
    'tree' => count($flat_tree) == 2 ? NULL : $tree,
    'start_sco' => $start_sco,
  ));
}

/**
 * Helper function to get SCORM CMI data while also providing a default value.
 *
 * @param int $uid
 * @param int $scorm_id
 * @param string $cmi_key
 * @param mixed $default_value
 *
 * @return mixed|null
 */
function opigno_scorm_ui_scorm_cmi_get($uid, $scorm_id, $cmi_key, $default_value = NULL) {
  $value = opigno_scorm_scorm_cmi_get($uid, $scorm_id, $cmi_key);
  return isset($value) ? $value : $default_value;
}

/**
 * Helper function to get SCO CMI data while also providing a default value.
 *
 * @param int $uid
 * @param int $scorm_id
 * @param string $cmi_key
 * @param mixed $default_value
 *
 * @return mixed|null
 */
function opigno_scorm_ui_sco_cmi_get($uid, $scorm_id, $cmi_key, $default_value = NULL) {
  $value = opigno_scorm_sco_cmi_get($uid, $scorm_id, $cmi_key);
  return isset($value) ? $value : $default_value;
}

Functions

Namesort descending Description
opigno_scorm_ui_field_delete Implements hook_field_delete().
opigno_scorm_ui_field_delete_revision Implements hook_field_delete_revision().
opigno_scorm_ui_field_formatter_info Implements hook_field_formatter_info().
opigno_scorm_ui_field_formatter_info_alter Implements hook_field_formatter_info_alter().
opigno_scorm_ui_field_formatter_view Implements hook_field_formatter_view().
opigno_scorm_ui_field_info Implements hook_field_info().
opigno_scorm_ui_field_insert Implements hook_field_insert().
opigno_scorm_ui_field_is_empty Implements hook_field_is_empty().
opigno_scorm_ui_field_load Implements hook_field_load().
opigno_scorm_ui_field_presave Implements hook_field_presave().
opigno_scorm_ui_field_update Implements hook_field_update().
opigno_scorm_ui_field_widget_info_alter Implements hook_field_widget_info_alter().
opigno_scorm_ui_menu Implements hook_menu().
opigno_scorm_ui_opigno_scorm_ui_commit Implements hook_opigno_scorm_ui_commit().
opigno_scorm_ui_opigno_scorm_ui_register_cmi_data Implements hook_opigno_scorm_ui_register_cmi_data().
opigno_scorm_ui_opigno_scorm_ui_register_cmi_paths Implements hook_opigno_scorm_ui_register_cmi_paths().
opigno_scorm_ui_render_player Render a SCORM player for the given SCORM object.
opigno_scorm_ui_scorm_cmi_get Helper function to get SCORM CMI data while also providing a default value.
opigno_scorm_ui_sco_cmi_get Helper function to get SCO CMI data while also providing a default value.
opigno_scorm_ui_theme Implements hook_theme().