From e9de4309071865bd7e7c2355097bdf8157bc02b6 Mon Sep 17 00:00:00 2001 From: Shamim Rezaie Date: Wed, 29 Jan 2020 19:11:37 +1100 Subject: [PATCH] MDL-69166 core_payment: display the gateways modal --- enrol/fee/classes/plugin.php | 9 +- lang/en/payment.php | 2 + payment/amd/build/gateways_modal.min.js | 2 + payment/amd/build/gateways_modal.min.js.map | 1 + payment/amd/build/repository.min.js | 2 + payment/amd/build/repository.min.js.map | 1 + payment/amd/build/selectors.min.js | 2 + payment/amd/build/selectors.min.js.map | 1 + payment/amd/src/gateways_modal.js | 94 +++++++++++++++++++ payment/amd/src/repository.js | 41 ++++++++ payment/amd/src/selectors.js | 29 ++++++ payment/classes/helper.php | 31 ++++++ payment/templates/gateway.mustache | 48 ++++++++++ payment/templates/gateways.mustache | 55 +++++++++++ payment/templates/gateways_modal.mustache | 37 ++++++++ .../templates/gateways_placeholder.mustache | 41 ++++++++ 16 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 payment/amd/build/gateways_modal.min.js create mode 100644 payment/amd/build/gateways_modal.min.js.map create mode 100644 payment/amd/build/repository.min.js create mode 100644 payment/amd/build/repository.min.js.map create mode 100644 payment/amd/build/selectors.min.js create mode 100644 payment/amd/build/selectors.min.js.map create mode 100644 payment/amd/src/gateways_modal.js create mode 100644 payment/amd/src/repository.js create mode 100644 payment/amd/src/selectors.js create mode 100644 payment/templates/gateway.mustache create mode 100644 payment/templates/gateways.mustache create mode 100644 payment/templates/gateways_modal.mustache create mode 100644 payment/templates/gateways_placeholder.mustache diff --git a/enrol/fee/classes/plugin.php b/enrol/fee/classes/plugin.php index 71b9e7e524a..f2d4200a6db 100644 --- a/enrol/fee/classes/plugin.php +++ b/enrol/fee/classes/plugin.php @@ -206,9 +206,12 @@ class enrol_fee_plugin extends enrol_plugin { echo '

'.get_string('loginsite').'

'; echo ''; } else { - echo '
'; - $PAGE->requires->js_call_amd('profilefield_conditional/conditionconfig', 'init', array('#id_param1', - '#profilefield_conditional_conditionconfiguration', '#id_conditionconfigbutton', $fieldid)); + \core_payment\helper::gateways_modal_requirejs(); + $attributes = core_payment\helper::gateways_modal_link_params($cost, $instance->currency); + + echo '
' . + html_writer::tag('button', get_string("sendpaymentbutton", "enrol_paypal"), $attributes) . + '
'; } } diff --git a/lang/en/payment.php b/lang/en/payment.php index a78b8ac7270..b9f6322e0f3 100644 --- a/lang/en/payment.php +++ b/lang/en/payment.php @@ -22,4 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['nogateway'] = 'There is no payment gateway that can be used.'; +$string['selectpaymenttype'] = 'Select payment type'; $string['supportedcurrencies'] = 'Supported currencies'; diff --git a/payment/amd/build/gateways_modal.min.js b/payment/amd/build/gateways_modal.min.js new file mode 100644 index 00000000000..f6c364ccbe3 --- /dev/null +++ b/payment/amd/build/gateways_modal.min.js @@ -0,0 +1,2 @@ +function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core_payment/gateways_modal",["exports","core/modal_factory","core/templates","core/str","core_payment/repository","./selectors","core/modal_events"],function(a,b,c,d,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.registerEventListeners=void 0;b=j(b);c=j(c);f=j(f);g=i(g);function h(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;h=function(){return a};return a}function i(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=h();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var f=d?Object.getOwnPropertyDescriptor(a,e):null;if(f&&(f.get||f.set)){Object.defineProperty(c,e,f)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function j(a){return a&&a.__esModule?a:{default:a}}function k(a){if("undefined"==typeof Symbol||null==a[Symbol.iterator]){if(Array.isArray(a)||(a=l(a))){var b=0,c=function(){};return{s:c,n:function n(){if(b>=a.length)return{done:!0};return{done:!1,value:a[b++]}},e:function e(a){throw a},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var d,e=!0,f=!1,g;return{s:function s(){d=a[Symbol.iterator]()},n:function n(){var a=d.next();e=a.done;return a},e:function e(a){f=!0;g=a},f:function f(){try{if(!e&&null!=d.return)d.return()}finally{if(f)throw g}}}}function l(a,b){if(!a)return;if("string"==typeof a)return m(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return m(a,b)}function m(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c.\n\n/**\n * Contain the logic for the gateways modal.\n *\n * @module core_payment/gateways_modal\n * @package core_payment\n * @copyright 2019 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalFactory from 'core/modal_factory';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\nimport {getGatewaysSupportingCurrency} from 'core_payment/repository';\nimport Selectors from './selectors';\nimport * as ModalEvents from 'core/modal_events';\n\n/**\n * Register event listeners for the module.\n *\n * @param {string} nodeSelector The root to listen to.\n */\nexport const registerEventListeners = (nodeSelector) => {\n const rootNode = document.querySelector(nodeSelector);\n\n rootNode.addEventListener('click', (e) => {\n e.preventDefault();\n show(rootNode, {focusOnClose: e.target});\n });\n};\n\n/**\n * Shows the gateway selector modal.\n *\n * @param {HTMLElement} rootNode\n * @param {Object} options - Additional options\n * @param {HTMLElement} options.focusOnClose The element to focus on when the modal is closed.\n */\nconst show = (rootNode, {\n focusOnClose = null,\n} = {}) => {\n Templates.render('core_payment/gateways_modal', {})\n .done(content => {\n ModalFactory.create({\n title: getString('selectpaymenttype', 'core_payment'),\n body: content,\n })\n .done(function(modal) {\n const currency = rootNode.dataset.currency;\n getGatewaysSupportingCurrency(currency)\n .done(gateways => {\n const context = {\n gateways: []\n };\n\n for (let gateway of gateways) {\n context.gateways.push(gateway);\n }\n\n Templates.render('core_payment/gateways', context)\n .done((html, js) => {\n Templates.replaceNodeContents(modal.getRoot().find(Selectors.regions.gatewaysContainer),\n html, js);\n });\n });\n\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n try {\n focusOnClose.focus();\n } catch (e) {\n // eslint-disable-line\n }\n });\n\n modal.show();\n });\n });\n};\n"],"file":"gateways_modal.min.js"} \ No newline at end of file diff --git a/payment/amd/build/repository.min.js b/payment/amd/build/repository.min.js new file mode 100644 index 00000000000..8357ed7bbaa --- /dev/null +++ b/payment/amd/build/repository.min.js @@ -0,0 +1,2 @@ +define ("core_payment/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.getGatewaysSupportingCurrency=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_payment_get_gateways_for_currency",args:{currency:a}}])[0]};a.getGatewaysSupportingCurrency=c}); +//# sourceMappingURL=repository.min.js.map diff --git a/payment/amd/build/repository.min.js.map b/payment/amd/build/repository.min.js.map new file mode 100644 index 00000000000..00832a1a84a --- /dev/null +++ b/payment/amd/build/repository.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/repository.js"],"names":["getGatewaysSupportingCurrency","currency","Ajax","call","methodname","args"],"mappings":"6KAwBA,uDAQO,GAAMA,CAAAA,CAA6B,CAAG,SAAAC,CAAQ,CAAI,CAOrD,MAAOC,WAAKC,IAAL,CAAU,CAND,CACZC,UAAU,CAAE,wCADA,CAEZC,IAAI,CAAE,CACFJ,QAAQ,CAARA,CADE,CAFM,CAMC,CAAV,EAAqB,CAArB,CACV,CARM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Repository for payment subsystem.\n *\n * @module core_payment/repository\n * @package core_payment\n * @copyright 2020 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Returns the list of gateways that can process payments in the given currency.\n *\n * @param {string} currency The currency in the three-character ISO-4217 format\n * @returns {Promise<{shortname: string, name: string, description: String}[]>}\n */\nexport const getGatewaysSupportingCurrency = currency => {\n const request = {\n methodname: 'core_payment_get_gateways_for_currency',\n args: {\n currency\n }\n };\n return Ajax.call([request])[0];\n};\n"],"file":"repository.min.js"} \ No newline at end of file diff --git a/payment/amd/build/selectors.min.js b/payment/amd/build/selectors.min.js new file mode 100644 index 00000000000..de2f08e223c --- /dev/null +++ b/payment/amd/build/selectors.min.js @@ -0,0 +1,2 @@ +define ("core_payment/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={regions:{gatewaysContainer:"[data-region=\"gateways-container\"]"}};return a.default}); +//# sourceMappingURL=selectors.min.js.map diff --git a/payment/amd/build/selectors.min.js.map b/payment/amd/build/selectors.min.js.map new file mode 100644 index 00000000000..f68775abafa --- /dev/null +++ b/payment/amd/build/selectors.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/selectors.js"],"names":["regions","gatewaysContainer"],"mappings":"kJAwBe,CACXA,OAAO,CAAE,CACLC,iBAAiB,CAAE,sCADd,CADE,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Define all of the selectors we will be using on the payment interface.\n *\n * @module core_payment/selectors\n * @package core_payment\n * @copyright 2019 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n regions: {\n gatewaysContainer: '[data-region=\"gateways-container\"]',\n },\n};\n"],"file":"selectors.min.js"} \ No newline at end of file diff --git a/payment/amd/src/gateways_modal.js b/payment/amd/src/gateways_modal.js new file mode 100644 index 00000000000..85791583b12 --- /dev/null +++ b/payment/amd/src/gateways_modal.js @@ -0,0 +1,94 @@ +// 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 . + +/** + * Contain the logic for the gateways modal. + * + * @module core_payment/gateways_modal + * @package core_payment + * @copyright 2019 Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import ModalFactory from 'core/modal_factory'; +import Templates from 'core/templates'; +import {get_string as getString} from 'core/str'; +import {getGatewaysSupportingCurrency} from 'core_payment/repository'; +import Selectors from './selectors'; +import * as ModalEvents from 'core/modal_events'; + +/** + * Register event listeners for the module. + * + * @param {string} nodeSelector The root to listen to. + */ +export const registerEventListeners = (nodeSelector) => { + const rootNode = document.querySelector(nodeSelector); + + rootNode.addEventListener('click', (e) => { + e.preventDefault(); + show(rootNode, {focusOnClose: e.target}); + }); +}; + +/** + * Shows the gateway selector modal. + * + * @param {HTMLElement} rootNode + * @param {Object} options - Additional options + * @param {HTMLElement} options.focusOnClose The element to focus on when the modal is closed. + */ +const show = (rootNode, { + focusOnClose = null, +} = {}) => { + Templates.render('core_payment/gateways_modal', {}) + .done(content => { + ModalFactory.create({ + title: getString('selectpaymenttype', 'core_payment'), + body: content, + }) + .done(function(modal) { + const currency = rootNode.dataset.currency; + getGatewaysSupportingCurrency(currency) + .done(gateways => { + const context = { + gateways: [] + }; + + for (let gateway of gateways) { + context.gateways.push(gateway); + } + + Templates.render('core_payment/gateways', context) + .done((html, js) => { + Templates.replaceNodeContents(modal.getRoot().find(Selectors.regions.gatewaysContainer), + html, js); + }); + }); + + modal.getRoot().on(ModalEvents.hidden, function() { + // Destroy when hidden. + modal.destroy(); + try { + focusOnClose.focus(); + } catch (e) { + // eslint-disable-line + } + }); + + modal.show(); + }); + }); +}; diff --git a/payment/amd/src/repository.js b/payment/amd/src/repository.js new file mode 100644 index 00000000000..758c80aa675 --- /dev/null +++ b/payment/amd/src/repository.js @@ -0,0 +1,41 @@ +// 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 . + +/** + * Repository for payment subsystem. + * + * @module core_payment/repository + * @package core_payment + * @copyright 2020 Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Ajax from 'core/ajax'; + +/** + * Returns the list of gateways that can process payments in the given currency. + * + * @param {string} currency The currency in the three-character ISO-4217 format + * @returns {Promise<{shortname: string, name: string, description: String}[]>} + */ +export const getGatewaysSupportingCurrency = currency => { + const request = { + methodname: 'core_payment_get_gateways_for_currency', + args: { + currency + } + }; + return Ajax.call([request])[0]; +}; diff --git a/payment/amd/src/selectors.js b/payment/amd/src/selectors.js new file mode 100644 index 00000000000..35be2db2265 --- /dev/null +++ b/payment/amd/src/selectors.js @@ -0,0 +1,29 @@ +// 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 . + +/** + * Define all of the selectors we will be using on the payment interface. + * + * @module core_payment/selectors + * @package core_payment + * @copyright 2019 Shamim Rezaie + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +export default { + regions: { + gatewaysContainer: '[data-region="gateways-container"]', + }, +}; diff --git a/payment/classes/helper.php b/payment/classes/helper.php index 4e611d99e91..1fb92612a70 100644 --- a/payment/classes/helper.php +++ b/payment/classes/helper.php @@ -75,4 +75,35 @@ class helper { return $gateways; } + + /** + * Requires the JS libraries for the pay button. + */ + public static function gateways_modal_requirejs(): void { + global $PAGE; + + static $done = false; + if ($done) { + return; + } + + $PAGE->requires->js_call_amd('core_payment/gateways_modal', 'registerEventListeners', ['#gateways-modal-trigger']); + $done = true; + } + + /** + * Returns the attributes to place on a pay button. + * + * @param float $amount Amount of payment + * @param string $currency Currency of payment + * @return array + */ + public static function gateways_modal_link_params(float $amount, string $currency) : array { + return [ + 'id' => 'gateways-modal-trigger', + 'role' => 'button', + 'data-amount' => $amount, + 'data-currency' => $currency, + ]; + } } diff --git a/payment/templates/gateway.mustache b/payment/templates/gateway.mustache new file mode 100644 index 00000000000..a363f80f5f6 --- /dev/null +++ b/payment/templates/gateway.mustache @@ -0,0 +1,48 @@ +{{! + 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 . +}} +{{! + @template core_payment/gateway + + This template will render the gateway option in the gateway selector modal. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * shortname + * name + * description + * image + + Example context (json): + { + "shortname": "paypal", + "name": "PayPal", + "description": "A description for PayPal.", + } + +}} +
+ + +
\ No newline at end of file diff --git a/payment/templates/gateways.mustache b/payment/templates/gateways.mustache new file mode 100644 index 00000000000..c2c1a39c503 --- /dev/null +++ b/payment/templates/gateways.mustache @@ -0,0 +1,55 @@ +{{! + 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 . +}} +{{! + @template core_payment/gateways + + This template will render the list of gateways in the gateway selector modal. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * gateways + + Example context (json): + { + "gateways" : [ + { + "shortname": "paypal", + "name": "PayPal", + "description": "A description for PayPal.", + "image": "../../../pix/help.svg" + }, + { + "shortname": "stripe", + "name": "Stripe", + "description": "A description for Stripe.", + "image": "../../../pix/help.svg" + } + ] + } + +}} +{{#gateways}} + {{> core_payment/gateway }} +{{/gateways}} +{{^gateways}} +

{{#str}}nogateway, core_payment{{/str}}

+{{/gateways}} \ No newline at end of file diff --git a/payment/templates/gateways_modal.mustache b/payment/templates/gateways_modal.mustache new file mode 100644 index 00000000000..9de46c4df89 --- /dev/null +++ b/payment/templates/gateways_modal.mustache @@ -0,0 +1,37 @@ +{{! + 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 . +}} +{{! + @template core_payment/gateways_modal + + This template will render the gateway selector modal. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * none + + Example context (json): + {} + +}} +
+ {{> core_payment/gateways_placeholder }} +
\ No newline at end of file diff --git a/payment/templates/gateways_placeholder.mustache b/payment/templates/gateways_placeholder.mustache new file mode 100644 index 00000000000..ad7a549fcf9 --- /dev/null +++ b/payment/templates/gateways_placeholder.mustache @@ -0,0 +1,41 @@ +{{! + 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 . +}} +{{! + @template core_payment/gateways_placeholder + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Context variables required for this template: + * none + + Example context (json): + {} + +}} +
+ + +
\ No newline at end of file