diff --git a/classes/log/store.php b/classes/log/store.php index a03ee4b4e..d3e2117ea 100755 --- a/classes/log/store.php +++ b/classes/log/store.php @@ -268,6 +268,11 @@ protected function get_handler_config() { 'send_short_course_id' => $this->get_config('shortcourseid', false), 'send_course_and_module_idnumber' => $this->get_config('sendidnumber', false), 'send_username' => $this->get_config('send_username', false), + // CINECA lrs.bestr.it extra user data start. + 'send_bestr_data' => $this->get_config('send_bestr_data', false), + 'bestr_custom_birthdate' => $this->get_config('bestr_custom_birthdate', false), + 'bestr_custom_cf' => $this->get_config('bestr_custom_cf', false), + // CINECA lrs.bestr.it extra user data stop. 'send_jisc_data' => $this->get_config('send_jisc_data', false), 'session_id' => sesskey(), 'plugin_url' => 'https://github.com/xAPI-vle/moodle-logstore_xapi', @@ -300,7 +305,6 @@ protected function get_handler_config() { } $handlerconfig['transformer'] = array_merge($handlerconfig['transformer'], $source); - return $handlerconfig; } diff --git a/lang/en/logstore_xapi.php b/lang/en/logstore_xapi.php index db4889182..0ae72e6cf 100644 --- a/lang/en/logstore_xapi.php +++ b/lang/en/logstore_xapi.php @@ -77,6 +77,12 @@ $string['send_username_desc'] = 'Statements will identify users with their username when this box is ticked, but only if identifying users by email is disabled.'; $string['send_jisc_data'] = 'Adds JISC data to statements'; $string['send_jisc_data_desc'] = 'Statements will contain data required by JISC.'; +$string['send_bestr_data'] = 'Adds bestr data to statements'; +$string['send_bestr_data_desc'] = 'Statements will contain data required by bestr.'; +$string['bestr_custom_birthdate'] = 'Adds birthdate to statements'; +$string['bestr_custom_birthdate_desc'] = 'Insert the name of the field where the birthdate data is in.'; +$string['bestr_custom_cf'] = 'Adds italian fiscal code data to statements'; +$string['bestr_custom_cf_desc'] = 'Insert the name of the field where the italian fiscal code data is in.'; $string['shortcourseid'] = 'Send short course name'; $string['shortcourseid_desc'] = 'Statements will contain the shortname for a course as a short course id extension'; $string['sendidnumber'] = 'Send course and activity ID number'; diff --git a/settings.php b/settings.php index 8994cb860..10afdabc7 100644 --- a/settings.php +++ b/settings.php @@ -84,6 +84,18 @@ get_string('send_jisc_data', 'logstore_xapi'), get_string('send_jisc_data_desc', 'logstore_xapi'), 0)); + $settings->add(new admin_setting_configcheckbox('logstore_xapi/send_bestr_data', + get_string('send_bestr_data', 'logstore_xapi'), + get_string('send_bestr_data_desc', 'logstore_xapi'), 0)); + + $settings->add(new admin_setting_configtext('logstore_xapi/bestr_custom_birthdate', + get_string('bestr_custom_birthdate', 'logstore_xapi'), + get_string('bestr_custom_birthdate_desc', 'logstore_xapi'), '', PARAM_TEXT)); + + $settings->add(new admin_setting_configtext('logstore_xapi/bestr_custom_cf', + get_string('bestr_custom_cf', 'logstore_xapi'), + get_string('bestr_custom_cf_desc', 'logstore_xapi'), '', PARAM_TEXT)); + $settings->add(new admin_setting_configcheckbox('logstore_xapi/sendresponsechoices', get_string('send_response_choices', 'logstore_xapi'), get_string('send_response_choices_desc', 'logstore_xapi'), 0)); diff --git a/src/transformer/utils/extensions/base.php b/src/transformer/utils/extensions/base.php index 48a609bfe..02efa0b9d 100644 --- a/src/transformer/utils/extensions/base.php +++ b/src/transformer/utils/extensions/base.php @@ -43,5 +43,11 @@ function base(array $config, \stdClass $event, $course=null) { $base = array_merge($base, utils\extensions\jisc($config, $event, $course)); } + // CINECA lrs.bestr.it extra user data start. + if (utils\is_enabled_config($config, 'send_bestr_data')) { + $base = array_merge($base, utils\extensions\bestr($config, $event, $course)); + } + // CINECA lrs.bestr.it extra user data stop. + return $base; } diff --git a/src/transformer/utils/extensions/bestr.php b/src/transformer/utils/extensions/bestr.php new file mode 100644 index 000000000..5af50e02a --- /dev/null +++ b/src/transformer/utils/extensions/bestr.php @@ -0,0 +1,104 @@ +. + +/** + * Transformer utility for Bestr xAPI extensions. + * + * @package logstore_xapi + * @copyright CINECA + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace src\transformer\utils\extensions; + +use src\transformer\utils as utils; + +/** + * Transformer utility for base xAPI extensions - Bestr specific. + * + * @param array $config The transformer config settings. + * @param \stdClass $event The event to be transformed. + * @param object $course The course object. + * @return array + */ +function bestr(array $config, \stdClass $event, $course) { + if (utils\is_enabled_config($config, 'send_bestr_data')) { + $repo = $config['repo']; + if (isset($event->relateduserid) && $event->relateduserid) { + $user = $repo->read_record_by_id('user', $event->relateduserid); + } else { + $user = $repo->read_record_by_id('user', $event->userid); + } + + // User not loggedin. + if (!$user) { + return []; + } + + $birthdatefieldname = $config['bestr_custom_birthdate']; + $cffieldname = $config['bestr_custom_cf']; + $extrafields = []; + $prefix = 'profile_field_'; + + // If $birthdatefieldname starts with $prefix. + if ($birthdatefieldname && (substr($birthdatefieldname, 0, strlen($prefix)) == $prefix)) { + $fieldname = substr($birthdatefieldname, strlen($prefix)); + // Use read_records to avoid exceptions in case the element doesn't exist. + $tmp = $repo->read_records('user_info_field', ['shortname' => $fieldname]); + $userextrafield = reset($tmp); // Take the first (and only) array element. + if ($userextrafield) { + // Use read_records to avoid exceptions in case the element doesn't exist. + $tmp2 = $repo->read_records('user_info_data', ['userid' => $user->id, 'fieldid' => $userextrafield->id]); + $extra = reset($tmp2); // Take the first (and only) array element. + if ($extra && isset($extra->data) && $extra->data) { + $extrafields["actor_birthday"] = $extra->data; + } + } + } else { + if ($birthdatefieldname && isset($user->$birthdatefieldname) && $user->$birthdatefieldname) { + $extrafields["actor_birthday"] = $user->$birthdatefieldname; + } + } + + if ($cffieldname && (substr($cffieldname, 0, strlen($prefix)) == $prefix)) { // If $cffieldname starts with $prefix. + $fieldname = substr($cffieldname, strlen($prefix)); + // Use read_records to avoid exceptions in case the element doesn't exist. + $tmp = $repo->read_records('user_info_field', ['shortname' => $fieldname]); + $userextrafield = reset($tmp); // Take the first (and only) array element. + if ($userextrafield) { + // Use read_records to avoid exceptions in case the element doesn't exist. + $tmp2 = $repo->read_records('user_info_data', ['userid' => $user->id, 'fieldid' => $userextrafield->id]); + $extra = reset($tmp2); // Take the first (and only) array element. + if ($extra && isset($extra->data) && $extra->data) { + $extrafields["actor_cf"] = $extra->data; + } + } + } else { + if ($cffieldname && isset($user->$cffieldname) && $user->$cffieldname) { + $extrafields["actor_cf"] = $user->$cffieldname; + } + } + + return [ + 'http://lrs.bestr.it/lrs/define/context/extensions/actor' => array_merge([ + "actor_name" => $user->firstname, + "actor_surname" => $user->lastname, + ], $extrafields // If extra fields are present, they are added here. + ), + ]; + } + return []; +} diff --git a/tests/core/course_completed/send_bestr_data/data.json b/tests/core/course_completed/send_bestr_data/data.json new file mode 100644 index 000000000..d77f87c2d --- /dev/null +++ b/tests/core/course_completed/send_bestr_data/data.json @@ -0,0 +1,20 @@ +{ + "user": [ + { + "id": 1, + "firstname": "test_firstname", + "lastname": "test_lastname", + "email": "test@test.com", + "datanascita": "31/12/1970", + "codicefiscale": "TESTTE12S34T567T" + } + ], + "course": [ + { + "id": 1, + "fullname": "test_name", + "lang": "en", + "shortname": "test_course_short_name" + } + ] +} \ No newline at end of file diff --git a/tests/core/course_completed/send_bestr_data/event.json b/tests/core/course_completed/send_bestr_data/event.json new file mode 100644 index 000000000..8691e0262 --- /dev/null +++ b/tests/core/course_completed/send_bestr_data/event.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "relateduserid": 1, + "courseid": 1, + "timecreated": 1433946701, + "objecttable": "course", + "objectid": 1, + "eventname": "\\core\\event\\course_completed", + "ip": "127.0.0.1" +} \ No newline at end of file diff --git a/tests/core/course_completed/send_bestr_data/send_bestr_data_test.php b/tests/core/course_completed/send_bestr_data/send_bestr_data_test.php new file mode 100644 index 000000000..f8754f135 --- /dev/null +++ b/tests/core/course_completed/send_bestr_data/send_bestr_data_test.php @@ -0,0 +1,67 @@ +. + +namespace logstore_xapi\core\course_completed\send_bestr_data; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/admin/tool/log/store/xapi/tests/xapi_test_case.php'); + +/** + * Unit test for course completed event (bestr-specific) event. + * + * @package logstore_xapi + * @copyright CINECA + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class send_bestr_data_test extends \logstore_xapi\xapi_test_case { + + /** + * Retrieve the directory of the unit test. + * + * @return string + */ + protected function get_test_dir() { + return __DIR__; + } + + /** + * Retrieve transformer configuration. + * + * @return string + */ + protected function get_transformer_config() { + $testdata = $this->get_test_data(); + $transformerconfig = parent::get_transformer_config(); + return array_merge($transformerconfig, [ + 'send_bestr_data' => true, + 'bestr_custom_birthdate' => 'datanascita', + 'bestr_custom_cf' => 'codicefiscale', + ]); + } + + /** + * Appease auto-detecting of test cases. xapi_test_case has default test cases. + * + * @covers ::course_completed + * @return void + */ + public function test_init() { + + } +} diff --git a/tests/core/course_completed/send_bestr_data/statements.json b/tests/core/course_completed/send_bestr_data/statements.json new file mode 100644 index 000000000..dcd09a522 --- /dev/null +++ b/tests/core/course_completed/send_bestr_data/statements.json @@ -0,0 +1,69 @@ +[ + { + "actor": { + "name": "test_firstname test_lastname", + "account": { + "homePage": "http:\/\/www.example.org", + "name": "1" + } + }, + "verb": { + "id": "http:\/\/adlnet.gov\/expapi\/verbs\/completed", + "display": { + "en": "completed" + } + }, + "object": { + "id": "http:\/\/www.example.org\/course\/view.php?id=1", + "definition": { + "type": "http:\/\/id.tincanapi.com\/activitytype\/lms\/course", + "name": { + "en": "test_name" + } + } + }, + "timestamp": "2015-06-10T15:31:41+01:00", + "context": { + "platform": "Moodle", + "language": "en", + "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\\course_completed", + "event_function": "\\src\\transformer\\events\\core\\course_completed" + }, + "http:\/\/lrs.bestr.it\/lrs\/define\/context\/extensions\/actor": { + "actor_name": "test_firstname", + "actor_surname": "test_lastname", + "actor_birthday": "31\/12\/1970", + "actor_cf": "TESTTE12S34T567T" + } + }, + "contextActivities": { + "grouping": [ + { + "id": "http:\/\/www.example.org", + "definition": { + "type": "http:\/\/id.tincanapi.com\/activitytype\/lms", + "name": { + "en": "test_name" + } + } + } + ], + "category": [ + { + "id": "http:\/\/moodle.org", + "definition": { + "type": "http:\/\/id.tincanapi.com\/activitytype\/source", + "name": { + "en": "Moodle" + } + } + } + ] + } + } + } +] \ No newline at end of file diff --git a/tests/xapi_test_case.php b/tests/xapi_test_case.php index 55df45067..975c1dffc 100644 --- a/tests/xapi_test_case.php +++ b/tests/xapi_test_case.php @@ -122,6 +122,7 @@ protected function get_transformer_config() { 'send_course_and_module_idnumber' => false, 'send_username' => false, 'send_jisc_data' => false, + 'send_bestr_data' => false, 'session_id' => 'test_session_id', 'plugin_url' => 'https://github.com/xAPI-vle/moodle-logstore_xapi', 'plugin_version' => '0.0.0-development',