diff --git a/blocks/private_files/block_private_files.php b/blocks/private_files/block_private_files.php
index dcebb0121ab..a299c229bdd 100644
--- a/blocks/private_files/block_private_files.php
+++ b/blocks/private_files/block_private_files.php
@@ -61,8 +61,14 @@ class block_private_files extends block_base {
$this->content->text = $renderer->private_files_tree();
if (has_capability('moodle/user:manageownfiles', $this->context)) {
$this->content->footer = html_writer::link(
- new moodle_url('/user/files.php', array('returnurl' => $this->page->url->out())),
- get_string('privatefilesmanage') . '...');
+ new moodle_url('/user/files.php'),
+ get_string('privatefilesmanage') . '...',
+ ['data-action' => 'manageprivatefiles']);
+ $this->page->requires->js_call_amd(
+ 'core_user/private_files',
+ 'initModal',
+ ['[data-action=manageprivatefiles]', \core_user\form\private_files::class]
+ );
}
}
diff --git a/files/tests/behat/license_help_modal.feature b/files/tests/behat/license_help_modal.feature
index 3aa3de0e2ac..38cf2e24ce2 100644
--- a/files/tests/behat/license_help_modal.feature
+++ b/files/tests/behat/license_help_modal.feature
@@ -17,10 +17,10 @@ Feature: View licence links
@javascript @_file_upload
Scenario: Altering a file should display licence list modal
Given I log in as "admin"
- And I follow "Manage private files..."
+ And I follow "Private files"
And I upload "lib/tests/fixtures/empty.txt" file to "Files" filemanager
And I press "Save changes"
- And I follow "Manage private files..."
+ And I follow "Private files"
And I click on "empty.txt" "link"
And I click on "Help with Choose licence" "icon"
Then I should see "Follow these links for further information on the available licence options:"
diff --git a/lib/behat/classes/partial_named_selector.php b/lib/behat/classes/partial_named_selector.php
index 3689733441e..c6677728888 100644
--- a/lib/behat/classes/partial_named_selector.php
+++ b/lib/behat/classes/partial_named_selector.php
@@ -144,6 +144,7 @@ XPATH
XPATH
, 'dialogue' => <<.\n\n/**\n * Module to handle AJAX interactions with user private files\n *\n * @module core_user/private_files\n * @copyright 2020 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport DynamicForm from 'core_form/dynamicform';\nimport ModalForm from 'core_form/modalform';\nimport {get_string as getString} from 'core/str';\nimport {add as addToast} from 'core/toast';\n\n/**\n * Initialize private files form as AJAX form\n *\n * @param {String} containerSelector\n * @param {String} formClass\n */\nexport const initDynamicForm = (containerSelector, formClass) => {\n const form = new DynamicForm(document.querySelector(containerSelector), formClass);\n // When form is saved, refresh it to remove validation errors, if any:\n form.addEventListener(form.events.FORM_SUBMITTED, () => {\n form.load();\n getString('changessaved')\n .then(addToast)\n .catch(null);\n });\n};\n\n/**\n * Initialize private files form as Modal form\n *\n * @param {String} elementSelector\n * @param {String} formClass\n */\nexport const initModal = (elementSelector, formClass) => {\n document.querySelector(elementSelector).addEventListener('click', function(e) {\n e.preventDefault();\n const form = new ModalForm({\n formClass,\n args: {nosubmit: true},\n modalConfig: {title: getString('privatefilesmanage')},\n returnFocus: e.target,\n });\n form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());\n form.show();\n });\n};\n"],"file":"private_files.min.js"}
\ No newline at end of file
diff --git a/user/amd/src/private_files.js b/user/amd/src/private_files.js
new file mode 100644
index 00000000000..adde6cb9391
--- /dev/null
+++ b/user/amd/src/private_files.js
@@ -0,0 +1,63 @@
+// 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 .
+
+/**
+ * Module to handle AJAX interactions with user private files
+ *
+ * @module core_user/private_files
+ * @copyright 2020 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+import DynamicForm from 'core_form/dynamicform';
+import ModalForm from 'core_form/modalform';
+import {get_string as getString} from 'core/str';
+import {add as addToast} from 'core/toast';
+
+/**
+ * Initialize private files form as AJAX form
+ *
+ * @param {String} containerSelector
+ * @param {String} formClass
+ */
+export const initDynamicForm = (containerSelector, formClass) => {
+ const form = new DynamicForm(document.querySelector(containerSelector), formClass);
+ // When form is saved, refresh it to remove validation errors, if any:
+ form.addEventListener(form.events.FORM_SUBMITTED, () => {
+ form.load();
+ getString('changessaved')
+ .then(addToast)
+ .catch(null);
+ });
+};
+
+/**
+ * Initialize private files form as Modal form
+ *
+ * @param {String} elementSelector
+ * @param {String} formClass
+ */
+export const initModal = (elementSelector, formClass) => {
+ document.querySelector(elementSelector).addEventListener('click', function(e) {
+ e.preventDefault();
+ const form = new ModalForm({
+ formClass,
+ args: {nosubmit: true},
+ modalConfig: {title: getString('privatefilesmanage')},
+ returnFocus: e.target,
+ });
+ form.addEventListener(form.events.FORM_SUBMITTED, () => window.location.reload());
+ form.show();
+ });
+};
diff --git a/user/classes/form/private_files.php b/user/classes/form/private_files.php
new file mode 100644
index 00000000000..2522f78449d
--- /dev/null
+++ b/user/classes/form/private_files.php
@@ -0,0 +1,190 @@
+.
+
+namespace core_user\form;
+
+use html_writer;
+use moodle_url;
+
+/**
+ * Manage user private area files form
+ *
+ * @package core_user
+ * @copyright 2010 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class private_files extends \core_form\dynamic_form {
+
+ /**
+ * Add elements to this form.
+ */
+ public function definition() {
+ global $OUTPUT;
+ $mform = $this->_form;
+ $options = $this->get_options();
+
+ // Show file area space usage.
+ $maxareabytes = $options['areamaxbytes'];
+ if ($maxareabytes != FILE_AREA_MAX_BYTES_UNLIMITED) {
+ $fileareainfo = file_get_file_area_info($this->get_context_for_dynamic_submission()->id, 'user', 'private');
+ // Display message only if we have files.
+ if ($fileareainfo['filecount']) {
+ $a = (object) [
+ 'used' => display_size($fileareainfo['filesize_without_references']),
+ 'total' => display_size($maxareabytes)
+ ];
+ $quotamsg = get_string('quotausage', 'moodle', $a);
+ $notification = new \core\output\notification($quotamsg, \core\output\notification::NOTIFY_INFO);
+ $mform->addElement('static', 'areabytes', '', $OUTPUT->render($notification));
+ }
+ }
+
+ $mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options);
+ if ($link = $this->get_emaillink()) {
+ $emaillink = html_writer::link(new moodle_url('mailto:' . $link), $link);
+ $mform->addElement('static', 'emailaddress', '',
+ get_string('emailtoprivatefiles', 'moodle', $emaillink));
+ }
+ $mform->setType('returnurl', PARAM_LOCALURL);
+
+ if (!$this->optional_param('nosubmit', false, PARAM_BOOL)) {
+ $this->add_action_buttons(false, get_string('savechanges'));
+ }
+ }
+
+ /**
+ * Validate incoming data.
+ *
+ * @param array $data
+ * @param array $files
+ * @return array
+ */
+ public function validation($data, $files) {
+ $errors = array();
+ $draftitemid = $data['files_filemanager'];
+ $options = $this->get_options();
+ if (file_is_draft_area_limit_reached($draftitemid, $options['areamaxbytes'])) {
+ $errors['files_filemanager'] = get_string('userquotalimit', 'error');
+ }
+
+ return $errors;
+ }
+
+ /**
+ * Link to email private files
+ *
+ * @return string|null
+ * @throws \coding_exception
+ */
+ protected function get_emaillink() {
+ global $USER;
+
+ // Attempt to generate an inbound message address to support e-mail to private files.
+ $generator = new \core\message\inbound\address_manager();
+ $generator->set_handler('\core\message\inbound\private_files_handler');
+ $generator->set_data(-1);
+ return $generator->generate($USER->id);
+ }
+
+ /**
+ * Check if current user has access to this form, otherwise throw exception
+ *
+ * Sometimes permission check may depend on the action and/or id of the entity.
+ * If necessary, form data is available in $this->_ajaxformdata or
+ * by calling $this->optional_param()
+ */
+ protected function check_access_for_dynamic_submission(): void {
+ require_capability('moodle/user:manageownfiles', $this->get_context_for_dynamic_submission());
+ }
+
+ /**
+ * Returns form context
+ *
+ * If context depends on the form data, it is available in $this->_ajaxformdata or
+ * by calling $this->optional_param()
+ *
+ * @return \context
+ */
+ protected function get_context_for_dynamic_submission(): \context {
+ global $USER;
+ return \context_user::instance($USER->id);
+ }
+
+ /**
+ * File upload options
+ *
+ * @return array
+ * @throws \coding_exception
+ */
+ protected function get_options(): array {
+ global $CFG;
+
+ $maxbytes = $CFG->userquota;
+ $maxareabytes = $CFG->userquota;
+ if (has_capability('moodle/user:ignoreuserquota', $this->get_context_for_dynamic_submission())) {
+ $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS;
+ $maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED;
+ }
+
+ return ['subdirs' => 1, 'maxbytes' => $maxbytes, 'maxfiles' => -1, 'accepted_types' => '*',
+ 'areamaxbytes' => $maxareabytes];
+ }
+
+ /**
+ * Process the form submission, used if form was submitted via AJAX
+ *
+ * This method can return scalar values or arrays that can be json-encoded, they will be passed to the caller JS.
+ *
+ * Submission data can be accessed as: $this->get_data()
+ *
+ * @return mixed
+ */
+ public function process_dynamic_submission() {
+ file_postupdate_standard_filemanager($this->get_data(), 'files',
+ $this->get_options(), $this->get_context_for_dynamic_submission(), 'user', 'private', 0);
+ return null;
+ }
+
+ /**
+ * Load in existing data as form defaults
+ *
+ * Can be overridden to retrieve existing values from db by entity id and also
+ * to preprocess editor and filemanager elements
+ *
+ * Example:
+ * $this->set_data(get_entity($this->_ajaxformdata['id']));
+ */
+ public function set_data_for_dynamic_submission(): void {
+ $data = new \stdClass();
+ file_prepare_standard_filemanager($data, 'files', $this->get_options(),
+ $this->get_context_for_dynamic_submission(), 'user', 'private', 0);
+ $this->set_data($data);
+ }
+
+ /**
+ * Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
+ *
+ * This is used in the form elements sensitive to the page url, such as Atto autosave in 'editor'
+ *
+ * If the form has arguments (such as 'id' of the element being edited), the URL should
+ * also have respective argument.
+ *
+ * @return \moodle_url
+ */
+ protected function get_page_url_for_dynamic_submission(): \moodle_url {
+ return new moodle_url('/user/files.php');
+ }
+}
\ No newline at end of file
diff --git a/user/files.php b/user/files.php
index dadaf619d94..1c645cd661a 100644
--- a/user/files.php
+++ b/user/files.php
@@ -24,25 +24,16 @@
*/
require('../config.php');
-require_once("$CFG->dirroot/user/files_form.php");
-require_once("$CFG->dirroot/repository/lib.php");
require_login();
if (isguestuser()) {
die();
}
-$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
-
-if (empty($returnurl)) {
- $returnurl = new moodle_url('/user/files.php');
-}
-
$context = context_user::instance($USER->id);
require_capability('moodle/user:manageownfiles', $context);
$title = get_string('privatefiles');
-$struser = get_string('user');
$PAGE->set_url('/user/files.php');
$PAGE->set_context($context);
@@ -51,52 +42,16 @@ $PAGE->set_heading(fullname($USER));
$PAGE->set_pagelayout('standard');
$PAGE->set_pagetype('user-files');
-$maxbytes = $CFG->userquota;
-$maxareabytes = $CFG->userquota;
-if (has_capability('moodle/user:ignoreuserquota', $context)) {
- $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS;
- $maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED;
-}
-
-$data = new stdClass();
-$data->returnurl = $returnurl;
-$options = array('subdirs' => 1, 'maxbytes' => $maxbytes, 'maxfiles' => -1, 'accepted_types' => '*',
- 'areamaxbytes' => $maxareabytes);
-file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0);
-
-// Attempt to generate an inbound message address to support e-mail to private files.
-$generator = new \core\message\inbound\address_manager();
-$generator->set_handler('\core\message\inbound\private_files_handler');
-$generator->set_data(-1);
-$data->emaillink = $generator->generate($USER->id);
-
-$mform = new user_files_form(null, array('data' => $data, 'options' => $options));
-
-if ($mform->is_cancelled()) {
- redirect($returnurl);
-} else if ($formdata = $mform->get_data()) {
- $formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $context, 'user', 'private', 0);
- redirect($returnurl);
-}
-
echo $OUTPUT->header();
echo $OUTPUT->box_start('generalbox');
-// Show file area space usage.
-if ($maxareabytes != FILE_AREA_MAX_BYTES_UNLIMITED) {
- $fileareainfo = file_get_file_area_info($context->id, 'user', 'private');
- // Display message only if we have files.
- if ($fileareainfo['filecount']) {
- $a = (object) [
- 'used' => display_size($fileareainfo['filesize_without_references']),
- 'total' => display_size($maxareabytes)
- ];
- $quotamsg = get_string('quotausage', 'moodle', $a);
- $notification = new \core\output\notification($quotamsg, \core\output\notification::NOTIFY_INFO);
- echo $OUTPUT->render($notification);
- }
-}
+echo html_writer::start_div('', ['id' => 'userfilesform']);
+$form = new \core_user\form\private_files();
+$form->set_data_for_dynamic_submission();
+$form->display();
+echo html_writer::end_div();
+$PAGE->requires->js_call_amd('core_user/private_files', 'initDynamicForm',
+ ['#userfilesform', \core_user\form\private_files::class]);
-$mform->display();
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
diff --git a/user/files_form.php b/user/files_form.php
deleted file mode 100644
index 709b3c9a86d..00000000000
--- a/user/files_form.php
+++ /dev/null
@@ -1,76 +0,0 @@
-.
-
-/**
- * minimalistic edit form
- *
- * @package core_user
- * @category files
- * @copyright 2010 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-defined('MOODLE_INTERNAL') || die();
-
-require_once("$CFG->libdir/formslib.php");
-
-/**
- * Class user_files_form
- * @copyright 2010 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class user_files_form extends moodleform {
-
- /**
- * Add elements to this form.
- */
- public function definition() {
- $mform = $this->_form;
-
- $data = $this->_customdata['data'];
- $options = $this->_customdata['options'];
-
- $mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options);
- $mform->addElement('hidden', 'returnurl', $data->returnurl);
- if (isset($data->emaillink)) {
- $emaillink = html_writer::link(new moodle_url('mailto:' . $data->emaillink), $data->emaillink);
- $mform->addElement('static', 'emailaddress', '',
- get_string('emailtoprivatefiles', 'moodle', $emaillink));
- }
- $mform->setType('returnurl', PARAM_LOCALURL);
-
- $this->add_action_buttons(true, get_string('savechanges'));
-
- $this->set_data($data);
- }
-
- /**
- * Validate incoming data.
- *
- * @param array $data
- * @param array $files
- * @return array
- */
- public function validation($data, $files) {
- $errors = array();
- $draftitemid = $data['files_filemanager'];
- if (file_is_draft_area_limit_reached($draftitemid, $this->_customdata['options']['areamaxbytes'])) {
- $errors['files_filemanager'] = get_string('userquotalimit', 'error');
- }
-
- return $errors;
- }
-}