on-demand release 4.0dev+
[moodle.git] / contentbank / classes / form / upload_files.php
CommitLineData
33b8ca26
AA
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
9c070644 17namespace core_contentbank\form;
33b8ca26
AA
18
19/**
9c070644 20 * Upload files to content bank form
33b8ca26
AA
21 *
22 * @package core_contentbank
23 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
dcf94b0c 26class upload_files extends \core_form\dynamic_form {
33b8ca26
AA
27
28 /**
29 * Add elements to this form.
30 */
31 public function definition() {
32 $mform = $this->_form;
33
dcf94b0c 34 $mform->addElement('hidden', 'contextid');
33b8ca26
AA
35 $mform->setType('contextid', PARAM_INT);
36
dcf94b0c
SA
37 $mform->addElement('hidden', 'id');
38 $mform->setType('id', PARAM_INT);
c5a8469a 39
dcf94b0c 40 $mform->addElement('filepicker', 'file', get_string('file', 'core_contentbank'), null, $this->get_options());
33b8ca26
AA
41 $mform->addHelpButton('file', 'file', 'core_contentbank');
42 $mform->addRule('file', null, 'required');
33b8ca26
AA
43 }
44
45 /**
46 * Validate incoming data.
47 *
48 * @param array $data
49 * @param array $files
50 * @return array
51 */
52 public function validation($data, $files) {
53 $errors = array();
54 $draftitemid = $data['file'];
dcf94b0c
SA
55 $options = $this->get_options();
56 if (file_is_draft_area_limit_reached($draftitemid, $options['areamaxbytes'])) {
33b8ca26
AA
57 $errors['file'] = get_string('userquotalimit', 'error');
58 }
59 return $errors;
60 }
dcf94b0c
SA
61
62 /**
63 * Check if current user has access to this form, otherwise throw exception
64 *
65 * Sometimes permission check may depend on the action and/or id of the entity.
66 * If necessary, form data is available in $this->_ajaxformdata or
67 * by calling $this->optional_param()
68 */
69 protected function check_access_for_dynamic_submission(): void {
70 require_capability('moodle/contentbank:upload', $this->get_context_for_dynamic_submission());
71
72 // Check the context used by the content bank is allowed.
73 $cb = new \core_contentbank\contentbank();
74 if (!$cb->is_context_allowed($this->get_context_for_dynamic_submission())) {
75 throw new \moodle_exception('contextnotallowed', 'core_contentbank');
76 }
77
78 // If $id is defined, the file content will be replaced (instead of uploading a new one).
79 // Check that the user has the right permissions to replace this content file.
80 $id = $this->optional_param('id', null, PARAM_INT);
81 if ($id) {
82 $content = $cb->get_content_from_id($id);
83 $contenttype = $content->get_content_type_instance();
84 if (!$contenttype->can_manage($content) || !$contenttype->can_upload()) {
85 throw new \moodle_exception('nopermissions', 'error', '', null, get_string('replacecontent', 'contentbank'));
86 }
87 }
88 }
89
90 /**
91 * Returns form context
92 *
93 * If context depends on the form data, it is available in $this->_ajaxformdata or
94 * by calling $this->optional_param()
95 *
96 * @return \context
97 */
98 protected function get_context_for_dynamic_submission(): \context {
99 $contextid = $this->optional_param('contextid', null, PARAM_INT);
100 return \context::instance_by_id($contextid, MUST_EXIST);
101 }
102
103 /**
104 * File upload options
105 *
106 * @return array
107 * @throws \coding_exception
108 */
109 protected function get_options(): array {
110 global $CFG;
111
112 $maxbytes = $CFG->userquota;
113 $maxareabytes = $CFG->userquota;
114 if (has_capability('moodle/user:ignoreuserquota', $this->get_context_for_dynamic_submission())) {
115 $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS;
116 $maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED;
117 }
118
119 $cb = new \core_contentbank\contentbank();
120 $id = $this->optional_param('id', null, PARAM_INT);
121 if ($id) {
122 $content = $cb->get_content_from_id($id);
123 $contenttype = $content->get_content_type_instance();
124 $extensions = $contenttype->get_manageable_extensions();
125 $acceptedtypes = implode(',', $extensions);
126 } else {
127 $acceptedtypes = $cb->get_supported_extensions_as_string($this->get_context_for_dynamic_submission());
128 }
129
130 return ['subdirs' => 1, 'maxbytes' => $maxbytes, 'maxfiles' => -1, 'accepted_types' => $acceptedtypes,
131 'areamaxbytes' => $maxareabytes];
132 }
133
134 /**
135 * Process the form submission, used if form was submitted via AJAX
136 *
137 * This method can return scalar values or arrays that can be json-encoded, they will be passed to the caller JS.
138 *
139 * Submission data can be accessed as: $this->get_data()
140 *
141 * @return mixed
142 */
143 public function process_dynamic_submission() {
144 global $USER;
145
146 // Get the file and create the content based on it.
147 $usercontext = \context_user::instance($USER->id);
148 $fs = get_file_storage();
149 $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $this->get_data()->file, 'itemid, filepath,
150 filename', false);
151 if (!empty($files)) {
152 $file = reset($files);
153 $cb = new \core_contentbank\contentbank();
39fa45e2
SA
154 try {
155 if ($this->get_data()->id) {
156 $content = $cb->get_content_from_id($this->get_data()->id);
157 $contenttype = $content->get_content_type_instance();
158 $content = $contenttype->replace_content($file, $content);
159 } else {
160 $content = $cb->create_content_from_file($this->get_context_for_dynamic_submission(), $USER->id, $file);
161 }
162 $params = ['id' => $content->get_id(), 'contextid' => $this->get_context_for_dynamic_submission()->id];
163 $url = new \moodle_url('/contentbank/view.php', $params);
164 } catch (\Exception $e) {
165 // Redirect to the right page (depending on if content is new or existing) and display an error.
166 if ($this->get_data()->id) {
167 $content = $cb->get_content_from_id($this->get_data()->id);
168 $params = [
169 'id' => $content->get_id(),
170 'contextid' => $this->get_context_for_dynamic_submission()->id,
171 'errormsg' => 'notvalidpackage',
172 ];
173 $url = new \moodle_url('/contentbank/view.php', $params);
174 } else {
175 $url = new \moodle_url('/contentbank/index.php', [
176 'contextid' => $this->get_context_for_dynamic_submission()->id,
177 'errormsg' => 'notvalidpackage'],
178 );
179 }
dcf94b0c 180 }
39fa45e2
SA
181
182 return ['returnurl' => $url->out(false)];
dcf94b0c
SA
183 }
184
185 return null;
186 }
187
188 /**
189 * Load in existing data as form defaults
190 *
191 * Can be overridden to retrieve existing values from db by entity id and also
192 * to preprocess editor and filemanager elements
193 *
194 * Example:
195 * $this->set_data(get_entity($this->_ajaxformdata['id']));
196 */
197 public function set_data_for_dynamic_submission(): void {
198 $data = (object)[
199 'contextid' => $this->optional_param('contextid', null, PARAM_INT),
200 'id' => $this->optional_param('id', null, PARAM_INT),
201 ];
202 $this->set_data($data);
203 }
204
205 /**
206 * Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
207 *
208 * This is used in the form elements sensitive to the page url, such as Atto autosave in 'editor'
209 *
210 * If the form has arguments (such as 'id' of the element being edited), the URL should
211 * also have respective argument.
212 *
213 * @return \moodle_url
214 */
215 protected function get_page_url_for_dynamic_submission(): \moodle_url {
216 $params = ['contextid' => $this->get_context_for_dynamic_submission()->id];
217
218 $id = $this->optional_param('id', null, PARAM_INT);
219 if ($id) {
220 $url = '/contentbank/view.php';
221 $params['id'] = $id;
222 } else {
223 $url = '/contentbank/index.php';
224 }
225
226 return new \moodle_url($url, $params);
227 }
33b8ca26 228}