MDL-43948 forms: setting types to filemanager and editor elements
[moodle.git] / lib / form / filemanager.php
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/>.
18 /**
19  * FileManager form element
20  *
21  * Contains HTML class for a filemanager form element
22  *
23  * @package   core_form
24  * @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
25  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 global $CFG;
30 require_once('HTML/QuickForm/element.php');
31 require_once($CFG->dirroot.'/lib/filelib.php');
32 require_once($CFG->dirroot.'/repository/lib.php');
34 /**
35  * Filemanager form element
36  *
37  * FilemaneManager lets user to upload/manage multiple files
38  * @package   core_form
39  * @category  form
40  * @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
41  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42  */
43 class MoodleQuickForm_filemanager extends HTML_QuickForm_element {
44     /** @var string html for help button, if empty then no help will icon will be dispalyed. */
45     public $_helpbutton = '';
47     /** @var array options provided to initalize filemanager */
48     // PHP doesn't support 'key' => $value1 | $value2 in class definition
49     // We cannot do $_options = array('return_types'=> FILE_INTERNAL | FILE_REFERENCE);
50     // So I have to set null here, and do it in constructor
51     protected $_options = array('mainfile' => '', 'subdirs' => 1, 'maxbytes' => -1, 'maxfiles' => -1,
52             'accepted_types' => '*', 'return_types' =>  null, 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED);
54     /**
55      * Constructor
56      *
57      * @param string $elementName (optional) name of the filemanager
58      * @param string $elementLabel (optional) filemanager label
59      * @param array $attributes (optional) Either a typical HTML attribute string
60      *              or an associative array
61      * @param array $options set of options to initalize filemanager
62      */
63     function MoodleQuickForm_filemanager($elementName=null, $elementLabel=null, $attributes=null, $options=null) {
64         global $CFG, $PAGE;
66         $options = (array)$options;
67         foreach ($options as $name=>$value) {
68             if (array_key_exists($name, $this->_options)) {
69                 $this->_options[$name] = $value;
70             }
71         }
72         if (!empty($options['maxbytes'])) {
73             $this->_options['maxbytes'] = get_user_max_upload_file_size($PAGE->context, $CFG->maxbytes, $options['maxbytes']);
74         }
75         if (empty($options['return_types'])) {
76             $this->_options['return_types'] = (FILE_INTERNAL | FILE_REFERENCE);
77         }
78         $this->_type = 'filemanager';
79         parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes);
80     }
82     /**
83      * Called by HTML_QuickForm whenever form event is made on this element
84      *
85      * @param string $event Name of event
86      * @param mixed $arg event arguments
87      * @param object $caller calling object
88      * @return bool
89      */
90     function onQuickFormEvent($event, $arg, &$caller)
91     {
92         switch ($event) {
93             case 'createElement':
94                 $caller->setType($arg[0], PARAM_INT);
95                 break;
96         }
97         return parent::onQuickFormEvent($event, $arg, $caller);
98     }
100     /**
101      * Sets name of filemanager
102      *
103      * @param string $name name of the filemanager
104      */
105     function setName($name) {
106         $this->updateAttributes(array('name'=>$name));
107     }
109     /**
110      * Returns name of filemanager
111      *
112      * @return string
113      */
114     function getName() {
115         return $this->getAttribute('name');
116     }
118     /**
119      * Updates filemanager attribute value
120      *
121      * @param string $value value to set
122      */
123     function setValue($value) {
124         $this->updateAttributes(array('value'=>$value));
125     }
127     /**
128      * Returns filemanager attribute value
129      *
130      * @return string
131      */
132     function getValue() {
133         return $this->getAttribute('value');
134     }
136     /**
137      * Returns maximum file size which can be uploaded
138      *
139      * @return int
140      */
141     function getMaxbytes() {
142         return $this->_options['maxbytes'];
143     }
145     /**
146      * Sets maximum file size which can be uploaded
147      *
148      * @param int $maxbytes file size
149      */
150     function setMaxbytes($maxbytes) {
151         global $CFG, $PAGE;
152         $this->_options['maxbytes'] = get_user_max_upload_file_size($PAGE->context, $CFG->maxbytes, $maxbytes);
153     }
155     /**
156      * Returns the maximum size of the area.
157      *
158      * @return int
159      */
160     function getAreamaxbytes() {
161         return $this->_options['areamaxbytes'];
162     }
164     /**
165      * Sets the maximum size of the area.
166      *
167      * @param int $areamaxbytes size limit
168      */
169     function setAreamaxbytes($areamaxbytes) {
170         $this->_options['areamaxbytes'] = $areamaxbytes;
171     }
173     /**
174      * Returns true if subdirectoy can be created, else false
175      *
176      * @return bool
177      */
178     function getSubdirs() {
179         return $this->_options['subdirs'];
180     }
182     /**
183      * Set option to create sub directory, while uploading  file
184      *
185      * @param bool $allow true if sub directory can be created.
186      */
187     function setSubdirs($allow) {
188         $this->_options['subdirs'] = $allow;
189     }
191     /**
192      * Returns maximum number of files which can be uploaded
193      *
194      * @return int
195      */
196     function getMaxfiles() {
197         return $this->_options['maxfiles'];
198     }
200     /**
201      * Sets maximum number of files which can be uploaded.
202      *
203      * @param int $num number of files
204      */
205     function setMaxfiles($num) {
206         $this->_options['maxfiles'] = $num;
207     }
209     /**
210      * Returns html for help button.
211      *
212      * @return string html for help button
213      */
214     function getHelpButton() {
215         return $this->_helpbutton;
216     }
218     /**
219      * Returns type of filemanager element
220      *
221      * @return string
222      */
223     function getElementTemplateType() {
224         if ($this->_flagFrozen){
225             return 'nodisplay';
226         } else {
227             return 'default';
228         }
229     }
231     /**
232      * Returns HTML for filemanager form element.
233      *
234      * @return string
235      */
236     function toHtml() {
237         global $CFG, $USER, $COURSE, $PAGE, $OUTPUT;
238         require_once("$CFG->dirroot/repository/lib.php");
240         // security - never ever allow guest/not logged in user to upload anything or use this element!
241         if (isguestuser() or !isloggedin()) {
242             print_error('noguest');
243         }
245         if ($this->_flagFrozen) {
246             return $this->getFrozenHtml();
247         }
249         $id          = $this->_attributes['id'];
250         $elname      = $this->_attributes['name'];
251         $subdirs     = $this->_options['subdirs'];
252         $maxbytes    = $this->_options['maxbytes'];
253         $draftitemid = $this->getValue();
254         $accepted_types = $this->_options['accepted_types'];
256         if (empty($draftitemid)) {
257             // no existing area info provided - let's use fresh new draft area
258             require_once("$CFG->libdir/filelib.php");
259             $this->setValue(file_get_unused_draft_itemid());
260             $draftitemid = $this->getValue();
261         }
263         $client_id = uniqid();
265         // filemanager options
266         $options = new stdClass();
267         $options->mainfile  = $this->_options['mainfile'];
268         $options->maxbytes  = $this->_options['maxbytes'];
269         $options->maxfiles  = $this->getMaxfiles();
270         $options->client_id = $client_id;
271         $options->itemid    = $draftitemid;
272         $options->subdirs   = $this->_options['subdirs'];
273         $options->target    = $id;
274         $options->accepted_types = $accepted_types;
275         $options->return_types = $this->_options['return_types'];
276         $options->context = $PAGE->context;
277         $options->areamaxbytes = $this->_options['areamaxbytes'];
279         $html = $this->_getTabs();
280         $fm = new form_filemanager($options);
281         $output = $PAGE->get_renderer('core', 'files');
282         $html .= $output->render($fm);
284         $html .= html_writer::empty_tag('input', array('value' => $draftitemid, 'name' => $elname, 'type' => 'hidden'));
285         // label element needs 'for' attribute work
286         $html .= html_writer::empty_tag('input', array('value' => '', 'id' => 'id_'.$elname, 'type' => 'hidden'));
288         return $html;
289     }
292 /**
293  * Data structure representing a file manager.
294  *
295  * This class defines the data structure for file mnager
296  *
297  * @package   core_form
298  * @copyright 2010 Dongsheng Cai
299  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
300  * @todo      do not use this abstraction (skodak)
301  */
302 class form_filemanager implements renderable {
303     /** @var stdClass $options options for filemanager */
304     public $options;
306     /**
307      * Constructor
308      *
309      * @param stdClass $options options for filemanager
310      *   default options are:
311      *       maxbytes=>-1,
312      *       areamaxbytes => FILE_AREA_MAX_BYTES_UNLIMITED,
313      *       maxfiles=>-1,
314      *       itemid=>0,
315      *       subdirs=>false,
316      *       client_id=>uniqid(),
317      *       acepted_types=>'*',
318      *       return_types=>FILE_INTERNAL,
319      *       context=>$PAGE->context,
320      *       author=>fullname($USER),
321      *       licenses=>array build from $CFG->licenses,
322      *       defaultlicense=>$CFG->sitedefaultlicense
323      */
324     public function __construct(stdClass $options) {
325         global $CFG, $USER, $PAGE;
326         require_once($CFG->dirroot. '/repository/lib.php');
327         $defaults = array(
328             'maxbytes'=>-1,
329             'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED,
330             'maxfiles'=>-1,
331             'itemid'=>0,
332             'subdirs'=>0,
333             'client_id'=>uniqid(),
334             'accepted_types'=>'*',
335             'return_types'=>FILE_INTERNAL,
336             'context'=>$PAGE->context,
337             'author'=>fullname($USER),
338             'licenses'=>array()
339             );
340         if (!empty($CFG->licenses)) {
341             $array = explode(',', $CFG->licenses);
342             foreach ($array as $license) {
343                 $l = new stdClass();
344                 $l->shortname = $license;
345                 $l->fullname = get_string($license, 'license');
346                 $defaults['licenses'][] = $l;
347             }
348         }
349         if (!empty($CFG->sitedefaultlicense)) {
350             $defaults['defaultlicense'] = $CFG->sitedefaultlicense;
351         }
352         foreach ($defaults as $key=>$value) {
353             // Using !isset() prevents us from overwriting falsey values with defaults (as empty() did).
354             if (!isset($options->$key)) {
355                 $options->$key = $value;
356             }
357         }
359         $fs = get_file_storage();
361         // initilise options, getting files in root path
362         $this->options = file_get_drafarea_files($options->itemid, '/');
364         // calculate file count
365         $usercontext = context_user::instance($USER->id);
366         $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $options->itemid, 'id', false);
367         $filecount = count($files);
368         $this->options->filecount = $filecount;
370         // copying other options
371         foreach ($options as $name=>$value) {
372             $this->options->$name = $value;
373         }
375         // calculate the maximum file size as minimum from what is specified in filepicker options,
376         // course options, global configuration and php settings
377         $coursebytes = $maxbytes = 0;
378         list($context, $course, $cm) = get_context_info_array($this->options->context->id);
379         if (is_object($course)) {
380             $coursebytes = $course->maxbytes;
381         }
382         if (!empty($this->options->maxbytes) && $this->options->maxbytes > 0) {
383             $maxbytes = $this->options->maxbytes;
384         }
385         $this->options->maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $coursebytes, $maxbytes);
387         // building file picker options
388         $params = new stdClass();
389         $params->accepted_types = $options->accepted_types;
390         $params->return_types = $options->return_types;
391         $params->context = $options->context;
392         $params->env = 'filemanager';
393         $params->disable_types = !empty($options->disable_types)?$options->disable_types:array();
394         $filepicker_options = initialise_filepicker($params);
395         $this->options->filepicker = $filepicker_options;
396     }
398     public function get_nonjsurl() {
399         global $PAGE;
400         return new moodle_url('/repository/draftfiles_manager.php', array(
401             'env'=>'filemanager',
402             'action'=>'browse',
403             'itemid'=>$this->options->itemid,
404             'subdirs'=>$this->options->subdirs,
405             'maxbytes'=>$this->options->maxbytes,
406             'areamaxbytes' => $this->options->areamaxbytes,
407             'maxfiles'=>$this->options->maxfiles,
408             'ctx_id'=>$PAGE->context->id, // TODO ?
409             'course'=>$PAGE->course->id, // TODO ?
410             'sesskey'=>sesskey(),
411             ));
412     }