diff --git a/lang/en/admin.php b/lang/en/admin.php index 7e1702d04b3..a3ae61fc53f 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -326,7 +326,7 @@ $string['configproxyport'] = 'If this server needs to use a proxy computer, then $string['configproxytype'] = 'Type of web proxy (PHP5 and cURL extension required for SOCKS5 support).'; $string['configproxyuser'] = 'Username needed to access internet through proxy if required, empty if none (PHP cURL extension required).'; $string['configrecaptchaprivatekey'] = 'String of characters (secret key) used to communicate between your Moodle server and the recaptcha server. ReCAPTCHA keys can be obtained from Google reCAPTCHA.'; -$string['configrecaptchapublickey'] = 'String of characters (site key) used to display the reCAPTCHA element in the signup form. ReCAPTCHA keys can be obtained from Google reCAPTCHA.'; +$string['configrecaptchapublickey'] = 'String of characters (site key) used to display the reCAPTCHA element in the signup form and site support form. ReCAPTCHA keys can be obtained from Google reCAPTCHA.'; $string['configrequestedstudentname'] = 'Word for student used in requested courses'; $string['configrequestedstudentsname'] = 'Word for students used in requested courses'; $string['configrequestedteachername'] = 'Word for teacher used in requested courses'; @@ -374,9 +374,9 @@ $string['configstatsruntimestart'] = 'What time should the cronjob that does the $string['configstatsuserthreshold'] = 'This setting specifies the minimum number of enrolled users for a course to be included in statistics calculations.'; $string['configstrictformsrequired'] = 'If enabled, users are prevented from entering a space or line break only in required fields in forms.'; $string['configstripalltitletags'] = 'Uncheck this setting to allow HTML tags in activity and resource names.'; -$string['configsupportemail'] = 'This email address will be published to users of this site as the one to email when they need general help (for example, when new users create their own accounts).'; +$string['configsupportemail'] = 'If SMTP is configured on this site and a support page is not configured, this email address will be sent general help requests submitted through the support form (for example, when new users create their own accounts). If SMTP is not configured, this email address will be displayed to logged in users on the support form page.'; $string['configsupportname'] = 'This is the name of a person or other entity offering general help via the support email or web address.'; -$string['configsupportpage'] = 'This web address will be published to users of this site as the one to go to when they need general help (for example, when new users create their own accounts). If this address is left blank then no link will be supplied.'; +$string['configsupportpage'] = 'This web address will be published to users of this site as the one to go to when they need general help (for example, when new users create their own accounts). If this address is left blank then a link to the support email form will be supplied.'; $string['configtempdatafoldercleanup'] = 'Remove temporary data files from the data folder that are older than the selected time.'; $string['configthemedesignermode'] = 'Normally all theme images and style sheets are cached in browsers and on the server for a very long time, for performance. If you are designing themes or developing code then you probably want to turn this mode on so that you are not served cached versions. Warning: this will make your site slower for all users! Alternatively, you can also reset the theme caches manually from the Theme selection page.'; $string['configthemelist'] = 'Leave this blank to allow any valid theme to be used. If you want to shorten the theme menu, you can specify a comma-separated list of names here (Don\'t use spaces!). @@ -1279,6 +1279,7 @@ $string['strictformsrequired'] = 'Strict validation of required fields'; $string['stripalltitletags'] = 'Remove HTML tags from all activity names'; $string['supportcontact'] = 'Support contact'; $string['supportemail'] = 'Support email'; +$string['supportemailsubject'] = 'Site support request - {$a}'; $string['supportname'] = 'Support name'; $string['supportpage'] = 'Support page'; $string['suspenduser'] = 'Suspend user account'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 05937463bfc..d07eb7058a6 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -1257,6 +1257,7 @@ $string['maxsizeandareasize'] = 'Maximum size for new files: {$a->size}, overall $string['maxsizeandattachments'] = 'Maximum file size: {$a->size}, maximum number of files: {$a->attachments}'; $string['maxsizeandattachmentsandareasize'] = 'Maximum file size: {$a->size}, maximum number of files: {$a->attachments}, maximum total size: {$a->areasize}'; $string['memberincourse'] = 'People in the course'; +$string['message'] = 'Message'; $string['messagebody'] = 'Message body'; $string['messagedselectedusers'] = 'Selected users have been messaged and the recipient list has been reset.'; $string['messagedselectedusersfailed'] = 'Something went wrong while messaging selected users. Some may have received the email.'; @@ -2087,6 +2088,7 @@ $string['subcategories'] = 'Subcategories'; $string['subcategory'] = 'Subcategory'; $string['subcategoryof'] = 'Subcategory of {$a}'; $string['submit'] = 'Submit'; +$string['subject'] = 'Subject'; $string['success'] = 'Success'; $string['successduration'] = 'Success ({$a} seconds)'; $string['summary'] = 'Summary'; diff --git a/lang/en/user.php b/lang/en/user.php index a47dacd0f5a..9d200d11fae 100644 --- a/lang/en/user.php +++ b/lang/en/user.php @@ -147,6 +147,10 @@ $string['privacy:privatefilespath'] = 'Private files'; $string['privacy:sessionpath'] = 'Session data'; $string['filterbykeyword'] = 'Keyword'; $string['selectfiltertype'] = 'Select'; +$string['supportmessagesent'] = 'Your support request has been submitted'; +$string['supportmessagesentforloggedoutuser'] = 'Be careful with this message - the sender was not logged in, so their identity has not been authenticated.'; +$string['supportmessagenotsent'] = "Unfortunately your support request can't be sent at this time!"; +$string['supportmessagealternative'] = 'You can still submit your support request to {$a}'; $string['target:upcomingactivitiesdue'] = 'Upcoming activities due'; $string['target:upcomingactivitiesdue_help'] = 'This target generates reminders for upcoming activities due.'; $string['target:upcomingactivitiesdueinfo'] = 'All upcoming activities due insights are listed here. These students have received these insights directly.'; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 944bbe6edc4..361fe1a0977 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -4135,14 +4135,18 @@ EOD; public function supportemail(): string { global $CFG; - if (empty($CFG->supportemail)) { - return ''; - } - - $supportemail = $CFG->supportemail; $label = get_string('contactsitesupport', 'admin'); $icon = $this->pix_icon('t/email', '', 'moodle', ['class' => 'iconhelp icon-pre']); - return html_writer::tag('a', $icon . $label, ['href' => 'mailto:' . $supportemail]); + $content = $icon . $label; + + if (!empty($CFG->supportpage)) { + $attributes = ['href' => $CFG->supportpage, 'target' => 'blank']; + $content .= $this->pix_icon('i/externallink', '', 'moodle', ['class' => 'iconhelp icon-pre']); + } else { + $attributes = ['href' => $CFG->wwwroot . '/user/contactsitesupport.php']; + } + + return html_writer::tag('a', $content, $attributes); } /** diff --git a/theme/boost/scss/moodle/user.scss b/theme/boost/scss/moodle/user.scss index 52f93e561c4..dc62fc561f7 100644 --- a/theme/boost/scss/moodle/user.scss +++ b/theme/boost/scss/moodle/user.scss @@ -317,3 +317,12 @@ @extend .align-top; } } + +#page-user-contactsitesupport { + .supporticon { + i { + font-size: 64px; + } + + } +} diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index 75e798e952f..f06ebde1212 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -17149,6 +17149,9 @@ body.path-question-type .mform fieldset.hidden { [data-filterverb="2"] [data-filterverbfor="2"] { display: block; } +#page-user-contactsitesupport .supporticon i { + font-size: 64px; } + .search-results .result { margin-left: 0; margin-right: 0; } diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css index e162bbc2b86..fdcfb9c83b4 100644 --- a/theme/classic/style/moodle.css +++ b/theme/classic/style/moodle.css @@ -17149,6 +17149,9 @@ body.path-question-type .mform fieldset.hidden { [data-filterverb="2"] [data-filterverbfor="2"] { display: block; } +#page-user-contactsitesupport .supporticon i { + font-size: 64px; } + .search-results .result { margin-left: 0; margin-right: 0; } diff --git a/user/classes/form/contactsitesupport_form.php b/user/classes/form/contactsitesupport_form.php new file mode 100644 index 00000000000..bdb3e73f040 --- /dev/null +++ b/user/classes/form/contactsitesupport_form.php @@ -0,0 +1,109 @@ +. + +namespace core_user\form; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot.'/lib/formslib.php'); + +/** + * Contact site support form. + * + * @package core_user + * @copyright 2022 Simey Lameze + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class contactsitesupport_form extends \moodleform { + + /** + * Define the contact site support form. + */ + public function definition(): void { + global $CFG; + + $mform = $this->_form; + $user = $this->_customdata; + $strrequired = get_string('required'); + + // Name. + $mform->addElement('text', 'name', get_string('name')); + $mform->addRule('name', $strrequired, 'required', null, 'client'); + $mform->setType('name', PARAM_TEXT); + + // Email. + $mform->addElement('text', 'email', get_string('email')); + $mform->addRule('email', get_string('missingemail'), 'required', null, 'client'); + $mform->setType('email', PARAM_EMAIL); + + // Subject. + $mform->addElement('text', 'subject', get_string('subject')); + $mform->addRule('subject', $strrequired, 'required', null, 'client'); + $mform->setType('subject', PARAM_TEXT); + + // Message. + $mform->addElement('textarea', 'message', get_string('message')); + $mform->addRule('message', $strrequired, 'required', null, 'client'); + $mform->setType('message', PARAM_TEXT); + + // If the user is logged in set name and email fields to the current user info. + if (isloggedin() && !isguestuser()) { + $mform->setDefault('name', fullname($user)); + $mform->hardFreeze('name'); + + $mform->setDefault('email', $user->email); + $mform->hardFreeze('email'); + } + + if (!empty($CFG->recaptchapublickey) && !empty($CFG->recaptchaprivatekey)) { + $mform->addElement('recaptcha', 'recaptcha_element', get_string('security_question', 'auth')); + $mform->addHelpButton('recaptcha_element', 'recaptcha', 'auth'); + $mform->closeHeaderBefore('recaptcha_element'); + } + + $this->add_action_buttons(true, get_string('submit')); + } + + /** + * Validate user supplied data on the contact site support form. + * + * @param array $data array of ("fieldname"=>value) of submitted data + * @param array $files array of uploaded files "element_name"=>tmp_file_path + * @return array of "element_name"=>"error_description" if there are errors, + * or an empty array if everything is OK (true allowed for backwards compatibility too). + */ + public function validation($data, $files): array { + $errors = parent::validation($data, $files); + if (!validate_email($data['email'])) { + $errors['email'] = get_string('invalidemail'); + } + if ($this->_form->elementExists('recaptcha_element')) { + $recaptchaelement = $this->_form->getElement('recaptcha_element'); + + if (!empty($this->_form->_submitValues['g-recaptcha-response'])) { + $response = $this->_form->_submitValues['g-recaptcha-response']; + if (!$recaptchaelement->verify($response)) { + $errors['recaptcha_element'] = get_string('incorrectpleasetryagain', 'auth'); + } + } else { + $errors['recaptcha_element'] = get_string('missingrecaptchachallengefield'); + } + } + + return $errors; + } + +} diff --git a/user/contactsitesupport.php b/user/contactsitesupport.php new file mode 100644 index 00000000000..7bf8342b358 --- /dev/null +++ b/user/contactsitesupport.php @@ -0,0 +1,73 @@ +. + +/** + * Contact site support. + * + * @copyright 2022 Simey Lameze + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package core_user + */ +require_once('../config.php'); +require_once($CFG->dirroot . '/user/lib.php'); + +if (!empty($CFG->supportpage)) { + redirect($CFG->supportpage); +} + +$PAGE->set_context(context_system::instance()); +$PAGE->set_url('/user/contactsitesupport.php'); +$PAGE->set_title(get_string('contactsitesupport', 'admin')); +$PAGE->set_heading(get_string('contactsitesupport', 'admin')); +$PAGE->set_pagelayout('standard'); +$PAGE->has_secondary_navigation_setter(false); + +$user = isloggedin() && !isguestuser() ? $USER : null; +$renderer = $PAGE->get_renderer('user'); + +if (!$CFG->smtphosts) { + $supportemail = $CFG->supportemail; + $templatectx = $user ? ['supportemail' => html_writer::link("mailto:{$supportemail}", $supportemail)] : []; + $output = $renderer->render_from_template('user/contact_site_support_not_available', $templatectx); +} else { + $form = new \core_user\form\contactsitesupport_form(null, $user); + if ($form->is_cancelled()) { + redirect($CFG->wwwroot); + } else if ($form->is_submitted() && $form->is_validated() && confirm_sesskey()) { + $data = $form->get_data(); + + $from = $user ?? core_user::get_noreply_user(); + $subject = get_string('supportemailsubject', 'admin', format_string($SITE->fullname)); + $data->notloggedinuser = (!$user); + $message = $renderer->render_from_template('user/contact_site_support_email_body', $data); + + if (!email_to_user(core_user::get_support_user(), $from, $subject, $message)) { + $form->set_data($data); + $notificationmessage = get_string('supportmessagenotsent', 'user'); + \core\notification::add($notificationmessage, \core\output\notification::NOTIFY_ERROR); + } else { + $level = \core\output\notification::NOTIFY_SUCCESS; + redirect($CFG->wwwroot, get_string('supportmessagesent', 'user'), 3, $level); + } + + } + $output = $form->render(); +} +echo $OUTPUT->header(); + +echo $output; + +echo $OUTPUT->footer(); diff --git a/user/templates/contact_site_support_email_body.mustache b/user/templates/contact_site_support_email_body.mustache new file mode 100644 index 00000000000..8022dc21225 --- /dev/null +++ b/user/templates/contact_site_support_email_body.mustache @@ -0,0 +1,102 @@ +{{! + 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_user/contact_site_support_email_body + + Support email email body. + + Example context (json): + { + "subject": "email subject", + "notloggedinuser": true, + "name": "Sender name", + "email": "sender@mail.com", + "description": "Support request message" + } +}} + + + + + + + + + + + +

{{#str}}subject{{/str}}: {{subject}}

+ + + + + {{#notloggedinuser}} + + {{/notloggedinuser}} + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{#str}}supportmessagesentforloggedoutuser, user{{/str}} +

 {{#str}}name{{/str}}{{name}}

 {{#str}}email{{/str}}{{email}}

 {{#str}}description{{/str}}{{message}}
+
+ diff --git a/user/templates/contact_site_support_not_available.mustache b/user/templates/contact_site_support_not_available.mustache new file mode 100644 index 00000000000..cf5571544b3 --- /dev/null +++ b/user/templates/contact_site_support_not_available.mustache @@ -0,0 +1,39 @@ +{{! + 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_user/contact_site_support_not_available + + Fallback for the contact support page if smtp is not configured. + + Example context (json): + { + "supportemail": "support@mail.com" + } +}} +
+
+
{{#pix}}t/life-ring, core{{/pix}}
+
{{#str}}supportmessagenotsent, user{{/str}}
+ {{#supportemail}} +
+ + {{#str}}supportmessagealternative, user, {{{supportemail}}}{{/str}} + +
+ {{/supportemail}} +
+