77ee16903e5490b9554c4d15887ac131b1565a7c
[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      * Sets name of filemanager
84      *
85      * @param string $name name of the filemanager
86      */
87     function setName($name) {
88         $this->updateAttributes(array('name'=>$name));
89     }
91     /**
92      * Returns name of filemanager
93      *
94      * @return string
95      */
96     function getName() {
97         return $this->getAttribute('name');
98     }
100     /**
101      * Updates filemanager attribute value
102      *
103      * @param string $value value to set
104      */
105     function setValue($value) {
106         $this->updateAttributes(array('value'=>$value));
107     }
109     /**
110      * Returns filemanager attribute value
111      *
112      * @return string
113      */
114     function getValue() {
115         return $this->getAttribute('value');
116     }
118     /**
119      * Returns maximum file size which can be uploaded
120      *
121      * @return int
122      */
123     function getMaxbytes() {
124         return $this->_options['maxbytes'];
125     }
127     /**
128      * Sets maximum file size which can be uploaded
129      *
130      * @param int $maxbytes file size
131      */
132     function setMaxbytes($maxbytes) {
133         global $CFG, $PAGE;
134         $this->_options['maxbytes'] = get_user_max_upload_file_size($PAGE->context, $CFG->maxbytes, $maxbytes);
135     }
137     /**
138      * Returns the maximum size of the area.
139      *
140      * @return int
141      */
142     function getAreamaxbytes() {
143         return $this->_options['areamaxbytes'];
144     }
146     /**
147      * Sets the maximum size of the area.
148      *
149      * @param int $areamaxbytes size limit
150      */
151     function setAreamaxbytes($areamaxbytes) {
152         $this->_options['areamaxbytes'] = $areamaxbytes;
153     }
155     /**
156      * Returns true if subdirectoy can be created, else false
157      *
158      * @return bool
159      */
160     function getSubdirs() {
161         return $this->_options['subdirs'];
162     }
164     /**
165      * Set option to create sub directory, while uploading  file
166      *
167      * @param bool $allow true if sub directory can be created.
168      */
169     function setSubdirs($allow) {
170         $this->_options['subdirs'] = $allow;
171     }
173     /**
174      * Returns maximum number of files which can be uploaded
175      *
176      * @return int
177      */
178     function getMaxfiles() {
179         return $this->_options['maxfiles'];
180     }
182     /**
183      * Sets maximum number of files which can be uploaded.
184      *
185      * @param int $num number of files
186      */
187     function setMaxfiles($num) {
188         $this->_options['maxfiles'] = $num;
189     }
191     /**
192      * Returns html for help button.
193      *
194      * @return string html for help button
195      */
196     function getHelpButton() {
197         return $this->_helpbutton;
198     }
200     /**
201      * Returns type of filemanager element
202      *
203      * @return string
204      */
205     function getElementTemplateType() {
206         if ($this->_flagFrozen){
207             return 'nodisplay';
208         } else {
209             return 'default';
210         }
211     }
213     /**
214      * Returns HTML for filemanager form element.
215      *
216      * @return string
217      */
218     function toHtml() {
219         global $CFG, $USER, $COURSE, $PAGE, $OUTPUT;
220         require_once("$CFG->dirroot/repository/lib.php");
222         // security - never ever allow guest/not logged in user to upload anything or use this element!
223         if (isguestuser() or !isloggedin()) {
224             print_error('noguest');
225         }
227         if ($this->_flagFrozen) {
228             return $this->getFrozenHtml();
229         }
231         $id          = $this->_attributes['id'];
232         $elname      = $this->_attributes['name'];
233         $subdirs     = $this->_options['subdirs'];
234         $maxbytes    = $this->_options['maxbytes'];
235         $draftitemid = $this->getValue();
236         $accepted_types = $this->_options['accepted_types'];
238         if (empty($draftitemid)) {
239             // no existing area info provided - let's use fresh new draft area
240             require_once("$CFG->libdir/filelib.php");
241             $this->setValue(file_get_unused_draft_itemid());
242             $draftitemid = $this->getValue();
243         }
245         $client_id = uniqid();
247         // filemanager options
248         $options = new stdClass();
249         $options->mainfile  = $this->_options['mainfile'];
250         $options->maxbytes  = $this->_options['maxbytes'];
251         $options->maxfiles  = $this->getMaxfiles();
252         $options->client_id = $client_id;
253         $options->itemid    = $draftitemid;
254         $options->subdirs   = $this->_options['subdirs'];
255         $options->target    = $id;
256         $options->accepted_types = $accepted_types;
257         $options->return_types = $this->_options['return_types'];
258         $options->context = $PAGE->context;
259         $options->areamaxbytes = $this->_options['areamaxbytes'];
261         $html = $this->_getTabs();
262         $fm = new form_filemanager($options);
263         $output = $PAGE->get_renderer('core', 'files');
264         $html .= $output->render($fm);
266         $html .= '<input value="'.$draftitemid.'" name="'.$elname.'" type="hidden" />';
267         // label element needs 'for' attribute work
268         $html .= '<input value="" id="id_'.$elname.'" type="hidden" />';
270         return $html;
271     }
274 /**
275  * Data structure representing a file manager.
276  *
277  * This class defines the data structure for file mnager
278  *
279  * @package   core_form
280  * @copyright 2010 Dongsheng Cai
281  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
282  * @todo      do not use this abstraction (skodak)
283  */
284 class form_filemanager implements renderable {
285     /** @var stdClass $options options for filemanager */
286     public $options;
288     /**
289      * Constructor
290      *
291      * @param stdClass $options options for filemanager
292      *   default options are:
293      *       maxbytes=>-1,
294      *       areamaxbytes => FILE_AREA_MAX_BYTES_UNLIMITED,
295      *       maxfiles=>-1,
296      *       itemid=>0,
297      *       subdirs=>false,
298      *       client_id=>uniqid(),
299      *       acepted_types=>'*',
300      *       return_types=>FILE_INTERNAL,
301      *       context=>$PAGE->context,
302      *       author=>fullname($USER),
303      *       licenses=>array build from $CFG->licenses,
304      *       defaultlicense=>$CFG->sitedefaultlicense
305      */
306     public function __construct(stdClass $options) {
307         global $CFG, $USER, $PAGE;
308         require_once($CFG->dirroot. '/repository/lib.php');
309         $defaults = array(
310             'maxbytes'=>-1,
311             'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED,
312             'maxfiles'=>-1,
313             'itemid'=>0,
314             'subdirs'=>0,
315             'client_id'=>uniqid(),
316             'accepted_types'=>'*',
317             'return_types'=>FILE_INTERNAL,
318             'context'=>$PAGE->context,
319             'author'=>fullname($USER),
320             'licenses'=>array()
321             );
322         if (!empty($CFG->licenses)) {
323             $array = explode(',', $CFG->licenses);
324             foreach ($array as $license) {
325                 $l = new stdClass();
326                 $l->shortname = $license;
327                 $l->fullname = get_string($license, 'license');
328                 $defaults['licenses'][] = $l;
329             }
330         }
331         if (!empty($CFG->sitedefaultlicense)) {
332             $defaults['defaultlicense'] = $CFG->sitedefaultlicense;
333         }
334         foreach ($defaults as $key=>$value) {
335             // Using !isset() prevents us from overwriting falsey values with defaults (as empty() did).
336             if (!isset($options->$key)) {
337                 $options->$key = $value;
338             }
339         }
341         $fs = get_file_storage();
343         // initilise options, getting files in root path
344         $this->options = file_get_drafarea_files($options->itemid, '/');
346         // calculate file count
347         $usercontext = context_user::instance($USER->id);
348         $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $options->itemid, 'id', false);
349         $filecount = count($files);
350         $this->options->filecount = $filecount;
352         // copying other options
353         foreach ($options as $name=>$value) {
354             $this->options->$name = $value;
355         }
357         // calculate the maximum file size as minimum from what is specified in filepicker options,
358         // course options, global configuration and php settings
359         $coursebytes = $maxbytes = 0;
360         list($context, $course, $cm) = get_context_info_array($this->options->context->id);
361         if (is_object($course)) {
362             $coursebytes = $course->maxbytes;
363         }
364         if (!empty($this->options->maxbytes) && $this->options->maxbytes > 0) {
365             $maxbytes = $this->options->maxbytes;
366         }
367         $this->options->maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $coursebytes, $maxbytes);
369         // building file picker options
370         $params = new stdClass();
371         $params->accepted_types = $options->accepted_types;
372         $params->return_types = $options->return_types;
373         $params->context = $options->context;
374         $params->env = 'filemanager';
375         $params->disable_types = !empty($options->disable_types)?$options->disable_types:array();
376         $filepicker_options = initialise_filepicker($params);
377         $this->options->filepicker = $filepicker_options;
378     }
380     public function get_nonjsurl() {
381         global $PAGE;
382         return new moodle_url('/repository/draftfiles_manager.php', array(
383             'env'=>'filemanager',
384             'action'=>'browse',
385             'itemid'=>$this->options->itemid,
386             'subdirs'=>$this->options->subdirs,
387             'maxbytes'=>$this->options->maxbytes,
388             'areamaxbytes' => $this->options->areamaxbytes,
389             'maxfiles'=>$this->options->maxfiles,
390             'ctx_id'=>$PAGE->context->id, // TODO ?
391             'course'=>$PAGE->course->id, // TODO ?
392             'sesskey'=>sesskey(),
393             ));
394     }