From 04b7c496f0b9dc502f307347793e341acbce2455 Mon Sep 17 00:00:00 2001 From: Safat Date: Wed, 12 Apr 2023 11:26:12 +1000 Subject: [PATCH] MDL-77357 core_communication: Add api for provider form fields --- .../amd/build/providerchooser.min.js | 12 +++ .../amd/build/providerchooser.min.js.map | 1 + communication/amd/src/providerchooser.js | 47 ++++++++++++ communication/classes/api.php | 76 +++++++++++++++---- communication/classes/form_provider.php | 50 ++++++++++++ communication/classes/processor.php | 42 +++++++++- 6 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 communication/amd/build/providerchooser.min.js create mode 100644 communication/amd/build/providerchooser.min.js.map create mode 100644 communication/amd/src/providerchooser.js create mode 100644 communication/classes/form_provider.php diff --git a/communication/amd/build/providerchooser.min.js b/communication/amd/build/providerchooser.min.js new file mode 100644 index 00000000000..b62029acef4 --- /dev/null +++ b/communication/amd/build/providerchooser.min.js @@ -0,0 +1,12 @@ +define("core_communication/providerchooser",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0; +/** + * Communication provider selection handler. + * + * @module core_communication/communicationchooser + * @copyright 2023 Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.2 + */ +const Selectors_fields={selector:'[data-communicationchooser-field="selector"]',updateButton:'[data-communicationchooser-field="updateButton"]'};_exports.init=()=>{document.querySelector(Selectors_fields.selector).addEventListener("change",(e=>{const form=e.target.closest("form"),updateButton=form.querySelector(Selectors_fields.updateButton),fieldset=updateButton.closest("fieldset"),url=new URL(form.action);url.hash=fieldset.id,form.action=url.toString(),updateButton.click()}))}})); + +//# sourceMappingURL=providerchooser.min.js.map \ No newline at end of file diff --git a/communication/amd/build/providerchooser.min.js.map b/communication/amd/build/providerchooser.min.js.map new file mode 100644 index 00000000000..2dd6bb97d4d --- /dev/null +++ b/communication/amd/build/providerchooser.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"providerchooser.min.js","sources":["../src/providerchooser.js"],"sourcesContent":["\n// This file is part of Moodle - http://moodle.org/ //\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 * Communication provider selection handler.\n *\n * @module core_communication/communicationchooser\n * @copyright 2023 Safat Shahin \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.2\n */\n\nconst Selectors = {\n fields: {\n selector: '[data-communicationchooser-field=\"selector\"]',\n updateButton: '[data-communicationchooser-field=\"updateButton\"]',\n },\n};\n\n/**\n * Initialise the format chooser.\n */\nexport const init = () => {\n document.querySelector(Selectors.fields.selector).addEventListener('change', e => {\n const form = e.target.closest('form');\n const updateButton = form.querySelector(Selectors.fields.updateButton);\n const fieldset = updateButton.closest('fieldset');\n\n const url = new URL(form.action);\n url.hash = fieldset.id;\n\n form.action = url.toString();\n updateButton.click();\n });\n};\n"],"names":["Selectors","selector","updateButton","document","querySelector","addEventListener","e","form","target","closest","fieldset","url","URL","action","hash","id","toString","click"],"mappings":";;;;;;;;;MAwBMA,iBACM,CACJC,SAAU,+CACVC,aAAc,kEAOF,KAChBC,SAASC,cAAcJ,iBAAiBC,UAAUI,iBAAiB,UAAUC,UACnEC,KAAOD,EAAEE,OAAOC,QAAQ,QACxBP,aAAeK,KAAKH,cAAcJ,iBAAiBE,cACnDQ,SAAWR,aAAaO,QAAQ,YAEhCE,IAAM,IAAIC,IAAIL,KAAKM,QACzBF,IAAIG,KAAOJ,SAASK,GAEpBR,KAAKM,OAASF,IAAIK,WAClBd,aAAae"} \ No newline at end of file diff --git a/communication/amd/src/providerchooser.js b/communication/amd/src/providerchooser.js new file mode 100644 index 00000000000..ccfbe69b890 --- /dev/null +++ b/communication/amd/src/providerchooser.js @@ -0,0 +1,47 @@ + +// 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 . + +/** + * Communication provider selection handler. + * + * @module core_communication/communicationchooser + * @copyright 2023 Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since 4.2 + */ + +const Selectors = { + fields: { + selector: '[data-communicationchooser-field="selector"]', + updateButton: '[data-communicationchooser-field="updateButton"]', + }, +}; + +/** + * Initialise the format chooser. + */ +export const init = () => { + document.querySelector(Selectors.fields.selector).addEventListener('change', e => { + const form = e.target.closest('form'); + const updateButton = form.querySelector(Selectors.fields.updateButton); + const fieldset = updateButton.closest('fieldset'); + + const url = new URL(form.action); + url.hash = fieldset.id; + + form.action = url.toString(); + updateButton.click(); + }); +}; diff --git a/communication/classes/api.php b/communication/classes/api.php index d7bc8ae3a36..6b3055d27b2 100644 --- a/communication/classes/api.php +++ b/communication/classes/api.php @@ -122,6 +122,9 @@ class api { * @param \MoodleQuickForm $mform The form element */ public function form_definition(\MoodleQuickForm $mform): void { + global $PAGE; + $PAGE->requires->js_call_amd('core_communication/providerchooser', 'init'); + $mform->addElement('header', 'communication', get_string('communication', 'communication')); // List the communication providers. @@ -130,22 +133,47 @@ class api { 'select', 'selectedcommunication', get_string('seleccommunicationprovider', 'communication'), - $communicationproviders); + $communicationproviders, + ['data-communicationchooser-field' => 'selector'], + ); $mform->addHelpButton('selectedcommunication', 'seleccommunicationprovider', 'communication'); $mform->setDefault('selectedcommunication', processor::PROVIDER_NONE); - // Room name for the communication provider. - $mform->addElement('text', - 'communicationroomname', - get_string('communicationroomname', 'communication'), - 'maxlength="100" size="20"'); - $mform->addHelpButton('communicationroomname', 'communicationroomname', 'communication'); - $mform->setType('communicationroomname', PARAM_TEXT); - $mform->hideIf( - 'communicationroomname', - 'selectedcommunication', - 'eq', - processor::PROVIDER_NONE); + $mform->registerNoSubmitButton('updatecommunicationprovider'); + $mform->addElement('submit', + 'updatecommunicationprovider', + 'update communication', + ['data-communicationchooser-field' => 'updateButton', 'class' => 'd-none',]); + + // Just a placeholder for the communication options. + $mform->addElement('hidden', 'addcommunicationoptionshere'); + $mform->setType('addcommunicationoptionshere', PARAM_BOOL); + } + + /** + * Set the form definitions for the plugins. + * + * @param \MoodleQuickForm $mform + * @return void + */ + public function form_definition_for_provider(\MoodleQuickForm $mform): void { + $provider = $mform->getElementValue('selectedcommunication'); + + if ($provider[0] !== processor::PROVIDER_NONE) { + // Room name for the communication provider. + $mform->insertElementBefore( + $mform->createElement( + 'text', + 'communicationroomname', + get_string('communicationroomname', 'communication'), 'maxlength="100" size="20"'), + 'addcommunicationoptionshere' + ); + $mform->addHelpButton('communicationroomname', 'communicationroomname', 'communication'); + $mform->setType('communicationroomname', PARAM_TEXT); + + processor::set_proider_form_definition($provider[0], $mform); + } + } /** @@ -223,6 +251,8 @@ class api { if (!empty($instance->id) && $this->communication) { $instance->selectedcommunication = $this->communication->get_provider(); $instance->communicationroomname = $this->communication->get_room_name(); + + $this->communication->get_form_provider()->set_form_data($instance); } } @@ -244,12 +274,14 @@ class api { * * @param string $selectedcommunication The selected communication provider * @param string $communicationroomname The communication room name + * @param \stdClass|null $instance The actual instance object * @param string|null $avatarurl The avatar url */ public function create_and_configure_room( string $selectedcommunication, string $communicationroomname, ?string $avatarurl = null, + ?\stdClass $instance = null, ): void { if ($selectedcommunication !== processor::PROVIDER_NONE && $selectedcommunication !== '') { @@ -262,6 +294,11 @@ class api { $communicationroomname, ); + // Update provider record from form data. + if ($instance !== null) { + $this->communication->get_form_provider()->save_form_data($instance); + } + // Set the avatar. if (!empty($avatarurl)) { $this->set_avatar_from_datauri_or_filepath($avatarurl); @@ -280,12 +317,14 @@ class api { * * @param string $selectedprovider The selected communication provider * @param string $communicationroomname The communication room name + * @param \stdClass|null $instance The actual instance object * @param string|null $avatarurl The avatar url */ public function update_room( string $selectedprovider, string $communicationroomname, ?string $avatarurl = null, + ?\stdClass $instance = null, ): void { // Existing object found, let's update the communication record and associated actions. @@ -297,6 +336,11 @@ class api { // Update communication record. $this->communication->update_instance($selectedprovider, $communicationroomname); + // Update provider record from form data. + if ($instance !== null) { + $this->communication->get_form_provider()->save_form_data($instance); + } + // Update the avatar. $imageupdaterequired = $this->set_avatar_from_datauri_or_filepath($avatarurl); @@ -306,9 +350,9 @@ class api { } // Add ad-hoc task to update the provider room if the room name changed. + // TODO add efficiency considering dynamic fields. if ( - $previousprovider === $selectedprovider && - ($previousroomname !== $communicationroomname || $imageupdaterequired) + $previousprovider === $selectedprovider ) { update_room_task::queue( $this->communication, @@ -323,7 +367,7 @@ class api { } } else { // The instance didn't have any communication record, so create one. - $this->create_and_configure_room($selectedprovider, $communicationroomname, $avatarurl); + $this->create_and_configure_room($selectedprovider, $communicationroomname, $avatarurl, $instance); } } diff --git a/communication/classes/form_provider.php b/communication/classes/form_provider.php new file mode 100644 index 00000000000..052608ae675 --- /dev/null +++ b/communication/classes/form_provider.php @@ -0,0 +1,50 @@ +. + +namespace core_communication; + +/** + * Interface form_provider to manage communication provider form options from provider plugins. + * + * Every provider plugin should implement this class to return the implemented form elements for custom data. + * + * @package core_communication + * @copyright 2023 Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface form_provider { + + /** + * Set the form data to the instance if any data is available. + * + * @param \stdClass $instance The actual instance to set the data + */ + public function save_form_data(\stdClass $instance): void; + + /** + * Set the form data to the instance if any data is available. + * + * @param \stdClass $instance The actual instance to set the data + */ + public function set_form_data(\stdClass $instance): void; + + /** + * Set the form definitions. + * + * @param \MoodleQuickForm $mform The form object + */ + public static function set_form_definition(\MoodleQuickForm $mform): void; +} diff --git a/communication/classes/processor.php b/communication/classes/processor.php index 576717a6722..a0532787e2c 100644 --- a/communication/classes/processor.php +++ b/communication/classes/processor.php @@ -409,7 +409,6 @@ class processor { * @return string|null */ public function get_provider(): ?string { - // var_dump($this->instancedata);die; if ((int)$this->instancedata->active === self::PROVIDER_ACTIVE) { return $this->instancedata->provider; } @@ -459,6 +458,27 @@ class processor { return $this->provider; } + /** + * Get communication provider for form feature. + * + * @param string $provider The provider name + * @param \MoodleQuickForm $mform The moodle form + */ + public static function set_proider_form_definition(string $provider, \MoodleQuickForm $mform): void { + $providerclass = "{$provider}\\communication_feature"; + $providerclass::set_form_definition($mform); + } + + /** + * Get communication instance for form feature. + * + * @return bool + */ + public function get_form_provider(): form_provider { + $this->requires_form_features(); + return $this->provider; + } + /** * Get communication instance id. * @@ -485,6 +505,26 @@ class processor { return ($this->provider instanceof room_user_provider); } + /** + * Check form feature available. + * + * @return bool + */ + public function requires_form_features(): void { + if (!$this->supports_form_features()) { + throw new \coding_exception('Form features are not supported by the provider'); + } + } + + /** + * Check support for form feature. + * + * @return bool + */ + public function supports_form_features(): bool { + return ($this->provider instanceof form_provider); + } + /** * Get communication instance id. */