2023-06-16 23:12:25 +02:00
|
|
|
<?php
|
2023-08-24 23:02:41 +02:00
|
|
|
// This file is part of the Studyplan plugin for Moodle
|
|
|
|
//
|
|
|
|
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @package local_treestudyplan
|
|
|
|
* @copyright 2023 P.M. Kuipers
|
|
|
|
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
|
|
*/
|
|
|
|
|
2023-06-16 23:12:25 +02:00
|
|
|
namespace local_treestudyplan;
|
|
|
|
require_once($CFG->libdir.'/externallib.php');
|
|
|
|
|
|
|
|
use \local_treestudyplan\studyplan;
|
|
|
|
|
2023-06-26 21:44:31 +02:00
|
|
|
class cascadecohortsync {
|
2023-06-19 22:48:33 +02:00
|
|
|
private const METHOD = "cohort";
|
2023-06-16 23:12:25 +02:00
|
|
|
private $studyplan;
|
2023-06-26 11:40:24 +02:00
|
|
|
private $studyplanid;
|
2023-06-16 23:12:25 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
function __construct(studyplan $studyplan) {
|
2023-06-16 23:12:25 +02:00
|
|
|
$this->studyplan = $studyplan;
|
2023-06-19 22:48:33 +02:00
|
|
|
$this->studyplanid = $studyplan->id();
|
|
|
|
}
|
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
static private function array_remove_value($array, $value) {
|
2023-06-26 21:44:31 +02:00
|
|
|
$a = [];
|
2023-08-24 23:02:41 +02:00
|
|
|
foreach ($array as $v) {
|
|
|
|
if ($v != $value) {
|
2023-06-26 21:44:31 +02:00
|
|
|
$a[] = $v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $a;
|
|
|
|
}
|
2023-08-24 23:02:41 +02:00
|
|
|
|
2023-06-26 21:44:31 +02:00
|
|
|
static function uploadenrolmentmethods_get_group($courseid, $groupname) {
|
2023-08-24 23:02:41 +02:00
|
|
|
// Function shamelessly copied from tool/uploadenrolmentmethods/locallib.php.
|
2023-06-26 21:44:31 +02:00
|
|
|
global $DB, $CFG;
|
2023-08-24 23:02:41 +02:00
|
|
|
|
2023-06-26 21:44:31 +02:00
|
|
|
require_once($CFG->dirroot.'/group/lib.php');
|
2023-08-24 23:02:41 +02:00
|
|
|
|
2023-06-26 21:44:31 +02:00
|
|
|
// Check to see if the group name already exists in this course.
|
|
|
|
if ($DB->record_exists('groups', array('name' => $groupname, 'courseid' => $courseid))) {
|
|
|
|
$group = $DB->get_record('groups', array('name' => $groupname, 'courseid' => $courseid));
|
|
|
|
return $group->id;
|
2023-06-19 22:48:33 +02:00
|
|
|
}
|
2023-06-26 21:44:31 +02:00
|
|
|
// The named group doesn't exist, so create a new one in the course.
|
|
|
|
$groupdata = new \stdClass();
|
|
|
|
$groupdata->courseid = $courseid;
|
|
|
|
$groupdata->name = $groupname;
|
|
|
|
$groupid = groups_create_group($groupdata);
|
2023-08-24 23:02:41 +02:00
|
|
|
|
2023-06-26 21:44:31 +02:00
|
|
|
return $groupid;
|
2023-06-16 23:12:25 +02:00
|
|
|
}
|
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
function sync() {
|
2023-06-19 22:48:33 +02:00
|
|
|
global $DB;
|
2023-06-26 21:44:31 +02:00
|
|
|
|
|
|
|
/* Explainer:
|
|
|
|
This script uses {enrol}.customtext4 to store a json array of all studyplans that need this cohort sync to exist.
|
|
|
|
Since the cohort-sync enrolment method uses only customint1 and customint2, this is a safe place to store the data.
|
2023-08-24 23:02:41 +02:00
|
|
|
(Should the cohortsync script at any future time be modified to use customtext fields, it is still extremely unlikely that
|
2023-06-26 21:44:31 +02:00
|
|
|
customtext4 will be used.)
|
|
|
|
Because of the overhead involved in keeping an extra table up to date and clean it up if cohort syncs are removed outside of this script,
|
|
|
|
it was determined to be the simplest and cleanest solution.
|
|
|
|
*/
|
2023-06-16 23:12:25 +02:00
|
|
|
|
2023-06-30 12:14:11 +02:00
|
|
|
$enrol = \enrol_get_plugin(self::METHOD);
|
2023-08-24 23:02:41 +02:00
|
|
|
// Find the courses that need to be synced to the associated cohorts.
|
2023-06-26 11:40:24 +02:00
|
|
|
$courseids = $this->studyplan->get_linked_course_ids();
|
|
|
|
// And find the cohorts that are linked to this studyplan.
|
|
|
|
$cohortids = $this->studyplan->get_linked_cohort_ids();
|
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
// Next, for each course that is linked:.
|
|
|
|
foreach ($courseids as $courseid) {
|
2023-06-30 12:14:11 +02:00
|
|
|
$course = \get_course($courseid);
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Processing Course {$courseid} {$course->shortname}");.
|
2023-08-25 09:44:34 +02:00
|
|
|
// First create any nonexistent links.
|
2023-08-24 23:02:41 +02:00
|
|
|
foreach ($cohortids as $cohortid) {
|
2023-08-25 10:41:56 +02:00
|
|
|
$cohort = $DB->get_record('cohort', ['id' => $cohortid]);
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Processing cohort {$cohortid} {$cohort->shortname}");.
|
2023-06-26 11:40:24 +02:00
|
|
|
|
|
|
|
$instanceparams = [
|
|
|
|
'courseid' => $courseid,
|
|
|
|
'customint1' => $cohortid,
|
|
|
|
'enrol' => self::METHOD,
|
2023-08-24 23:02:41 +02:00
|
|
|
'roleid' => get_config("local_treestudyplan", "csync_roleid"),
|
2023-06-26 11:40:24 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
$instancenewparams = [
|
|
|
|
'customint1' => $cohortid,
|
|
|
|
'enrol' => self::METHOD,
|
2023-08-24 23:02:41 +02:00
|
|
|
'roleid' => get_config("local_treestudyplan", "csync_roleid"),
|
2023-06-26 11:40:24 +02:00
|
|
|
];
|
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
// Create group: .
|
2023-06-26 11:40:24 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
// 1: check if a link exists.
|
|
|
|
// If not, make it (maybe use some of the custom text to list the studyplans involved).
|
2023-06-26 11:40:24 +02:00
|
|
|
if ($instance = $DB->get_record('enrol', $instanceparams)) {
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Instance exists");.
|
2023-08-25 09:44:34 +02:00
|
|
|
// It already exists.
|
|
|
|
// Check if this studyplan is already referenced in customtext4 in json format.
|
2023-06-26 21:44:31 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
//TODO: Check this code - Maybe add option to not remember manually added stuff .
|
2023-06-26 21:44:31 +02:00
|
|
|
$plans = json_decode($instance->customtext4);
|
2023-08-24 23:02:41 +02:00
|
|
|
if ($plans == false || !is_array(($plans))) {
|
|
|
|
// If the data was not an array (null or garbled), count it as manually added.
|
|
|
|
// This will prevent it's deletion upon.
|
|
|
|
if (get_config("local_treestudyplan", "csync_remember_manual_csync")) {
|
2023-06-26 21:44:31 +02:00
|
|
|
$plans = ["manual"];
|
|
|
|
} else {
|
|
|
|
$plans = [];
|
|
|
|
}
|
2023-06-26 11:40:24 +02:00
|
|
|
}
|
2023-08-24 23:02:41 +02:00
|
|
|
if (!in_array($this->studyplanid , $plans)) {
|
2023-08-25 09:44:34 +02:00
|
|
|
// If not, add it to the reference.
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Adding this plan to the list");.
|
2023-06-30 10:54:59 +02:00
|
|
|
$plans[] = (int)($this->studyplanid);
|
2023-08-25 10:41:56 +02:00
|
|
|
$enrol->update_instance($instance, (object)["customtext4" => json_encode($plans)]);
|
2023-06-26 11:40:24 +02:00
|
|
|
}
|
2023-06-16 23:12:25 +02:00
|
|
|
|
2023-06-26 11:40:24 +02:00
|
|
|
} else {
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("New instance should be made");.
|
2023-06-26 11:40:24 +02:00
|
|
|
// If method members should be added to a group, create it or get its ID.
|
2023-06-16 23:12:25 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
if (get_config("local_treestudyplan", "csync_creategroup")) {
|
|
|
|
// Make or get new new cohort group - but only on creating of instances.
|
2023-06-26 21:44:31 +02:00
|
|
|
$groupname = $cohort->name." ".strtolower(\get_string('defaultgroupname', 'core_group'));
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Adding group {$groupname} for this method");.
|
2023-08-25 09:44:34 +02:00
|
|
|
// And make sure the .
|
2023-06-26 21:44:31 +02:00
|
|
|
$instancenewparams['customint2'] = self::uploadenrolmentmethods_get_group($courseid, $groupname);
|
2023-06-26 11:40:24 +02:00
|
|
|
}
|
2023-08-24 23:02:41 +02:00
|
|
|
|
2023-06-26 11:40:24 +02:00
|
|
|
if ($instanceid = $enrol->add_instance($course, $instancenewparams)) {
|
2023-08-25 09:44:34 +02:00
|
|
|
// Also record the (as of yet only) studyplans id requiring this association.
|
|
|
|
// In the customtext4 field in json format.
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Instance ({$instanceid} created. Updateing instance with studyplan id");.
|
2023-06-26 21:44:31 +02:00
|
|
|
$instance = $DB->get_record('enrol', array('id' => $instanceid));
|
2023-08-25 10:41:56 +02:00
|
|
|
$enrol->update_instance($instance, (object)["customtext4" => json_encode([(int)($this->studyplanid)])]);
|
2023-08-24 23:02:41 +02:00
|
|
|
|
|
|
|
//\mtrace("Synchronize the enrolment");.
|
2023-06-26 11:40:24 +02:00
|
|
|
// Successfully added a valid new instance, so now instantiate it.
|
|
|
|
// First synchronise the enrolment.
|
|
|
|
$cohorttrace = new \null_progress_trace();
|
2023-06-26 21:44:31 +02:00
|
|
|
$result = enrol_cohort_sync($cohorttrace, $cohortid);
|
2023-08-24 23:02:41 +02:00
|
|
|
if ($result > 0) {
|
|
|
|
//\mtrace("Error during 'enrol_cohort_sync': code {$result}");.
|
2023-06-26 21:44:31 +02:00
|
|
|
}
|
2023-06-26 11:40:24 +02:00
|
|
|
$cohorttrace->finished();
|
2023-06-16 23:12:25 +02:00
|
|
|
|
2023-06-19 22:48:33 +02:00
|
|
|
} else {
|
2023-08-24 23:02:41 +02:00
|
|
|
// Instance not added for some reason, so report an error somewhere.
|
|
|
|
// (or not).
|
|
|
|
//\mtrace("Error - instance not added for some reason");.
|
2023-06-26 11:40:24 +02:00
|
|
|
}
|
2023-08-24 23:02:41 +02:00
|
|
|
}
|
2023-06-26 11:40:24 +02:00
|
|
|
}
|
2023-06-19 22:48:33 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
// 2: Check if there are cohort links for this studyplan in this course that should be removed.
|
|
|
|
// A: Check if there are cohort links that are no longer related to this studyplan.
|
2023-06-26 11:40:24 +02:00
|
|
|
// B: Check if these links are valid through another studyplan...
|
|
|
|
// If no one uses the link anymore, deactivate it...
|
2023-08-24 23:02:41 +02:00
|
|
|
// INFO: This does not remove the sync from courses that are unlinked from a studplan. But maybe we do not want that anyway.
|
|
|
|
// since it is generally a good idea to keep student access to courses available .
|
2023-06-26 11:40:24 +02:00
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
if (get_config("local_treestudyplan", "csync_autoremove")) {
|
|
|
|
// Only try the autoremove if the option is enabled.
|
|
|
|
//\mtrace("Autoremove scan for course {$courseid} {$course->shortname}");.
|
2023-08-25 09:44:34 +02:00
|
|
|
// Find all cohort syncs for this course.
|
2023-06-26 11:40:24 +02:00
|
|
|
$searchparams = [
|
|
|
|
'courseid' => $courseid,
|
|
|
|
'enrol' => self::METHOD,
|
2023-08-24 23:02:41 +02:00
|
|
|
'roleid' => get_config("local_treestudyplan", "csync_roleid"),
|
2023-06-26 11:40:24 +02:00
|
|
|
];
|
|
|
|
|
2023-08-24 23:02:41 +02:00
|
|
|
$records = $DB->get_records("enrol", $searchparams);
|
|
|
|
foreach ($records as $instance) {
|
2023-08-25 10:41:56 +02:00
|
|
|
if (!empty($instance->customtext4)) {
|
|
|
|
// Only check the records that have studyplan information in the customtext4 field.
|
2023-08-25 09:44:34 +02:00
|
|
|
// First check if the cohort is not one of the cohort id's we have associated.
|
2023-08-24 23:02:41 +02:00
|
|
|
if (!in_array($instance->customint1, $cohortids)) {
|
|
|
|
//\mtrace("Found cohort sync instance that is not currently liked to the studyplan: {$instance->id}");.
|
|
|
|
// So it may or may not need to be removed.
|
2023-06-26 11:40:24 +02:00
|
|
|
$plans = json_decode($instance->customtext4);
|
2023-08-24 23:02:41 +02:00
|
|
|
if ($plans !== null && is_array($plans)) {
|
|
|
|
//if a valid array is not returned, better leave it be, we don't want to mess with it.
|
2023-08-25 09:44:34 +02:00
|
|
|
// Otherwise, check if we should remove it.
|
2023-08-24 23:02:41 +02:00
|
|
|
if (in_array($this->studyplanid, $plans)) {
|
|
|
|
//\mtrace("Found this studyplan in the id list - removing from list");.
|
|
|
|
//if this plan was referenced before.
|
2023-08-25 09:44:34 +02:00
|
|
|
// First remove the link.
|
2023-08-24 23:02:41 +02:00
|
|
|
$fplans = self::array_remove_value($plans, $this->studyplanid);
|
|
|
|
if (count($fplans) == 0) {
|
2023-08-25 09:44:34 +02:00
|
|
|
// Delete the sync if there are no studyplan references left.
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("No references are left, removing instance");.
|
2023-06-26 11:40:24 +02:00
|
|
|
$enrol->delete_instance($instance);
|
|
|
|
} else {
|
2023-08-25 09:44:34 +02:00
|
|
|
// Otherwise just update the references so this studyplan is no longer linked.
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Still references left in the list, updating list...");.
|
2023-08-25 10:41:56 +02:00
|
|
|
$enrol->update_instance($instance, (object)["customtext4" => json_encode($fplans)]);
|
2023-06-19 22:48:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-24 23:02:41 +02:00
|
|
|
//\mtrace("Cascading complete");.
|
2023-06-19 22:48:33 +02:00
|
|
|
}
|
2023-06-16 23:12:25 +02:00
|
|
|
}
|