MDL-29766 Add drag and drop upload to filemanager / filepicker elements
[moodle.git] / lib / form / filemanager.php
CommitLineData
ae4a98a1 1<?php
56a7bf68 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 * File manager
19 *
20 * @package moodlecore
21 * @subpackage file
22 * @copyright 1999 onwards Dongsheng Cai <dongsheng@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
ae4a98a1 25
26global $CFG;
8546def3 27
28require_once('HTML/QuickForm/element.php');
ae4a98a1 29require_once($CFG->dirroot.'/lib/filelib.php');
133fd70b 30require_once($CFG->dirroot.'/repository/lib.php');
8546def3 31
241431cd 32class MoodleQuickForm_filemanager extends HTML_QuickForm_element {
12f11f23 33 public $_helpbutton = '';
1dce6261 34 protected $_options = array('mainfile'=>'', 'subdirs'=>1, 'maxbytes'=>-1, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL);
8546def3 35
9d54b8cd 36 function MoodleQuickForm_filemanager($elementName=null, $elementLabel=null, $attributes=null, $options=null) {
56a7bf68 37 global $CFG, $PAGE;
56a7bf68 38
adb7cbb4 39 $options = (array)$options;
40 foreach ($options as $name=>$value) {
41 if (array_key_exists($name, $this->_options)) {
42 $this->_options[$name] = $value;
43 }
b5b188ce 44 }
ad620df3 45 if (!empty($options['maxbytes'])) {
a83ad946 46 $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']);
45d0b872 47 }
c6aa3670 48 $this->_type = 'filemanager';
adb7cbb4 49 parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
8546def3 50 }
51
52 function setName($name) {
53 $this->updateAttributes(array('name'=>$name));
54 }
55
56 function getName() {
57 return $this->getAttribute('name');
58 }
59
60 function setValue($value) {
b933a139 61 $this->updateAttributes(array('value'=>$value));
8546def3 62 }
63
64 function getValue() {
b933a139 65 return $this->getAttribute('value');
8546def3 66 }
67
45d0b872 68 function getMaxbytes() {
69 return $this->_options['maxbytes'];
70 }
71
72 function setMaxbytes($maxbytes) {
a83ad946 73 global $CFG;
74 $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $maxbytes);
45d0b872 75 }
76
77 function getSubdirs() {
78 return $this->_options['subdirs'];
79 }
80
81 function setSubdirs($allow) {
82 $this->_options['subdirs'] = $allow;
83 }
84
4664b66c 85 function getMaxfiles() {
86 return $this->_options['maxfiles'];
87 }
88
89 function setMaxfiles($num) {
90 $this->_options['maxfiles'] = $num;
91 }
92
12fab708 93 function setHelpButton($helpbuttonargs, $function='helpbutton'){
4bcc5118 94 debugging('component setHelpButton() is not used any more, please use $mform->setHelpButton() instead');
8546def3 95 }
96
97 function getHelpButton() {
98 return $this->_helpbutton;
99 }
100
101 function getElementTemplateType() {
102 if ($this->_flagFrozen){
103 return 'nodisplay';
104 } else {
105 return 'default';
106 }
107 }
108
109 function toHtml() {
1420162a 110 global $CFG, $USER, $COURSE, $PAGE, $OUTPUT;
b5cb48de 111 require_once("$CFG->dirroot/repository/lib.php");
112
b933a139 113 // security - never ever allow guest/not logged in user to upload anything or use this element!
114 if (isguestuser() or !isloggedin()) {
115 print_error('noguest');
116 }
8546def3 117
118 if ($this->_flagFrozen) {
119 return $this->getFrozenHtml();
120 }
121
b5b188ce 122 $id = $this->_attributes['id'];
123 $elname = $this->_attributes['name'];
124 $subdirs = $this->_options['subdirs'];
a83ad946 125 $maxbytes = $this->_options['maxbytes'];
b933a139 126 $draftitemid = $this->getValue();
99eaca9d 127 $accepted_types = $this->_options['accepted_types'];
8546def3 128
b933a139 129 if (empty($draftitemid)) {
8546def3 130 // no existing area info provided - let's use fresh new draft area
131 require_once("$CFG->libdir/filelib.php");
edc0c493 132 $this->setValue(file_get_unused_draft_itemid());
b933a139 133 $draftitemid = $this->getValue();
8546def3 134 }
135
99eaca9d 136 $client_id = uniqid();
4bb7f787 137
133fd70b 138 // filemanager options
6bdfef5d 139 $options = new stdClass();
56a7bf68 140 $options->mainfile = $this->_options['mainfile'];
8a3e6a56 141 $options->maxbytes = $this->_options['maxbytes'];
56a7bf68 142 $options->maxfiles = $this->getMaxfiles();
143 $options->client_id = $client_id;
144 $options->itemid = $draftitemid;
be4487f4 145 $options->subdirs = $this->_options['subdirs'];
56a7bf68 146 $options->target = $id;
4d2ee4c2
DC
147 $options->accepted_types = $accepted_types;
148 $options->return_types = FILE_INTERNAL;
149 $options->context = $PAGE->context;
56a7bf68 150
151 $html = $this->_getTabs();
64f93798 152 $html .= form_filemanager_render($options);
4d2ee4c2 153
f0e23170
EL
154 $html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
155 // label element needs 'for' attribute work
156 $html .= '<input value="" id="id_'.$elname.'" type="hidden" />';
157
56a7bf68 158 return $html;
8546def3 159 }
8546def3 160}
64f93798
PS
161
162
163
164/**
165 * Data structure representing a file manager.
166 *
167 * @copyright 2010 Dongsheng Cai
168 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
169 * @since Moodle 2.0
170 */
171class form_filemanaer_x {
172 //TODO: do not use this abstraction (skodak)
173
174 public $options;
175 public function __construct(stdClass $options) {
176 global $CFG, $USER, $PAGE;
177 require_once($CFG->dirroot. '/repository/lib.php');
178 $defaults = array(
179 'maxbytes'=>-1,
180 'maxfiles'=>-1,
181 'itemid'=>0,
182 'subdirs'=>0,
183 'client_id'=>uniqid(),
184 'accepted_types'=>'*',
185 'return_types'=>FILE_INTERNAL,
186 'context'=>$PAGE->context
187 );
188 foreach ($defaults as $key=>$value) {
189 if (empty($options->$key)) {
190 $options->$key = $value;
191 }
192 }
193
194 $fs = get_file_storage();
195
196 // initilise options, getting files in root path
197 $this->options = file_get_drafarea_files($options->itemid, '/');
198
199 // calculate file count
200 $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
201 $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $options->itemid, 'id', false);
202 $filecount = count($files);
203 $this->options->filecount = $filecount;
204
205 // copying other options
206 foreach ($options as $name=>$value) {
207 $this->options->$name = $value;
208 }
209
210 // building file picker options
6bdfef5d 211 $params = new stdClass();
64f93798
PS
212 $params->accepted_types = $options->accepted_types;
213 $params->return_types = $options->return_types;
214 $params->context = $options->context;
215 $params->env = 'filemanager';
216 $params->disable_types = !empty($options->disable_types)?$options->disable_types:array();
217 $filepicker_options = initialise_filepicker($params);
218 $this->options->filepicker = $filepicker_options;
219 }
220}
221
222/**
223 * Print the file manager
224 *
225 * <pre>
226 * $OUTPUT->file_manager($options);
227 * </pre>
228 *
229 * @param array $options associative array with file manager options
230 * options are:
231 * maxbytes=>-1,
232 * maxfiles=>-1,
233 * itemid=>0,
234 * subdirs=>false,
235 * client_id=>uniqid(),
236 * acepted_types=>'*',
237 * return_types=>FILE_INTERNAL,
238 * context=>$PAGE->context
239 * @return string HTML fragment
240 */
241function form_filemanager_render($options) {
242 global $CFG, $OUTPUT, $PAGE;
243
244 $fm = new form_filemanaer_x($options); //TODO: this is unnecessary here, the nested options are getting too complex
245
246 static $filemanagertemplateloaded;
247
248 $html = '';
64f93798 249 $options = $fm->options;
6d30723e 250 $straddfile = get_string('addfile', 'repository');
64f93798
PS
251 $strmakedir = get_string('makeafolder', 'moodle');
252 $strdownload = get_string('downloadfolder', 'repository');
253 $strloading = get_string('loading', 'repository');
254
64f93798
PS
255 $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).'';
256
257 $client_id = $options->client_id;
258 $itemid = $options->itemid;
c8f0b534
DC
259 list($context, $course, $cm) = get_context_info_array($options->context->id);
260 if (is_object($course)) {
261 $course_maxbytes = $course->maxbytes;
262 } else {
263 $course_maxbytes = $CFG->maxbytes;
264 }
265
266 if ($options->maxbytes == -1 || empty($options->maxbytes)) {
267 $options->maxbytes = $CFG->maxbytes;
268 }
64f93798
PS
269
270 if (empty($options->filecount)) {
271 $extra = ' style="display:none"';
272 } else {
273 $extra = '';
274 }
275
c8f0b534 276 $maxsize = get_string('maxfilesize', 'moodle', display_size(get_max_upload_file_size($CFG->maxbytes, $course_maxbytes, $options->maxbytes)));
f08fac7c 277 $strdndenabled = get_string('dndenabled', 'moodle').$OUTPUT->help_icon('dndenabled');
64f93798
PS
278 $html .= <<<FMHTML
279<div class="filemanager-loading mdl-align" id='filemanager-loading-{$client_id}'>
280$icon_progress
281</div>
282<div id="filemanager-wrapper-{$client_id}" style="display:none">
283 <div class="fm-breadcrumb" id="fm-path-{$client_id}"></div>
284 <div class="filemanager-toolbar">
6d30723e
DC
285 <input type="button" class="fm-btn-add" id="btnadd-{$client_id}" onclick="return false" value="{$straddfile}" />
286 <input type="button" class="fm-btn-mkdir" id="btncrt-{$client_id}" onclick="return false" value="{$strmakedir}" />
287 <input type="button" class="fm-btn-download" id="btndwn-{$client_id}" onclick="return false" {$extra} value="{$strdownload}" />
fa7f2a45 288 <span> $maxsize </span>
f08fac7c 289 <span id="dndenabled-{$client_id}" style="display: none"> - $strdndenabled </span>
64f93798
PS
290 </div>
291 <div class="filemanager-container" id="filemanager-{$client_id}">
292 <ul id="draftfiles-{$client_id}" class="fm-filelist">
293 <li>Loading...</li>
294 </ul>
295 </div>
296</div>
297<div class='clearer'></div>
298FMHTML;
299 if (empty($filemanagertemplateloaded)) {
300 $filemanagertemplateloaded = true;
301 $html .= <<<FMHTML
302<div id="fm-template" style="display:none">___fullname___ ___action___</div>
303FMHTML;
304 }
305
64f93798
PS
306 $module = array(
307 'name'=>'form_filemanager',
308 'fullpath'=>'/lib/form/filemanager.js',
f08fac7c 309 'requires' => array('core_filepicker', 'base', 'io-base', 'node', 'json', 'yui2-button', 'yui2-container', 'yui2-layout', 'yui2-menu', 'yui2-treeview', 'core_dndupload'),
64f93798
PS
310 'strings' => array(array('loading', 'repository'), array('nomorefiles', 'repository'), array('confirmdeletefile', 'repository'),
311 array('add', 'repository'), array('accessiblefilepicker', 'repository'), array('move', 'moodle'),
312 array('cancel', 'moodle'), array('download', 'moodle'), array('ok', 'moodle'),
313 array('emptylist', 'repository'), array('nofilesattached', 'repository'), array('entername', 'repository'), array('enternewname', 'repository'),
314 array('zip', 'editor'), array('unzip', 'moodle'), array('rename', 'moodle'), array('delete', 'moodle'),
315 array('cannotdeletefile', 'error'), array('confirmdeletefile', 'repository'),
316 array('nopathselected', 'repository'), array('popupblockeddownload', 'repository'),
6d30723e
DC
317 array('draftareanofiles', 'repository'), array('path', 'moodle'), array('setmainfile', 'repository'),
318 array('moving', 'repository'), array('files', 'moodle')
64f93798
PS
319 )
320 );
321 $PAGE->requires->js_module($module);
322 $PAGE->requires->js_init_call('M.form_filemanager.init', array($options), true, $module);
323
324 // non javascript file manager
563d0417
DC
325 $filemanagerurl = new moodle_url('/repository/draftfiles_manager.php', array(
326 'env'=>'filemanager',
327 'action'=>'browse',
328 'itemid'=>$itemid,
329 'subdirs'=>$options->subdirs,
330 'maxbytes'=>$options->maxbytes,
331 'maxfiles'=>$options->maxfiles,
332 'ctx_id'=>$PAGE->context->id,
333 'course'=>$PAGE->course->id,
71267723 334 'sesskey'=>sesskey(),
563d0417
DC
335 ));
336
337 $html .= '<noscript>';
6ef1402e 338 $html .= "<div><object type='text/html' data='$filemanagerurl' height='160' width='600' style='border:1px solid #000'></object></div>";
563d0417 339 $html .= '</noscript>';
64f93798
PS
340
341
342 return $html;
343}