first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+338
View File
@@ -0,0 +1,338 @@
<?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/>.
/**
* Privacy Subsystem implementation for enrol_paypal.
*
* @package enrol_paypal
* @category privacy
* @copyright 2018 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_paypal\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\userlist;
use core_privacy\local\request\writer;
/**
* Privacy Subsystem implementation for enrol_paypal.
*
* @copyright 2018 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
// Transactions store user data.
\core_privacy\local\metadata\provider,
// The paypal enrolment plugin contains user's transactions.
\core_privacy\local\request\plugin\provider,
// This plugin is capable of determining which users have data within it.
\core_privacy\local\request\core_userlist_provider {
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
$collection->add_external_location_link(
'paypal.com',
[
'os0' => 'privacy:metadata:enrol_paypal:paypal_com:os0',
'custom' => 'privacy:metadata:enrol_paypal:paypal_com:custom',
'first_name' => 'privacy:metadata:enrol_paypal:paypal_com:first_name',
'last_name' => 'privacy:metadata:enrol_paypal:paypal_com:last_name',
'address' => 'privacy:metadata:enrol_paypal:paypal_com:address',
'city' => 'privacy:metadata:enrol_paypal:paypal_com:city',
'email' => 'privacy:metadata:enrol_paypal:paypal_com:email',
'country' => 'privacy:metadata:enrol_paypal:paypal_com:country',
],
'privacy:metadata:enrol_paypal:paypal_com'
);
// The enrol_paypal has a DB table that contains user data.
$collection->add_database_table(
'enrol_paypal',
[
'business' => 'privacy:metadata:enrol_paypal:enrol_paypal:business',
'receiver_email' => 'privacy:metadata:enrol_paypal:enrol_paypal:receiver_email',
'receiver_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:receiver_id',
'item_name' => 'privacy:metadata:enrol_paypal:enrol_paypal:item_name',
'courseid' => 'privacy:metadata:enrol_paypal:enrol_paypal:courseid',
'userid' => 'privacy:metadata:enrol_paypal:enrol_paypal:userid',
'instanceid' => 'privacy:metadata:enrol_paypal:enrol_paypal:instanceid',
'memo' => 'privacy:metadata:enrol_paypal:enrol_paypal:memo',
'tax' => 'privacy:metadata:enrol_paypal:enrol_paypal:tax',
'option_selection1_x' => 'privacy:metadata:enrol_paypal:enrol_paypal:option_selection1_x',
'payment_status' => 'privacy:metadata:enrol_paypal:enrol_paypal:payment_status',
'pending_reason' => 'privacy:metadata:enrol_paypal:enrol_paypal:pending_reason',
'reason_code' => 'privacy:metadata:enrol_paypal:enrol_paypal:reason_code',
'txn_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:txn_id',
'parent_txn_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:parent_txn_id',
'payment_type' => 'privacy:metadata:enrol_paypal:enrol_paypal:payment_type',
'timeupdated' => 'privacy:metadata:enrol_paypal:enrol_paypal:timeupdated'
],
'privacy:metadata:enrol_paypal:enrol_paypal'
);
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid): contextlist {
$contextlist = new contextlist();
// Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal,
// therefore there is no need to use LOWER() on them in the following query.
$sql = "SELECT ctx.id
FROM {enrol_paypal} ep
JOIN {enrol} e ON ep.instanceid = e.id
JOIN {context} ctx ON e.courseid = ctx.instanceid AND ctx.contextlevel = :contextcourse
JOIN {user} u ON u.id = ep.userid OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business
WHERE u.id = :userid";
$params = [
'contextcourse' => CONTEXT_COURSE,
'userid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
if (!$context instanceof \context_course) {
return;
}
// Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal,
// therefore there is no need to use LOWER() on them in the following query.
$sql = "SELECT u.id
FROM {enrol_paypal} ep
JOIN {enrol} e ON ep.instanceid = e.id
JOIN {user} u ON ep.userid = u.id OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business
WHERE e.courseid = :courseid";
$params = ['courseid' => $context->instanceid];
$userlist->add_from_sql('id', $sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist->count())) {
return;
}
$user = $contextlist->get_user();
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
// Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal,
// therefore there is no need to use LOWER() on them in the following query.
$sql = "SELECT ep.*
FROM {enrol_paypal} ep
JOIN {enrol} e ON ep.instanceid = e.id
JOIN {context} ctx ON e.courseid = ctx.instanceid AND ctx.contextlevel = :contextcourse
JOIN {user} u ON u.id = ep.userid OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business
WHERE ctx.id {$contextsql} AND u.id = :userid
ORDER BY e.courseid";
$params = [
'contextcourse' => CONTEXT_COURSE,
'userid' => $user->id,
'emailuserid' => $user->id,
];
$params += $contextparams;
// Reference to the course seen in the last iteration of the loop. By comparing this with the current record, and
// because we know the results are ordered, we know when we've moved to the PayPal transactions for a new course
// and therefore when we can export the complete data for the last course.
$lastcourseid = null;
$strtransactions = get_string('transactions', 'enrol_paypal');
$transactions = [];
$paypalrecords = $DB->get_recordset_sql($sql, $params);
foreach ($paypalrecords as $paypalrecord) {
if ($lastcourseid != $paypalrecord->courseid) {
if (!empty($transactions)) {
$coursecontext = \context_course::instance($paypalrecord->courseid);
writer::with_context($coursecontext)->export_data(
[$strtransactions],
(object) ['transactions' => $transactions]
);
}
$transactions = [];
}
$transaction = (object) [
'receiver_id' => $paypalrecord->receiver_id,
'item_name' => $paypalrecord->item_name,
'userid' => $paypalrecord->userid,
'memo' => $paypalrecord->memo,
'tax' => $paypalrecord->tax,
'option_name1' => $paypalrecord->option_name1,
'option_selection1_x' => $paypalrecord->option_selection1_x,
'option_name2' => $paypalrecord->option_name2,
'option_selection2_x' => $paypalrecord->option_selection2_x,
'payment_status' => $paypalrecord->payment_status,
'pending_reason' => $paypalrecord->pending_reason,
'reason_code' => $paypalrecord->reason_code,
'txn_id' => $paypalrecord->txn_id,
'parent_txn_id' => $paypalrecord->parent_txn_id,
'payment_type' => $paypalrecord->payment_type,
'timeupdated' => \core_privacy\local\request\transform::datetime($paypalrecord->timeupdated),
];
if ($paypalrecord->userid == $user->id) {
$transaction->userid = $paypalrecord->userid;
}
if ($paypalrecord->business == \core_text::strtolower($user->email)) {
$transaction->business = $paypalrecord->business;
}
if ($paypalrecord->receiver_email == \core_text::strtolower($user->email)) {
$transaction->receiver_email = $paypalrecord->receiver_email;
}
$transactions[] = $paypalrecord;
$lastcourseid = $paypalrecord->courseid;
}
$paypalrecords->close();
// The data for the last activity won't have been written yet, so make sure to write it now!
if (!empty($transactions)) {
$coursecontext = \context_course::instance($paypalrecord->courseid);
writer::with_context($coursecontext)->export_data(
[$strtransactions],
(object) ['transactions' => $transactions]
);
}
}
/**
* Delete all data for all users in the specified context.
*
* @param \context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
if (!$context instanceof \context_course) {
return;
}
$DB->delete_records('enrol_paypal', array('courseid' => $context->instanceid));
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist->count())) {
return;
}
$user = $contextlist->get_user();
$contexts = $contextlist->get_contexts();
$courseids = [];
foreach ($contexts as $context) {
if ($context instanceof \context_course) {
$courseids[] = $context->instanceid;
}
}
list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
$select = "userid = :userid AND courseid $insql";
$params = $inparams + ['userid' => $user->id];
$DB->delete_records_select('enrol_paypal', $select, $params);
// We do not want to delete the payment record when the user is just the receiver of payment.
// In that case, we just delete the receiver's info from the transaction record.
$select = "business = :business AND courseid $insql";
$params = $inparams + ['business' => \core_text::strtolower($user->email)];
$DB->set_field_select('enrol_paypal', 'business', '', $select, $params);
$select = "receiver_email = :receiver_email AND courseid $insql";
$params = $inparams + ['receiver_email' => \core_text::strtolower($user->email)];
$DB->set_field_select('enrol_paypal', 'receiver_email', '', $select, $params);
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
$context = $userlist->get_context();
if ($context->contextlevel != CONTEXT_COURSE) {
return;
}
$userids = $userlist->get_userids();
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params = ['courseid' => $context->instanceid] + $userparams;
$select = "courseid = :courseid AND userid $usersql";
$DB->delete_records_select('enrol_paypal', $select, $params);
// We do not want to delete the payment record when the user is just the receiver of payment.
// In that case, we just delete the receiver's info from the transaction record.
$select = "courseid = :courseid AND business IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)";
$DB->set_field_select('enrol_paypal', 'business', '', $select, $params);
$select = "courseid = :courseid AND receiver_email IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)";
$DB->set_field_select('enrol_paypal', 'receiver_email', '', $select, $params);
}
}
@@ -0,0 +1,58 @@
<?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/>.
/**
* Process expirations task.
*
* @package enrol_paypal
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_paypal\task;
defined('MOODLE_INTERNAL') || die();
/**
* Process expirations task.
*
* @package enrol_paypal
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class process_expirations extends \core\task\scheduled_task {
/**
* Name for this task.
*
* @return string
*/
public function get_name() {
return get_string('processexpirationstask', 'enrol_paypal');
}
/**
* Run task for processing expirations.
*/
public function execute() {
$enrol = enrol_get_plugin('paypal');
$trace = new \text_progress_trace();
$enrol->process_expirations($trace);
}
}
+91
View File
@@ -0,0 +1,91 @@
<?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 utility class.
*
* @package enrol_paypal
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_paypal;
defined('MOODLE_INTERNAL') || die();
/**
* PayPal enrolment plugin utility class.
*
* @package enrol_paypal
* @copyright 2016 Cameron Ball <cameron@cameron1729.xyz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class util {
/**
* Alerts site admin of potential problems.
*
* @param string $subject email subject
* @param \stdClass $data PayPal IPN data
*/
public static function message_paypal_error_to_admin($subject, $data) {
$admin = get_admin();
$site = get_site();
$message = "$site->fullname: Transaction failed.\n\n$subject\n\n";
foreach ($data as $key => $value) {
$message .= "$key => $value\n";
}
$eventdata = new \core\message\message();
$eventdata->courseid = empty($data->courseid) ? SITEID : $data->courseid;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paypal';
$eventdata->name = 'paypal_enrolment';
$eventdata->userfrom = $admin;
$eventdata->userto = $admin;
$eventdata->subject = "PAYPAL ERROR: ".$subject;
$eventdata->fullmessage = $message;
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}
/**
* Silent exception handler.
*
* @return callable exception handler
*/
public static function get_exception_handler() {
return function($ex) {
$info = get_exception_info($ex);
$logerrmsg = "enrol_paypal IPN exception handler: ".$info->message;
if (debugging('', DEBUG_NORMAL)) {
$logerrmsg .= ' Debug: '.$info->debuginfo."\n".format_backtrace($info->backtrace, true);
}
error_log($logerrmsg);
if (http_response_code() == 200) {
http_response_code(500);
}
exit(0);
};
}
}
+75
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);
+62
View File
@@ -0,0 +1,62 @@
<?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/>.
/**
* Capabilities for paypal enrolment plugin.
*
* @package enrol_paypal
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'enrol/paypal:config' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
)
),
'enrol/paypal:manage' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
)
),
'enrol/paypal:unenrol' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
'manager' => CAP_ALLOW,
)
),
'enrol/paypal:unenrolself' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => array(
)
),
);
+43
View File
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="enrol/paypal/db" VERSION="20180625" COMMENT="XMLDB file for Moodle enrol/paypal"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="enrol_paypal" COMMENT="Holds all known information about PayPal transactions">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="business" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="receiver_email" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="receiver_id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="item_name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="instanceid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="memo" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="tax" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="option_name1" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="option_selection1_x" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="option_name2" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="option_selection2_x" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="payment_status" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="pending_reason" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="reason_code" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="txn_id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="parent_txn_id" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="payment_type" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timeupdated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="courseid" TYPE="foreign" FIELDS="courseid" REFTABLE="course" REFFIELDS="id"/>
<KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
<KEY NAME="instanceid" TYPE="foreign" FIELDS="instanceid" REFTABLE="enrol" REFFIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="business" UNIQUE="false" FIELDS="business"/>
<INDEX NAME="receiver_email" UNIQUE="false" FIELDS="receiver_email"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
+34
View File
@@ -0,0 +1,34 @@
<?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/>.
/**
* Defines message providers (types of message sent) for the PayPal enrolment plugin.
*
* @package enrol_paypal
* @copyright 2012 Chris Follin
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$messageproviders = array(
'paypal_enrolment' => [
'defaults' => [
'popup' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
'email' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED,
],
],
);
+39
View File
@@ -0,0 +1,39 @@
<?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/>.
/**
* Task definition for enrol_paypal.
* @author Farhan Karmali <farhan6318@gmail.com>
* @copyright Farhan Karmali
* @package enrol_paypal
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$tasks = array(
array(
'classname' => '\enrol_paypal\task\process_expirations',
'blocking' => 0,
'minute' => '*',
'hour' => '*',
'day' => '*',
'month' => '*',
'dayofweek' => '*',
'disabled' => 0
)
);
+57
View File
@@ -0,0 +1,57 @@
<?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/>.
/**
* This file keeps track of upgrades to the paypal enrolment plugin
*
* @package enrol_paypal
* @copyright 2010 Eugene Venter
* @author Eugene Venter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// Sometimes, changes between versions involve
// alterations to database structures and other
// major things that may break installations.
//
// The upgrade function in this file will attempt
// to perform all the necessary actions to upgrade
// your older installation to the current version.
//
// If there's something it cannot do itself, it
// will tell you what you need to do.
//
// The commands in here will all be database-neutral,
// using the methods of database_manager class
//
// Please do not forget to use upgrade_set_timeout()
// before any action that may take longer time to finish.
function xmldb_enrol_paypal_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+46
View File
@@ -0,0 +1,46 @@
<div align="center">
<p><?php print_string("paymentrequired") ?></p>
<p><b><?php echo $instancename; ?></b></p>
<p><b><?php echo get_string("cost").": {$instance->currency} {$localisedcost}"; ?></b></p>
<p><img alt="<?php print_string('paypalaccepted', 'enrol_paypal') ?>" src="https://www.paypal.com/en_US/i/logo/PayPal_mark_60x38.gif" /></p>
<p><?php print_string("paymentinstant") ?></p>
<?php
$paypalurl = empty($CFG->usepaypalsandbox) ? 'https://www.paypal.com/cgi-bin/webscr' : 'https://www.sandbox.paypal.com/cgi-bin/webscr';
?>
<form action="<?php echo $paypalurl ?>" method="post">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="charset" value="utf-8" />
<input type="hidden" name="business" value="<?php p($this->get_config('paypalbusiness'))?>" />
<input type="hidden" name="item_name" value="<?php p($coursefullname) ?>" />
<input type="hidden" name="item_number" value="<?php p($courseshortname) ?>" />
<input type="hidden" name="quantity" value="1" />
<input type="hidden" name="on0" value="<?php print_string("user") ?>" />
<input type="hidden" name="os0" value="<?php p($userfullname) ?>" />
<input type="hidden" name="custom" value="<?php echo "{$USER->id}-{$course->id}-{$instance->id}" ?>" />
<input type="hidden" name="currency_code" value="<?php p($instance->currency) ?>" />
<input type="hidden" name="amount" value="<?php p($cost) ?>" />
<input type="hidden" name="for_auction" value="false" />
<input type="hidden" name="no_note" value="1" />
<input type="hidden" name="no_shipping" value="1" />
<input type="hidden" name="notify_url" value="<?php echo "$CFG->wwwroot/enrol/paypal/ipn.php"?>" />
<input type="hidden" name="return" value="<?php echo "$CFG->wwwroot/enrol/paypal/return.php?id=$course->id" ?>" />
<input type="hidden" name="cancel_return" value="<?php echo $CFG->wwwroot ?>" />
<input type="hidden" name="rm" value="2" />
<input type="hidden" name="cbt" value="<?php print_string("continuetocourse") ?>" />
<input type="hidden" name="first_name" value="<?php p($userfirstname) ?>" />
<input type="hidden" name="last_name" value="<?php p($userlastname) ?>" />
<input type="hidden" name="address" value="<?php p($useraddress) ?>" />
<input type="hidden" name="city" value="<?php p($usercity) ?>" />
<input type="hidden" name="email" value="<?php p($USER->email) ?>" />
<input type="hidden" name="country" value="<?php p($USER->country) ?>" />
<input type="submit" value="<?php print_string("sendpaymentbutton", "enrol_paypal") ?>" />
</form>
</div>
+328
View File
@@ -0,0 +1,328 @@
<?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/>.
/**
* Listens for Instant Payment Notification from PayPal
*
* This script waits for Payment notification from PayPal,
* then double checks that data by sending it back to PayPal.
* If PayPal verifies this then it sets up the enrolment for that
* user.
*
* @package enrol_paypal
* @copyright 2010 Eugene Venter
* @author Eugene Venter - based on code by others
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// Disable moodle specific debug messages and any errors in output,
// comment out when debugging or better look into error log!
define('NO_DEBUG_DISPLAY', true);
// This script does not require login.
require("../../config.php"); // phpcs:ignore
require_once("lib.php");
require_once($CFG->libdir.'/enrollib.php');
require_once($CFG->libdir . '/filelib.php');
// PayPal does not like when we return error messages here,
// the custom handler just logs exceptions and stops.
set_exception_handler(\enrol_paypal\util::get_exception_handler());
// Make sure we are enabled in the first place.
if (!enrol_is_enabled('paypal')) {
http_response_code(503);
throw new moodle_exception('errdisabled', 'enrol_paypal');
}
/// Keep out casual intruders
if (empty($_POST) or !empty($_GET)) {
http_response_code(400);
throw new moodle_exception('invalidrequest', 'core_error');
}
/// Read all the data from PayPal and get it ready for later;
/// we expect only valid UTF-8 encoding, it is the responsibility
/// of user to set it up properly in PayPal business account,
/// it is documented in docs wiki.
$req = 'cmd=_notify-validate';
$data = new stdClass();
foreach ($_POST as $key => $value) {
if ($key !== clean_param($key, PARAM_ALPHANUMEXT)) {
throw new moodle_exception('invalidrequest', 'core_error', '', null, $key);
}
if (is_array($value)) {
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Unexpected array param: '.$key);
}
$req .= "&$key=".urlencode($value);
$data->$key = fix_utf8($value);
}
if (empty($data->custom)) {
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Missing request param: custom');
}
$custom = explode('-', $data->custom);
unset($data->custom);
if (empty($custom) || count($custom) < 3) {
throw new moodle_exception('invalidrequest', 'core_error', '', null, 'Invalid value of the request param: custom');
}
$data->userid = (int)$custom[0];
$data->courseid = (int)$custom[1];
$data->instanceid = (int)$custom[2];
$data->payment_gross = $data->mc_gross;
$data->payment_currency = $data->mc_currency;
$data->timeupdated = time();
$user = $DB->get_record("user", array("id" => $data->userid), "*", MUST_EXIST);
$course = $DB->get_record("course", array("id" => $data->courseid), "*", MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);
$PAGE->set_context($context);
$plugin_instance = $DB->get_record("enrol", array("id" => $data->instanceid, "enrol" => "paypal", "status" => 0), "*", MUST_EXIST);
$plugin = enrol_get_plugin('paypal');
/// Open a connection back to PayPal to validate the data
$paypaladdr = empty($CFG->usepaypalsandbox) ? 'ipnpb.paypal.com' : 'ipnpb.sandbox.paypal.com';
$c = new curl();
$options = array(
'returntransfer' => true,
'httpheader' => array('application/x-www-form-urlencoded', "Host: $paypaladdr"),
'timeout' => 30,
'CURLOPT_HTTP_VERSION' => CURL_HTTP_VERSION_1_1,
);
$location = "https://$paypaladdr/cgi-bin/webscr";
$result = $c->post($location, $req, $options);
if ($c->get_errno()) {
throw new moodle_exception('errpaypalconnect', 'enrol_paypal', '', array('url' => $paypaladdr, 'result' => $result),
json_encode($data));
}
/// Connection is OK, so now we post the data to validate it
/// Now read the response and check if everything is OK.
if (strlen($result) > 0) {
if (strcmp($result, "VERIFIED") == 0) { // VALID PAYMENT!
// check the payment_status and payment_reason
// If status is not completed or pending then unenrol the student if already enrolled
// and notify admin
if ($data->payment_status != "Completed" and $data->payment_status != "Pending") {
$plugin->unenrol_user($plugin_instance, $data->userid);
\enrol_paypal\util::message_paypal_error_to_admin("Status not completed or pending. User unenrolled from course",
$data);
die;
}
// If currency is incorrectly set then someone maybe trying to cheat the system
if ($data->mc_currency != $plugin_instance->currency) {
\enrol_paypal\util::message_paypal_error_to_admin(
"Currency does not match course settings, received: ".$data->mc_currency,
$data);
die;
}
// If status is pending and reason is other than echeck then we are on hold until further notice
// Email user to let them know. Email admin.
if ($data->payment_status == "Pending" and $data->pending_reason != "echeck") {
$eventdata = new \core\message\message();
$eventdata->courseid = empty($data->courseid) ? SITEID : $data->courseid;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paypal';
$eventdata->name = 'paypal_enrolment';
$eventdata->userfrom = get_admin();
$eventdata->userto = $user;
$eventdata->subject = "Moodle: PayPal payment";
$eventdata->fullmessage = "Your PayPal payment is pending.";
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
\enrol_paypal\util::message_paypal_error_to_admin("Payment pending", $data);
die;
}
// If our status is not completed or not pending on an echeck clearance then ignore and die
// This check is redundant at present but may be useful if paypal extend the return codes in the future
if (! ( $data->payment_status == "Completed" or
($data->payment_status == "Pending" and $data->pending_reason == "echeck") ) ) {
die;
}
// At this point we only proceed with a status of completed or pending with a reason of echeck
// Make sure this transaction doesn't exist already.
if ($existing = $DB->get_record("enrol_paypal", array("txn_id" => $data->txn_id), "*", IGNORE_MULTIPLE)) {
\enrol_paypal\util::message_paypal_error_to_admin("Transaction $data->txn_id is being repeated!", $data);
die;
}
// Check that the receiver email is the one we want it to be.
if (isset($data->business)) {
$recipient = $data->business;
} else if (isset($data->receiver_email)) {
$recipient = $data->receiver_email;
} else {
$recipient = 'empty';
}
if (core_text::strtolower($recipient) !== core_text::strtolower($plugin->get_config('paypalbusiness'))) {
\enrol_paypal\util::message_paypal_error_to_admin("Business email is {$recipient} (not ".
$plugin->get_config('paypalbusiness').")", $data);
die;
}
if (!$user = $DB->get_record('user', array('id'=>$data->userid))) { // Check that user exists
\enrol_paypal\util::message_paypal_error_to_admin("User $data->userid doesn't exist", $data);
die;
}
if (!$course = $DB->get_record('course', array('id'=>$data->courseid))) { // Check that course exists
\enrol_paypal\util::message_paypal_error_to_admin("Course $data->courseid doesn't exist", $data);
die;
}
$coursecontext = context_course::instance($course->id, IGNORE_MISSING);
// Check that amount paid is the correct amount
if ( (float) $plugin_instance->cost <= 0 ) {
$cost = (float) $plugin->get_config('cost');
} else {
$cost = (float) $plugin_instance->cost;
}
// Use the same rounding of floats as on the enrol form.
$cost = format_float($cost, 2, false);
if ($data->payment_gross < $cost) {
\enrol_paypal\util::message_paypal_error_to_admin("Amount paid is not enough ($data->payment_gross < $cost))", $data);
die;
}
// Use the queried course's full name for the item_name field.
$data->item_name = $course->fullname;
// ALL CLEAR !
$DB->insert_record("enrol_paypal", $data);
if ($plugin_instance->enrolperiod) {
$timestart = time();
$timeend = $timestart + $plugin_instance->enrolperiod;
} else {
$timestart = 0;
$timeend = 0;
}
// Enrol user
$plugin->enrol_user($plugin_instance, $user->id, $plugin_instance->roleid, $timestart, $timeend);
// Pass $view=true to filter hidden caps if the user cannot see them
if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
'', '', '', '', false, true)) {
$users = sort_by_roleassignment_authority($users, $context);
$teacher = array_shift($users);
} else {
$teacher = false;
}
$mailstudents = $plugin->get_config('mailstudents');
$mailteachers = $plugin->get_config('mailteachers');
$mailadmins = $plugin->get_config('mailadmins');
$shortname = format_string($course->shortname, true, array('context' => $context));
if (!empty($mailstudents)) {
$a = new stdClass();
$a->coursename = format_string($course->fullname, true, array('context' => $coursecontext));
$a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id";
$eventdata = new \core\message\message();
$eventdata->courseid = $course->id;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paypal';
$eventdata->name = 'paypal_enrolment';
$eventdata->userfrom = empty($teacher) ? core_user::get_noreply_user() : $teacher;
$eventdata->userto = $user;
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
$eventdata->fullmessage = get_string('welcometocoursetext', '', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}
if (!empty($mailteachers) && !empty($teacher)) {
$a->course = format_string($course->fullname, true, array('context' => $coursecontext));
$a->user = fullname($user);
$eventdata = new \core\message\message();
$eventdata->courseid = $course->id;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paypal';
$eventdata->name = 'paypal_enrolment';
$eventdata->userfrom = $user;
$eventdata->userto = $teacher;
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
$eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}
if (!empty($mailadmins)) {
$a->course = format_string($course->fullname, true, array('context' => $coursecontext));
$a->user = fullname($user);
$admins = get_admins();
foreach ($admins as $admin) {
$eventdata = new \core\message\message();
$eventdata->courseid = $course->id;
$eventdata->modulename = 'moodle';
$eventdata->component = 'enrol_paypal';
$eventdata->name = 'paypal_enrolment';
$eventdata->userfrom = $user;
$eventdata->userto = $admin;
$eventdata->subject = get_string("enrolmentnew", 'enrol', $shortname);
$eventdata->fullmessage = get_string('enrolmentnewuser', 'enrol', $a);
$eventdata->fullmessageformat = FORMAT_PLAIN;
$eventdata->fullmessagehtml = '';
$eventdata->smallmessage = '';
message_send($eventdata);
}
}
} else if (strcmp ($result, "INVALID") == 0) { // ERROR
$DB->insert_record("enrol_paypal", $data, false);
throw new moodle_exception('erripninvalid', 'enrol_paypal', '', null, json_encode($data));
}
}
+91
View File
@@ -0,0 +1,91 @@
<?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/>.
/**
* Strings for component 'enrol_paypal', language 'en'.
*
* @package enrol_paypal
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['assignrole'] = 'Assign role';
$string['businessemail'] = 'PayPal business email';
$string['businessemail_desc'] = 'The email address of your business PayPal account';
$string['cost'] = 'Enrol cost';
$string['costerror'] = 'The enrolment cost is not numeric';
$string['costorkey'] = 'Please choose one of the following methods of enrolment.';
$string['currency'] = 'Currency';
$string['defaultrole'] = 'Default role assignment';
$string['defaultrole_desc'] = 'Select role which should be assigned to users during PayPal enrolments';
$string['enrolenddate'] = 'End date';
$string['enrolenddate_help'] = 'If enabled, users can be enrolled until this date only.';
$string['enrolenddaterror'] = 'Enrolment end date cannot be earlier than start date';
$string['enrolperiod'] = 'Enrolment duration';
$string['enrolperiod_desc'] = 'Default length of time that the enrolment is valid. If set to zero, the enrolment duration will be unlimited by default.';
$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['errdisabled'] = 'The PayPal enrolment plugin is disabled and does not handle payment notifications.';
$string['erripninvalid'] = 'Instant payment notification has not been verified by PayPal.';
$string['errpaypalconnect'] = 'Could not connect to {$a->url} to verify the instant payment notification: {$a->result}';
$string['expiredaction'] = 'Enrolment expiry 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';
$string['messageprovider:paypal_enrolment'] = 'PayPal enrolment messages';
$string['nocost'] = 'There is no cost associated with enrolling in this course!';
$string['paypal:config'] = 'Configure PayPal enrol instances';
$string['paypal:manage'] = 'Manage enrolled users';
$string['paypal:unenrol'] = 'Unenrol users from course';
$string['paypal:unenrolself'] = 'Unenrol self from the course';
$string['paypalaccepted'] = 'PayPal payments accepted';
$string['pluginname'] = 'PayPal';
$string['pluginname_desc'] = 'The PayPal module allows you to set up paid courses. If the cost for any course is zero, then students are not asked to pay for entry. There is a site-wide cost that you set here as a default for the whole site and then a course setting that you can set for each course individually. The course cost overrides the site cost.';
$string['privacy:metadata:enrol_paypal:enrol_paypal'] = 'Information about the PayPal transactions for PayPal enrolments.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:business'] = 'Email address or PayPal account ID of the payment recipient (that is, the merchant).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:courseid'] = 'The ID of the course that is sold.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:instanceid'] = 'The ID of the enrolment instance in the course.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:item_name'] = 'The full name of the course that its enrolment has been sold.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:memo'] = 'A note that was entered by the buyer in PayPal website payments note field.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:option_selection1_x'] = 'Full name of the buyer.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:parent_txn_id'] = 'In the case of a refund, reversal, or canceled reversal, this would be the transaction ID of the original transaction.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:payment_status'] = 'The status of the payment.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:payment_type'] = 'Holds whether the payment was funded with an eCheck (echeck), or was funded with PayPal balance, credit card, or instant transfer (instant).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:pending_reason'] = 'The reason why payment status is pending (if that is).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:reason_code'] = 'The reason why payment status is Reversed, Refunded, Canceled_Reversal, or Denied (if the status is one of them).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:receiver_email'] = 'Primary email address of the payment recipient (that is, the merchant).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:receiver_id'] = 'Unique PayPal account ID of the payment recipient (i.e., the merchant).';
$string['privacy:metadata:enrol_paypal:enrol_paypal:tax'] = 'Amount of tax charged on payment.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:timeupdated'] = 'The time of Moodle being notified by PayPal about the payment.';
$string['privacy:metadata:enrol_paypal:enrol_paypal:txn_id'] = 'The merchant\'s original transaction identification number for the payment from the buyer, against which the case was registered';
$string['privacy:metadata:enrol_paypal:enrol_paypal:userid'] = 'The ID of the user who bought the course enrolment.';
$string['privacy:metadata:enrol_paypal:paypal_com'] = 'The PayPal enrolment plugin transmits user data from Moodle to the PayPal website.';
$string['privacy:metadata:enrol_paypal:paypal_com:address'] = 'Address of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:city'] = 'City of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:country'] = 'Country of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:custom'] = 'A hyphen-separated string that contains ID of the user (the buyer), ID of the course, ID of the enrolment instance.';
$string['privacy:metadata:enrol_paypal:paypal_com:email'] = 'Email address of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:first_name'] = 'First name of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:last_name'] = 'Last name of the user who is buying the course.';
$string['privacy:metadata:enrol_paypal:paypal_com:os0'] = 'Full name of the buyer.';
$string['processexpirationstask'] = 'PayPal enrolment send expiry notifications task';
$string['sendpaymentbutton'] = 'Send payment via PayPal';
$string['status'] = 'Allow PayPal enrolments';
$string['status_desc'] = 'Allow users to use PayPal to enrol into a course by default.';
$string['transactions'] = 'PayPal transactions';
$string['unenrolselfconfirm'] = 'Do you really want to unenrol yourself from course "{$a}"?';
+424
View File
@@ -0,0 +1,424 @@
<?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.
*
* This plugin allows you to set up paid courses.
*
* @package enrol_paypal
* @copyright 2010 Eugene Venter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Paypal enrolment plugin implementation.
* @author Eugene Venter - based on code by Martin Dougiamas and others
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class enrol_paypal_plugin extends enrol_plugin {
public function get_currencies() {
// See https://www.paypal.com/cgi-bin/webscr?cmd=p/sell/mc/mc_intro-outside,
// 3-character ISO-4217: https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_currency_codes
$codes = array(
'AUD', 'BRL', 'CAD', 'CHF', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'ILS', 'INR', 'JPY',
'MXN', 'MYR', 'NOK', 'NZD', 'PHP', 'PLN', 'RUB', 'SEK', 'SGD', 'THB', 'TRY', 'TWD', 'USD');
$currencies = array();
foreach ($codes as $c) {
$currencies[$c] = new lang_string($c, 'core_currencies');
}
return $currencies;
}
/**
* Returns optional enrolment information icons.
*
* This is used in course list for quick overview of enrolment options.
*
* We are not using single instance parameter because sometimes
* we might want to prevent icon repetition when multiple instances
* of one type exist. One instance may also produce several icons.
*
* @param array $instances all enrol instances of this type in one course
* @return array of pix_icon
*/
public function get_info_icons(array $instances) {
$found = false;
foreach ($instances as $instance) {
if ($instance->enrolstartdate != 0 && $instance->enrolstartdate > time()) {
continue;
}
if ($instance->enrolenddate != 0 && $instance->enrolenddate < time()) {
continue;
}
$found = true;
break;
}
if ($found) {
return array(new pix_icon('icon', get_string('pluginname', 'enrol_paypal'), 'enrol_paypal'));
}
return array();
}
public function roles_protected() {
// users with role assign cap may tweak the roles later
return false;
}
public function allow_unenrol(stdClass $instance) {
// users with unenrol cap may unenrol other users manually - requires enrol/paypal:unenrol
return true;
}
public function allow_manage(stdClass $instance) {
// users with manage cap may tweak period and status - requires enrol/paypal:manage
return true;
}
public function show_enrolme_link(stdClass $instance) {
return ($instance->status == ENROL_INSTANCE_ENABLED);
}
/**
* Returns true if the user can add a new instance in this course.
* @param int $courseid
* @return boolean
*/
public function can_add_instance($courseid) {
$context = context_course::instance($courseid, MUST_EXIST);
if (!has_capability('moodle/course:enrolconfig', $context) or !has_capability('enrol/paypal:config', $context)) {
return false;
}
// multiple instances supported - different cost for different roles
return true;
}
/**
* We are a good plugin and don't invent our own UI/validation code path.
*
* @return boolean
*/
public function use_standard_editing_ui() {
return true;
}
/**
* Add new instance of enrol plugin.
* @param object $course
* @param array $fields instance fields
* @return int id of new instance, null if can not be created
*/
public function add_instance($course, array $fields = null) {
if ($fields && !empty($fields['cost'])) {
$fields['cost'] = unformat_float($fields['cost']);
}
return parent::add_instance($course, $fields);
}
/**
* Update instance of enrol plugin.
* @param stdClass $instance
* @param stdClass $data modified instance fields
* @return boolean
*/
public function update_instance($instance, $data) {
if ($data) {
$data->cost = unformat_float($data->cost);
}
return parent::update_instance($instance, $data);
}
/**
* Creates course enrol form, checks if form submitted
* and enrols user if necessary. It can also redirect.
*
* @param stdClass $instance
* @return string html text, usually a form in a text box
*/
function enrol_page_hook(stdClass $instance) {
global $CFG, $USER, $OUTPUT, $PAGE, $DB;
ob_start();
if ($DB->record_exists('user_enrolments', array('userid'=>$USER->id, 'enrolid'=>$instance->id))) {
return ob_get_clean();
}
if ($instance->enrolstartdate != 0 && $instance->enrolstartdate > time()) {
return ob_get_clean();
}
if ($instance->enrolenddate != 0 && $instance->enrolenddate < time()) {
return ob_get_clean();
}
$course = $DB->get_record('course', array('id'=>$instance->courseid));
$context = context_course::instance($course->id);
$shortname = format_string($course->shortname, true, array('context' => $context));
$strloginto = get_string("loginto", "", $shortname);
$strcourses = get_string("courses");
// Pass $view=true to filter hidden caps if the user cannot see them
if ($users = get_users_by_capability($context, 'moodle/course:update', 'u.*', 'u.id ASC',
'', '', '', '', false, true)) {
$users = sort_by_roleassignment_authority($users, $context);
$teacher = array_shift($users);
} else {
$teacher = false;
}
if ( (float) $instance->cost <= 0 ) {
$cost = (float) $this->get_config('cost');
} else {
$cost = (float) $instance->cost;
}
if (abs($cost) < 0.01) { // no cost, other enrolment methods (instances) should be used
echo '<p>'.get_string('nocost', 'enrol_paypal').'</p>';
} else {
// Calculate localised and "." cost, make sure we send PayPal the same value,
// please note PayPal expects amount with 2 decimal places and "." separator.
$localisedcost = format_float($cost, 2, true);
$cost = format_float($cost, 2, false);
if (isguestuser()) { // force login only for guest user, not real users with guest role
$wwwroot = $CFG->wwwroot;
echo '<div class="mdl-align"><p>'.get_string('paymentrequired').'</p>';
echo '<p><b>'.get_string('cost').": $instance->currency $localisedcost".'</b></p>';
echo '<p><a href="'.$wwwroot.'/login/">'.get_string('loginsite').'</a></p>';
echo '</div>';
} else {
//Sanitise some fields before building the PayPal form
$coursefullname = format_string($course->fullname, true, array('context'=>$context));
$courseshortname = $shortname;
$userfullname = fullname($USER);
$userfirstname = $USER->firstname;
$userlastname = $USER->lastname;
$useraddress = $USER->address;
$usercity = $USER->city;
$instancename = $this->get_instance_name($instance);
include($CFG->dirroot.'/enrol/paypal/enrol.html');
}
}
return $OUTPUT->box(ob_get_clean());
}
/**
* Restore instance and map settings.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $course
* @param int $oldid
*/
public function restore_instance(restore_enrolments_structure_step $step, stdClass $data, $course, $oldid) {
global $DB;
if ($step->get_task()->get_target() == backup::TARGET_NEW_COURSE) {
$merge = false;
} else {
$merge = array(
'courseid' => $data->courseid,
'enrol' => $this->get_name(),
'roleid' => $data->roleid,
'cost' => $data->cost,
'currency' => $data->currency,
);
}
if ($merge and $instances = $DB->get_records('enrol', $merge, 'id')) {
$instance = reset($instances);
$instanceid = $instance->id;
} else {
$instanceid = $this->add_instance($course, (array)$data);
}
$step->set_mapping('enrol', $oldid, $instanceid);
}
/**
* Restore user enrolment.
*
* @param restore_enrolments_structure_step $step
* @param stdClass $data
* @param stdClass $instance
* @param int $oldinstancestatus
* @param int $userid
*/
public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) {
$this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, $data->status);
}
/**
* Return an array of valid options for the status.
*
* @return array
*/
protected function get_status_options() {
$options = array(ENROL_INSTANCE_ENABLED => get_string('yes'),
ENROL_INSTANCE_DISABLED => get_string('no'));
return $options;
}
/**
* Return an array of valid options for the roleid.
*
* @param stdClass $instance
* @param context $context
* @return array
*/
protected function get_roleid_options($instance, $context) {
if ($instance->id) {
$roles = get_default_enrol_roles($context, $instance->roleid);
} else {
$roles = get_default_enrol_roles($context, $this->get_config('roleid'));
}
return $roles;
}
/**
* Add elements to the edit instance form.
*
* @param stdClass $instance
* @param MoodleQuickForm $mform
* @param context $context
* @return bool
*/
public function edit_instance_form($instance, MoodleQuickForm $mform, $context) {
$mform->addElement('text', 'name', get_string('custominstancename', 'enrol'));
$mform->setType('name', PARAM_TEXT);
$options = $this->get_status_options();
$mform->addElement('select', 'status', get_string('status', 'enrol_paypal'), $options);
$mform->setDefault('status', $this->get_config('status'));
$mform->addElement('text', 'cost', get_string('cost', 'enrol_paypal'), array('size' => 4));
$mform->setType('cost', PARAM_RAW);
$mform->setDefault('cost', format_float($this->get_config('cost'), 2, true));
$paypalcurrencies = $this->get_currencies();
$mform->addElement('select', 'currency', get_string('currency', 'enrol_paypal'), $paypalcurrencies);
$mform->setDefault('currency', $this->get_config('currency'));
$roles = $this->get_roleid_options($instance, $context);
$mform->addElement('select', 'roleid', get_string('assignrole', 'enrol_paypal'), $roles);
$mform->setDefault('roleid', $this->get_config('roleid'));
$options = array('optional' => true, 'defaultunit' => 86400);
$mform->addElement('duration', 'enrolperiod', get_string('enrolperiod', 'enrol_paypal'), $options);
$mform->setDefault('enrolperiod', $this->get_config('enrolperiod'));
$mform->addHelpButton('enrolperiod', 'enrolperiod', 'enrol_paypal');
$options = array('optional' => true);
$mform->addElement('date_time_selector', 'enrolstartdate', get_string('enrolstartdate', 'enrol_paypal'), $options);
$mform->setDefault('enrolstartdate', 0);
$mform->addHelpButton('enrolstartdate', 'enrolstartdate', 'enrol_paypal');
$options = array('optional' => true);
$mform->addElement('date_time_selector', 'enrolenddate', get_string('enrolenddate', 'enrol_paypal'), $options);
$mform->setDefault('enrolenddate', 0);
$mform->addHelpButton('enrolenddate', 'enrolenddate', 'enrol_paypal');
if (enrol_accessing_via_instance($instance)) {
$warningtext = get_string('instanceeditselfwarningtext', 'core_enrol');
$mform->addElement('static', 'selfwarn', get_string('instanceeditselfwarning', 'core_enrol'), $warningtext);
}
}
/**
* Perform custom validation of the data used to edit the instance.
*
* @param array $data array of ("fieldname"=>value) of submitted data
* @param array $files array of uploaded files "element_name"=>tmp_file_path
* @param object $instance The instance loaded from the DB
* @param context $context The context of the instance we are editing
* @return array of "element_name"=>"error_description" if there are errors,
* or an empty array if everything is OK.
* @return void
*/
public function edit_instance_validation($data, $files, $instance, $context) {
$errors = array();
if (!empty($data['enrolenddate']) and $data['enrolenddate'] < $data['enrolstartdate']) {
$errors['enrolenddate'] = get_string('enrolenddaterror', 'enrol_paypal');
}
$cost = str_replace(get_string('decsep', 'langconfig'), '.', $data['cost']);
if (!is_numeric($cost)) {
$errors['cost'] = get_string('costerror', 'enrol_paypal');
}
$validstatus = array_keys($this->get_status_options());
$validcurrency = array_keys($this->get_currencies());
$validroles = array_keys($this->get_roleid_options($instance, $context));
$tovalidate = array(
'name' => PARAM_TEXT,
'status' => $validstatus,
'currency' => $validcurrency,
'roleid' => $validroles,
'enrolperiod' => PARAM_INT,
'enrolstartdate' => PARAM_INT,
'enrolenddate' => PARAM_INT
);
$typeerrors = $this->validate_param_types($data, $tovalidate);
$errors = array_merge($errors, $typeerrors);
return $errors;
}
/**
* 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;
}
/**
* Is it possible to delete enrol instance via standard UI?
*
* @param stdClass $instance
* @return bool
*/
public function can_delete_instance($instance) {
$context = context_course::instance($instance->courseid);
return has_capability('enrol/paypal:config', $context);
}
/**
* Is it possible to hide/show enrol instance via standard UI?
*
* @param stdClass $instance
* @return bool
*/
public function can_hide_show_instance($instance) {
$context = context_course::instance($instance->courseid);
return has_capability('enrol/paypal:config', $context);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

+3
View File
@@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-0.1 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M14.3 3.8c.5.3.8.7 1 1.1.2.5.4 1 .4 1.7 0 1.5-.6 2.8-1.9 3.8-1.3.9-3.1 1.4-5.4 1.4h-.3c-.6 0-1.1.4-1.2 1L6.4 15c-.1.5-.7 1-1.2 1H3.8c-.5 0-.9-.4-.8-1l.2-1h.3c.5 0 1.1-.4 1.2-1l.5-2.3c.1-.5.7-1 1.2-1h.3c2.3 0 4.1-.5 5.4-1.4 1.3-1 1.9-2.2 1.9-3.8 0-.3 0-.7-.1-1 .2.2.3.2.4.3zm-1.9-1.9c-.2-.5-.6-.8-1-1.1-.5-.3-1-.5-1.6-.6C9.1.1 8.5 0 8.5 0H3.8c-.5 0-1.1.4-1.2 1L0 12c-.1.5.2 1 .8 1h1.4c.5 0 1.1-.4 1.2-1l.5-2.3c.1-.5.7-1 1.2-1h.3c2.3 0 4.1-.5 5.4-1.4 1.3-1 1.9-2.2 1.9-3.7 0-.7-.1-1.3-.3-1.7zM8.3 5.7c-.6.4-1.4.5-1.4.5-.5.1-1.2.1-1.6.1-.3 0-.5-.4-.4-1l.5-1.9c.1-.5.7-1 1.2-1H7c.7 0 1.3.1 1.6.4.4.2.6.6.6 1.1 0 .8-.3 1.4-.9 1.8z" fill="#888"/></svg>

After

Width:  |  Height:  |  Size: 951 B

+60
View File
@@ -0,0 +1,60 @@
<?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 utility script
*
* @package enrol_paypal
* @copyright 2004 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require("../../config.php");
require_once("$CFG->dirroot/enrol/paypal/lib.php");
$id = required_param('id', PARAM_INT);
if (!$course = $DB->get_record("course", array("id"=>$id))) {
redirect($CFG->wwwroot);
}
$context = context_course::instance($course->id, MUST_EXIST);
$PAGE->set_context($context);
require_login();
if (!empty($SESSION->wantsurl)) {
$destination = $SESSION->wantsurl;
unset($SESSION->wantsurl);
} else {
$destination = "$CFG->wwwroot/course/view.php?id=$course->id";
}
$fullname = format_string($course->fullname, true, array('context' => $context));
if (is_enrolled($context, NULL, '', true)) { // TODO: use real paypal check
redirect($destination, get_string('paymentthanks', '', $fullname));
} else { /// Somehow they aren't enrolled yet! :-(
$PAGE->set_url($destination);
echo $OUTPUT->header();
$a = new stdClass();
$a->teacher = get_string('defaultcourseteacher');
$a->fullname = $fullname;
notice(get_string('paymentsorry', '', $a), $destination);
}
+77
View File
@@ -0,0 +1,77 @@
<?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 enrolments plugin settings and presets.
*
* @package enrol_paypal
* @copyright 2010 Eugene Venter
* @author Eugene Venter - based on code by Petr Skoda and others
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
if ($ADMIN->fulltree) {
//--- settings ------------------------------------------------------------------------------------------
$settings->add(new admin_setting_heading('enrol_paypal_settings', '', get_string('pluginname_desc', 'enrol_paypal')));
$settings->add(new admin_setting_configtext('enrol_paypal/paypalbusiness', get_string('businessemail', 'enrol_paypal'), get_string('businessemail_desc', 'enrol_paypal'), '', PARAM_EMAIL));
$settings->add(new admin_setting_configcheckbox('enrol_paypal/mailstudents', get_string('mailstudents', 'enrol_paypal'), '', 0));
$settings->add(new admin_setting_configcheckbox('enrol_paypal/mailteachers', get_string('mailteachers', 'enrol_paypal'), '', 0));
$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')));
$options = array(ENROL_INSTANCE_ENABLED => get_string('yes'),
ENROL_INSTANCE_DISABLED => get_string('no'));
$settings->add(new admin_setting_configselect('enrol_paypal/status',
get_string('status', 'enrol_paypal'), get_string('status_desc', 'enrol_paypal'), ENROL_INSTANCE_DISABLED, $options));
$settings->add(new admin_setting_configtext('enrol_paypal/cost', get_string('cost', 'enrol_paypal'), '', 0, PARAM_FLOAT, 4));
$paypalcurrencies = enrol_get_plugin('paypal')->get_currencies();
$settings->add(new admin_setting_configselect('enrol_paypal/currency', get_string('currency', 'enrol_paypal'), '', 'USD', $paypalcurrencies));
if (!during_initial_install()) {
$options = get_default_enrol_roles(context_system::instance());
$student = get_archetype_roles('student');
$student = reset($student);
$settings->add(new admin_setting_configselect('enrol_paypal/roleid',
get_string('defaultrole', 'enrol_paypal'),
get_string('defaultrole_desc', 'enrol_paypal'),
$student->id ?? null,
$options));
}
$settings->add(new admin_setting_configduration('enrol_paypal/enrolperiod',
get_string('enrolperiod', 'enrol_paypal'), get_string('enrolperiod_desc', 'enrol_paypal'), 0));
}
+225
View File
@@ -0,0 +1,225 @@
<?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 enrol_paypal;
/**
* paypal enrolment plugin tests.
*
* @package enrol_paypal
* @category test
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class paypal_test 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(): void {
$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(): void {
$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(): void {
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)));
}
/**
* Test for getting user enrolment actions.
*/
public function test_get_user_enrolment_actions(): void {
global $CFG, $PAGE;
$this->resetAfterTest();
// Set page URL to prevent debugging messages.
$PAGE->set_url('/enrol/editinstance.php');
$pluginname = 'paypal';
// Only enable the paypal enrol plugin.
$CFG->enrol_plugins_enabled = $pluginname;
$generator = $this->getDataGenerator();
// Get the enrol plugin.
$plugin = enrol_get_plugin($pluginname);
// Create a course.
$course = $generator->create_course();
// Enable this enrol plugin for the course.
$plugin->add_instance($course);
// Create a student.
$student = $generator->create_user();
// Enrol the student to the course.
$generator->enrol_user($student->id, $course->id, 'student', $pluginname);
require_once($CFG->dirroot . '/enrol/locallib.php');
$manager = new \course_enrolment_manager($PAGE, $course);
$userenrolments = $manager->get_user_enrolments($student->id);
$this->assertCount(1, $userenrolments);
$ue = reset($userenrolments);
// Login as admin to see all enrol actions.
$this->setAdminUser();
$actions = $plugin->get_user_enrolment_actions($manager, $ue);
// Paypal enrolment has 2 enrol actions for active users when logged in as admin: edit and unenrol.
$this->assertCount(2, $actions);
// Enrol actions when viewing as a teacher.
// Create a teacher.
$teacher = $generator->create_user();
// Enrol the teacher to the course.
$generator->enrol_user($teacher->id, $course->id, 'editingteacher', $pluginname);
// Login as the teacher.
$this->setUser($teacher);
$actions = $plugin->get_user_enrolment_actions($manager, $ue);
// Teachers don't have the enrol/paypal:unenrol capability by default, but have enrol/paypal:manage.
$this->assertCount(1, $actions);
}
}
@@ -0,0 +1,839 @@
<?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/>.
/**
* Privacy provider tests.
*
* @package enrol_paypal
* @category test
* @copyright 2018 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace enrol_paypal\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
use enrol_paypal\privacy\provider;
use core_privacy\local\request\writer;
use stdClass;
/**
* Privacy provider test for enrol_paypal.
*
* @copyright 2018 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends \core_privacy\tests\provider_testcase {
/** @var stdClass A user whose email address matches the business field in some of the PayPal transactions. */
protected $businessuser1;
/** @var stdClass A user whose email address matches the business field in some of the PayPal transactions. */
protected $businessuser2;
/** @var stdClass A user whose email address matches the business field in some of the PayPal transactions. */
protected $businessuser3;
/** @var stdClass A user whose email address matches the receiver_email field in some of the PayPal transactions. */
protected $receiveruser1;
/** @var stdClass A user whose email address matches the receiver_email field in some of the PayPal transactions. */
protected $receiveruser2;
/** @var stdClass A user whose email address matches the receiver_email field in some of the PayPal transactions. */
protected $receiveruser3;
/** @var stdClass A user who is not enrolled in any course. */
protected $student0;
/** @var stdClass A student who is only enrolled in course1. */
protected $student1;
/** @var stdClass A student who is only enrolled in course2 with 2 transaction histories in the course. */
protected $student2;
/** @var stdClass A student who is only enrolled in course3 with 1 transaction histories in the course. */
protected $student3;
/** @var stdClass A student who is enrolled in both course1 and course2. */
protected $student12;
/** @var stdClass A test course with 2 enrolments for student1 and student12. */
protected $course1;
/** @var stdClass A test course with 2 enrolments for student2 and student12. */
protected $course2;
/** @var stdClass A test course with 2 enrolments for student2 and student12. */
protected $course3;
protected function setUp(): void {
global $DB;
$this->resetAfterTest();
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$generator = $this->getDataGenerator();
// Create seller accounts.
$this->businessuser1 = $generator->create_user(['email' => 'business1@domain.invalid']);
$this->businessuser2 = $generator->create_user(['email' => 'business2@domain.invalid']);
$this->businessuser3 = $generator->create_user(['email' => 'business3@domain.invalid']);
$this->receiveruser1 = $generator->create_user(['email' => 'receiver1@domain.invalid']);
$this->receiveruser2 = $generator->create_user(['email' => 'receiver2@domain.invalid']);
$this->receiveruser3 = $generator->create_user(['email' => 'receiver3@domain.invalid']);
// Create courses.
$this->course1 = $generator->create_course();
$this->course2 = $generator->create_course();
$this->course3 = $generator->create_course();
// Create enrolment instances.
$paypalplugin = enrol_get_plugin('paypal');
$enrolinstanceid = $paypalplugin->add_instance($this->course1,
['roleid' => $studentrole->id, 'courseid' => $this->course1->id]);
$enrolinstance1 = $DB->get_record('enrol', array('id' => $enrolinstanceid));
$enrolinstanceid = $paypalplugin->add_instance($this->course2,
['roleid' => $studentrole->id, 'courseid' => $this->course2->id]);
$enrolinstance2 = $DB->get_record('enrol', array('id' => $enrolinstanceid));
$enrolinstanceid = $paypalplugin->add_instance($this->course3,
['roleid' => $studentrole->id, 'courseid' => $this->course3->id]);
$enrolinstance3 = $DB->get_record('enrol', array('id' => $enrolinstanceid));
// Create students.
$this->student0 = $generator->create_user(); // This user will not be enrolled in any course.
$this->student1 = $generator->create_user();
$this->student2 = $generator->create_user();
$this->student3 = $generator->create_user();
$this->student12 = $generator->create_user();
// Enrol student1 in course1.
$paypalplugin->enrol_user($enrolinstance1, $this->student1->id, $studentrole->id);
$this->create_enrol_paypal_record(
$this->businessuser1,
$this->receiveruser1,
$this->course1,
$this->student1,
$enrolinstance1,
'STUDENT1-IN-COURSE1-00',
time()
);
// Enrol student2 in course2.
$paypalplugin->enrol_user($enrolinstance2, $this->student2->id, $studentrole->id);
// This user has 2 transaction histories.
// Here is the first one.
$this->create_enrol_paypal_record(
$this->businessuser1,
$this->receiveruser2,
$this->course2,
$this->student2,
$enrolinstance2,
'STUDENT2-IN-COURSE2-00',
// Yesterday.
time() - DAYSECS
);
// And now, the second one.
$this->create_enrol_paypal_record(
$this->businessuser1,
$this->receiveruser2,
$this->course2,
$this->student2,
$enrolinstance2,
'STUDENT2-IN-COURSE2-01',
time()
);
// Enrol student12 in course1 and course2.
// First in course1.
$paypalplugin->enrol_user($enrolinstance1, $this->student12->id, $studentrole->id);
$this->create_enrol_paypal_record(
$this->businessuser2,
$this->receiveruser1,
$this->course1,
$this->student12,
$enrolinstance1,
'STUDENT12-IN-COURSE1-00',
time()
);
// Then in course2.
$paypalplugin->enrol_user($enrolinstance2, $this->student12->id, $studentrole->id);
$this->create_enrol_paypal_record(
$this->businessuser2,
$this->receiveruser2,
$this->course2,
$this->student12,
$enrolinstance2,
'STUDENT12-IN-COURSE2-00',
time()
);
// Enrol student3 in course3 with businessuser3 as the receiver.
$paypalplugin->enrol_user($enrolinstance1, $this->student3->id, $studentrole->id);
$this->create_enrol_paypal_record(
$this->businessuser3,
$this->receiveruser3,
$this->course3,
$this->student3,
$enrolinstance3,
'STUDENT3-IN-COURSE3-00',
time()
);
}
/**
* Test for provider::get_metadata().
*/
public function test_get_metadata(): void {
$collection = new collection('enrol_paypal');
$newcollection = provider::get_metadata($collection);
$itemcollection = $newcollection->get_collection();
$this->assertCount(2, $itemcollection);
$location = reset($itemcollection);
$this->assertEquals('paypal.com', $location->get_name());
$this->assertEquals('privacy:metadata:enrol_paypal:paypal_com', $location->get_summary());
$privacyfields = $location->get_privacy_fields();
$this->assertArrayHasKey('os0', $privacyfields);
$this->assertArrayHasKey('custom', $privacyfields);
$this->assertArrayHasKey('first_name', $privacyfields);
$this->assertArrayHasKey('last_name', $privacyfields);
$this->assertArrayHasKey('address', $privacyfields);
$this->assertArrayHasKey('city', $privacyfields);
$this->assertArrayHasKey('email', $privacyfields);
$this->assertArrayHasKey('country', $privacyfields);
$table = next($itemcollection);
$this->assertEquals('enrol_paypal', $table->get_name());
$this->assertEquals('privacy:metadata:enrol_paypal:enrol_paypal', $table->get_summary());
$privacyfields = $table->get_privacy_fields();
$this->assertArrayHasKey('business', $privacyfields);
$this->assertArrayHasKey('receiver_email', $privacyfields);
$this->assertArrayHasKey('receiver_id', $privacyfields);
$this->assertArrayHasKey('item_name', $privacyfields);
$this->assertArrayHasKey('courseid', $privacyfields);
$this->assertArrayHasKey('userid', $privacyfields);
$this->assertArrayHasKey('instanceid', $privacyfields);
$this->assertArrayHasKey('memo', $privacyfields);
$this->assertArrayHasKey('tax', $privacyfields);
$this->assertArrayHasKey('option_selection1_x', $privacyfields);
$this->assertArrayHasKey('payment_status', $privacyfields);
$this->assertArrayHasKey('pending_reason', $privacyfields);
$this->assertArrayHasKey('reason_code', $privacyfields);
$this->assertArrayHasKey('txn_id', $privacyfields);
$this->assertArrayHasKey('parent_txn_id', $privacyfields);
$this->assertArrayHasKey('payment_type', $privacyfields);
$this->assertArrayHasKey('timeupdated', $privacyfields);
}
/**
* Test for provider::get_contexts_for_userid().
*/
public function test_get_contexts_for_userid(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$coursecontext2 = \context_course::instance($this->course2->id);
// Student1 is only enrolled in 1 course.
$contextlist = provider::get_contexts_for_userid($this->student1->id);
$this->assertCount(1, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEquals([$coursecontext1->id], $contextids);
// Student12 is enrolled in 2 course.
$contextlist = provider::get_contexts_for_userid($this->student12->id);
$this->assertCount(2, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertContainsEquals($coursecontext1->id, $contextids);
$this->assertContainsEquals($coursecontext2->id, $contextids);
}
/**
* Test for provider::get_contexts_for_userid with a user who is a receiver.
*/
public function test_get_contexts_for_userid_receiver(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$coursecontext2 = \context_course::instance($this->course2->id);
// Receiver User 1 is the Receiver of one course.
$contextlist = provider::get_contexts_for_userid($this->receiveruser1->id);
$this->assertCount(1, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEquals([$coursecontext1->id], $contextids);
// Receiver User 2 is the Receiver of course.
$contextlist = provider::get_contexts_for_userid($this->receiveruser2->id);
$this->assertCount(1, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEquals([$coursecontext2->id], $contextids);
}
/**
* Test for provider::get_contexts_for_userid with a user who is a business.
*/
public function test_get_contexts_for_userid_business(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$coursecontext2 = \context_course::instance($this->course2->id);
$coursecontext3 = \context_course::instance($this->course3->id);
// Business User 1 is the Receiver of course 1 and course 2.
$contextlist = provider::get_contexts_for_userid($this->businessuser1->id);
$this->assertCount(2, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEqualsCanonicalizing([$coursecontext1->id, $coursecontext2->id], $contextids);
// Business User 3 is the Receiver of course 3 only.
$contextlist = provider::get_contexts_for_userid($this->businessuser3->id);
$this->assertCount(1, $contextlist);
$contextids = $contextlist->get_contextids();
$this->assertEquals([$coursecontext3->id], $contextids);
}
/**
* Test for provider::export_user_data().
*/
public function test_export_user_data(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->student1);
// Export all of the data for the context.
$this->export_context_data_for_user($this->student1->id, $coursecontext1, 'enrol_paypal');
$writer = writer::with_context($coursecontext1);
$this->assertTrue($writer->has_any_data());
$data = $writer->get_data([get_string('transactions', 'enrol_paypal')]);
}
/**
* Test for provider::export_user_data() when user is not enrolled.
*/
public function test_export_user_data_not_enrolled(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->student2);
// Export all of the data for the context.
$this->export_context_data_for_user($this->student2->id, $coursecontext1, 'enrol_paypal');
$writer = writer::with_context($coursecontext1);
$this->assertFalse($writer->has_any_data());
}
/**
* Test for provider::export_user_data() when user has no enrolment.
*/
public function test_export_user_data_no_enrolment(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->student0);
// Export all of the data for the context.
$this->export_context_data_for_user($this->student0->id, $coursecontext1, 'enrol_paypal');
$writer = writer::with_context($coursecontext1);
$this->assertFalse($writer->has_any_data());
}
public function test_export_user_data_multiple_paypal_history(): void {
$coursecontext2 = \context_course::instance($this->course2->id);
$this->setUser($this->student2);
// Export all of the data for the context.
$this->export_context_data_for_user($this->student2->id, $coursecontext2, 'enrol_paypal');
$writer = writer::with_context($coursecontext2);
$this->assertTrue($writer->has_any_data());
$data = $writer->get_data([get_string('transactions', 'enrol_paypal')]);
$this->assertCount(2, $data->transactions);
$this->assertEqualsCanonicalizing(
['STUDENT2-IN-COURSE2-00', 'STUDENT2-IN-COURSE2-01'],
array_column($data->transactions, 'txn_id'));
}
/**
* Test for provider::delete_data_for_all_users_in_context().
*/
public function test_delete_data_for_all_users_in_context(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->student1);
// Before deletion, we should have 2 PayPal transactions in course1 and 3 PayPal transactions in course2.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
// Delete data based on context.
provider::delete_data_for_all_users_in_context($coursecontext1);
// After deletion, PayPal transactions in course1 should have been deleted.
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
}
/**
* Test for provider::delete_data_for_all_users_in_context() when there is multiple transaction histories for a user.
*/
public function test_delete_data_for_all_users_in_context_multiple_transactions(): void {
global $DB;
$coursecontext2 = \context_course::instance($this->course2->id);
$this->setUser($this->student2);
// Before deletion, we should have 2 PayPal transactions in course1 and 3 PayPal transactions in course2.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
// Delete data based on context.
provider::delete_data_for_all_users_in_context($coursecontext2);
// After deletion, PayPal transactions in course2 should have been deleted.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
}
/**
* Test for provider::delete_data_for_user() when student is enrolled in multiple courses and deleting from one of them.
*/
public function test_delete_data_for_user_from_single_context(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->student12);
// Before deletion, we should have 2 PayPal transactions (1 of them for student12) in course1
// and 3 PayPal transactions (1 of them for student12) in course2.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'userid' => $this->student12->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id, 'userid' => $this->student12->id])
);
// Delete data for user.
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student12, 'enrol_paypal',
[$coursecontext1->id]);
provider::delete_data_for_user($contextlist);
// After deletion, PayPal transactions for student12 in course1 should have been deleted.
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'userid' => $this->student12->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id, 'userid' => $this->student12->id])
);
}
/**
* Test for provider::delete_data_for_user() when student is enrolled in multiple courses and deleting from all of them.
*/
public function test_delete_data_for_user_from_multiple_context(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
$coursecontext2 = \context_course::instance($this->course2->id);
$this->setUser($this->student12);
// Before deletion, we should have 2 PayPal transactions (1 of them for student12) in course1
// and 3 PayPal transactions (1 of them for student12) in course2.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'userid' => $this->student12->id])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id, 'userid' => $this->student12->id])
);
// Delete data for user.
$contextlist = new \core_privacy\local\request\approved_contextlist($this->student12, 'enrol_paypal',
[$coursecontext1->id, $coursecontext2->id]);
provider::delete_data_for_user($contextlist);
// After deletion, PayPal enrolment data for student12 in both course1 and course2 should have been deleted.
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'userid' => $this->student12->id])
);
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id, 'userid' => $this->student12->id])
);
}
/**
* Test for provider::delete_data_for_user() when user is not enrolled, but is the receiver of the payment.
*/
public function test_delete_data_for_user_for_business_user(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->businessuser1);
// Before deletion, we should have 5 PayPal enrolments.
// 3 of which paid to businessuser1 and 2 of which paid to businessuser2.
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['business' => $this->businessuser1->email])
);
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['business' => $this->businessuser2->email])
);
// Delete data for user in $coursecontext1.
$contextlist = new \core_privacy\local\request\approved_contextlist($this->businessuser1, 'enrol_paypal',
[$coursecontext1->id]);
provider::delete_data_for_user($contextlist);
// After deletion, PayPal enrolment data for businessuser1 in course1 should have been deleted.
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'business' => $this->businessuser1->email])
);
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['business' => $this->businessuser1->email])
);
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id, 'business' => ''])
);
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['business' => $this->businessuser2->email])
);
}
/**
* Test for provider::delete_data_for_user() when user is not enrolled, but is the receiver of the payment.
*/
public function test_delete_data_for_user_for_receiver_user(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
$this->setUser($this->receiveruser1);
// Before deletion, we should have 5 PayPal enrolments.
// 2 of which paid to receiveruser1 and 3 of which paid to receiveruser2.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser1->email])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser2->email])
);
// Delete data for user.
$contextlist = new \core_privacy\local\request\approved_contextlist($this->receiveruser1, 'enrol_paypal',
[$coursecontext1->id]);
provider::delete_data_for_user($contextlist);
// After deletion, PayPal enrolment data for receiveruser1 in course1 should have been deleted.
$this->assertEquals(
0,
$DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser1->email])
);
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['receiver_email' => ''])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser2->email])
);
}
/**
* Helper function to create an enrol_paypal record.
*
* @param \stdClass $business The user associated with the business
* @param \stdClass $receiver The user associated with the receiver
* @param \stdClass $course The course to associate with
* @param \stdClass $user The user associated with the student
* @param \stdClass $enrol The enrolment instance
* @param String $txnid The Paypal txnid to use
* @param int $time The txn time
*/
protected function create_enrol_paypal_record($business, $receiver, $course, $user, $enrol, $txnid, $time) {
global $DB;
$paypaldata = [
'business' => $business->email,
'receiver_email' => $receiver->email,
'receiver_id' => 'SELLERSID',
'item_name' => $course->fullname,
'courseid' => $course->id,
'userid' => $user->id,
'instanceid' => $enrol->id,
'payment_status' => 'Completed',
'txn_id' => $txnid,
'payment_type' => 'instant',
'timeupdated' => $time,
];
$DB->insert_record('enrol_paypal', $paypaldata);
}
/**
* Test for provider::get_users_in_context().
*/
public function test_get_users_in_context(): void {
$coursecontext1 = \context_course::instance($this->course1->id);
$coursecontext2 = \context_course::instance($this->course2->id);
$coursecontext3 = \context_course::instance($this->course3->id);
$userlist1 = new \core_privacy\local\request\userlist($coursecontext1, 'enrol_paypal');
provider::get_users_in_context($userlist1);
$this->assertEqualsCanonicalizing(
[
$this->businessuser1->id,
$this->businessuser2->id,
$this->receiveruser1->id,
$this->student1->id,
$this->student12->id
],
$userlist1->get_userids()
);
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, 'enrol_paypal');
provider::get_users_in_context($userlist2);
$this->assertEqualsCanonicalizing(
[
$this->businessuser1->id,
$this->businessuser2->id,
$this->receiveruser2->id,
$this->student2->id,
$this->student12->id
],
$userlist2->get_userids()
);
$userlist3 = new \core_privacy\local\request\userlist($coursecontext3, 'enrol_paypal');
provider::get_users_in_context($userlist3);
$this->assertEqualsCanonicalizing(
[
$this->businessuser3->id,
$this->receiveruser3->id,
$this->student3->id
],
$userlist3->get_userids()
);
}
/**
* Test for provider::delete_data_for_users().
*/
public function test_delete_data_for_users(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
// Before deletion, we should have 2 PayPal transactions (1 of them for student12) in course1
// and 3 PayPal transactions (1 of them for student12) in course2.
// Student12 is enrolled in course1 and course2.
// There is 1 transaction in course1 and 2 transactions in course2 under the name of businessuser1.
$this->assertEquals(
2,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEqualsCanonicalizing(
[$this->course1->id, $this->course2->id],
$DB->get_fieldset_select('enrol_paypal', 'courseid', 'userid = ?', [$this->student12->id])
);
$this->assertEqualsCanonicalizing(
[$this->course1->id, $this->course2->id, $this->course2->id],
$DB->get_fieldset_select('enrol_paypal', 'courseid', 'business = ?',
[\core_text::strtolower($this->businessuser1->email)])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
// Delete data of student12 and businessuser1 in course1.
$approveduserlist = new \core_privacy\local\request\approved_userlist($coursecontext1, 'enrol_paypal',
[$this->student12->id, $this->businessuser1->id]);
provider::delete_data_for_users($approveduserlist);
// After deletion, PayPal transactions for student12 in course1 should have been deleted.
// Now, we should have 1 PayPal transaction (which is not related to student12) in course1.
// There should still be 3 PayPal transactions (1 of them for student12) in course2.
// Student12 is not enrolled in course1 anymore, but s/he is still enrolled in course2.
// There is no transaction in course1 under the name of businessuser1, but the 2 transactions in course2
// that were under his/her name are intact.
$this->assertEquals(
1,
$DB->count_records('enrol_paypal', ['courseid' => $this->course1->id])
);
$this->assertEqualsCanonicalizing(
[$this->course2->id],
$DB->get_fieldset_select('enrol_paypal', 'courseid', 'userid = ?', [$this->student12->id])
);
$this->assertEqualsCanonicalizing(
[$this->course2->id, $this->course2->id],
$DB->get_fieldset_select('enrol_paypal', 'courseid', 'business = ?',
[\core_text::strtolower($this->businessuser1->email)])
);
$this->assertEquals(
3,
$DB->count_records('enrol_paypal', ['courseid' => $this->course2->id])
);
}
/**
* Test for provider::delete_data_for_users() for business user deletion.
*/
public function test_delete_data_for_users_business(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
// Before deletion, there are 3 transactions under the name of businessuser1 and one of them is in course1.
$this->assertEquals(3, $DB->count_records('enrol_paypal', ['business' => $this->businessuser1->email]));
$transactions = $DB->get_records('enrol_paypal', [
'courseid' => $this->course1->id,
'business' => $this->businessuser1->email
]);
$this->assertCount(1, $transactions);
$transaction = reset($transactions);
// Delete data of businessuser1 in course1.
$approveduserlist = new \core_privacy\local\request\approved_userlist($coursecontext1, 'enrol_paypal',
[$this->businessuser1->id]);
provider::delete_data_for_users($approveduserlist);
// After deletion, there should be 2 transactions under the name of businessuser1 and none of them should be in course1.
$this->assertEquals(2, $DB->count_records('enrol_paypal', ['business' => $this->businessuser1->email]));
$this->assertEquals(0, $DB->count_records('enrol_paypal', [
'courseid' => $this->course1->id,
'business' => $this->businessuser1->email
]));
// Also, the transaction in course1 that was under the name of businessuser1 should still exist,
// but it should not be under the name of businessuser1 anymore.
$newtransaction = $DB->get_record('enrol_paypal', ['id' => $transaction->id]);
$this->assertEquals('', $newtransaction->business);
}
/**
* Test for provider::delete_data_for_users() for receiver user deletion.
*/
public function test_delete_data_for_users_receiver(): void {
global $DB;
$coursecontext1 = \context_course::instance($this->course1->id);
// Before deletion, there are 2 transactions under the name of receiveruser1 and both of them are in course1.
$this->assertEquals(2, $DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser1->email]));
$transactions = $DB->get_records('enrol_paypal', [
'courseid' => $this->course1->id,
'receiver_email' => $this->receiveruser1->email
]);
$this->assertCount(2, $transactions);
// Delete data of receiveruser1 in course1.
$approveduserlist = new \core_privacy\local\request\approved_userlist($coursecontext1, 'enrol_paypal',
[$this->receiveruser1->id]);
provider::delete_data_for_users($approveduserlist);
// After deletion, there should be no transaction under the name of receiveruser1.
$this->assertEquals(0, $DB->count_records('enrol_paypal', ['receiver_email' => $this->receiveruser1->email]));
// Also, the transactions in course1 that were under the name of receiveruser1 should still exist,
// but they should not be under the name of receiveruser1 anymore.
foreach ($transactions as $transaction) {
$newtransaction = $DB->get_record('enrol_paypal', ['id' => $transaction->id]);
$this->assertEquals('', $newtransaction->receiver_email);
}
}
}
+61
View File
@@ -0,0 +1,61 @@
<?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 - support for user self unenrolment.
*
* @package enrol_paypal
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require('../../config.php');
$enrolid = required_param('enrolid', PARAM_INT);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$instance = $DB->get_record('enrol', array('id'=>$enrolid, 'enrol'=>'paypal'), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
$context = context_course::instance($course->id, MUST_EXIST);
require_login();
if (!is_enrolled($context)) {
redirect(new moodle_url('/'));
}
require_login($course);
$plugin = enrol_get_plugin('paypal');
// security defined inside following function
if (!$plugin->get_unenrolself_link($instance)) {
redirect(new moodle_url('/course/view.php', array('id'=>$course->id)));
}
$PAGE->set_url('/enrol/paypal/unenrolself.php', array('enrolid'=>$instance->id));
$PAGE->set_title($plugin->get_instance_name($instance));
if ($confirm and confirm_sesskey()) {
$plugin->unenrol_user($instance, $USER->id);
redirect(new moodle_url('/index.php'));
}
echo $OUTPUT->header();
$yesurl = new moodle_url($PAGE->url, array('confirm'=>1, 'sesskey'=>sesskey()));
$nourl = new moodle_url('/course/view.php', array('id'=>$course->id));
$message = get_string('unenrolselfconfirm', 'enrol_paypal', format_string($course->fullname));
echo $OUTPUT->confirm($message, $yesurl, $nourl);
echo $OUTPUT->footer();
+30
View File
@@ -0,0 +1,30 @@
<?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 version specification.
*
* @package enrol_paypal
* @copyright 2010 Eugene Venter
* @author Eugene Venter
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'enrol_paypal'; // Full name of the plugin (used for diagnostics)