See Release Notes
Long Term Support Release
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Privacy Subsystem implementation for enrol_paypal. 19 * 20 * @package enrol_paypal 21 * @category privacy 22 * @copyright 2018 Shamim Rezaie <shamim@moodle.com> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace enrol_paypal\privacy; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 use core_privacy\local\metadata\collection; 31 use core_privacy\local\request\approved_contextlist; 32 use core_privacy\local\request\approved_userlist; 33 use core_privacy\local\request\contextlist; 34 use core_privacy\local\request\userlist; 35 use core_privacy\local\request\writer; 36 37 /** 38 * Privacy Subsystem implementation for enrol_paypal. 39 * 40 * @copyright 2018 Shamim Rezaie <shamim@moodle.com> 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class provider implements 44 // Transactions store user data. 45 \core_privacy\local\metadata\provider, 46 47 // The paypal enrolment plugin contains user's transactions. 48 \core_privacy\local\request\plugin\provider, 49 50 // This plugin is capable of determining which users have data within it. 51 \core_privacy\local\request\core_userlist_provider { 52 53 /** 54 * Returns meta data about this system. 55 * 56 * @param collection $collection The initialised collection to add items to. 57 * @return collection A listing of user data stored through this system. 58 */ 59 public static function get_metadata(collection $collection) : collection { 60 $collection->add_external_location_link( 61 'paypal.com', 62 [ 63 'os0' => 'privacy:metadata:enrol_paypal:paypal_com:os0', 64 'custom' => 'privacy:metadata:enrol_paypal:paypal_com:custom', 65 'first_name' => 'privacy:metadata:enrol_paypal:paypal_com:first_name', 66 'last_name' => 'privacy:metadata:enrol_paypal:paypal_com:last_name', 67 'address' => 'privacy:metadata:enrol_paypal:paypal_com:address', 68 'city' => 'privacy:metadata:enrol_paypal:paypal_com:city', 69 'email' => 'privacy:metadata:enrol_paypal:paypal_com:email', 70 'country' => 'privacy:metadata:enrol_paypal:paypal_com:country', 71 ], 72 'privacy:metadata:enrol_paypal:paypal_com' 73 ); 74 75 // The enrol_paypal has a DB table that contains user data. 76 $collection->add_database_table( 77 'enrol_paypal', 78 [ 79 'business' => 'privacy:metadata:enrol_paypal:enrol_paypal:business', 80 'receiver_email' => 'privacy:metadata:enrol_paypal:enrol_paypal:receiver_email', 81 'receiver_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:receiver_id', 82 'item_name' => 'privacy:metadata:enrol_paypal:enrol_paypal:item_name', 83 'courseid' => 'privacy:metadata:enrol_paypal:enrol_paypal:courseid', 84 'userid' => 'privacy:metadata:enrol_paypal:enrol_paypal:userid', 85 'instanceid' => 'privacy:metadata:enrol_paypal:enrol_paypal:instanceid', 86 'memo' => 'privacy:metadata:enrol_paypal:enrol_paypal:memo', 87 'tax' => 'privacy:metadata:enrol_paypal:enrol_paypal:tax', 88 'option_selection1_x' => 'privacy:metadata:enrol_paypal:enrol_paypal:option_selection1_x', 89 'payment_status' => 'privacy:metadata:enrol_paypal:enrol_paypal:payment_status', 90 'pending_reason' => 'privacy:metadata:enrol_paypal:enrol_paypal:pending_reason', 91 'reason_code' => 'privacy:metadata:enrol_paypal:enrol_paypal:reason_code', 92 'txn_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:txn_id', 93 'parent_txn_id' => 'privacy:metadata:enrol_paypal:enrol_paypal:parent_txn_id', 94 'payment_type' => 'privacy:metadata:enrol_paypal:enrol_paypal:payment_type', 95 'timeupdated' => 'privacy:metadata:enrol_paypal:enrol_paypal:timeupdated' 96 ], 97 'privacy:metadata:enrol_paypal:enrol_paypal' 98 ); 99 100 return $collection; 101 } 102 103 /** 104 * Get the list of contexts that contain user information for the specified user. 105 * 106 * @param int $userid The user to search. 107 * @return contextlist The contextlist containing the list of contexts used in this plugin. 108 */ 109 public static function get_contexts_for_userid(int $userid) : contextlist { 110 $contextlist = new contextlist(); 111 112 // Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal, 113 // therefore there is no need to use LOWER() on them in the following query. 114 $sql = "SELECT ctx.id 115 FROM {enrol_paypal} ep 116 JOIN {enrol} e ON ep.instanceid = e.id 117 JOIN {context} ctx ON e.courseid = ctx.instanceid AND ctx.contextlevel = :contextcourse 118 JOIN {user} u ON u.id = ep.userid OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business 119 WHERE u.id = :userid"; 120 $params = [ 121 'contextcourse' => CONTEXT_COURSE, 122 'userid' => $userid, 123 ]; 124 125 $contextlist->add_from_sql($sql, $params); 126 127 return $contextlist; 128 } 129 130 /** 131 * Get the list of users who have data within a context. 132 * 133 * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. 134 */ 135 public static function get_users_in_context(userlist $userlist) { 136 $context = $userlist->get_context(); 137 138 if (!$context instanceof \context_course) { 139 return; 140 } 141 142 // Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal, 143 // therefore there is no need to use LOWER() on them in the following query. 144 $sql = "SELECT u.id 145 FROM {enrol_paypal} ep 146 JOIN {enrol} e ON ep.instanceid = e.id 147 JOIN {user} u ON ep.userid = u.id OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business 148 WHERE e.courseid = :courseid"; 149 $params = ['courseid' => $context->instanceid]; 150 151 $userlist->add_from_sql('id', $sql, $params); 152 } 153 154 /** 155 * Export all user data for the specified user, in the specified contexts. 156 * 157 * @param approved_contextlist $contextlist The approved contexts to export information for. 158 */ 159 public static function export_user_data(approved_contextlist $contextlist) { 160 global $DB; 161 162 if (empty($contextlist->count())) { 163 return; 164 } 165 166 $user = $contextlist->get_user(); 167 168 list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); 169 170 // Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal, 171 // therefore there is no need to use LOWER() on them in the following query. 172 $sql = "SELECT ep.* 173 FROM {enrol_paypal} ep 174 JOIN {enrol} e ON ep.instanceid = e.id 175 JOIN {context} ctx ON e.courseid = ctx.instanceid AND ctx.contextlevel = :contextcourse 176 JOIN {user} u ON u.id = ep.userid OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business 177 WHERE ctx.id {$contextsql} AND u.id = :userid 178 ORDER BY e.courseid"; 179 180 $params = [ 181 'contextcourse' => CONTEXT_COURSE, 182 'userid' => $user->id, 183 'emailuserid' => $user->id, 184 ]; 185 $params += $contextparams; 186 187 // Reference to the course seen in the last iteration of the loop. By comparing this with the current record, and 188 // because we know the results are ordered, we know when we've moved to the PayPal transactions for a new course 189 // and therefore when we can export the complete data for the last course. 190 $lastcourseid = null; 191 192 $strtransactions = get_string('transactions', 'enrol_paypal'); 193 $transactions = []; 194 $paypalrecords = $DB->get_recordset_sql($sql, $params); 195 foreach ($paypalrecords as $paypalrecord) { 196 if ($lastcourseid != $paypalrecord->courseid) { 197 if (!empty($transactions)) { 198 $coursecontext = \context_course::instance($paypalrecord->courseid); 199 writer::with_context($coursecontext)->export_data( 200 [$strtransactions], 201 (object) ['transactions' => $transactions] 202 ); 203 } 204 $transactions = []; 205 } 206 207 $transaction = (object) [ 208 'receiver_id' => $paypalrecord->receiver_id, 209 'item_name' => $paypalrecord->item_name, 210 'userid' => $paypalrecord->userid, 211 'memo' => $paypalrecord->memo, 212 'tax' => $paypalrecord->tax, 213 'option_name1' => $paypalrecord->option_name1, 214 'option_selection1_x' => $paypalrecord->option_selection1_x, 215 'option_name2' => $paypalrecord->option_name2, 216 'option_selection2_x' => $paypalrecord->option_selection2_x, 217 'payment_status' => $paypalrecord->payment_status, 218 'pending_reason' => $paypalrecord->pending_reason, 219 'reason_code' => $paypalrecord->reason_code, 220 'txn_id' => $paypalrecord->txn_id, 221 'parent_txn_id' => $paypalrecord->parent_txn_id, 222 'payment_type' => $paypalrecord->payment_type, 223 'timeupdated' => \core_privacy\local\request\transform::datetime($paypalrecord->timeupdated), 224 ]; 225 if ($paypalrecord->userid == $user->id) { 226 $transaction->userid = $paypalrecord->userid; 227 } 228 if ($paypalrecord->business == \core_text::strtolower($user->email)) { 229 $transaction->business = $paypalrecord->business; 230 } 231 if ($paypalrecord->receiver_email == \core_text::strtolower($user->email)) { 232 $transaction->receiver_email = $paypalrecord->receiver_email; 233 } 234 235 $transactions[] = $paypalrecord; 236 237 $lastcourseid = $paypalrecord->courseid; 238 } 239 $paypalrecords->close(); 240 241 // The data for the last activity won't have been written yet, so make sure to write it now! 242 if (!empty($transactions)) { 243 $coursecontext = \context_course::instance($paypalrecord->courseid); 244 writer::with_context($coursecontext)->export_data( 245 [$strtransactions], 246 (object) ['transactions' => $transactions] 247 ); 248 } 249 } 250 251 /** 252 * Delete all data for all users in the specified context. 253 * 254 * @param \context $context The specific context to delete data for. 255 */ 256 public static function delete_data_for_all_users_in_context(\context $context) { 257 global $DB; 258 259 if (!$context instanceof \context_course) { 260 return; 261 } 262 263 $DB->delete_records('enrol_paypal', array('courseid' => $context->instanceid)); 264 } 265 266 /** 267 * Delete all user data for the specified user, in the specified contexts. 268 * 269 * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. 270 */ 271 public static function delete_data_for_user(approved_contextlist $contextlist) { 272 global $DB; 273 274 if (empty($contextlist->count())) { 275 return; 276 } 277 278 $user = $contextlist->get_user(); 279 280 $contexts = $contextlist->get_contexts(); 281 $courseids = []; 282 foreach ($contexts as $context) { 283 if ($context instanceof \context_course) { 284 $courseids[] = $context->instanceid; 285 } 286 } 287 288 list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED); 289 290 $select = "userid = :userid AND courseid $insql"; 291 $params = $inparams + ['userid' => $user->id]; 292 $DB->delete_records_select('enrol_paypal', $select, $params); 293 294 // We do not want to delete the payment record when the user is just the receiver of payment. 295 // In that case, we just delete the receiver's info from the transaction record. 296 297 $select = "business = :business AND courseid $insql"; 298 $params = $inparams + ['business' => \core_text::strtolower($user->email)]; 299 $DB->set_field_select('enrol_paypal', 'business', '', $select, $params); 300 301 $select = "receiver_email = :receiver_email AND courseid $insql"; 302 $params = $inparams + ['receiver_email' => \core_text::strtolower($user->email)]; 303 $DB->set_field_select('enrol_paypal', 'receiver_email', '', $select, $params); 304 } 305 306 /** 307 * Delete multiple users within a single context. 308 * 309 * @param approved_userlist $userlist The approved context and user information to delete information for. 310 */ 311 public static function delete_data_for_users(approved_userlist $userlist) { 312 global $DB; 313 314 $context = $userlist->get_context(); 315 316 if ($context->contextlevel != CONTEXT_COURSE) { 317 return; 318 } 319 320 $userids = $userlist->get_userids(); 321 322 list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); 323 324 $params = ['courseid' => $context->instanceid] + $userparams; 325 326 $select = "courseid = :courseid AND userid $usersql"; 327 $DB->delete_records_select('enrol_paypal', $select, $params); 328 329 // We do not want to delete the payment record when the user is just the receiver of payment. 330 // In that case, we just delete the receiver's info from the transaction record. 331 332 $select = "courseid = :courseid AND business IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)"; 333 $DB->set_field_select('enrol_paypal', 'business', '', $select, $params); 334 335 $select = "courseid = :courseid AND receiver_email IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)"; 336 $DB->set_field_select('enrol_paypal', 'receiver_email', '', $select, $params); 337 } 338 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body