You are here

opigno_scorm_quiz.module in Opigno 7

Module hook definitions.

File

modules/scorm/quiz/opigno_scorm_quiz.module
View source
<?php

/**
 * @file
 * Module hook definitions.
 */

/**
 * Implements hook_opigno_scorm_ui_register_cmi_paths().
 */
function opigno_scorm_quiz_opigno_scorm_ui_register_cmi_paths($scorm_version) {
  switch ($scorm_version) {
    case '2004':
      $data = array(
        'cmi.score.raw' => array(),
        'cmi.score.min' => array(),
        'cmi.score.max' => array(),
        'cmi.score.scaled' => array(),
        'cmi.suspend_data' => array(),
        'cmi.success_status' => array(),
        'cmi.objectives' => array(),
        'cmi.objectives._count' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives._children' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives.n.id' => array(),
        'cmi.objectives.n.score' => array(),
        'cmi.objectives.n.score._children' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives.n.score.scaled' => array(),
        'cmi.objectives.n.score.raw' => array(),
        'cmi.objectives.n.score.min' => array(),
        'cmi.objectives.n.score.max' => array(),
        'cmi.objectives.n.success_status' => array(),
        'cmi.objectives.n.completion_status' => array(),
        'cmi.objectives.n.progress_measure' => array(),
        'cmi.objectives.n.description' => array(),
      );
      break;
    case '1.2':
      $data = array(
        'cmi.core.score.raw' => array(),
        'cmi.core.score.max' => array(),
        'cmi.core.score.min' => array(),
        'cmi.core.score._children' => array(),
        'cmi.suspend_data' => array(),
        'cmi.core.lesson_status' => array(),
        'cmi.objectives' => array(),
        'cmi.objectives._count' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives._children' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives.n.id' => array(),
        'cmi.objectives.n.score' => array(),
        'cmi.objectives.n.score._children' => array(
          'readOnly' => 1,
        ),
        'cmi.objectives.n.score.raw' => array(),
        'cmi.objectives.n.score.min' => array(),
        'cmi.objectives.n.score.max' => array(),
        'cmi.objectives.n.status' => array(),
      );
      break;
  }
  return $data;
}

/**
 * Implements hook_opigno_scorm_ui_register_cmi_data().
 */
function opigno_scorm_quiz_opigno_scorm_ui_register_cmi_data($scorm, $scos, $scorm_version) {
  global $user;
  switch ($scorm_version) {
    case '2004':
      $data = array(
        'cmi.score.raw' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.score.raw', ''),
        'cmi.score.min' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.score.min', ''),
        'cmi.score.max' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.score.max', ''),
        'cmi.score.scaled' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.score.scaled', ''),
        'cmi.success_status' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.success_status', ''),
        'cmi.objectives' => array(),
      );

      // Get last visited SCO.
      $last_sco = opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'user.sco', '');
      if ($last_sco != '') {
        $data['cmi.suspend_data'] = opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.suspend_data.' . $last_sco, '');
      }
      else {
        $data['cmi.suspend_data'] = opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.suspend_data', '');
      }
      break;
    case '1.2':
      $data = array(
        'cmi.core.score.raw' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.score.raw', ''),
        'cmi.core.score.min' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.score.min', ''),
        'cmi.core.score.max' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.score.max', ''),
        'cmi.core.lesson_status' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.lesson_status', ''),
        'cmi.suspend_data' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.suspend_data', ''),
        'cmi.core.score._children' => opigno_scorm_ui_scorm_cmi_get($user->uid, $scorm->id, 'cmi.core.score._children', 'raw,min,max'),
        'cmi.objectives' => array(),
      );
      break;
  }

  // Fetch the objectives.
  foreach ($scos as $sco) {
    if (!empty($sco->attributes['objectives'])) {
      foreach ($sco->attributes['objectives'] as $objective) {
        $stored_objective = opigno_scorm_quiz_load_objective($user->uid, $scorm->id, $objective['id']);
        if ($scorm_version == '2004') {
          $defaults = array(
            'id' => $objective['id'],
            'score' => array(
              'scaled' => 0,
              'raw' => 0,
              'min' => 0,
              'max' => 0,
            ),
            'success_status' => '',
            'completion_status' => '',
            'progress_measure' => '',
            'description' => '',
          );
        }
        else {
          $defaults = array(
            'id' => $objective['id'],
            'score' => array(
              'raw' => 0,
              'min' => 0,
              'max' => 0,
            ),
            'status' => '',
          );
        }
        if (!empty($stored_objective)) {
          $stored_objective = (array) $stored_objective;
          $stored_objective += $defaults;
        }
        else {
          $stored_objective = $defaults;
        }
        $data['cmi.objectives'][] = $stored_objective;
      }
    }
  }
  return $data;
}

/**
 * Implements hook_opigno_scorm_ui_add_assets().
 */
function opigno_scorm_quiz_opigno_scorm_ui_add_assets() {
  $path = drupal_get_path('module', 'opigno_scorm_quiz');
  drupal_add_js("{$path}/js/opigno_scorm_quiz.js");
}

/**
 * Implements hook_opigno_scorm_ui_commit().
 */
function opigno_scorm_quiz_opigno_scorm_ui_commit($scorm, $sco_id, $data) {
  global $user;

  // Store objectives and results.
  if (!empty($data->cmi->objectives)) {
    for ($i = 0, $len = count($data->cmi->objectives); $i < $len; $i++) {
      opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, "cmi.objectives.{$i}", $data->cmi->objectives[$i]);
    }
  }
  if (!empty($data->scorm_version)) {
    switch ($data->scorm_version) {
      case '2004':

        // Store the score.
        if (!empty($data->cmi->score)) {
          foreach (array(
            'raw',
            'min',
            'max',
            'scaled',
          ) as $key) {
            if (isset($data->cmi->score->{$key})) {
              opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, "cmi.score.{$key}", $data->cmi->score->{$key});
            }
          }
        }

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

        // Store the score.
        if (!empty($data->cmi->core->score)) {
          foreach (array(
            'raw',
            'min',
            'max',
          ) as $key) {
            if (isset($data->cmi->core->score->{$key})) {
              opigno_scorm_scorm_cmi_set($user->uid, $scorm->id, "cmi.core.score.{$key}", $data->cmi->core->score->{$key});
            }
          }
        }
        break;
    }
  }
}

/**
 * Implements of hook_quiz_question_info().
 */
function opigno_scorm_quiz_quiz_question_info() {
  return array(
    'opigno_scorm_quiz_question' => array(
      'name' => t('SCORM Package'),
      'description' => t('Question using SCORM packages.'),
      'question provider' => 'OpignoScormQuizQuestion',
      'response provider' => 'OpignoScormQuizResponse',
      'module' => 'quiz_question',
    ),
  );
}

/**
 * Implements hook_config().
 *
 * Quiz Question triggers a Fatal Error if this function is not present.
 * This is a no op.
 */
function opigno_scorm_quiz_question_config() {

  // No op
}

/**
 * Implements hook_node_type_insert().
 */
function opigno_scorm_quiz_node_type_insert($info) {
  if ($info->type == 'opigno_scorm_quiz_question') {
    quiz_question_add_body_field('opigno_scorm_quiz_question');
    variable_set('node_options_opigno_scorm_quiz_question', array(
      'status',
    ));

    // Disable comments by default.
    if (module_exists('comment')) {
      variable_set('comment_opigno_scorm_quiz_question', COMMENT_NODE_CLOSED);
    }
    variable_set('node_submitted_opigno_scorm_quiz_question', 0);
    $field = field_info_field('opigno_scorm_package');
    if (empty($field)) {
      field_create_field(array(
        'active' => 1,
        'cardinality' => 1,
        'deleted' => 0,
        'entity_types' => array(),
        'field_name' => 'opigno_scorm_package',
        'foreign keys' => array(
          'fid' => array(
            'columns' => array(
              'fid' => 'fid',
            ),
            'table' => 'file_managed',
          ),
        ),
        'indexes' => array(
          'fid' => array(
            0 => 'fid',
          ),
        ),
        'locked' => 0,
        'module' => 'opigno_scorm_ui',
        'settings' => array(
          'display_default' => 0,
          'display_field' => 0,
          'uri_scheme' => 'public',
        ),
        'translatable' => 0,
        'type' => 'opigno_scorm_package',
      ));
    }
    $field = field_info_field('opigno_scorm_round_method');
    if (empty($field)) {
      field_create_field(array(
        'active' => 1,
        'cardinality' => 1,
        'deleted' => 0,
        'entity_types' => array(),
        'field_name' => 'opigno_scorm_round_method',
        'foreign keys' => array(),
        'indexes' => array(
          'value' => array(
            0 => 'value',
          ),
        ),
        'locked' => 0,
        'module' => 'list',
        'settings' => array(
          'allowed_values' => array(
            'ceil' => 'Round up',
            'round' => 'Round to closest',
            'floor' => 'Round down',
          ),
          'allowed_values_function' => '',
        ),
        'translatable' => 0,
        'type' => 'list_text',
      ));
    }
    $instance = field_info_instance('node', 'opigno_scorm_quiz_question', 'opigno_scorm_package');
    if (empty($instance)) {
      field_create_instance(array(
        'bundle' => 'opigno_scorm_quiz_question',
        'deleted' => 0,
        'description' => '',
        'display' => array(
          'default' => array(
            'label' => 'hidden',
            'module' => 'opigno_scorm_ui',
            'settings' => array(),
            'type' => 'opigno_scorm_player',
            'weight' => 0,
          ),
          'teaser' => array(
            'label' => 'hidden',
            'module' => 'opigno_scorm_ui',
            'settings' => array(),
            'type' => 'opigno_scorm_player',
            'weight' => 0,
          ),
        ),
        'entity_type' => 'node',
        'field_name' => 'opigno_scorm_package',
        'label' => 'SCORM',
        'required' => 1,
        'settings' => array(
          'description_field' => 0,
          'file_directory' => 'opigno_scorm',
          'file_extensions' => 'zip',
          'max_filesize' => '',
          'user_register_form' => FALSE,
        ),
        'widget' => array(
          'active' => 1,
          'module' => 'file',
          'settings' => array(
            'progress_indicator' => 'throbber',
          ),
          'type' => 'file_generic',
          'weight' => 32,
        ),
      ));
    }
    $instance = field_info_instance('node', 'opigno_scorm_quiz_question', 'opigno_scorm_round_method');
    if (empty($instance)) {
      field_create_instance(array(
        'bundle' => 'opigno_scorm_quiz_question',
        'default_value' => array(
          0 => array(
            'value' => 'round',
          ),
        ),
        'deleted' => 0,
        'description' => 'Some SCORM packages use a float point number for scoring, whereas we require an integer. Choose the appropriate method for rounding the final score.',
        'display' => array(
          'default' => array(
            'label' => 'above',
            'settings' => array(),
            'type' => 'hidden',
            'weight' => 2,
          ),
          'teaser' => array(
            'label' => 'above',
            'settings' => array(),
            'type' => 'hidden',
            'weight' => 0,
          ),
        ),
        'entity_type' => 'node',
        'field_name' => 'opigno_scorm_round_method',
        'label' => 'Round method',
        'required' => 1,
        'settings' => array(
          'user_register_form' => FALSE,
        ),
        'widget' => array(
          'active' => 1,
          'module' => 'options',
          'settings' => array(),
          'type' => 'options_buttons',
          'weight' => 33,
        ),
      ));
    }
  }
}

/**
 * Load all objective data for the given SCORM.
 *
 * Helper function to load objective CMI data that was stored. Pass the ID
 * of the objective to fetch the data for it.
 *
 * @param int $uid
 * @param int $scorm_id
 * @param string $objective_id
 *
 * @return object|null
 */
function opigno_scorm_quiz_load_objective($uid, $scorm_id, $objective_id) {
  $objectives =& drupal_static(__FUNCTION__);
  if (!isset($objectives)) {

    // We query the database ourselves here instead of relying on opigno_scorm_scorm_cmi_get(),
    // as we need a LIKE query.
    $result = db_select('opigno_scorm_scorm_cmi_data', 'o')
      ->fields('o')
      ->condition('o.uid', $uid)
      ->condition('o.scorm_id', $scorm_id)
      ->condition('o.cmi_key', 'cmi.objectives.%', 'LIKE')
      ->execute();
    while ($row = $result
      ->fetchObject()) {

      // Make sure this is one of ours.
      if (preg_match('/^cmi\\.objectives\\.[0-9]+$/', $row->cmi_key)) {
        $data = unserialize($row->value);

        // Allow modules to alter the data.
        $context = array(
          'uid' => $uid,
          'scorm_id' => $scorm_id,
          'original_value' => $data,
        );
        drupal_alter('opigno_scorm_scorm_cmi_get', $data, $row->cmi_key, $context);
        $objectives[$data->id] = $data;
      }
    }
  }
  return isset($objectives[$objective_id]) ? $objectives[$objective_id] : NULL;
}