MDL-32387 add paypal enrolment expiration action

This commit is contained in:
Petr Škoda 2012-12-23 16:46:52 +01:00
parent ca48fe5f97
commit d9a707adc2
6 changed files with 380 additions and 1 deletions

75
enrol/paypal/cli/sync.php Normal file
View File

@ -0,0 +1,75 @@
<?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/>.
/**
* PayPal CLI tool.
*
* Notes:
* - it is required to use the web server account when executing PHP CLI scripts
* - you need to change the "www-data" to match the apache user account
* - use "su" if "sudo" not available
*
* @package enrol_paypal
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__.'/../../../config.php');
require_once("$CFG->libdir/clilib.php");
// Now get cli options.
list($options, $unrecognized) = cli_get_params(array('verbose'=>false, 'help'=>false), array('v'=>'verbose', 'h'=>'help'));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
if ($options['help']) {
$help =
"Process PayPal expiration sync
Options:
-v, --verbose Print verbose progress information
-h, --help Print out this help
Example:
\$ sudo -u www-data /usr/bin/php enrol/paypal/cli/sync.php
";
echo $help;
die;
}
if (!enrol_is_enabled('paypal')) {
echo('enrol_paypal plugin is disabled'."\n");
exit(2);
}
if (empty($options['verbose'])) {
$trace = new null_progress_trace();
} else {
$trace = new text_progress_trace();
}
/** @var $plugin enrol_paypal_plugin */
$plugin = enrol_get_plugin('paypal');
$result = $plugin->sync($trace);
exit($result);

View File

@ -41,6 +41,8 @@ $string['enrolperiod_desc'] = 'Default length of time that the enrolment is vali
$string['enrolperiod_help'] = 'Length of time that the enrolment is valid, starting with the moment the user is enrolled. If disabled, the enrolment duration will be unlimited.';
$string['enrolstartdate'] = 'Start date';
$string['enrolstartdate_help'] = 'If enabled, users can be enrolled from this date onward only.';
$string['expiredaction'] = 'Enrolment expiration action';
$string['expiredaction_help'] = 'Select action to carry out when user enrolment expires. Please note that some user data and settings are purged from course during course unenrolment.';
$string['mailadmins'] = 'Notify admin';
$string['mailstudents'] = 'Notify students';
$string['mailteachers'] = 'Notify teachers';

View File

@ -283,4 +283,125 @@ class enrol_paypal_plugin extends enrol_plugin {
}
return $actions;
}
public function cron() {
$trace = new text_progress_trace();
$this->process_expirations($trace);
}
/**
* Execute synchronisation.
* @param progress_trace $trace
* @return int exit code, 0 means ok
*/
public function sync(progress_trace $trace) {
$this->process_expirations($trace);
return 0;
}
/**
* Do any enrolment expiration processing.
*
* @param progress_trace $trace
* @return bool true if any data processed, false if not
*/
protected function process_expirations(progress_trace $trace) {
global $DB;
//TODO: this method should be moved to parent class once we refactor all existing enrols, see MDL-36504.
$processed = false;
$name = $this->get_name();
// Deal with expired accounts.
$action = $this->get_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
if ($action == ENROL_EXT_REMOVED_UNENROL) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'enrol'=>$name);
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $ue) {
if (!$processed) {
$trace->output("Starting processing of enrol_$name expirations...");
$processed = true;
}
if (empty($instances[$ue->enrolid])) {
$instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
$instance = $instances[$ue->enrolid];
if (!$this->roles_protected()) {
// Let's just guess what extra roles are supposed to be removed.
if ($instance->roleid) {
role_unassign($instance->roleid, $ue->userid, $ue->contextid);
}
}
// The unenrol cleans up all subcontexts if this is the only course enrolment for this user.
$this->unenrol_user($instance, $ue->userid);
$trace->output("Unenrolling expired user $ue->userid from course $instance->courseid", 1);
}
$rs->close();
unset($instances);
} else if ($action == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
$instances = array();
$sql = "SELECT ue.*, e.courseid, c.id AS contextid
FROM {user_enrolments} ue
JOIN {enrol} e ON (e.id = ue.enrolid AND e.enrol = :enrol)
JOIN {context} c ON (c.instanceid = e.courseid AND c.contextlevel = :courselevel)
WHERE ue.timeend > 0 AND ue.timeend < :now
AND ue.status = :useractive";
$params = array('now'=>time(), 'courselevel'=>CONTEXT_COURSE, 'useractive'=>ENROL_USER_ACTIVE, 'enrol'=>$name);
$rs = $DB->get_recordset_sql($sql, $params);
foreach ($rs as $ue) {
if (!$processed) {
$trace->output("Starting processing of enrol_$name expirations...");
$processed = true;
}
if (empty($instances[$ue->enrolid])) {
$instances[$ue->enrolid] = $DB->get_record('enrol', array('id'=>$ue->enrolid));
}
$instance = $instances[$ue->enrolid];
if (!$this->roles_protected()) {
// Let's just guess what roles should be removed.
$count = $DB->count_records('role_assignments', array('userid'=>$ue->userid, 'contextid'=>$ue->contextid));
if ($count == 1) {
role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0));
} else if ($count > 1 and $instance->roleid) {
role_unassign($instance->roleid, $ue->userid, $ue->contextid, '', 0);
}
}
// In any case remove all roles that belong to this instance and user.
role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'enrol_'.$name, 'itemid'=>$instance->id), true);
// Final cleanup of subcontexts if there are no more course roles.
if (0 == $DB->count_records('role_assignments', array('userid'=>$ue->userid, 'contextid'=>$ue->contextid))) {
role_unassign_all(array('userid'=>$ue->userid, 'contextid'=>$ue->contextid, 'component'=>'', 'itemid'=>0), true);
}
$this->update_user_enrol($instance, $ue->userid, ENROL_USER_SUSPENDED);
$trace->output("Suspending expired user $ue->userid in course $instance->courseid", 1);
}
$rs->close();
unset($instances);
} else {
// ENROL_EXT_REMOVED_KEEP means no changes.
}
if ($processed) {
$trace->output("...finished processing of enrol_$name expirations");
} else {
$trace->output("No expired enrol_$name enrolments detected");
}
$trace->finished();
return $processed;
}
}

View File

@ -40,6 +40,15 @@ if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configcheckbox('enrol_paypal/mailadmins', get_string('mailadmins', 'enrol_paypal'), '', 0));
// Note: let's reuse the ext sync constants and strings here, internally it is very similar,
// it describes what should happen when users are not supposed to be enrolled any more.
$options = array(
ENROL_EXT_REMOVED_KEEP => get_string('extremovedkeep', 'enrol'),
ENROL_EXT_REMOVED_SUSPENDNOROLES => get_string('extremovedsuspendnoroles', 'enrol'),
ENROL_EXT_REMOVED_UNENROL => get_string('extremovedunenrol', 'enrol'),
);
$settings->add(new admin_setting_configselect('enrol_paypal/expiredaction', get_string('expiredaction', 'enrol_paypal'), get_string('expiredaction_help', 'enrol_paypal'), ENROL_EXT_REMOVED_SUSPENDNOROLES, $options));
//--- enrol instance defaults ----------------------------------------------------------------------------
$settings->add(new admin_setting_heading('enrol_paypal_defaults',
get_string('enrolinstancedefaults', 'admin'), get_string('enrolinstancedefaults_desc', 'admin')));

View File

@ -0,0 +1,171 @@
<?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/>.
/**
* paypal enrolment plugin tests.
*
* @package enrol_paypal
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
class enrol_paypal_testcase extends advanced_testcase {
protected function enable_plugin() {
$enabled = enrol_get_plugins(true);
$enabled['paypal'] = true;
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
protected function disable_plugin() {
$enabled = enrol_get_plugins(true);
unset($enabled['paypal']);
$enabled = array_keys($enabled);
set_config('enrol_plugins_enabled', implode(',', $enabled));
}
public function test_basics() {
$this->assertFalse(enrol_is_enabled('paypal'));
$plugin = enrol_get_plugin('paypal');
$this->assertInstanceOf('enrol_paypal_plugin', $plugin);
$this->assertEquals(ENROL_EXT_REMOVED_SUSPENDNOROLES, get_config('enrol_paypal', 'expiredaction'));
}
public function test_sync_nothing() {
$this->resetAfterTest();
$this->enable_plugin();
$paypalplugin = enrol_get_plugin('paypal');
// Just make sure the sync does not throw any errors when nothing to do.
$paypalplugin->sync(new null_progress_trace());
}
public function test_expired() {
global $DB;
$this->resetAfterTest();
/** @var enrol_paypal_plugin $paypalplugin */
$paypalplugin = enrol_get_plugin('paypal');
/** @var enrol_manual_plugin $manualplugin */
$manualplugin = enrol_get_plugin('manual');
$this->assertNotEmpty($manualplugin);
$now = time();
$trace = new null_progress_trace();
$this->enable_plugin();
// Prepare some data.
$studentrole = $DB->get_record('role', array('shortname'=>'student'));
$this->assertNotEmpty($studentrole);
$teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
$this->assertNotEmpty($teacherrole);
$managerrole = $DB->get_record('role', array('shortname'=>'manager'));
$this->assertNotEmpty($managerrole);
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
$course1 = $this->getDataGenerator()->create_course();
$course2 = $this->getDataGenerator()->create_course();
$context1 = context_course::instance($course1->id);
$context2 = context_course::instance($course2->id);
$data = array('roleid'=>$studentrole->id, 'courseid'=>$course1->id);
$id = $paypalplugin->add_instance($course1, $data);
$instance1 = $DB->get_record('enrol', array('id'=>$id));
$data = array('roleid'=>$studentrole->id, 'courseid'=>$course2->id);
$id = $paypalplugin->add_instance($course2, $data);
$instance2 = $DB->get_record('enrol', array('id'=>$id));
$data = array('roleid'=>$teacherrole->id, 'courseid'=>$course2->id);
$id = $paypalplugin->add_instance($course2, $data);
$instance3 = $DB->get_record('enrol', array('id'=>$id));
$maninstance1 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$manualplugin->enrol_user($maninstance1, $user3->id, $studentrole->id);
$this->assertEquals(1, $DB->count_records('user_enrolments'));
$this->assertEquals(1, $DB->count_records('role_assignments'));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$paypalplugin->enrol_user($instance1, $user1->id, $studentrole->id);
$paypalplugin->enrol_user($instance1, $user2->id, $studentrole->id);
$paypalplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
$paypalplugin->enrol_user($instance2, $user1->id, $studentrole->id, 0, 0);
$paypalplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now-60*60);
$paypalplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now+60*60);
$paypalplugin->enrol_user($instance3, $user1->id, $teacherrole->id, $now-60*60*24*7, $now-60);
$paypalplugin->enrol_user($instance3, $user4->id, $teacherrole->id);
role_assign($managerrole->id, $user3->id, $context1->id);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(9, $DB->count_records('role_assignments'));
$this->assertEquals(6, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$managerrole->id)));
// Execute tests.
$paypalplugin->set_config('expiredaction', ENROL_EXT_REMOVED_KEEP);
$code = $paypalplugin->sync($trace);
$this->assertSame(0, $code);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(9, $DB->count_records('role_assignments'));
$paypalplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
$paypalplugin->sync($trace);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(6, $DB->count_records('role_assignments'));
$this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user3->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user2->id, 'roleid'=>$studentrole->id)));
$this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
$this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context2->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id)));
$paypalplugin->set_config('expiredaction', ENROL_EXT_REMOVED_UNENROL);
role_assign($studentrole->id, $user3->id, $context1->id);
role_assign($studentrole->id, $user2->id, $context2->id);
role_assign($teacherrole->id, $user1->id, $context2->id);
$this->assertEquals(9, $DB->count_records('user_enrolments'));
$this->assertEquals(9, $DB->count_records('role_assignments'));
$this->assertEquals(6, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
$paypalplugin->sync($trace);
$this->assertEquals(6, $DB->count_records('user_enrolments'));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user3->id)));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance2->id, 'userid'=>$user2->id)));
$this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
$this->assertEquals(5, $DB->count_records('role_assignments'));
$this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
$this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
}
}

View File

@ -26,6 +26,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2012112900; // The current plugin version (Date: YYYYMMDDXX)
$plugin->version = 2012122300; // The current plugin version (Date: YYYYMMDDXX)
$plugin->requires = 2012112900; // Requires this Moodle version
$plugin->component = 'enrol_paypal'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 60;