diff --git a/modules/tincanapi_content_types/tincanapi_content_types.module b/modules/tincanapi_content_types/tincanapi_content_types.module index 8c6fa6f..57d3837 100644 --- a/modules/tincanapi_content_types/tincanapi_content_types.module +++ b/modules/tincanapi_content_types/tincanapi_content_types.module @@ -77,28 +77,10 @@ function tincanapi_content_types_data_from_node($node, $view_mode = '') { $data['verb'] = tincanapi_get_verb('viewed'); $data['object'] = tincanapi_get_object('node', $node); - $data['object']['definition']['name']['en-US'] = trim($content_type->name . ': ' . $data['object']['definition']['name']['en-US']); - $data['object']['definition']['type'] = TINCANAPI_CUSTOM_URI . '/content/type/' . $node->type; - $data['storage']['node'] = $node; $data['storage']['view_mode'] = $view_mode; - // Add organic group (class) information. - if (isset($node->og_group_ref)) { - $og_group_values = field_get_items('node', $node, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } + tincanapi_add_og_context($node, $data); return $data; } diff --git a/modules/tincanapi_quiz/tincanapi_quiz.module b/modules/tincanapi_quiz/tincanapi_quiz.module index 37f12f6..59b1ca1 100644 --- a/modules/tincanapi_quiz/tincanapi_quiz.module +++ b/modules/tincanapi_quiz/tincanapi_quiz.module @@ -11,9 +11,8 @@ function tincanapi_quiz_quiz_begin($quiz, $rid) { $data = array(); - $data['verb'] = tincanapi_get_verb('started'); + $data['verb'] = tincanapi_get_verb('launched'); $data['object'] = tincanapi_get_object('node', $quiz); - $data['object']['definition']['type'] = "http://orw.iminds.be/media/quiz"; // Add organic group (class) information. if (isset($quiz->og_group_ref)) { @@ -25,10 +24,8 @@ function tincanapi_quiz_quiz_begin($quiz, $rid) { $group_node = node_load($group_nid); if ($group_node) { $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), 'objectType' => 'Activity', - ); + ) + tincanapi_get_object('node', $group_node); $data['context']['contextActivities']['grouping'] = $group; } @@ -48,9 +45,8 @@ function tincanapi_quiz_quiz_finished($quiz, $score, $session_data) { $data = array(); - $data['verb'] = tincanapi_get_verb('finished'); + $data['verb'] = tincanapi_get_verb('completed'); $data['object'] = tincanapi_get_object('node', $quiz); - $data['object']['definition']['type'] = "http://orw.iminds.be/media/quiz"; $data['context']['extensions'][TINCANAPI_CUSTOM_URI . '/duration'] = tincanapi_format_iso8601_duration($timestamp); @@ -62,24 +58,7 @@ function tincanapi_quiz_quiz_finished($quiz, $score, $session_data) { $data['result']['completion'] = FALSE; } - // Add organic group (class) information. - if (isset($quiz->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $quiz, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } + tincanapi_add_og_context($quiz, $data); tincanapi_track_data('quiz', $data); } @@ -97,28 +76,10 @@ function tincanapi_quiz_quiz_scored($quiz, $score, $rid) { $data['verb'] = tincanapi_get_verb('scored'); $data['object'] = tincanapi_get_object('node', $quiz); - $data['object']['definition']['type'] = "http://orw.iminds.be/media/quiz"; $data['result'] = _tincanapi_quiz_get_result($score, $quiz); - // Add organic group (class) information. - if (isset($quiz->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $quiz, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } + tincanapi_add_og_context($quiz, $data); tincanapi_track_data('quiz', $data, (int) $record->uid); } @@ -265,24 +226,7 @@ function tincanapi_quiz_tincanapi_quiz_data_multichoice(&$data, $question, $answ $data['object']['definition']['choices'] = $choices; $data['result']['response'] = implode(",", $data['result']['response']); - // Add organic group (class) information. - if (isset($question->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $question, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } + tincanapi_add_og_context($question, $data); } @@ -331,25 +275,7 @@ function tincanapi_quiz_tincanapi_quiz_data_scale(&$data, $question, $answers) { $data['object']['definition']['scale'] = $scale; - // Add organic group (class) information. - if (isset($question->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $question, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } - + tincanapi_add_og_context($question, $data); } /** @@ -377,24 +303,7 @@ function tincanapi_quiz_tincanapi_quiz_data_short_answer(&$data, $question, $ans 'max' => (int) $max, ); - // Add organic group (class) information. - if (isset($question->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $question, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } + tincanapi_add_og_context($question, $data); } /** @@ -411,25 +320,7 @@ function tincanapi_quiz_tincanapi_quiz_data_truefalse(&$data, $question, $answer $correct = ($question->correct_answer == 1 ? 'true' : 'false'); $data['object']['definition']['correctResponsesPattern'] = array($correct); - // Add organic group (class) information. - if (isset($question->og_group_ref)) { - global $base_url; - - $og_group_values = field_get_items('node', $question, 'og_group_ref'); - $group_nid = $og_group_values[0]['target_id']; - - $group_node = node_load($group_nid); - if ($group_node) { - $group = array( - 'id' => $base_url . '/node/' . $group_node->nid, - 'definition' => array('name' => array('en-US' => $group_node->title)), - 'objectType' => 'Activity', - ); - - $data['context']['contextActivities']['grouping'] = $group; - } - } - + tincanapi_add_og_context($question, $data); } /** @@ -458,13 +349,10 @@ function _tincanapi_quiz_track_answers($quiz, $rid, $uid = NULL) { $data['verb'] = tincanapi_get_verb('answered'); $data['object'] = tincanapi_get_object('node', $question); - $data['object']['objectType'] = 'Activity'; - $data['object']['definition']['type'] = "http://orw.iminds.be/media/quiz"; $parent = array( - 'id' => $base_url . '/node/' . $quiz->nid, 'objectType' => 'Activity', - ); + ) + tincanapi_get_object('node', $quiz); $data['context']['contextActivities']['parent'] = $parent; $data['context']['extensions'][TINCANAPI_CUSTOM_URI . '/order'] = $i; diff --git a/tincanapi.module b/tincanapi.module index a41166e..3d2d802 100644 --- a/tincanapi.module +++ b/tincanapi.module @@ -155,6 +155,56 @@ function tincanapi_get_actor($account = NULL) { /** * Return a 'object' for the LRS. * + * The function support these types : + * - assessment + * - attempt + * - blog + * - book + * - chat-channel + * - chat-message + * - checklist + * - checklist-item + * - code-commit + * - conference + * - conference-session + * - conference-track + * - course + * - discussion + * - email + * - essay + * - file + * - interaction + * - legacy-learning-standard + * - lesson + * - link + * - lms + * - media + * - meeting + * - module + * - objective + * - paragraph + * - performance + * - profile + * - question + * - recipe + * - research-report + * - sales-opportunity + * - scenario + * - school-assignment + * - security-role + * - simulation + * - slide + * - slide-deck + * - source + * - tag + * - test-data-batch + * - tutor-session + * - tweet + * - unit-test + * - unit-test-suite + * - voicemail + * - webinar + * * @param string $entity_type * The type of entity provided. * @param object $entity @@ -163,27 +213,131 @@ function tincanapi_get_actor($account = NULL) { * @return array * An array representing an 'object'. */ -function tincanapi_get_object($entity_type, $entity) { +function tincanapi_get_object($entity_type, $entity, $type='default', $id=-1, $name='No name') { global $base_url; + // This array is used to replace the unknown types to a more generic one + $relations_workaround = array( + 'question' => array('cloze','long_answer','matching','multichoice','opigno_scorm_quiz_question','quizfileupload', + 'quiz_ddlines','quiz_drag_drop','h5p_content','scale','short_answer','truefalse'), + 'lesson' => array('quiz'), + 'conference' => array('class') + ); + + + $all_activity_types = array( + 'http://adlnet.gov/expapi/activities/' => array('assessment','attempt','course','file','interaction','lesson', + 'link','media','meeting','module','objective','performance','profile','question','simulation'), + 'http://id.tincanapi.com/activitytype/' => array('blog','book','chat-channel','chat-message','checklist', + 'checklist-item','code-commit','conference','conference-session','conference-track','discussion','email','essay', + 'legacy-learning-standard','lms','paragraph','recipe','research-report','sales-opportunity','scenario', + 'school-assignment','security-role','slide','slide-deck','source','tag','test-data-batch','tutor-session','tweet', + 'unit-test','unit-test-suite','voicemail','webinar') + ); + + switch ($entity_type) { case 'node': $id = $entity->nid; $name = $entity->title; + $type = $entity->type; break; } $object = array(); - $object['id'] = $base_url . '/' . $entity_type . '/' . $id; + $object['id'] = $base_url . '/' . $type . '/' . $id; $object['definition']['name']['en-US'] = $name; + + foreach($relations_workaround as $replacement => $relations) + if (in_array($type, $relations)) { + $type = $replacement; + break; + } + + + foreach($all_activity_types as $url => $activity_types) + { + if (in_array($type, $activity_types)) { + $object['definition']['type'] = $url . $type; + return $object; + } + } + + + $object['definition']['type'] = $base_url .'/tincan/types/'. $type; + watchdog('TinCan API', 'Usage of a type that is not registered: %type', array('%type' => $type), WATCHDOG_WARNING); + + return $object; } /** * Return a 'verb' array. * + * This function supports these verbs : + * - abandoned + * - added + * - adjourned + * - answered + * - asked + * - attempted + * - attended + * - bookmarked + * - called + * - closed-sale + * - commented + * - completed + * - created-opportunity + * - earned + * - exited + * - experienced + * - failed + * - focused + * - hired + * - imported + * - initialized + * - interacted + * - interviewed + * - launched + * - logged-in + * - logged-out + * - mastered + * - mentored + * - passed + * - paused + * - preferred + * - pressed + * - previewed + * - progressed + * - ran + * - rated + * - registered + * - released + * - removed + * - replied-to-tweet + * - requested-attention + * - responded + * - resumed + * - retweeted + * - reviewed + * - satisfied + * - scored + * - shared + * - skipped + * - suspended + * - terminated + * - tweeted + * - unfocused + * - unregistered + * - viewed + * - voted-down + * - voted-up + * - voided + * - waived + * - walked + * * @param string $id * The id of the verb. * @param string $display @@ -197,11 +351,35 @@ function tincanapi_get_verb($id, $display = NULL) { $display = $id; } - $verb = array(); - $verb['id'] = 'http://adlnet.gov/expapi/verbs/' . $id; + $all_verbs = array( + 'https://w3id.org/xapi/adl/verbs/' => array('abandoned','logged-in','logged-out','satisfied','waived'), + 'http://id.tincanapi.com/verb/' => array('adjourned','bookmarked','called','closed-sale','created-opportunity', + 'focused','hired','interviewed','mentored','paused','previewed','rated','replied-to-tweet','requested-attention', + 'retweeted','reviewed','skipped','tweeted','unfocused','unregistered','viewed','voted-down','voted-up'), + 'http://adlnet.gov/expapi/verbs/' => array('answered','asked','attempted','attended','commented','completed', + 'exited','experienced','failed','imported','initialized','interacted','launched','mastered','passed','preferred', + 'progressed','registered','responded','resumed','scored','shared','suspended','terminated','voided'), + 'https://brindlewaye.com/xAPITerms/verbs/' => array('added','removed','ran','walked'), + 'http://specification.openbadges.org/xapi/verbs/' => array('earned'), + 'http://future-learning.info/xAPI/verb/' => array('released','pressed') + ); + + + $verb = array(); $verb['display']['en-US'] = $display; + foreach($all_verbs as $url => $verbs) + if (in_array($id, $verbs)) { + $verb['id'] = $url . $id; + return $verb; + } + + + global $base_url; + $verb['id'] = $base_url .'/tincan/verbs/'. $id; + watchdog('TinCan API', 'Usage of a verb that is not registered: %id', array('%id' => $id), WATCHDOG_WARNING); + return $verb; } @@ -454,3 +632,33 @@ function tincanapi_format_iso8601_duration($timestamp) { return $output; } + + +/** + * Fill statement group context with OG context + * + * @param object $node + * A Drupal node object. + * + * @return array + * A structured data array. + */ +function tincanapi_add_og_context($node, &$data) +{ + global $base_url; + + // Add organic group (class) information. + if (isset($node->og_group_ref)) { + $og_group_values = field_get_items('node', $node, 'og_group_ref'); + $group_nid = $og_group_values[0]['target_id']; + + $group_node = node_load($group_nid); + if ($group_node) { + $group = array( + 'objectType' => 'Activity', + ) + tincanapi_get_object('node', $group_node); + + $data['context']['contextActivities']['grouping'][] = $group; + } + } +}