Skip to content
Snippets Groups Projects
Unverified Commit 3da6e753 authored by Ryan Smith's avatar Ryan Smith Committed by GitHub
Browse files

feat: Adds moodle_curl_lrs loader to close #238 (#242)

parent 02bc2f0d
No related branches found
No related tags found
No related merge requests found
......@@ -13,3 +13,4 @@ charset = utf-8
[*.{php,json}]
indent_size = 4
trim_trailing_whitespace=true
......@@ -109,7 +109,7 @@ class store extends php_obj implements log_writer {
'app_url' => $CFG->wwwroot,
],
'loader' => [
'loader' => 'lrs',
'loader' => 'moodle_curl_lrs',
'lrs_endpoint' => $this->get_config('endpoint', ''),
'lrs_username' => $this->get_config('username', ''),
'lrs_password' => $this->get_config('password', ''),
......
......@@ -19,82 +19,35 @@ defined('MOODLE_INTERNAL') || die();
use src\loader\utils as utils;
function correct_endpoint($endpoint) {
$endswithstatements = substr($endpoint, -11) === "/statements";
if ($endswithstatements) {
return substr($endpoint, 0, -11);
}
return rtrim($endpoint, '/');
}
function send_http_statements(array $config, array $statements) {
$endpoint = $config['lrs_endpoint'];
$username = $config['lrs_username'];
$password = $config['lrs_password'];
$url = correct_endpoint($endpoint).'/statements';
$auth = base64_encode($username.':'.$password);
$postdata = json_encode($statements);
$request = curl_init();
curl_setopt($request, CURLOPT_URL, $url);
curl_setopt($request, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($request, CURLOPT_HTTPHEADER, [
'Authorization: Basic '.$auth,
'X-Experience-API-Version: 1.0.0',
'Content-Type: application/json',
]);
$responsetext = curl_exec($request);
$responsecode = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
curl_close($request);
if ($responsecode !== 200) {
throw new \Exception($responsetext);
}
}
function load_transormed_events_to_lrs(array $config, array $transformedevents) {
try {
$statements = array_reduce($transformedevents, function ($result, $transformedevent) {
$eventstatements = $transformedevent['statements'];
return array_merge($result, $eventstatements);
}, []);
send_http_statements($config, $statements);
$loadedevents = utils\construct_loaded_events($transformedevents, true);
return $loadedevents;
} catch (\Exception $e) {
$logerror = $config['log_error'];
$logerror("Failed load for event id #" . $eventobj->id . ": " . $e->getMessage());
$logerror($e->getTraceAsString());
$loadedevents = utils\construct_loaded_events($transformedevents, false);
return $loadedevents;
}
}
function get_event_batches(array $config, array $transformedevents) {
$maxbatchsize = $config['lrs_max_batch_size'];
if (!empty($maxbatchsize) && $maxbatchsize < count($transformedevents)) {
return array_chunk($transformedevents, $maxbatchsize);
}
return [$transformedevents];
}
function load(array $config, array $events) {
// Attempts to load events that were transformed successfully in batches.
$successfultransformevents = utils\filter_transformed_events($events, true);
$batches = get_event_batches($config, $successfultransformevents);
$loadedevents = array_reduce($batches, function ($result, $batch) use ($config) {
$loadedbatchevents = load_transormed_events_to_lrs($config, $batch);
return array_merge($result, $loadedbatchevents);
}, []);
// Flags events that weren't transformed successfully as events that didn't load.
$failedtransformevents = utils\filter_transformed_events($events, false);
$nonloadedevents = utils\construct_loaded_events($failedtransformevents, false);
// Returns loaded and non-loaded events to avoid re-processing.
return array_merge($loadedevents, $nonloadedevents);
$sendhttpstatements = function (array $config, array $statements) {
$endpoint = $config['lrs_endpoint'];
$username = $config['lrs_username'];
$password = $config['lrs_password'];
$proxyendpoint = $config['lrs_proxy_endpoint'];
$url = utils\correct_endpoint($endpoint).'/statements';
$auth = base64_encode($username.':'.$password);
$postdata = json_encode($statements);
$request = curl_init();
curl_setopt($request, CURLOPT_URL, $url);
curl_setopt($request, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($request, CURLOPT_HTTPHEADER, [
'Authorization: Basic '.$auth,
'X-Experience-API-Version: 1.0.0',
'Content-Type: application/json',
]);
$responsetext = curl_exec($request);
$responsecode = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
curl_close($request);
if ($responsecode !== 200) {
throw new \Exception($responsetext);
}
};
return utils\load_in_batches($config, $events, $sendhttpstatements);
}
\ No newline at end of file
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\moodle_curl_lrs;
defined('MOODLE_INTERNAL') || die();
global $CFG;
if (!isset($CFG)) {
$CFG = (object) [ 'libdir' => 'utils' ];
}
require_once($CFG->libdir . '/filelib.php');
use src\loader\utils as utils;
function load(array $config, array $events) {
$sendhttpstatements = function (array $config, array $statements) {
$endpoint = $config['lrs_endpoint'];
$username = $config['lrs_username'];
$password = $config['lrs_password'];
$proxyendpoint = $config['lrs_proxy_endpoint'];
$url = utils\correct_endpoint($endpoint).'/statements';
$auth = base64_encode($username.':'.$password);
$postdata = json_encode($statements);
$request = new \curl();
$responsetext = $request->post($url, $postdata, [
'CURLOPT_HTTPHEADER' => [
'Authorization: Basic '.$auth,
'X-Experience-API-Version: 1.0.0',
'Content-Type: application/json',
],
]);
$responsecode = $request->info['http_code'];
if ($responsecode !== 200) {
throw new \Exception($responsetext);
}
};
return utils\load_in_batches($config, $events, $sendhttpstatements);
}
\ No newline at end of file
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\utils;
defined('MOODLE_INTERNAL') || die();
function correct_endpoint($endpoint) {
$endswithstatements = substr($endpoint, -11) === "/statements";
if ($endswithstatements) {
return substr($endpoint, 0, -11);
}
return rtrim($endpoint, '/');
}
\ No newline at end of file
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\utils;
defined('MOODLE_INTERNAL') || die();
class curl {
// This is just a dummy file to avoid failures in CI.
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\utils;
defined('MOODLE_INTERNAL') || die();
function get_event_batches(array $config, array $transformedevents) {
$maxbatchsize = $config['lrs_max_batch_size'];
if (!empty($maxbatchsize) && $maxbatchsize < count($transformedevents)) {
return array_chunk($transformedevents, $maxbatchsize);
}
return [$transformedevents];
}
\ No newline at end of file
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\utils;
defined('MOODLE_INTERNAL') || die();
function load_batch(array $config, array $transformedevents, callable $loader) {
try {
$statements = array_reduce($transformedevents, function ($result, $transformedevent) {
$eventstatements = $transformedevent['statements'];
return array_merge($result, $eventstatements);
}, []);
$loader($config, $statements);
$loadedevents = construct_loaded_events($transformedevents, true);
return $loadedevents;
} catch (\Exception $e) {
$logerror = $config['log_error'];
$logerror("Failed load for event id #" . $eventobj->id . ": " . $e->getMessage());
$logerror($e->getTraceAsString());
$loadedevents = construct_loaded_events($transformedevents, false);
return $loadedevents;
}
}
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace src\loader\utils;
defined('MOODLE_INTERNAL') || die();
function load_in_batches(array $config, array $events, callable $loader) {
// Attempts to load events that were transformed successfully in batches.
$successfultransformevents = filter_transformed_events($events, true);
$batches = get_event_batches($config, $successfultransformevents);
$loadedevents = array_reduce($batches, function ($result, $batch) use ($config, $loader) {
$loadedbatchevents = load_batch($config, $batch, $loader);
return array_merge($result, $loadedbatchevents);
}, []);
// Flags events that weren't transformed successfully as events that didn't load.
$failedtransformevents = filter_transformed_events($events, false);
$nonloadedevents = construct_loaded_events($failedtransformevents, false);
// Returns loaded and non-loaded events to avoid re-processing.
return array_merge($loadedevents, $nonloadedevents);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment