MDL-69050 lang: Rename and deprecate filetypes_util methods
[moodle.git] / lib / form / filetypes.php
CommitLineData
97bb4f75
JF
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
17/**
18 * Provides the {@link MoodleQuickForm_filetypes} class.
19 *
20 * @package core_form
21 * @copyright 2016 Jonathon Fowler <fowlerj@usq.edu.au>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25use core_form\filetypes_util;
26
27defined('MOODLE_INTERNAL') || die;
28
29global $CFG;
30require_once($CFG->dirroot.'/lib/form/group.php');
31
32/**
33 * File types and type groups selection form element.
34 *
35 * @package core_form
36 * @category form
37 * @copyright 2016 Jonathon Fowler <fowlerj@usq.edu.au>
38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class MoodleQuickForm_filetypes extends MoodleQuickForm_group {
41
42 /** @var array Allow selection from these file types only. */
43 protected $onlytypes = [];
44
45 /** @var bool Allow selection of 'All file types' (will be stored as '*'). */
46 protected $allowall = true;
47
572d6fde
DM
48 /** @var bool Skip implicit validation against known file types. */
49 protected $allowunknown = false;
50
97bb4f75
JF
51 /** @var core_form\filetypes_util instance to use as a helper. */
52 protected $util = null;
53
54 /**
55 * Constructor
56 *
8b493eb0
DM
57 * @param string $elementname Element's name
58 * @param string $elementlabel Label(s) for an element
97bb4f75
JF
59 * @param array $options element options:
60 * 'onlytypes': Allow selection from these file types only; for example ['onlytypes' => ['web_image']].
61 * 'allowall': Allow to select 'All file types', defaults to true. Does not apply with onlytypes are set.
572d6fde 62 * 'allowunknown': Skip implicit validation against the list of known file types.
97bb4f75
JF
63 * @param array|string $attributes Either a typical HTML attribute string or an associative array
64 */
8b493eb0 65 public function __construct($elementname = null, $elementlabel = null, $options = null, $attributes = null) {
97bb4f75 66
8b493eb0 67 parent::__construct($elementname, $elementlabel);
97bb4f75
JF
68 $this->_type = 'filetypes';
69
70 // Hard-frozen elements do not get the name populated automatically,
71 // which leads to PHP notice. Add it explicitly here.
8b493eb0 72 $this->setAttributes(array('name' => $elementname));
97bb4f75
JF
73 $this->updateAttributes($attributes);
74
75 if (is_array($options) && $options) {
76 if (array_key_exists('onlytypes', $options) && is_array($options['onlytypes'])) {
77 $this->onlytypes = $options['onlytypes'];
78 }
79 if (!$this->onlytypes && array_key_exists('allowall', $options)) {
80 $this->allowall = (bool)$options['allowall'];
81 }
572d6fde
DM
82 if (array_key_exists('allowunknown', $options)) {
83 $this->allowunknown = (bool)$options['allowunknown'];
84 }
97bb4f75
JF
85 }
86
87 $this->util = new filetypes_util();
88 }
89
90 /**
91 * Assemble the elements of the form control.
92 */
93 public function _createElements() {
94
95 $this->_generateId();
96
97 $this->setElements([
9aabf267 98 $this->createFormElement('text', 'filetypes', $this->getLabel(), [
97bb4f75
JF
99 'id' => $this->getAttribute('id'),
100 ]),
101
102 $this->createFormElement('static', 'browser', null,
103 '<span data-filetypesbrowser="'.$this->getAttribute('id').'"></span>'),
104
8b493eb0
DM
105 $this->createFormElement('static', 'descriptions', null,
106 '<div data-filetypesdescriptions="'.$this->getAttribute('id').'"></div>')
97bb4f75
JF
107 ]);
108 }
109
110 /**
111 * Return the selected file types.
112 *
8b493eb0 113 * @param array $submitted submitted values
97bb4f75
JF
114 * @param bool $assoc if true the retured value is associated array
115 * @return array
116 */
8b493eb0 117 public function exportValue(&$submitted, $assoc = false) {
97bb4f75
JF
118
119 $value = '';
120 $filetypeselement = null;
121
122 foreach ($this->_elements as $key => $element) {
123 if ($element->_attributes['name'] === 'filetypes') {
124 $filetypeselement = $this->_elements[$key];
125 }
126 }
127
128 if ($filetypeselement) {
8b493eb0 129 $formval = $filetypeselement->exportValue($submitted[$this->getName()], false);
97bb4f75
JF
130 if ($formval) {
131 $value = $this->util->normalize_file_types($formval);
132 if ($value === ['*'] && !$this->allowall) {
133 $value = [];
134 }
135 $value = implode(',', $value);
136 }
137 }
138
139 return $this->_prepareValue($value, $assoc);
140 }
141
142 /**
143 * Accepts a renderer (called shortly before the renderer's toHtml() method).
144 *
145 * @param HTML_QuickForm_Renderer $renderer An HTML_QuickForm_Renderer object
146 * @param bool $required Whether a group is required
147 * @param string $error An error message associated with a group
148 */
149 public function accept(&$renderer, $required = false, $error = null) {
150 global $PAGE;
151
8b493eb0
DM
152 $PAGE->requires->js_call_amd('core_form/filetypes', 'init', [
153 $this->getAttribute('id'),
154 $this->getLabel(),
155 $this->onlytypes,
156 $this->allowall,
157 ]);
158
97bb4f75
JF
159 if ($this->isFrozen()) {
160 // Don't render the choose button if the control is frozen.
161 foreach ($this->_elements as $key => $element) {
162 if ($element->_attributes['name'] === 'browser') {
163 unset($this->_elements[$key]);
164 }
165 }
166 }
167
168 parent::accept($renderer, $required, $error);
169 }
170
171 /**
172 * Called by HTML_QuickForm whenever form event is made on this element
173 *
174 * @param string $event Name of event
175 * @param mixed $arg event arguments
176 * @param object $caller calling object
177 * @return bool
178 */
179 public function onQuickFormEvent($event, $arg, &$caller) {
180 global $OUTPUT;
181
182 switch ($event) {
183 case 'updateValue':
184 $value = $this->_findValue($caller->_constantValues);
185 if (null === $value) {
186 if ($caller->isSubmitted()) {
187 $value = $this->_findValue($caller->_submitValues);
188 } else {
189 $value = (string)$this->_findValue($caller->_defaultValues);
190 }
191 }
192 if (!is_array($value)) {
193 $value = array('filetypes' => $value);
194 }
195 if ($value['filetypes'] !== null) {
196 $filetypes = $this->util->normalize_file_types($value['filetypes']);
8b493eb0
DM
197 if ($filetypes === ['*'] && !$this->allowall) {
198 $filetypes = [];
199 }
200 $value['descriptions'] = '<div data-filetypesdescriptions="'.$this->getAttribute('id').'">' .
201 $OUTPUT->render_from_template('core_form/filetypes-descriptions',
202 $this->util->describe_file_types($filetypes)).'</div>';
97bb4f75
JF
203 }
204 $this->setValue($value);
205 return true;
572d6fde
DM
206 break;
207
97bb4f75
JF
208 }
209
210 return parent::onQuickFormEvent($event, $arg, $caller);
211 }
572d6fde
DM
212
213 /**
214 * Check that the submitted list contains only known and allowed file types.
215 *
216 * The validation obeys the element options 'allowall', 'allowunknown' and
217 * 'onlytypes' passed when creating the element.
218 *
219 * @param array $value Submitted value.
220 * @return string|null Validation error message or null.
221 */
222 public function validateSubmitValue($value) {
223
4621917c
EL
224 $value = $value ?? ['filetypes' => null]; // A null $value can arrive here. Coalesce, creating the default array.
225
572d6fde
DM
226 if (!$this->allowall) {
227 // Assert that there is an actual list provided.
228 $normalized = $this->util->normalize_file_types($value['filetypes']);
229 if (empty($normalized) || $normalized == ['*']) {
230 return get_string('filetypesnotall', 'core_form');
231 }
232 }
233
234 if (!$this->allowunknown) {
235 // Assert that all file types are known.
236 $unknown = $this->util->get_unknown_file_types($value['filetypes']);
237
238 if ($unknown) {
239 return get_string('filetypesunknown', 'core_form', implode(', ', $unknown));
240 }
241 }
242
243 if ($this->onlytypes) {
244 // Assert that all file types are allowed here.
781545d3 245 $notlisted = $this->util->get_not_listed($value['filetypes'], $this->onlytypes);
572d6fde 246
781545d3
DM
247 if ($notlisted) {
248 return get_string('filetypesnotallowed', 'core_form', implode(', ', $notlisted));
572d6fde
DM
249 }
250 }
251
252 return;
253 }
97bb4f75 254}