mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
Merge branch 'MDL-66679-master' of https://github.com/sammarshallou/moodle
This commit is contained in:
commit
f025022d62
@ -45,6 +45,9 @@ class grade_export_xls extends grade_export {
|
||||
|
||||
$strgrades = get_string('grades');
|
||||
|
||||
// If this file was requested from a form, then mark download as complete (before sending headers).
|
||||
\core_form\util::form_download_complete();
|
||||
|
||||
// Calculate file name
|
||||
$shortname = format_string($this->course->shortname, true, array('context' => context_course::instance($this->course->id)));
|
||||
$downloadfilename = clean_filename("$shortname $strgrades.xls");
|
||||
|
@ -503,6 +503,9 @@ class csv_export_writer {
|
||||
* Download the csv file.
|
||||
*/
|
||||
public function download_file() {
|
||||
// If this file was requested from a form, then mark download as complete.
|
||||
\core_form\util::form_download_complete();
|
||||
|
||||
$this->send_header();
|
||||
$this->print_csv_data();
|
||||
exit;
|
||||
|
@ -54,6 +54,9 @@ function download_as_dataformat($filename, $dataformat, $columns, $iterator, $ca
|
||||
// Close the session so that the users other tabs in the same session are not blocked.
|
||||
\core\session\manager::write_close();
|
||||
|
||||
// If this file was requested from a form, then mark download as complete (before sending headers).
|
||||
\core_form\util::form_download_complete();
|
||||
|
||||
$format->set_filename($filename);
|
||||
$format->send_http_headers();
|
||||
// This exists to support all dataformats - see MDL-56046.
|
||||
|
@ -2299,6 +2299,9 @@ function send_temp_file($path, $filename, $pathisstring=false) {
|
||||
$filename = urlencode($filename);
|
||||
}
|
||||
|
||||
// If this file was requested from a form, then mark download as complete.
|
||||
\core_form\util::form_download_complete();
|
||||
|
||||
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
||||
if (is_https()) { // HTTPS sites - watch out for IE! KB812935 and KB316431.
|
||||
header('Cache-Control: private, max-age=10, no-transform');
|
||||
@ -2450,6 +2453,9 @@ function send_file($path, $filename, $lifetime = null , $filter=0, $pathisstring
|
||||
|
||||
if ($forcedownload) {
|
||||
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
||||
|
||||
// If this file was requested from a form, then mark download as complete.
|
||||
\core_form\util::form_download_complete();
|
||||
} else if ($mimetype !== 'application/x-shockwave-flash') {
|
||||
// If this is an swf don't pass content-disposition with filename as this makes the flash player treat the file
|
||||
// as an upload and enforces security that may prevent the file from being loaded.
|
||||
|
2
lib/form/amd/build/submit.min.js
vendored
2
lib/form/amd/build/submit.min.js
vendored
@ -1,2 +1,2 @@
|
||||
define ("core_form/submit",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;a.init=function init(a){var b=document.getElementById(a);b.form.addEventListener("submit",function(){var a=function(){b.disabled=!0};window.addEventListener("beforeunload",a);setTimeout(function(){window.removeEventListener("beforeunload",a)},0)},!1)}});
|
||||
define ("core_form/submit",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var b=0,c=[],d=function(a){c.push(a);if(!b){b=setInterval(function(){var a=document.cookie.split(e()+"=");if(2==a.length){f();clearInterval(b);b=0;c.forEach(function(a){a.disabled=!1})}},500)}},e=function(){return"moodledownload_"+M.cfg.sesskey},f=function(){document.cookie=encodeURIComponent(e())+"=deleted; expires="+new Date(0).toUTCString()};a.init=function init(a){var b=document.getElementById(a);if("off"===b.form.dataset.doubleSubmitProtection){return}b.form.addEventListener("submit",function(a){var c=function(){if(a.defaultPrevented||b.disabled){return}b.disabled=!0;f();d(b)};window.addEventListener("beforeunload",c);setTimeout(function(){window.removeEventListener("beforeunload",c)},0)},!1)}});
|
||||
//# sourceMappingURL=submit.min.js.map
|
||||
|
File diff suppressed because one or more lines are too long
@ -24,6 +24,60 @@
|
||||
* @since 3.8
|
||||
*/
|
||||
|
||||
/** @type {number} ID for setInterval used when polling for download cookie */
|
||||
let cookieListener = 0;
|
||||
|
||||
/** @type {Array} Array of buttons that need re-enabling if we get a download cookie */
|
||||
const cookieListeningButtons = [];
|
||||
|
||||
/**
|
||||
* Listens in case a download cookie is provided.
|
||||
*
|
||||
* This function is used to detect file downloads. If there is a file download then we get a
|
||||
* beforeunload event, but the page is never unloaded and when the file download completes we
|
||||
* should re-enable the buttons. We detect this by watching for a specific cookie.
|
||||
*
|
||||
* PHP function \core_form\util::form_download_complete() can be used to send this cookie.
|
||||
*
|
||||
* @param {HTMLElement} button Button to re-enable
|
||||
*/
|
||||
const listenForDownloadCookie = (button) => {
|
||||
cookieListeningButtons.push(button);
|
||||
if (!cookieListener) {
|
||||
cookieListener = setInterval(() => {
|
||||
// Look for cookie.
|
||||
const parts = document.cookie.split(getCookieName() + '=');
|
||||
if (parts.length == 2) {
|
||||
// We found the cookie, so the file is ready. Expire the cookie and cancel polling.
|
||||
clearDownloadCookie();
|
||||
clearInterval(cookieListener);
|
||||
cookieListener = 0;
|
||||
|
||||
// Re-enable all the buttons.
|
||||
cookieListeningButtons.forEach((button) => {
|
||||
button.disabled = false;
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a unique name for the download cookie.
|
||||
*
|
||||
* @returns {string} Cookie name
|
||||
*/
|
||||
const getCookieName = () => {
|
||||
return 'moodledownload_' + M.cfg.sesskey;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the download cookie if there is one.
|
||||
*/
|
||||
const clearDownloadCookie = () => {
|
||||
document.cookie = encodeURIComponent(getCookieName()) + '=deleted; expires=' + new Date(0).toUTCString();
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialises submit buttons.
|
||||
*
|
||||
@ -31,11 +85,22 @@
|
||||
*/
|
||||
export const init = (elementId) => {
|
||||
const button = document.getElementById(elementId);
|
||||
button.form.addEventListener('submit', function() {
|
||||
// If the form has double submit protection disabled, do nothing.
|
||||
if (button.form.dataset.doubleSubmitProtection === 'off') {
|
||||
return;
|
||||
}
|
||||
button.form.addEventListener('submit', function(event) {
|
||||
// Only disable it if the browser is really going to another page as a result of the
|
||||
// submit.
|
||||
const disableAction = function() {
|
||||
// If the submit was cancelled, or the button is already disabled, don't do anything.
|
||||
if (event.defaultPrevented || button.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.disabled = true;
|
||||
clearDownloadCookie();
|
||||
listenForDownloadCookie(button);
|
||||
};
|
||||
window.addEventListener('beforeunload', disableAction);
|
||||
// If there is no beforeunload event as a result of this form submit, then the form
|
||||
|
64
lib/form/classes/util.php
Normal file
64
lib/form/classes/util.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Provides the {@link core_form\util} class.
|
||||
*
|
||||
* @package core_form
|
||||
* @copyright 2019 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* General utility class for form-related methods.
|
||||
*
|
||||
* @copyright 2019 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class util {
|
||||
/**
|
||||
* This function should be called if a form submit results in a file download (i.e. with the
|
||||
* Content-Disposition: attachment header) instead of navigating to a new page, before the
|
||||
* file download is sent. It will set a cookie which is used to inform page javascript in
|
||||
* submit.js.
|
||||
*
|
||||
* You may call this function in scripts which might not necessarily be called from forms; it
|
||||
* will only set the cookie if there is a POST request from a form.
|
||||
*
|
||||
* This is automatically called from various points in Moodle such as send_file_xx functions
|
||||
* in filelib.php.
|
||||
*/
|
||||
public static function form_download_complete() {
|
||||
// If this doesn't look like a Moodle QuickForms request, ignore.
|
||||
$quickform = false;
|
||||
foreach ($_POST as $name => $value) {
|
||||
if (preg_match('~^_qf__~', $name)) {
|
||||
$quickform = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$quickform) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set a session cookie.
|
||||
setcookie('moodledownload_' . sesskey(), time());
|
||||
}
|
||||
}
|
@ -169,6 +169,10 @@ abstract class moodleform {
|
||||
* @param mixed $attributes you can pass a string of html attributes here or an array.
|
||||
* Special attribute 'data-random-ids' will randomise generated elements ids. This
|
||||
* is necessary when there are several forms on the same page.
|
||||
* Special attribute 'data-double-submit-protection' set to 'off' will turn off
|
||||
* double-submit protection JavaScript - this may be necessary if your form sends
|
||||
* downloadable files in response to a submit button, and can't call
|
||||
* \core_form\util::form_download_complete();
|
||||
* @param bool $editable
|
||||
* @param array $ajaxformdata Forms submitted via ajax, must pass their data here, instead of relying on _GET and _POST.
|
||||
*/
|
||||
|
@ -76,6 +76,13 @@ validation against and defaults to null (so, no user needed) if not provided.
|
||||
the itemid and filepath for the filearea and path defined in $args. It has been added in order to get the correct itemid and
|
||||
filepath because some components, such as mod_page or mod_resource, add the revision to the URL where the itemid should be placed
|
||||
(to prevent caching problems), but then they don't store it in database.
|
||||
* New utility function \core_form\util::form_download_complete should be called if your code sends
|
||||
a file with Content-Disposition: Attachment in response to a Moodle form submit button (to ensure
|
||||
that disabled submit buttons get re-enabled in that case). It is automatically called by the
|
||||
filelib.php send_xx functions.
|
||||
* If you have a form which sends a file in response to a Moodle form submit button, but you cannot
|
||||
call the above function because the file is sent by a third party library, then you should add
|
||||
the attribute data-double-submit-protection="off" to your form.
|
||||
|
||||
=== 3.7 ===
|
||||
|
||||
|
@ -140,6 +140,10 @@ if (optional_param('sesskey', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
|
||||
header('Pragma: public');
|
||||
|
||||
// If this file was requested from a form, then mark download as complete.
|
||||
\core_form\util::form_download_complete();
|
||||
|
||||
$exportfilehandler = fopen($exportfile, 'rb');
|
||||
print fread($exportfilehandler, filesize($exportfile));
|
||||
fclose($exportfilehandler);
|
||||
|
Loading…
x
Reference in New Issue
Block a user