diff --git a/src/transformer/events/core/group_deleted.php b/src/transformer/events/core/group_deleted.php new file mode 100644 index 000000000..69263443d --- /dev/null +++ b/src/transformer/events/core/group_deleted.php @@ -0,0 +1,65 @@ +. + +/** + * Transform for the group deleted event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\events\core; + +use src\transformer\utils as utils; + +/** + * Transformer for group deleted event. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @return array + */ +function group_deleted(array $config, \stdClass $event) { + $repo = $config['repo']; + $user = $repo->read_record_by_id('user', $event->userid); + $course = $repo->read_record_by_id('course', $event->courseid); + $lang = utils\get_course_lang($course); + $group = new \stdClass(); + $group->id = $event->objectid; + + return [[ + 'actor' => utils\get_user($config, $user), + 'verb' => [ + 'id' => 'http://activitystrea.ms/delete', + 'display' => [ + $lang => 'Deleted' + ], + ], + 'object' => utils\get_activity\course_group($config, $course, $group), + 'context' => [ + 'extensions' => utils\extensions\base($config, $event, null), + 'contextActivities' => [ + 'parent' => [ + utils\get_activity\course($config, $course), + ], + 'category' => [ + utils\get_activity\site($config), + ], + ], + ] + ]]; +} diff --git a/src/transformer/events/core/group_member_added.php b/src/transformer/events/core/group_member_added.php new file mode 100644 index 000000000..78f99efaf --- /dev/null +++ b/src/transformer/events/core/group_member_added.php @@ -0,0 +1,66 @@ +. + +/** + * Transform for the group member added event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\events\core; + +use src\transformer\utils as utils; + +/** + * Transform for the group member added event. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @return array + */ +function group_member_added(array $config, \stdClass $event) { + $repo = $config['repo']; + $user = $repo->read_record_by_id('user', $event->userid); + $member = $repo->read_record_by_id('user', $event->relateduserid); + $course = $repo->read_record_by_id('course', $event->courseid); + $lang = utils\get_course_lang($course); + $group = $repo->read_record_by_id($event->objecttable, $event->objectid); + + return [[ + 'actor' => utils\get_user($config, $member), + 'verb' => [ + 'id' => 'http://activitystrea.ms/join', + 'display' => [ + $lang => 'Joined' + ], + ], + 'object' => utils\get_activity\course_group($config, $course, $group), + 'context' => [ + 'instructor' => utils\get_user($config, $user), + 'extensions' => utils\extensions\base($config, $event, null), + 'contextActivities' => [ + 'parent' => [ + utils\get_activity\course($config, $course), + ], + 'category' => [ + utils\get_activity\site($config), + ], + ], + ] + ]]; +} diff --git a/src/transformer/events/core/group_member_removed.php b/src/transformer/events/core/group_member_removed.php new file mode 100644 index 000000000..e60381d8c --- /dev/null +++ b/src/transformer/events/core/group_member_removed.php @@ -0,0 +1,66 @@ +. + +/** + * Transform for the group member removed event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\events\core; + +use src\transformer\utils as utils; + +/** + * Transform for the group member removed event. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @return array + */ +function group_member_removed(array $config, \stdClass $event) { + $repo = $config['repo']; + $user = $repo->read_record_by_id('user', $event->userid); + $member = $repo->read_record_by_id('user', $event->relateduserid); + $course = $repo->read_record_by_id('course', $event->courseid); + $lang = utils\get_course_lang($course); + $group = $repo->read_record_by_id($event->objecttable, $event->objectid); + + return [[ + 'actor' => utils\get_user($config, $member), + 'verb' => [ + 'id' => 'http://activitystrea.ms/leave', + 'display' => [ + $lang => 'Left' + ], + ], + 'object' => utils\get_activity\course_group($config, $course, $group), + 'context' => [ + 'instructor' => utils\get_user($config, $user), + 'extensions' => utils\extensions\base($config, $event, null), + 'contextActivities' => [ + 'parent' => [ + utils\get_activity\course($config, $course), + ], + 'category' => [ + utils\get_activity\site($config), + ], + ], + ] + ]]; +} diff --git a/src/transformer/events/core/group_message_sent.php b/src/transformer/events/core/group_message_sent.php new file mode 100644 index 000000000..a5a7342bc --- /dev/null +++ b/src/transformer/events/core/group_message_sent.php @@ -0,0 +1,74 @@ +. + +/** + * Transformer fn for group message sent event. + * + * @package logstore_xapi + * @copyright Milt Reder + * + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\events\core; + +use src\transformer\utils as utils; + +/** + * Transformer fn for group message sent event. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @return array + */ + +function group_message_sent(array $config, \stdClass $event) { + $repo = $config['repo']; + $user = $repo->read_record_by_id('user', $event->userid); + $message = $repo->read_record_by_id('messages', $event->objectid); + $conversation = $repo->read_record_by_id( + 'message_conversations', + $message->conversationid + ); + $group = $repo->read_record_by_id('groups', $conversation->itemid); + $course = $repo->read_record_by_id('course', $group->courseid); + $lang = utils\get_course_lang($course); + + return [[ + 'actor' => utils\get_user($config, $user), + 'verb' => [ + 'id' => 'http://activitystrea.ms/send', + 'display' => [ + $lang => 'Sent' + ], + ], + 'object' => utils\get_activity\message($config, $lang, $message), + 'context' => [ + 'extensions' => utils\extensions\base($config, $event, null), + 'contextActivities' => [ + 'grouping' => [ + utils\get_activity\course_group($config, $course, $group) + ], + 'parent' => [ + utils\get_activity\course($config, $course), + ], + 'category' => [ + utils\get_activity\site($config), + ], + ], + ] + ]]; +} diff --git a/src/transformer/events/core/question_created.php b/src/transformer/events/core/question_created.php new file mode 100644 index 000000000..00e2e40fb --- /dev/null +++ b/src/transformer/events/core/question_created.php @@ -0,0 +1,74 @@ +. + +/** + * Transformer fn for question created event. + * + * @package logstore_xapi + * @copyright Milt Reder + * + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\events\core; + +use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as qdef; + +/** + * Transformer fn for question created event. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @return array + */ + +function question_created(array $config, \stdClass $event) { + $repo = $config['repo']; + $user = $repo->read_record_by_id('user', $event->userid); + $course = $repo->read_record_by_id('course', $event->courseid); + $question = $repo->read_record_by_id('question', $event->objectid); + $lang = utils\get_course_lang($course); + + $definition = qdef\get_definition($config, $question, $lang); + + $definition['extensions']['https://xapi.edlm/profiles/edlm-lms/concepts/activity-extensions/moodle-question-type'] = $question->qtype; + + return [[ + 'actor' => utils\get_user($config, $user), + 'verb' => [ + 'id' => 'http://activitystrea.ms/create', + 'display' => [ + $lang => 'Created' + ], + ], + 'object' => [ + 'id' => $config['app_url'] . '/question?id=' . $question->id, + 'definition' => $definition, + ], + 'context' => [ + 'extensions' => utils\extensions\base($config, $event, null), + 'contextActivities' => [ + 'parent' => [ + utils\get_activity\course($config, $course) + ], + 'category' => [ + utils\get_activity\site($config), + ], + ], + ] + ]]; +} diff --git a/src/transformer/events/debug/debug_event.php b/src/transformer/events/debug/debug_event.php index 098c0e973..8ff4e8bd9 100644 --- a/src/transformer/events/debug/debug_event.php +++ b/src/transformer/events/debug/debug_event.php @@ -38,7 +38,7 @@ function debug_event(array $config, \stdClass $event) { //debug $repo = $config['repo']; - if (isset($event->objecttable) && isset($event->objectid)) { + if (isset($event->objecttable) && isset($event->objectid) && $event->action !== 'deleted') { $event_object = $repo->read_record_by_id($event->objecttable, $event->objectid); } else { $event_object = array(); diff --git a/src/transformer/events/mod_quiz/question_answered/essay.php b/src/transformer/events/mod_quiz/question_answered/essay.php index 5ce97471f..5dc1773d3 100644 --- a/src/transformer/events/mod_quiz/question_answered/essay.php +++ b/src/transformer/events/mod_quiz/question_answered/essay.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (essay) answered event. @@ -58,13 +59,9 @@ function essay(array $config, \stdClass $event, \stdClass $questionattempt, \std ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext) - ], - 'interactionType' => 'long-fill-in', - ] + 'definition' => question\get_essay_definition( + $config, $question, $lang + ) ], 'result' => [ 'response' => $responsesummary, diff --git a/src/transformer/events/mod_quiz/question_answered/gapselect.php b/src/transformer/events/mod_quiz/question_answered/gapselect.php index 48da62aa1..8006f2c5d 100644 --- a/src/transformer/events/mod_quiz/question_answered/gapselect.php +++ b/src/transformer/events/mod_quiz/question_answered/gapselect.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (gapselect) answered event. @@ -57,7 +58,13 @@ function gapselect(array $config, \stdClass $event, \stdClass $questionattempt, ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => utils\get_multichoice_definition($config, $questionattempt, $question, $lang, 'sequencing'), + 'definition' => question\get_multichoice_definition( + $config, + $question, + $lang, + 'sequencing', + $questionattempt->rightanswer + ), ], 'result' => [ 'response' => implode ('[,]', $selections), diff --git a/src/transformer/events/mod_quiz/question_answered/match.php b/src/transformer/events/mod_quiz/question_answered/match.php index 0de71cd07..b231bea9d 100644 --- a/src/transformer/events/mod_quiz/question_answered/match.php +++ b/src/transformer/events/mod_quiz/question_answered/match.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (match) answered event. @@ -67,13 +68,7 @@ function ($reduction, $selection) { ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext) - ], - 'interactionType' => 'matching', - ] + 'definition' => question\get_match_definition($config, $question, $lang) ], 'result' => [ 'response' => $questionattempt->responsesummary, diff --git a/src/transformer/events/mod_quiz/question_answered/multichoice.php b/src/transformer/events/mod_quiz/question_answered/multichoice.php index 83b9900b6..d9e8a90ea 100644 --- a/src/transformer/events/mod_quiz/question_answered/multichoice.php +++ b/src/transformer/events/mod_quiz/question_answered/multichoice.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (multichoice) answered event. @@ -56,7 +57,13 @@ function multichoice(array $config, \stdClass $event, \stdClass $questionattempt ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => utils\get_multichoice_definition($config, $questionattempt, $question, $lang), + 'definition' => question\get_multichoice_definition( + $config, + $question, + $lang, + 'choice', + $questionattempt->rightanswer + ), ], 'result' => [ 'response' => implode ('[,]', $selections), diff --git a/src/transformer/events/mod_quiz/question_answered/numerical.php b/src/transformer/events/mod_quiz/question_answered/numerical.php index fd0248d45..338f794eb 100644 --- a/src/transformer/events/mod_quiz/question_answered/numerical.php +++ b/src/transformer/events/mod_quiz/question_answered/numerical.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (numerical) answered event. @@ -56,13 +57,7 @@ function numerical(array $config, \stdClass $event, \stdClass $questionattempt, ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext) - ], - 'interactionType' => 'numeric', - ] + 'definition' => question\get_numerical_definition($config, $question, $lang) ], 'result' => [ 'response' => $questionattempt->responsesummary, diff --git a/src/transformer/events/mod_quiz/question_answered/randomsamatch.php b/src/transformer/events/mod_quiz/question_answered/randomsamatch.php index a557b7876..a21951d60 100644 --- a/src/transformer/events/mod_quiz/question_answered/randomsamatch.php +++ b/src/transformer/events/mod_quiz/question_answered/randomsamatch.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (randomsamatch) answered event. @@ -67,13 +68,7 @@ function ($reduction, $selection) { ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext) - ], - 'interactionType' => 'matching', - ] + 'definition' => question\get_match_definition($config, $question, $lang) ], 'result' => [ 'response' => $questionattempt->responsesummary, diff --git a/src/transformer/events/mod_quiz/question_answered/shortanswer.php b/src/transformer/events/mod_quiz/question_answered/shortanswer.php index a02499b6c..9e9d4a879 100644 --- a/src/transformer/events/mod_quiz/question_answered/shortanswer.php +++ b/src/transformer/events/mod_quiz/question_answered/shortanswer.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (shortanswer) answered event. @@ -56,13 +57,7 @@ function shortanswer(array $config, \stdClass $event, \stdClass $questionattempt ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext) - ], - 'interactionType' => 'fill-in', - ] + 'definition' => question\get_shortanswer_definition($config, $question, $lang) ], 'result' => [ 'response' => $questionattempt->responsesummary, diff --git a/src/transformer/events/mod_quiz/question_answered/truefalse.php b/src/transformer/events/mod_quiz/question_answered/truefalse.php index edd3236ee..1fca5d529 100644 --- a/src/transformer/events/mod_quiz/question_answered/truefalse.php +++ b/src/transformer/events/mod_quiz/question_answered/truefalse.php @@ -27,6 +27,7 @@ namespace src\transformer\events\mod_quiz\question_answered; use src\transformer\utils as utils; +use src\transformer\utils\get_activity\definition\question as question; /** * Transformer for quiz question (truefalse) answered event. @@ -55,13 +56,7 @@ function truefalse(array $config, \stdClass $event, \stdClass $questionattempt, ], 'object' => [ 'id' => utils\get_quiz_question_id($config, $coursemodule->id, $question->id), - 'definition' => [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext), - ], - 'interactionType' => 'true-false', - ] + 'definition' => question\get_true_false_definition($config, $question, $lang) ], 'result' => [ 'response' => utils\get_string_html_removed($questionattempt->responsesummary), diff --git a/src/transformer/get_event_function_map.php b/src/transformer/get_event_function_map.php index 8b661d57a..db3b4d5e8 100644 --- a/src/transformer/get_event_function_map.php +++ b/src/transformer/get_event_function_map.php @@ -34,8 +34,8 @@ function get_event_function_map() { $availableevents = [ '\core\event\course_category_created' => 'core\course_category_created', - '\core\event\badge_awarded' => 'core\badge_awarded', //'debug\debug_event', - '\core\event\badge_revoked' => 'core\badge_revoked', //'debug\debug_event' + '\core\event\badge_awarded' => 'core\badge_awarded', + '\core\event\badge_revoked' => 'core\badge_revoked', '\core\event\course_created' => 'core\course_created', '\core\event\course_updated' => 'core\course_updated', '\core\event\calendar_event_created' => 'core\calendar_event_created', @@ -47,6 +47,10 @@ function get_event_function_map() { '\core\event\course_section_created' => 'core\course_section_created', '\core\event\course_resources_list_viewed' => 'core\course_resources_list_viewed', '\core\event\group_created' => 'core\group_created', + '\core\event\group_deleted' => 'core\group_deleted', + '\core\event\group_message_sent' => 'core\group_message_sent', + '\core\event\group_member_added' => 'core\group_member_added', + '\core\event\group_member_removed' => 'core\group_member_removed', '\core\event\user_created' => 'core\user_created', '\core\event\user_enrolment_created' => 'core\user_enrolment_created', '\core\event\user_loggedin' => 'core\user_loggedin', @@ -54,6 +58,7 @@ function get_event_function_map() { '\core\event\course_module_created' => 'core\course_module_created', '\core\event\course_module_completion_updated' => 'core\course_module_completion_updated', '\core\event\questions_imported' => 'core\questions_imported', + '\core\event\question_created' => 'core\question_created', '\mod_assign\event\assessable_submitted' => 'mod_assign\assignment_submitted', '\mod_assign\event\submission_graded' => 'mod_assign\assignment_graded', '\mod_bigbluebuttonbn\event\activity_viewed' => 'mod_bigbluebuttonbn\activity_viewed', diff --git a/src/transformer/utils/get_activity/course_group.php b/src/transformer/utils/get_activity/course_group.php index f9fb5f16e..2bab364ad 100644 --- a/src/transformer/utils/get_activity/course_group.php +++ b/src/transformer/utils/get_activity/course_group.php @@ -38,14 +38,20 @@ function course_group(array $config, \stdClass $course, \stdClass $group) { $coursename = $course->fullname ? $course->fullname : 'A Moodle course'; $courselang = utils\get_course_lang($course); - return [ + $activity = [ 'id' => $config['app_url'] . '/group/index.php?id=' . $group->id, 'objectType' => 'Activity', 'definition' => [ 'type' => 'https://xapi.edlm/profiles/edlm-lms/concepts/activity-types/group', - 'name' => [ - $courselang => $group->name, - ], ], ]; + + // moodle groups only have names when they aren't deleted + if (isset($group->name)) { + $activity['definition']['name'] = [ + $courselang => $group->name, + ]; + } + + return $activity; } diff --git a/src/transformer/utils/get_activity/definition/question.php b/src/transformer/utils/get_activity/definition/question.php new file mode 100644 index 000000000..005ade74e --- /dev/null +++ b/src/transformer/utils/get_activity/definition/question.php @@ -0,0 +1,237 @@ +. + +/** + * Transformer utilities for creating Question xAPI Activity object definitions. + * + * @package logstore_xapi + * @copyright Jerret Fowler + * Ryan Smith + * David Pesce + * Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\utils\get_activity\definition\question; + +use src\transformer\utils as utils; + +/** + * Helper for getting basic interaction activity def data. + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_def_base(array $config, \stdClass $question, string $lang) { + return [ + 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', + 'name' => [ + $lang => $question->name, + ], + 'description' => [ + $lang => utils\get_string_html_removed($question->questiontext), + ], + ]; +} + +/** + * Transformer util for creating essay definitions + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_essay_definition(array $config, \stdClass $question, string $lang) { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => 'long-fill-in', + ] + ); +} + +/** + * Transformer util for creating multichoice definitions. + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + * @param ?string $interactiontype The type of interaction. + * @param ?string $rightanswer The correct answer, not always available. + * @return array + */ +function get_multichoice_definition( + array $config, + \stdClass $question, + string $lang, + ?string $interactiontype = 'choice', + ?string $rightanswer = null +) { + if ($config['send_response_choices']) { + $repo = $config['repo']; + $answers = $repo->read_records('question_answers', [ + 'question' => $question->id + ]); + $choices = array_map(function ($answer) use ($lang) { + return [ + "id" => "$answer->id", + "description" => [ + $lang => utils\get_string_html_removed($answer->answer) + ] + ]; + }, $answers); + + $correctresponsepattern; + + if (!is_null($rightanswer)) { + switch ($interactiontype) { + case 'sequencing': + $selections = explode('} {', rtrim(ltrim($rightanswer, '{'), '}')); + $correctresponsepattern = implode ('[,]', $selections); + break; + default: + $selections = explode('; ', utils\get_string_html_removed($rightanswer)); + $correctresponsepattern = implode ('[,]', $selections); + break; + } + } + + $def = array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => $interactiontype, + 'correctResponsesPattern' => [$correctresponsepattern], + // Need to pull out id's that are appended during array_map so json parses it correctly as an array. + 'choices' => array_values($choices) + ] + ); + + if (!is_null($correctresponsepattern)) { + $def['correctResponsesPattern'] = [$correctresponsepattern]; + } + + return $def; + } else { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => $interactiontype + ] + ); + } + + +} + +/** + * Transformer util for creating match definitions + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_match_definition(array $config, \stdClass $question, string $lang) { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => 'matching', + ] + ); +} + +/** + * Transformer util for creating numerical definitions + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_numerical_definition(array $config, \stdClass $question, string $lang) { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => 'numeric', + ] + ); +} + +/** + * Transformer util for creating shortanswer definitions + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_shortanswer_definition(array $config, \stdClass $question, string $lang) { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => 'fill-in', + ] + ); +} + +/** + * Transformer util for creating true/false definitions + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question object. + * @param string $lang The language. + */ +function get_true_false_definition(array $config, \stdClass $question, string $lang) { + return array_merge( + get_def_base($config, $question, $lang), + [ + 'interactionType' => 'true-false', + ] + ); +} + +/** + * Generic handler for question definitions. + * + * @param array $config The transformer config settings. + * @param \stdClass $question The question. + * @param string $lang The language to use. + * @return array + */ +function get_definition(array $config, \stdClass $question, string $lang) { + switch ($question->qtype) { + case 'essay': + return get_essay_definition($config, $question, $lang); + case 'gapselect': + return get_multichoice_definition( + $config, $question, $lang, 'sequencing' + ); + case 'truefalse': + return get_true_false_definition($config, $question, $lang); + case 'randomsamatch': + case 'match': + return get_match_definition($config, $question, $lang); + case 'shortanswer': + return get_shortanswer_definition($config, $question, $lang); + case 'multichoice': + case 'multichoiceset': + return get_multichoice_definition( + $config, $question, $lang, 'choice' + ); + case 'numerical': + return get_numerical_definition($config, $question, $lang); + default: + return []; + } +} diff --git a/src/transformer/utils/get_activity/message.php b/src/transformer/utils/get_activity/message.php new file mode 100644 index 000000000..5c2640eee --- /dev/null +++ b/src/transformer/utils/get_activity/message.php @@ -0,0 +1,51 @@ +. + +/** + * Transformer utility for retrieving message activities. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\utils\get_activity; + +use src\transformer\utils as utils; + +/** + * Transformer utility for retrieving message activities. + * + * @param array $config The transformer config settings. + * @param string $lang The language tag to use. + * @param \stdClass $message The message. + * @return array + */ +function message(array $config, string $lang, \stdClass $message) { + return [ + 'id' => $config['app_url'] . '/message?id=' . $message->id, + 'objectType' => 'Activity', + 'definition' => [ + 'type' => 'http://id.tincanapi.com/activitytype/chat-message', + 'name' => [ + $lang => $message->subject ?? '[Untitled Message]', + ], + 'description' => [ + $lang => $message->fullmessage, + ], + ] + ]; +} diff --git a/src/transformer/utils/get_multichoice_definition.php b/src/transformer/utils/get_multichoice_definition.php deleted file mode 100644 index 671f857bd..000000000 --- a/src/transformer/utils/get_multichoice_definition.php +++ /dev/null @@ -1,87 +0,0 @@ -. - -/** - * Transformer utility for retrieving the multichoice definition. - * - * @package logstore_xapi - * @copyright Jerret Fowler - * Ryan Smith - * David Pesce - * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace src\transformer\utils; -use src\transformer\utils as utils; - -/** - * Transformer for course module viewed event. - * - * @param array $config The transformer config settings. - * @param \stdClass $questionattempt The questionattempt object. - * @param \stdClass $question The question object. - * @param string $lang The language. - * @param string $interactiontype The type of interaction. - * @return array - */ -function get_multichoice_definition(array $config, \stdClass $questionattempt, -\stdClass $question, string $lang, string $interactiontype = 'choice') { - if ($config['send_response_choices']) { - $repo = $config['repo']; - $answers = $repo->read_records('question_answers', [ - 'question' => $questionattempt->questionid - ]); - $choices = array_map(function ($answer) use ($lang) { - return [ - "id" => "$answer->id", - "description" => [ - $lang => utils\get_string_html_removed($answer->answer) - ] - ]; - }, $answers); - - $correctresponsepattern; - switch ($interactiontype) { - case 'sequencing': - $selections = explode('} {', rtrim(ltrim($questionattempt->rightanswer, '{'), '}')); - $correctresponsepattern = implode ('[,]', $selections); - break; - default: - $selections = explode('; ', utils\get_string_html_removed($questionattempt->rightanswer)); - $correctresponsepattern = implode ('[,]', $selections); - break; - } - - return [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext), - ], - 'interactionType' => $interactiontype, - 'correctResponsesPattern' => [$correctresponsepattern], - // Need to pull out id's that are appended during array_map so json parses it correctly as an array. - 'choices' => array_values($choices) - ]; - } - - return [ - 'type' => 'http://adlnet.gov/expapi/activities/cmi.interaction', - 'name' => [ - $lang => utils\get_string_html_removed($question->questiontext), - ], - 'interactionType' => $interactiontype - ]; -} diff --git a/src/transformer/utils/get_scaled_score.php b/src/transformer/utils/get_scaled_score.php index 4b279c2a5..835717f53 100644 --- a/src/transformer/utils/get_scaled_score.php +++ b/src/transformer/utils/get_scaled_score.php @@ -21,6 +21,7 @@ * @copyright Jerret Fowler * Ryan Smith * David Pesce + * Milt Reder * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,9 +36,5 @@ * @return int */ function get_scaled_score($rawscore, $minscore, $maxscore) { - if ($rawscore >= 0) { - return $rawscore / $maxscore; - } else { - return $rawscore / $minscore; - } + return (($rawscore - $minscore) / ($maxscore - $minscore) * 2) - 1; } diff --git a/tests/core/group_created/creating_new_group/data.json b/tests/core/group_created/creating_new_group/data.json index e6b422e2b..5de89bbb8 100644 --- a/tests/core/group_created/creating_new_group/data.json +++ b/tests/core/group_created/creating_new_group/data.json @@ -1,18 +1,4 @@ { - "course": [ - { - "id": 1, - "fullname": "test_name", - "lang": "en" - } - ], - "user": [ - { - "id": 1, - "firstname": "test_fullname", - "email": "test@test.com" - } - ], "groups": [ { "id": 1, diff --git a/tests/core/group_deleted/existing_group_deleted/data.json b/tests/core/group_deleted/existing_group_deleted/data.json new file mode 100644 index 000000000..d0ad6768b --- /dev/null +++ b/tests/core/group_deleted/existing_group_deleted/data.json @@ -0,0 +1,3 @@ +{ + "groups": [] +} diff --git a/tests/core/group_deleted/existing_group_deleted/event.json b/tests/core/group_deleted/existing_group_deleted/event.json new file mode 100644 index 000000000..e1e7e3378 --- /dev/null +++ b/tests/core/group_deleted/existing_group_deleted/event.json @@ -0,0 +1,9 @@ +{ + "courseid": 1, + "eventname": "\\core\\event\\group_deleted", + "id": 1, + "objectid": 1, + "objecttable": "groups", + "timecreated": 1433946701, + "userid": 1 +} diff --git a/tests/core/group_deleted/existing_group_deleted/existing_group_deleted_test.php b/tests/core/group_deleted/existing_group_deleted/existing_group_deleted_test.php new file mode 100644 index 000000000..0ea98ed99 --- /dev/null +++ b/tests/core/group_deleted/existing_group_deleted/existing_group_deleted_test.php @@ -0,0 +1,70 @@ +. + +namespace logstore_xapi\core\group_deleted\existing_group_deleted_test; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test group_deleted event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class existing_group_deleted_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve the plugin type being tested. + * + * @return string + */ + protected function get_plugin_type() { + return "core"; + } + + /** + * Retrieve the plugin name being tested. + * + * @return string + */ + protected function get_plugin_name() { + return "course"; + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::attempt_submitted + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/group_deleted/existing_group_deleted/statements.json b/tests/core/group_deleted/existing_group_deleted/statements.json new file mode 100644 index 000000000..2964ce2a1 --- /dev/null +++ b/tests/core/group_deleted/existing_group_deleted/statements.json @@ -0,0 +1,58 @@ +[ + { + "actor": { + "account": { + "homePage": "http://www.example.org", + "name": "1" + }, + "name": "test_fullname" + }, + "verb": { + "id": "http://activitystrea.ms/delete", + "display": { + "en": "Deleted" + } + }, + "object": { + "id": "http://www.example.org/group/index.php?id=1", + "objectType": "Activity", + "definition": { + "type": "https://xapi.edlm/profiles/edlm-lms/concepts/activity-types/group" + } + }, + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://www.example.org/course/view.php?id=1", + "definition": { + "type": "https://w3id.org/xapi/cmi5/activitytype/course", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http://www.example.org", + "definition": { + "type": "http://id.tincanapi.com/activitytype/lms", + "name": { + "en": "test_name" + } + } + } + ] + }, + "extensions": { + "http://lrs.learninglocker.net/define/extensions/info": { + "event_function": "\\src\\transformer\\events\\core\\group_deleted", + "event_name": "\\core\\event\\group_deleted", + "http://moodle.org": "1.0.0", + "https://github.com/xAPI-vle/moodle-logstore_xapi": "0.0.0-development" + } + } + } + } +] diff --git a/tests/core/group_member_added/new_group_member_added/data.json b/tests/core/group_member_added/new_group_member_added/data.json new file mode 100644 index 000000000..a58cca882 --- /dev/null +++ b/tests/core/group_member_added/new_group_member_added/data.json @@ -0,0 +1,20 @@ +{ + "user": [ + { + "id": 1, + "firstname": "test_fullname1", + "email": "test1@test.com" + }, + { + "id": 2, + "firstname": "test_fullname2", + "email": "test2@test.com" + } + ], + "groups": [ + { + "id": 1, + "name": "test_name" + } + ] +} diff --git a/tests/core/group_member_added/new_group_member_added/event.json b/tests/core/group_member_added/new_group_member_added/event.json new file mode 100644 index 000000000..b0d97e497 --- /dev/null +++ b/tests/core/group_member_added/new_group_member_added/event.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "objecttable": "groups", + "timecreated": 1433946701, + "objectid": 1, + "courseid": 1, + "eventname": "\\core\\event\\group_member_added", + "userid": 1, + "relateduserid": 2 +} diff --git a/tests/core/group_member_added/new_group_member_added/new_group_member_added_test.php b/tests/core/group_member_added/new_group_member_added/new_group_member_added_test.php new file mode 100644 index 000000000..3ab1a44fb --- /dev/null +++ b/tests/core/group_member_added/new_group_member_added/new_group_member_added_test.php @@ -0,0 +1,70 @@ +. + +namespace logstore_xapi\core\group_member_added\new_group_member_added_test; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test for group member added event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class new_group_member_added_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve the plugin type being tested. + * + * @return string + */ + protected function get_plugin_type() { + return "core"; + } + + /** + * Retrieve the plugin name being tested. + * + * @return string + */ + protected function get_plugin_name() { + return "course"; + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::attempt_submitted + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/group_member_added/new_group_member_added/statements.json b/tests/core/group_member_added/new_group_member_added/statements.json new file mode 100644 index 000000000..3ab0f906f --- /dev/null +++ b/tests/core/group_member_added/new_group_member_added/statements.json @@ -0,0 +1,68 @@ +[ + { + "actor": { + "account": { + "homePage": "http://www.example.org", + "name": "2" + }, + "name": "test_fullname2" + }, + "verb": { + "id": "http://activitystrea.ms/join", + "display": { + "en": "Joined" + } + }, + "object": { + "id": "http://www.example.org/group/index.php?id=1", + "objectType": "Activity", + "definition": { + "type": "https://xapi.edlm/profiles/edlm-lms/concepts/activity-types/group", + "name": { + "en": "test_name" + } + } + }, + "context": { + "instructor": { + "account": { + "homePage": "http://www.example.org", + "name": "1" + }, + "name": "test_fullname1" + }, + "contextActivities": { + "parent": [ + { + "id": "http://www.example.org/course/view.php?id=1", + "definition": { + "type": "https://w3id.org/xapi/cmi5/activitytype/course", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http://www.example.org", + "definition": { + "type": "http://id.tincanapi.com/activitytype/lms", + "name": { + "en": "test_name" + } + } + } + ] + }, + "extensions": { + "http://lrs.learninglocker.net/define/extensions/info": { + "http://moodle.org": "1.0.0", + "https://github.com/xAPI-vle/moodle-logstore_xapi": "0.0.0-development", + "event_name": "\\core\\event\\group_member_added", + "event_function": "\\src\\transformer\\events\\core\\group_member_added" + } + } + } + } +] diff --git a/tests/core/group_member_removed/existing_group_member_removed/data.json b/tests/core/group_member_removed/existing_group_member_removed/data.json new file mode 100644 index 000000000..a58cca882 --- /dev/null +++ b/tests/core/group_member_removed/existing_group_member_removed/data.json @@ -0,0 +1,20 @@ +{ + "user": [ + { + "id": 1, + "firstname": "test_fullname1", + "email": "test1@test.com" + }, + { + "id": 2, + "firstname": "test_fullname2", + "email": "test2@test.com" + } + ], + "groups": [ + { + "id": 1, + "name": "test_name" + } + ] +} diff --git a/tests/core/group_member_removed/existing_group_member_removed/event.json b/tests/core/group_member_removed/existing_group_member_removed/event.json new file mode 100644 index 000000000..4ac35312c --- /dev/null +++ b/tests/core/group_member_removed/existing_group_member_removed/event.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "objecttable": "groups", + "timecreated": 1433946701, + "objectid": 1, + "courseid": 1, + "eventname": "\\core\\event\\group_member_removed", + "userid": 1, + "relateduserid": 2 +} diff --git a/tests/core/group_member_removed/existing_group_member_removed/existing_group_member_removed_test.php b/tests/core/group_member_removed/existing_group_member_removed/existing_group_member_removed_test.php new file mode 100644 index 000000000..942464ab3 --- /dev/null +++ b/tests/core/group_member_removed/existing_group_member_removed/existing_group_member_removed_test.php @@ -0,0 +1,70 @@ +. + +namespace logstore_xapi\core\group_member_removed\existing_group_member_removed_test; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test for group member removed event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class existing_group_member_removed_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve the plugin type being tested. + * + * @return string + */ + protected function get_plugin_type() { + return "core"; + } + + /** + * Retrieve the plugin name being tested. + * + * @return string + */ + protected function get_plugin_name() { + return "course"; + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::attempt_submitted + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/group_member_removed/existing_group_member_removed/statements.json b/tests/core/group_member_removed/existing_group_member_removed/statements.json new file mode 100644 index 000000000..ae714fdcc --- /dev/null +++ b/tests/core/group_member_removed/existing_group_member_removed/statements.json @@ -0,0 +1,68 @@ +[ + { + "actor": { + "account": { + "homePage": "http://www.example.org", + "name": "2" + }, + "name": "test_fullname2" + }, + "verb": { + "id": "http://activitystrea.ms/leave", + "display": { + "en": "Left" + } + }, + "object": { + "id": "http://www.example.org/group/index.php?id=1", + "objectType": "Activity", + "definition": { + "type": "https://xapi.edlm/profiles/edlm-lms/concepts/activity-types/group", + "name": { + "en": "test_name" + } + } + }, + "context": { + "instructor": { + "account": { + "homePage": "http://www.example.org", + "name": "1" + }, + "name": "test_fullname1" + }, + "contextActivities": { + "parent": [ + { + "id": "http://www.example.org/course/view.php?id=1", + "definition": { + "type": "https://w3id.org/xapi/cmi5/activitytype/course", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http://www.example.org", + "definition": { + "type": "http://id.tincanapi.com/activitytype/lms", + "name": { + "en": "test_name" + } + } + } + ] + }, + "extensions": { + "http://lrs.learninglocker.net/define/extensions/info": { + "http://moodle.org": "1.0.0", + "https://github.com/xAPI-vle/moodle-logstore_xapi": "0.0.0-development", + "event_name": "\\core\\event\\group_member_removed", + "event_function": "\\src\\transformer\\events\\core\\group_member_removed" + } + } + } + } +] diff --git a/tests/core/group_message_sent/new_group_message_sent/data.json b/tests/core/group_message_sent/new_group_message_sent/data.json new file mode 100644 index 000000000..7c8d49e43 --- /dev/null +++ b/tests/core/group_message_sent/new_group_message_sent/data.json @@ -0,0 +1,23 @@ +{ + "groups": [ + { + "id": 1, + "name": "test_name", + "courseid": 1 + } + ], + "messages": [ + { + "id": 1, + "subject": "test_message_subject", + "fullmessage": "test_message_body", + "conversationid": 1 + } + ], + "message_conversations": [ + { + "id": 1, + "itemid": 1 + } + ] +} diff --git a/tests/core/group_message_sent/new_group_message_sent/event.json b/tests/core/group_message_sent/new_group_message_sent/event.json new file mode 100644 index 000000000..d73534937 --- /dev/null +++ b/tests/core/group_message_sent/new_group_message_sent/event.json @@ -0,0 +1,9 @@ +{ + "courseid": 1, + "eventname": "\\core\\event\\group_message_sent", + "id": 1, + "objectid": 1, + "objecttable": "messages", + "timecreated": 1433946701, + "userid": 1 +} diff --git a/tests/core/group_message_sent/new_group_message_sent/new_group_message_sent_test.php b/tests/core/group_message_sent/new_group_message_sent/new_group_message_sent_test.php new file mode 100644 index 000000000..8f9f0ed46 --- /dev/null +++ b/tests/core/group_message_sent/new_group_message_sent/new_group_message_sent_test.php @@ -0,0 +1,70 @@ +. + +namespace logstore_xapi\core\group_message_sent\new_group_message_sent; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test for group_message_sent event. + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class new_group_message_sent_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve the plugin type being tested. + * + * @return string + */ + protected function get_plugin_type() { + return "core"; + } + + /** + * Retrieve the plugin name being tested. + * + * @return string + */ + protected function get_plugin_name() { + return "course"; + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::attempt_submitted + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/group_message_sent/new_group_message_sent/statements.json b/tests/core/group_message_sent/new_group_message_sent/statements.json new file mode 100644 index 000000000..b913c4494 --- /dev/null +++ b/tests/core/group_message_sent/new_group_message_sent/statements.json @@ -0,0 +1,76 @@ +[ + { + "actor": { + "account": { + "homePage": "http://www.example.org", + "name": "1" + }, + "name": "test_fullname" + }, + "verb": { + "display": { + "en": "Sent" + }, + "id": "http://activitystrea.ms/send" + }, + "object": { + "id": "http://www.example.org/message?id=1", + "objectType": "Activity", + "definition": { + "name": { + "en": "test_message_subject" + }, + "description": { + "en": "test_message_body" + }, + "type": "http://id.tincanapi.com/activitytype/chat-message" + } + }, + "context": { + "contextActivities": { + "grouping": [ + { + "id": "http://www.example.org/group/index.php?id=1", + "objectType": "Activity", + "definition": { + "type": "https://xapi.edlm/profiles/edlm-lms/concepts/activity-types/group", + "name": { + "en": "test_name" + } + } + } + ], + "parent": [ + { + "id": "http://www.example.org/course/view.php?id=1", + "definition": { + "type": "https://w3id.org/xapi/cmi5/activitytype/course", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http://www.example.org", + "definition": { + "type": "http://id.tincanapi.com/activitytype/lms", + "name": { + "en": "test_name" + } + } + } + ] + }, + "extensions": { + "http://lrs.learninglocker.net/define/extensions/info": { + "event_function": "\\src\\transformer\\events\\core\\group_message_sent", + "event_name": "\\core\\event\\group_message_sent", + "http://moodle.org": "1.0.0", + "https://github.com/xAPI-vle/moodle-logstore_xapi": "0.0.0-development" + } + } + } + } +] diff --git a/tests/core/question_created/new_question_created/data.json b/tests/core/question_created/new_question_created/data.json new file mode 100644 index 000000000..170132afa --- /dev/null +++ b/tests/core/question_created/new_question_created/data.json @@ -0,0 +1,10 @@ +{ + "question": [ + { + "id": 1, + "qtype": "truefalse", + "name": "True or False?", + "questiontext": "

Is the sky blue?

" + } + ] +} diff --git a/tests/core/question_created/new_question_created/event.json b/tests/core/question_created/new_question_created/event.json new file mode 100644 index 000000000..e16203a9e --- /dev/null +++ b/tests/core/question_created/new_question_created/event.json @@ -0,0 +1,9 @@ +{ + "courseid": 1, + "eventname": "\\core\\event\\question_created", + "id": 1, + "objectid": 1, + "objecttable": "question", + "timecreated": 1433946701, + "userid": 1 +} diff --git a/tests/core/question_created/new_question_created/new_question_created_test.php b/tests/core/question_created/new_question_created/new_question_created_test.php new file mode 100644 index 000000000..4bd39c2f5 --- /dev/null +++ b/tests/core/question_created/new_question_created/new_question_created_test.php @@ -0,0 +1,70 @@ +. + +namespace logstore_xapi\core\question_created\new_question_created_test; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test for question_created event + * + * @package logstore_xapi + * @copyright Milt Reder + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class new_question_created_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve the plugin type being tested. + * + * @return string + */ + protected function get_plugin_type() { + return "core"; + } + + /** + * Retrieve the plugin name being tested. + * + * @return string + */ + protected function get_plugin_name() { + return "core"; + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::attempt_submitted + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/question_created/new_question_created/statements.json b/tests/core/question_created/new_question_created/statements.json new file mode 100644 index 000000000..8f57a393a --- /dev/null +++ b/tests/core/question_created/new_question_created/statements.json @@ -0,0 +1,67 @@ +[ + { + "actor": { + "name": "test_fullname", + "account": { + "homePage": "http://www.example.org", + "name": "1" + } + }, + "verb": { + "display": { + "en": "Created" + }, + "id": "http://activitystrea.ms/create" + }, + "object": { + "id": "http://www.example.org/question?id=1", + "definition": { + "name": { + "en": "True or False?" + }, + "description": { + "en": "Is the sky blue?" + }, + "type": "http://adlnet.gov/expapi/activities/cmi.interaction", + "interactionType": "true-false", + "extensions": { + "https://xapi.edlm/profiles/edlm-lms/concepts/activity-extensions/moodle-question-type": "truefalse" + } + } + }, + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://www.example.org/course/view.php?id=1", + "definition": { + "type": "https://w3id.org/xapi/cmi5/activitytype/course", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http://www.example.org", + "definition": { + "type": "http://id.tincanapi.com/activitytype/lms", + "name": { + "en": "test_name" + } + } + } + ] + }, + "extensions": { + "http://lrs.learninglocker.net/define/extensions/info": { + "event_function": "\\src\\transformer\\events\\core\\question_created", + "event_name": "\\core\\event\\question_created", + "http://moodle.org": "1.0.0", + "https://github.com/xAPI-vle/moodle-logstore_xapi": "0.0.0-development" + } + } + } + } +] diff --git a/tests/mod_quiz/attempt_submitted/essay/data.json b/tests/mod_quiz/attempt_submitted/essay/data.json index e11b39952..2ace8c900 100644 --- a/tests/mod_quiz/attempt_submitted/essay/data.json +++ b/tests/mod_quiz/attempt_submitted/essay/data.json @@ -49,6 +49,7 @@ { "id": 1, "qtype": "essay", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/essay/statements.json b/tests/mod_quiz/attempt_submitted/essay/statements.json index 6ea2648ca..210a0dc06 100644 --- a/tests/mod_quiz/attempt_submitted/essay/statements.json +++ b/tests/mod_quiz/attempt_submitted/essay/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "long-fill-in" diff --git a/tests/mod_quiz/attempt_submitted/essay_null_response/data.json b/tests/mod_quiz/attempt_submitted/essay_null_response/data.json index 9901dd72c..73ea53c4f 100644 --- a/tests/mod_quiz/attempt_submitted/essay_null_response/data.json +++ b/tests/mod_quiz/attempt_submitted/essay_null_response/data.json @@ -49,6 +49,7 @@ { "id": 1, "qtype": "essay", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/essay_null_response/statements.json b/tests/mod_quiz/attempt_submitted/essay_null_response/statements.json index cfc37195f..9c7fd0a1e 100644 --- a/tests/mod_quiz/attempt_submitted/essay_null_response/statements.json +++ b/tests/mod_quiz/attempt_submitted/essay_null_response/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "long-fill-in" diff --git a/tests/mod_quiz/attempt_submitted/gapselect/data.json b/tests/mod_quiz/attempt_submitted/gapselect/data.json index 2214fbb76..24ce66d32 100644 --- a/tests/mod_quiz/attempt_submitted/gapselect/data.json +++ b/tests/mod_quiz/attempt_submitted/gapselect/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "gapselect", + "name": "test_name", "questiontext": "

Example [[1]] missing [[2]] words [[3]]

" } ], diff --git a/tests/mod_quiz/attempt_submitted/gapselect/statements.json b/tests/mod_quiz/attempt_submitted/gapselect/statements.json index 39191467a..dc799cc41 100644 --- a/tests/mod_quiz/attempt_submitted/gapselect/statements.json +++ b/tests/mod_quiz/attempt_submitted/gapselect/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "Example [[1]] missing [[2]] words [[3]]" }, "interactionType": "sequencing" diff --git a/tests/mod_quiz/attempt_submitted/match/data.json b/tests/mod_quiz/attempt_submitted/match/data.json index 158229b72..e75a6ce16 100644 --- a/tests/mod_quiz/attempt_submitted/match/data.json +++ b/tests/mod_quiz/attempt_submitted/match/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "match", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/match/statements.json b/tests/mod_quiz/attempt_submitted/match/statements.json index da00b4e5d..29044727e 100644 --- a/tests/mod_quiz/attempt_submitted/match/statements.json +++ b/tests/mod_quiz/attempt_submitted/match/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "matching" diff --git a/tests/mod_quiz/attempt_submitted/multichoice/data.json b/tests/mod_quiz/attempt_submitted/multichoice/data.json index 2095ee4b7..26f52b325 100644 --- a/tests/mod_quiz/attempt_submitted/multichoice/data.json +++ b/tests/mod_quiz/attempt_submitted/multichoice/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "multichoice", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/multichoice/statements.json b/tests/mod_quiz/attempt_submitted/multichoice/statements.json index 432e882b6..8e801224e 100644 --- a/tests/mod_quiz/attempt_submitted/multichoice/statements.json +++ b/tests/mod_quiz/attempt_submitted/multichoice/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "choice" diff --git a/tests/mod_quiz/attempt_submitted/multichoice_withchoices/data.json b/tests/mod_quiz/attempt_submitted/multichoice_withchoices/data.json index db6b38782..d6edf04cd 100644 --- a/tests/mod_quiz/attempt_submitted/multichoice_withchoices/data.json +++ b/tests/mod_quiz/attempt_submitted/multichoice_withchoices/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "multichoice", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/multichoice_withchoices/statements.json b/tests/mod_quiz/attempt_submitted/multichoice_withchoices/statements.json index 4c1a38be6..e7f80b696 100644 --- a/tests/mod_quiz/attempt_submitted/multichoice_withchoices/statements.json +++ b/tests/mod_quiz/attempt_submitted/multichoice_withchoices/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "choice", diff --git a/tests/mod_quiz/attempt_submitted/multichoiceset/data.json b/tests/mod_quiz/attempt_submitted/multichoiceset/data.json index bb2300cc5..0fc560517 100644 --- a/tests/mod_quiz/attempt_submitted/multichoiceset/data.json +++ b/tests/mod_quiz/attempt_submitted/multichoiceset/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "multichoiceset", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/multichoiceset/statements.json b/tests/mod_quiz/attempt_submitted/multichoiceset/statements.json index 4eb088886..5ea3c7c4f 100644 --- a/tests/mod_quiz/attempt_submitted/multichoiceset/statements.json +++ b/tests/mod_quiz/attempt_submitted/multichoiceset/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "choice" diff --git a/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/data.json b/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/data.json index bb2300cc5..0fc560517 100644 --- a/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/data.json +++ b/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "multichoiceset", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/statements.json b/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/statements.json index adb9a5277..ace45bcb9 100644 --- a/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/statements.json +++ b/tests/mod_quiz/attempt_submitted/multichoiceset_withchoices/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "choice", diff --git a/tests/mod_quiz/attempt_submitted/no_questions/statements.json b/tests/mod_quiz/attempt_submitted/no_questions/statements.json index 49b90b123..f913ed1c6 100644 --- a/tests/mod_quiz/attempt_submitted/no_questions/statements.json +++ b/tests/mod_quiz/attempt_submitted/no_questions/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, diff --git a/tests/mod_quiz/attempt_submitted/numerical/data.json b/tests/mod_quiz/attempt_submitted/numerical/data.json index 29e6097d4..354d469aa 100644 --- a/tests/mod_quiz/attempt_submitted/numerical/data.json +++ b/tests/mod_quiz/attempt_submitted/numerical/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "numerical", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/numerical/statements.json b/tests/mod_quiz/attempt_submitted/numerical/statements.json index f97e330da..b171e5059 100644 --- a/tests/mod_quiz/attempt_submitted/numerical/statements.json +++ b/tests/mod_quiz/attempt_submitted/numerical/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "numeric" diff --git a/tests/mod_quiz/attempt_submitted/randomsamatch/data.json b/tests/mod_quiz/attempt_submitted/randomsamatch/data.json index 25bb26415..fcf45eecf 100644 --- a/tests/mod_quiz/attempt_submitted/randomsamatch/data.json +++ b/tests/mod_quiz/attempt_submitted/randomsamatch/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "randomsamatch", + "name": "test_name", "questiontext": "

Example Random short-answer matching question

" } ], diff --git a/tests/mod_quiz/attempt_submitted/randomsamatch/statements.json b/tests/mod_quiz/attempt_submitted/randomsamatch/statements.json index 698e0d1e8..88454309f 100644 --- a/tests/mod_quiz/attempt_submitted/randomsamatch/statements.json +++ b/tests/mod_quiz/attempt_submitted/randomsamatch/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "Example Random short-answer matching question" }, "interactionType": "matching" diff --git a/tests/mod_quiz/attempt_submitted/shortanswer/data.json b/tests/mod_quiz/attempt_submitted/shortanswer/data.json index 18a603450..61e655fc0 100644 --- a/tests/mod_quiz/attempt_submitted/shortanswer/data.json +++ b/tests/mod_quiz/attempt_submitted/shortanswer/data.json @@ -49,6 +49,7 @@ { "id": 1, "qtype": "shortanswer", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/shortanswer/statements.json b/tests/mod_quiz/attempt_submitted/shortanswer/statements.json index 190c0ed04..f3589b05a 100644 --- a/tests/mod_quiz/attempt_submitted/shortanswer/statements.json +++ b/tests/mod_quiz/attempt_submitted/shortanswer/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "fill-in" diff --git a/tests/mod_quiz/attempt_submitted/truefalse/data.json b/tests/mod_quiz/attempt_submitted/truefalse/data.json index 1127a5efc..16dbf9981 100644 --- a/tests/mod_quiz/attempt_submitted/truefalse/data.json +++ b/tests/mod_quiz/attempt_submitted/truefalse/data.json @@ -50,6 +50,7 @@ { "id": 1, "qtype": "truefalse", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/truefalse/statements.json b/tests/mod_quiz/attempt_submitted/truefalse/statements.json index 138aeca59..3b2b0e42f 100644 --- a/tests/mod_quiz/attempt_submitted/truefalse/statements.json +++ b/tests/mod_quiz/attempt_submitted/truefalse/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true, @@ -109,6 +109,9 @@ "definition": { "type": "http://adlnet.gov/expapi/activities/cmi.interaction", "name": { + "en": "test_name" + }, + "description": { "en": "test_question" }, "interactionType": "true-false" diff --git a/tests/mod_quiz/attempt_submitted/unknown_qtype/data.json b/tests/mod_quiz/attempt_submitted/unknown_qtype/data.json index ab066f907..4fc1c6fe5 100644 --- a/tests/mod_quiz/attempt_submitted/unknown_qtype/data.json +++ b/tests/mod_quiz/attempt_submitted/unknown_qtype/data.json @@ -49,6 +49,7 @@ { "id": 1, "qtype": "unknown", + "name": "test_name", "questiontext": "test_question" } ], diff --git a/tests/mod_quiz/attempt_submitted/unknown_qtype/statements.json b/tests/mod_quiz/attempt_submitted/unknown_qtype/statements.json index 49b90b123..f913ed1c6 100644 --- a/tests/mod_quiz/attempt_submitted/unknown_qtype/statements.json +++ b/tests/mod_quiz/attempt_submitted/unknown_qtype/statements.json @@ -27,7 +27,7 @@ "raw": 50, "min": 0, "max": 100, - "scaled": 0.5 + "scaled": 0.0 }, "completion": true, "success": true,