diff --git a/admin/apiretries.php b/admin/apiretries.php
index eb0a4ebe84b..5d3f4e0b70f 100644
--- a/admin/apiretries.php
+++ b/admin/apiretries.php
@@ -26,6 +26,7 @@
use enrol_arlo\api;
use enrol_arlo\local\tablesql\apiretries;
use enrol_arlo\adminsettings\configarlostatus;
+use enrol_arlo\form\syncold;
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
@@ -36,6 +37,7 @@
$action = optional_param('action', null, PARAM_ALPHA);
$course = optional_param('course', null, PARAM_INT);
$regid = optional_param('regid', null, PARAM_INT);
+$message = optional_param('message', null, PARAM_TEXT);
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('apiretries', 'enrol_arlo'));
@@ -50,6 +52,10 @@
echo $OUTPUT->single_button(new moodle_url($PAGE->url, ['action' => 'enablecommunication']), get_string('enablecommunication', 'enrol_arlo'));
}
+if (!enrol_arlo_sync_adhoc_queued()) {
+ echo $OUTPUT->single_button('', get_string('synoldreg', 'enrol_arlo'), '', ['data-action' => 'syncold']);
+}
+
if (!empty($pluginconfig->get('redirectcount'))) {
echo get_string('apifails', 'enrol_arlo') . $pluginconfig->get('redirectcount');
echo $OUTPUT->single_button(new moodle_url($PAGE->url, ['action' => 'resetredirects']), get_string('resetredirects', 'enrol_arlo'));
@@ -72,6 +78,10 @@
}
$report = new apiretries('enrolsettingsarloapiretries');
+if ($message) {
+ echo $OUTPUT->notification(get_string($message, 'enrol_arlo'), \core\output\notification::NOTIFY_INFO);
+}
$report->out(apiretries::PAGINATION_MAX_LIMIT, false);
+$PAGE->requires->js_call_amd('enrol_arlo/syncold', 'init', ['[data-action="syncold"]', syncold::class]);
echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/amd/build/syncold.min.js b/amd/build/syncold.min.js
new file mode 100644
index 00000000000..c3b0dbe0e7f
--- /dev/null
+++ b/amd/build/syncold.min.js
@@ -0,0 +1,3 @@
+define("enrol_arlo/syncold",["exports","core_form/modalform","core/config","core/str"],(function(_exports,_modalform,_config,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_config=_interopRequireDefault(_config);_exports.init=(linkSelector,formClass)=>{document.querySelector(linkSelector).addEventListener("click",(async e=>{e.preventDefault();const form=new _modalform.default({formClass:formClass,args:{},modalConfig:{title:await(0,_str.get_string)("dateselector","enrol_arlo")},saveButtonText:await(0,_str.get_string)("synchronize","enrol_arlo"),returnFocus:e.currentTarget});form.addEventListener(form.events.FORM_SUBMITTED,(e=>{const response=e.detail;let redirect="".concat(_config.default.wwwroot,"/enrol/arlo/admin/apiretries.php?"),first=!1;for(let key in response)first?first=!1:redirect+="&",redirect+="".concat(key,"=").concat(response[key]);window.location.assign(redirect)})),form.show()}))}}));
+
+//# sourceMappingURL=syncold.min.js.map
\ No newline at end of file
diff --git a/amd/build/syncold.min.js.map b/amd/build/syncold.min.js.map
new file mode 100644
index 00000000000..f509b4093fa
--- /dev/null
+++ b/amd/build/syncold.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"syncold.min.js","sources":["../src/syncold.js"],"sourcesContent":["import ModalForm from 'core_form/modalform';\nimport Config from 'core/config';\nimport {get_string as getString} from 'core/str';\n\nexport const init = (linkSelector, formClass) => {\n let syncbutton = document.querySelector(linkSelector);\n\n syncbutton.addEventListener('click', async(e) => {\n e.preventDefault();\n\n const form = new ModalForm(({\n formClass,\n args: {},\n modalConfig: {\n title: await getString('dateselector', 'enrol_arlo'),\n },\n saveButtonText: await getString('synchronize', 'enrol_arlo'),\n returnFocus: e.currentTarget\n }));\n\n form.addEventListener(form.events.FORM_SUBMITTED, (e) => {\n const response = e.detail;\n let redirect = `${Config.wwwroot}/enrol/arlo/admin/apiretries.php?`;\n let first = false;\n for (let key in response) {\n if (first) {\n first = false;\n } else {\n redirect = redirect + '&';\n }\n redirect = redirect + `${key}=${response[key]}`;\n }\n window.location.assign(redirect);\n });\n\n form.show();\n });\n\n};\n"],"names":["linkSelector","formClass","document","querySelector","addEventListener","async","e","preventDefault","form","ModalForm","args","modalConfig","title","saveButtonText","returnFocus","currentTarget","events","FORM_SUBMITTED","response","detail","redirect","Config","wwwroot","first","key","window","location","assign","show"],"mappings":"sYAIoB,CAACA,aAAcC,aACdC,SAASC,cAAcH,cAE7BI,iBAAiB,SAASC,MAAAA,IACjCC,EAAEC,uBAEIC,KAAO,IAAIC,mBAAW,CACxBR,UAAAA,UACAS,KAAM,GACNC,YAAa,CACTC,YAAa,mBAAU,eAAgB,eAE3CC,qBAAsB,mBAAU,cAAe,cAC/CC,YAAaR,EAAES,gBAGnBP,KAAKJ,iBAAiBI,KAAKQ,OAAOC,gBAAiBX,UACzCY,SAAWZ,EAAEa,WACfC,mBAAcC,gBAAOC,6CACrBC,OAAQ,MACP,IAAIC,OAAON,SACRK,MACAA,OAAQ,EAERH,UAAsB,IAE1BA,oBAAyBI,gBAAON,SAASM,MAE7CC,OAAOC,SAASC,OAAOP,aAG3BZ,KAAKoB"}
\ No newline at end of file
diff --git a/amd/src/syncold.js b/amd/src/syncold.js
new file mode 100644
index 00000000000..95a24a0bfc7
--- /dev/null
+++ b/amd/src/syncold.js
@@ -0,0 +1,39 @@
+import ModalForm from 'core_form/modalform';
+import Config from 'core/config';
+import {get_string as getString} from 'core/str';
+
+export const init = (linkSelector, formClass) => {
+ let syncbutton = document.querySelector(linkSelector);
+
+ syncbutton.addEventListener('click', async(e) => {
+ e.preventDefault();
+
+ const form = new ModalForm(({
+ formClass,
+ args: {},
+ modalConfig: {
+ title: await getString('dateselector', 'enrol_arlo'),
+ },
+ saveButtonText: await getString('synchronize', 'enrol_arlo'),
+ returnFocus: e.currentTarget
+ }));
+
+ form.addEventListener(form.events.FORM_SUBMITTED, (e) => {
+ const response = e.detail;
+ let redirect = `${Config.wwwroot}/enrol/arlo/admin/apiretries.php?`;
+ let first = false;
+ for (let key in response) {
+ if (first) {
+ first = false;
+ } else {
+ redirect = redirect + '&';
+ }
+ redirect = redirect + `${key}=${response[key]}`;
+ }
+ window.location.assign(redirect);
+ });
+
+ form.show();
+ });
+
+};
diff --git a/classes/api.php b/classes/api.php
index 13d731af12b..d679bcf308e 100644
--- a/classes/api.php
+++ b/classes/api.php
@@ -453,7 +453,6 @@ public static function run_instance_jobs($instanceid, $full = false, $trace = nu
}
}
-
if (!empty($outcomesjobpersistent)) {
$outcomesjob = \enrol_arlo\local\factory\job_factory::create_from_persistent($outcomesjobpersistent);
$outcomestatus = $outcomesjob->run();
diff --git a/classes/form/syncold.php b/classes/form/syncold.php
new file mode 100644
index 00000000000..f2dafa99f28
--- /dev/null
+++ b/classes/form/syncold.php
@@ -0,0 +1,98 @@
+.
+
+namespace enrol_arlo\form;
+
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once($CFG->libdir . '/formslib.php');
+use core_form\dynamic_form;
+use enrol_arlo\task\enrolments_adhoc;
+use moodle_url;
+use stdClass;
+
+class syncold extends dynamic_form {
+
+ /**
+ * Get context.
+ *
+ * @return \context
+ * @throws \dml_exception
+ */
+ protected function get_context_for_dynamic_submission(): \context {
+ return \context_system::instance();
+ }
+
+ /**
+ * Check access.
+ *
+ * @return void
+ * @throws \dml_exception
+ * @throws \required_capability_exception
+ */
+ protected function check_access_for_dynamic_submission(): void {
+ require_capability('moodle/course:create', \context_system::instance());
+ }
+
+ /**
+ * Process submission.
+ *
+ * @return array
+ */
+ public function process_dynamic_submission() {
+ $data = $this->get_data();
+ $task = new enrolments_adhoc();
+ $task->set_custom_data($data->startdate);
+ \core\task\manager::queue_adhoc_task($task);
+ return ['message' => 'taskqueued'];
+ }
+
+ /**
+ * Set form data.
+ *
+ * @return void
+ * @throws Exception No record in persistent table
+ */
+ public function set_data_for_dynamic_submission(): void {
+ $this->set_data(new stdClass());
+ }
+
+ /**
+ * Get page url.
+ *
+ * @return moodle_url
+ */
+ protected function get_page_url_for_dynamic_submission(): moodle_url {
+ return new moodle_url('/enrol/arlo/admin/apiretries.php');
+ }
+
+ public function definition() {
+ global $DB, $COURSE;
+ $form = $this->_form;
+ $form->addElement('date_selector', 'startdate', get_string('syncsince', 'enrol_arlo'));
+ $form->addHelpButton('startdate', 'syncsince', 'enrol_arlo');
+ }
+
+ public function validation($data, $files) {
+ $errors = parent::validation($data, $files);
+ $time = time();
+ if ($data['startdate'] > $time) {
+ $errors['startdate'] = get_string('invalidstartdate', 'enrol_arlo');
+ }
+ return $errors;
+ }
+}
diff --git a/classes/local/job/contact_merge_requests_job.php b/classes/local/job/contact_merge_requests_job.php
index 2e5ba26c569..b3f0b3ac7be 100644
--- a/classes/local/job/contact_merge_requests_job.php
+++ b/classes/local/job/contact_merge_requests_job.php
@@ -69,8 +69,7 @@ class contact_merge_requests_job extends job {
public function run() {
$pluginconfig = new arlo_plugin_config();
$jobpersistent = $this->get_job_persistent();
- $disableskip = get_config('enrol_arlo', 'disableskip');
- $lastime = empty($disableskip) ? $jobpersistent->get('lastsourcetimemodified') : 0;
+ $lastime = $jobpersistent->get('lastsourcetimemodified');
try {
$hasnext = true;
while ($hasnext) {
diff --git a/classes/local/job/memberships_job.php b/classes/local/job/memberships_job.php
index a745b97a308..88186c927e9 100644
--- a/classes/local/job/memberships_job.php
+++ b/classes/local/job/memberships_job.php
@@ -247,7 +247,7 @@ public function sync_resource($resource) {
* @return bool
* @throws \GuzzleHttp\Exception\GuzzleException
*/
- public static function sync_memberships($trace) {
+ public static function sync_memberships($trace, $timetosync = null) {
global $DB;
$plugin = api::get_enrolment_plugin();
@@ -294,14 +294,13 @@ public static function sync_memberships($trace) {
// adjusting and the filter each call so we get all records and don't end up
// getting same 250 each call.
$hasnext = true;
- $disableskip = get_config('enrol_arlo', 'disableskip');
- $lastime = empty($disableskip) ? get_config('enrol_arlo', 'lastregtimemodified') : date('c', 0);
- $lastregid = empty($disableskip) ? get_config('enrol_arlo', 'lastregid') : 0;
+ $lastime = empty($timetosync) ? get_config('enrol_arlo', 'lastregtimemodified') : date('c', $timetosync);
+ $lastregid = empty($timetosync) ? get_config('enrol_arlo', 'lastregid') : 0;
while ($hasnext) {
$hasnext = false; // Break paging by default.
// Update contact merge requests records every page.
$contactmergerequestsjob = job_factory::get_job(['type' => 'contact_merge_requests']);
- $contactmergerequestsjob->run();
+ $contactmergerequestsjob->run($timetosync);
$uri = new RequestUri();
$uri->setHost($pluginconfig->get('platform'));
$uri->setResourcePath('registrations/');
diff --git a/classes/task/enrolments_adhoc.php b/classes/task/enrolments_adhoc.php
new file mode 100644
index 00000000000..f5206c171f3
--- /dev/null
+++ b/classes/task/enrolments_adhoc.php
@@ -0,0 +1,73 @@
+.
+
+namespace enrol_arlo\task;
+
+use core\task\adhoc_task;
+use core\task\scheduled_task;
+use enrol_arlo\api;
+use enrol_arlo\local\job\memberships_job;
+use enrol_arlo\manager;
+use null_progress_trace;
+use text_progress_trace;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Create Moodle enrolments based off Arlo registrations adhoc.
+ *
+ * @package enrol_arlo
+ * @copyright 2020 LearningWorks Ltd {@link http://www.learningworks.co.nz}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class enrolments_adhoc extends adhoc_task {
+
+ /**
+ * Get schedule task human readable name.
+ *
+ * @return string
+ * @throws \coding_exception
+ */
+ public function get_name() {
+ return get_string('enrolmentstaskadhoc', 'enrol_arlo');
+ }
+
+ /**
+ * Execute the task.
+ *
+ * @throws \coding_exception
+ * @throws \dml_exception
+ * @throws \moodle_exception
+ */
+ public function execute() {
+ global $CFG;
+ require_once($CFG->dirroot . '/enrol/arlo/lib.php');
+ if (!enrol_is_enabled('arlo')) {
+ return;
+ }
+ $trace = new null_progress_trace();
+ if ($CFG->debug == DEBUG_DEVELOPER) {
+ $trace = new text_progress_trace();
+ }
+ $timetosync = $this->get_custom_data();
+ memberships_job::sync_memberships($trace, $timetosync);
+
+ $manager = new manager();
+ $manager->process_email_queue();
+ return true;
+ }
+
+}
diff --git a/lang/en/enrol_arlo.php b/lang/en/enrol_arlo.php
index c273e22061c..9d5bc2ddbef 100644
--- a/lang/en/enrol_arlo.php
+++ b/lang/en/enrol_arlo.php
@@ -451,8 +451,6 @@
$string['useadhoctask_desc'] = 'Enable this if you are planning to perform a large synchronisation between Arlo and Moodle (e.g. 100+ records at once).';
$string['onlyactive'] = 'Only active events';
$string['onlyactive_desc'] = 'Only process registrations for active Arlo courses and online activities.';
-$string['disableskip'] = 'Disable registration skip';
-$string['disableskip_desc'] = 'Disables the ability to skip processing old registrations (A sync will run for all registrations even the ones already processed).';
$string['enable_multisync'] = 'Enable multisync';
$string['enable_multisync_desc'] = 'When the webhook is enabled the sync is done only trough the webhooks. This setting allows to run the sync through the scheduled task as well.';
$string['technicalcontact'] = 'Contact email';
@@ -492,4 +490,9 @@
$string['retry_sync'] = 'Retry sync';
$string['connectionstatus'] = 'Connection Status: ';
$string['apifails'] = 'Global API fails: ';
-
+$string['synoldreg'] = 'Sync old registrations';
+$string['dateselector'] = 'Sync date selector';
+$string['syncsince'] = 'Sync since';
+$string['syncsince_help'] = 'Sync registrations since selected date.';
+$string['invalidstartdate'] = 'Date must be in the past';
+$string['taskqueued'] = 'Syncronisation task has been queued.';
diff --git a/locallib.php b/locallib.php
index b81886f6173..51b422edd33 100644
--- a/locallib.php
+++ b/locallib.php
@@ -387,3 +387,14 @@ function enrol_arlo_update_all_course_registrations($courseid) {
$DB->update_record('enrol_arlo_registration', $registration);
}
}
+
+/**
+ * Check if there are any adhoc syncs queued.
+ *
+ * @return bool
+ */
+function enrol_arlo_sync_adhoc_queued() {
+ global $DB;
+ $sql = "SELECT * FROM {task_adhoc} WHERE classname = '\\enrol_arlo\\task\\enrolments_adhoc'";
+ return $DB->record_exists_sql($sql);
+}
diff --git a/settings.php b/settings.php
index bc640f7930e..f103733400d 100644
--- a/settings.php
+++ b/settings.php
@@ -113,10 +113,6 @@
$name = get_string('onlyactive', 'enrol_arlo');
$settings->add(new admin_setting_configcheckbox('enrol_arlo/onlyactive', $name, $description, 0));
- $description = get_string('disableskip_desc', 'enrol_arlo');
- $name = get_string('disableskip', 'enrol_arlo');
- $settings->add(new admin_setting_configcheckbox('enrol_arlo/disableskip', $name, $description, 0));
-
// Only display management category if plugin enabled.
if ($enrol->is_enabled()) {
$name = get_string('managearlo', 'enrol_arlo');