-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
02df042
commit b257f38
Showing
6 changed files
with
308 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// 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/>. | ||
|
||
/* | ||
* @package local_catquiz | ||
* @copyright Wunderbyte GmbH <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
|
||
import {get_string as getString} from 'core/str'; | ||
import Ajax from 'core/ajax'; | ||
import Notification from 'core/notification'; | ||
|
||
const SELECTORS = { | ||
FORMCONTAINER: '#lcq_select_context_form', | ||
CALCULATEBUTTON: '#sync_button' | ||
}; | ||
/** | ||
* Add event listener to buttons. | ||
*/ | ||
export const init = () => { | ||
|
||
const syncButton = document.querySelector(SELECTORS.SYNCBUTTON); | ||
// Hardcoded values for testing. | ||
const centralurl = 'https://192.168.56.6'; | ||
const wstoken = '2f36a8dc27525b97a93e50186035d49e'; | ||
const scalelabel = 'simulation'; | ||
|
||
const contextId = parseInt(calculateButton.dataset.contextid); | ||
calculateButton.onclick = () => { | ||
updateParameters(contextId); | ||
}; | ||
|
||
const updateParameters = async(contextid) => { | ||
const urlParams = new URLSearchParams(window.location.search); | ||
const catscaleid = urlParams.get('scaleid'); | ||
|
||
// Fallback if the translation can not be loaded | ||
let errorMessage = 'Something went wrong'; | ||
try { | ||
errorMessage = await getString('somethingwentwrong', 'local_catquiz'); | ||
} catch (error) { | ||
// We already have a fallback message, nothing to do here. | ||
} | ||
Ajax.call([{ | ||
methodname: 'local_catquiz_update_parameters', | ||
args: {contextid, catscaleid}, | ||
done: async function(res) { | ||
if (res.success) { | ||
disableButton(); | ||
// Fallback if the translation can not be loaded | ||
let successMessage = 'Recalculation was scheduled'; | ||
try { | ||
successMessage = await getString('recalculationscheduled', 'local_catquiz'); | ||
} catch (error) { | ||
// We already have a fallback message, nothing to do here. | ||
} | ||
|
||
Notification.addNotification({ | ||
message: successMessage, | ||
type: 'success' | ||
}); | ||
} else { | ||
disableButton(); | ||
Notification.addNotification({ | ||
message: errorMessage, | ||
type: 'danger' | ||
}); | ||
} | ||
}, | ||
fail: () => { | ||
disableButton(); | ||
Notification.addNotification({ | ||
message: errorMessage, | ||
type: 'danger' | ||
}); | ||
}, | ||
}]); | ||
}; | ||
|
||
const disableButton = () => { | ||
document.querySelector(SELECTORS.CALCULATEBUTTON).setAttribute('disabled', true); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
<?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/>. | ||
|
||
defined('MOODLE_INTERNAL') || die(); | ||
|
||
require_once($CFG->libdir . '/externallib.php'); | ||
require_once($CFG->libdir . '/filelib.php'); | ||
|
||
namespace local_catquiz\external; | ||
|
||
use core_external\external_api; | ||
use core_external\external_function_parameters; | ||
use core_external\external_single_structure; | ||
use core_external\external_value; | ||
use core_external\external_multiple_structure; | ||
use local_catquiz\catscale; | ||
|
||
/** | ||
* This class contains a list of webservice functions related to the catquiz Module by Wunderbyte. | ||
* | ||
* @package local_catquiz | ||
* @copyright 2024 Wunderbyte GmbH | ||
* @author David Szkiba | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
class fetch_parameters extends external_api { | ||
/** | ||
* Returns description of method parameters | ||
* @return external_function_parameters | ||
*/ | ||
public static function execute_parameters() { | ||
return new external_function_parameters([ | ||
'centralurl' => new external_value(PARAM_URL, 'URL of central instance'), | ||
'token' => new external_value(PARAM_TEXT, 'Web service token'), | ||
'scalelabel' => new external_value(PARAM_TEXT, 'Label of the scale to sync'), | ||
]); | ||
} | ||
|
||
/** | ||
* Returns description of method return values | ||
* @return external_single_structure | ||
*/ | ||
public static function execute_returns() { | ||
return new external_single_structure([ | ||
'status' => new external_value(PARAM_BOOL, 'Status of the sync'), | ||
'duration' => new external_value(PARAM_FLOAT, 'Duration in seconds'), | ||
'synced' => new external_value(PARAM_INT, 'Number of parameters synced'), | ||
'errors' => new external_value(PARAM_INT, 'Number of errors encountered'), | ||
'message' => new external_value(PARAM_TEXT, 'Status message'), | ||
'warnings' => new external_multiple_structure( | ||
new external_single_structure([ | ||
'item' => new external_value(PARAM_TEXT, 'Item identifier'), | ||
'warning' => new external_value(PARAM_TEXT, 'Warning message'), | ||
]) | ||
), | ||
]); | ||
} | ||
|
||
/** | ||
* Fetches and synchronizes item parameters from a central instance | ||
* | ||
* @param string $centralurl URL of the central Moodle instance | ||
* @param string $token Web service token for authentication | ||
* @param string $scalelabel Label of the scale to synchronize | ||
* @return array Returns status information about the sync operation including: | ||
* - status (bool): Whether any parameters were successfully synced | ||
* - duration (float): Time taken for the operation in seconds | ||
* - synced (int): Number of parameters successfully synchronized | ||
* - errors (int): Number of errors encountered | ||
* - message (string): Status message describing the operation | ||
* - warnings (array): List of specific warnings/errors encountered | ||
* @throws \invalid_parameter_exception If parameters are invalid | ||
*/ | ||
public static function execute(string $centralurl, string $token, string $scalelabel) { | ||
global $DB; | ||
|
||
$params = self::validate_parameters(self::execute_parameters(), [ | ||
'centralurl' => $centralurl, | ||
'token' => $token, | ||
'scalelabel' => $scalelabel, | ||
]); | ||
|
||
$starttime = microtime(true); | ||
$warnings = []; | ||
$stored = 0; | ||
$errors = 0; | ||
|
||
// Get the local scale. | ||
$scale = $DB->get_record('local_catquiz_catscales', ['label' => $params['scalelabel']], '*', MUST_EXIST); | ||
|
||
// Call central instance. | ||
$serverurl = rtrim($params['centralurl'], '/') . '/webservice/rest/server.php'; | ||
$wsparams = [ | ||
'wstoken' => $params['token'], | ||
'wsfunction' => 'local_catquiz_fetch_item_parameters', | ||
'moodlewsrestformat' => 'json', | ||
'scalelabel' => $params['scalelabel'], | ||
]; | ||
$CFG->curlsecurityblockedhosts = ''; // TODO: Remove. | ||
$curl = new \curl(); | ||
$curl->setopt(['CURLOPT_SSL_VERIFYPEER' => false, 'CURLOPT_SSL_VERIFYHOST' => false]); | ||
$response = $curl->post($serverurl, $wsparams); | ||
unset($CFG->curlsecurityblockedhosts); | ||
$result = json_decode($response); | ||
|
||
if (!$result || isset($result->exception)) { | ||
return [ | ||
'status' => false, | ||
'duration' => 0, | ||
'synced' => 0, | ||
'errors' => 1, | ||
'message' => $result->message ?? 'Invalid response from server', | ||
'warnings' => [], | ||
]; | ||
} | ||
|
||
// Create a mapping of catscale labels to IDs. | ||
$scalemapping = []; | ||
$catscaleids = [$scale->id, ...catscale::get_subscale_ids($scale->id)]; | ||
[$inscalesql, $inscaleparams] = $DB->get_in_or_equal($catscaleids, SQL_PARAMS_NAMED, 'scaleid'); | ||
|
||
$sql = <<<SQL | ||
SELECT * | ||
FROM {local_catquiz_catscales} lcs | ||
WHERE lcs.id $inscalesql | ||
SQL; | ||
|
||
$scalerecords = $DB->get_records_sql($sql, $inscaleparams); | ||
foreach ($scalerecords as $s) { | ||
$scalemapping[$s->label] = $s->id; | ||
} | ||
|
||
// Create new context. | ||
$source = "Fetch from " . parse_url($params['centralurl'], PHP_URL_HOST); | ||
$newcontext = \local_catquiz\data\dataapi::create_new_context_for_scale( | ||
$scale->id, | ||
$scale->name, | ||
$source, | ||
false | ||
); | ||
|
||
// Process and store parameters. | ||
foreach ($result->parameters as $param) { | ||
$questionid = \local_catquiz\remote\hash\question_hasher::get_questionid_from_hash($param->questionhash); | ||
if (!$questionid) { | ||
$warnings[] = ['item' => $param->questionhash, 'warning' => 'Question not found locally']; | ||
$errors++; | ||
continue; | ||
} | ||
|
||
try { | ||
$itemrecord = new \stdClass(); | ||
$itemrecord->componentid = $questionid; | ||
$itemrecord->componentname = 'question'; | ||
$itemrecord->catscaleid = $scale->id; | ||
$itemrecord->contextid = $newcontext->id; | ||
$itemrecord->status = LOCAL_CATQUIZ_TESTITEM_STATUS_ACTIVE; | ||
$itemid = $DB->insert_record('local_catquiz_items', $itemrecord); | ||
|
||
$paramrecord = new \stdClass(); | ||
$paramrecord->itemid = $itemid; | ||
$paramrecord->componentid = $questionid; | ||
$paramrecord->componentname = 'question'; | ||
$paramrecord->contextid = $newcontext->id; | ||
$paramrecord->model = $param->model; | ||
$paramrecord->difficulty = $param->difficulty; | ||
$paramrecord->discrimination = $param->discrimination; | ||
$paramrecord->status = $param->status; | ||
$paramrecord->json = $param->json; | ||
|
||
$itemparam = \local_catquiz\local\model\model_item_param::from_record($paramrecord); | ||
$itemparam->save(); | ||
$stored++; | ||
} catch (\Exception $e) { | ||
debugging('Error storing parameter: ' . $e->getMessage(), DEBUG_DEVELOPER); | ||
$warnings[] = ['item' => $param->questionhash, 'warning' => $e->getMessage()]; | ||
$errors++; | ||
} | ||
} | ||
|
||
$duration = microtime(true) - $starttime; | ||
|
||
return [ | ||
'status' => $stored > 0, | ||
'duration' => round($duration, 2), | ||
'synced' => $stored, | ||
'errors' => $errors, | ||
'message' => $stored > 0 ? "Successfully synced $stored parameters" : 'No parameters were synced', | ||
'warnings' => $warnings, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters