opigno_scorm_ui.module in Opigno 7
Opigno SCORM UI.
File
modules/scorm/ui/opigno_scorm_ui.moduleView 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;
}