filebrowser.php 63.7 KB
Newer Older
1
2
3
4
5
6
<?php
/**
 *
 * @package    mahara
 * @subpackage artefact-file
 * @author     Catalyst IT Ltd
7
8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
9
10
11
12
 *
 */

defined('INTERNAL') || die();
13
define('FILEBROWSERS', 1);
14
15
16
17
18
19
20
21
/**
 * Browser for files area.
 *
 * @param Pieform  $form    The form to render the element for
 * @param array    $element The element to render
 * @return string           The HTML for the element
 */
function pieform_element_filebrowser(Pieform $form, $element) {
22
    require_once('license.php');
23
    global $USER, $_PIEFORM_FILEBROWSERS, $SESSION;
24
    $smarty = smarty_core();
25

26
27
28
29
30
31
32
33
    // See if the filebrowser has indicated it's a group element
    if (!empty($element['group'])) {
        $group = $element['group'];
    }
    else {
        // otherwise check if the form knows it's in a group setting
        $group = $form->get_property('group');
    }
34
35
36
37
38
39
40
41
    // See if the filebrowser has indicated it's an institution element
    if (!empty($element['institution'])) {
        $institution = $element['institution'];
    }
    else {
        // otherwise check if the form knows it's in an institution setting
        $institution = $form->get_property('institution');
    }
42
43
44
45

    $formid = $form->get_name();
    $prefix = $formid . '_' . $element['name'];

46
    if (!empty($element['tabs'])) {
47
        $tabdata = pieform_element_filebrowser_configure_tabs($element['tabs'], $prefix);
48
        $smarty->assign('tabs', $tabdata);
49
        if (!$group && $tabdata['owner'] == 'group') {
50
            $group = $tabdata['ownerid'];
51
52
        }
        else if (!$institution) {
53
54
            if ($tabdata['owner'] == 'institution') {
                $institution = $tabdata['ownerid'];
55
56
            }
            else if ($tabdata['owner'] == 'site') {
57
58
                $institution = 'mahara';
            }
59
60
61
62
        }
    }

    $userid = ($group || $institution) ? null : $USER->get('id');
63

64
65
66
67
68
    // refresh quotas
    if ($userid) {
        $USER->quota_refresh();
    }

69
    $folder = $element['folder'];
70
71
72
    if ($group && !pieform_element_filebrowser_view_group_folder($group, $folder)) {
        $folder = null;
    }
73
74
75
76
77
    $path = pieform_element_filebrowser_get_path($folder);
    $smarty->assign('folder', $folder);
    $smarty->assign('foldername', $path[0]->title);
    $smarty->assign('path', array_reverse($path));
    $smarty->assign('highlight', $element['highlight'][0]);
78
    $smarty->assign('edit', !empty($element['edit']) ? $element['edit'] : -1);
79
80
81
    if (isset($element['browse'])) {
        $smarty->assign('browse', (int) $element['browse']);
    }
82

83
    $config = array_map('intval', $element['config']);
84

85
86
87
88
    if ($group && $config['edit']) {
        $smarty->assign('groupinfo', pieform_element_filebrowser_get_groupinfo($group));
    }

89
    if ($config['select']) {
90
        $selected = array();
91
        if (function_exists($element['selectlistcallback'])) {
92
93
            if ($form->is_submitted() && $form->has_errors() && param_exists($prefix . '_selected') && is_array(param_array($prefix . '_selected'))) {
                $value = array_keys(param_array($prefix . '_selected'));
94
95
96
97
98
99
100
            }
            else if (isset($element['defaultvalue'])) {
                $value = $element['defaultvalue'];
            }
            else {
                $value = null;
            }
101
102
103
104
105
            // check to see if attached artefact items in $value array are actually allowed
            // to be seen by this user
            if (!empty($value)) {
                foreach ($value as $k => $v) {
                    $file = artefact_instance_from_id($v);
106
                    if ((!($file instanceof ArtefactTypeFile) && !($file instanceof ArtefactTypeFolder))
107
                        || !$USER->can_view_artefact($file)) {
108
109
110
111
                        unset($value[$k]);
                    }
                }
            }
112
            $selected = $element['selectlistcallback']($value);
113
        }
114
115
116
        foreach ($selected as $k => $v) {
            $v->time = '&time=' . time();
        }
117
118
119
        $smarty->assign('selectedlist', $selected);
        $selectedliststr = json_encode($selected);
    }
120

121
    if ($config['uploadagreement']) {
122
123
        if (get_config_plugin('artefact', 'file', 'usecustomagreement')) {
            $smarty->assign('agreementtext', get_field('site_content', 'content', 'name', 'uploadcopyright'));
124
125
        }
        else {
126
            $smarty->assign('agreementtext', get_string('uploadcopyrightdefaultcontent', 'install'));
127
128
        }
    }
129
130
131
132
    else if (!isset($config['simpleupload'])) {
        $config['simpleupload'] = 1;
    }

133
    $licensing = license_form_files($prefix);
134
135
    $smarty->assign('licenseform', $licensing);

136
137
138
139
140
141
    if ($config['resizeonuploaduseroption'] == 1) {
        $smarty->assign('resizeonuploadenable', get_config_plugin('artefact', 'file', 'resizeonuploadenable'));
        $smarty->assign('resizeonuploadmaxwidth', get_config_plugin('artefact', 'file', 'resizeonuploadmaxwidth'));
        $smarty->assign('resizeonuploadmaxheight', get_config_plugin('artefact', 'file', 'resizeonuploadmaxheight'));
    }

142
    if ($config['upload']) {
143
        $maxuploadsize = display_size(get_max_upload_size(!$institution && !$group));
144
        $smarty->assign('maxuploadsize', $maxuploadsize);
145
        $smarty->assign('phpmaxfilesize', get_max_upload_size(false));
146
147
148
        if ($group) {
            $smarty->assign('uploaddisabled', !pieform_element_filebrowser_edit_group_folder($group, $folder));
        }
149
    }
150

Richard Mansfield's avatar
Richard Mansfield committed
151
    if (!empty($element['browsehelp'])) {
152
153
154
155
        $config['plugintype'] = $form->get_property('plugintype');
        $config['pluginname'] = $form->get_property('pluginname');
        $config['browsehelp'] = $element['browsehelp'];
    }
156

157
158
159
    $config['showtags'] = !empty($config['tag']) ? (int) $userid : 0;
    $config['editmeta'] = (int) ($userid && !$config['edit'] && !empty($config['tag']));

160
161
    $smarty->assign('config', $config);

162
163
    $filters = isset($element['filters']) ? $element['filters'] : null;
    $filedata = ArtefactTypeFileBase::get_my_files_data($folder, $userid, $group, $institution, $filters);
164
165
166
167
168
169
    // Only allow 'Download folder content as zip' link if theres some kind of content (file or subfolder with content)
    $addzipdownloadlink = false;
    foreach ($filedata as $k => $v) {
        if (empty($v->isparent) && ($v->artefacttype != 'folder' || ($v->artefacttype == 'folder' && !empty($v->childcount)))) {
            $addzipdownloadlink = true;
        }
170
171
172
        if ($v->artefacttype == 'image' || $v->artefacttype == 'profileicon') {
            $v->icon .= '&time=' . time();
        }
173
    }
174
    $smarty->assign('filelist', $filedata);
175
    $smarty->assign('downloadfolderaszip', $addzipdownloadlink);
176
177
178
    $configstr = json_encode($config);
    $fileliststr = json_encode($filedata);

179
    $smarty->assign('prefix', $prefix);
180
181
    $accepts = isset($element['accept']) ? 'accept="' . Pieform::hsc($element['accept']) . '"' : '';
    $smarty->assign('accepts', $accepts);
182

183
    $initjs = "{$prefix} = new FileBrowser('{$prefix}', {$folder}, {$configstr}, config);
184
185
186
187
{$prefix}.filedata = {$fileliststr};";
    if ($config['select']) {
        $initjs .= "{$prefix}.selecteddata = {$selectedliststr};";
    }
188

189
190
191
192
    if (isset($tabdata)) {
        $initjs .= "{$prefix}.tabdata = " . json_encode($tabdata) . ';';
    }

193
194
    $_PIEFORM_FILEBROWSERS[$prefix]['views_js'] = $initjs;

195
    $initjs .= "jQuery({$prefix}.init);";
196
    $initjs .= "upload_max_filesize = '" . get_real_size(ini_get('upload_max_filesize')) . "';";
197
198
199
200
201
202
203
    if ($form->is_submitted() && $form->has_errors()) {
        // need to reapply bootstrap file browser stuff
        $initjs .= "jQuery('.js-filebrowser').each(function() {";
        $initjs .= "  jQuery(this).wrapInner('<div class=\"modal-dialog modal-lg\"><div class=\"modal-content modal-filebrowser\"></div></div>');";
        $initjs .= "  jQuery(this).modal('hide');";
        $initjs .= "});";
    }
204
    $smarty->assign('initjs', $initjs);
205
206
    $smarty->assign('querybase', $element['page'] . (strpos($element['page'], '?') === false ? '?' : '&'));

207
208
209
210
211
212
213
    $params = 'folder=' . $folder;
    if ($group) {
        $params .= '&group=' . $group;
    }
    if ($institution) {
        $params .= '&institution=' . $institution;
    }
214

215
216
    $smarty->assign('folderparams', $params);

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    // Add mobile media-capture form tags when users are on mobile or tablet
    if ($SESSION->get('mobile') || $SESSION->get('tablet')) {
        $supportedmediatypes = array('image/*');
        if (isset($element['accept'])) {
            $accepted = explode(',', $element['accept']);
            foreach ($accepted as $type) {
                if (in_array($type, $supportedmediatypes)) {
                    switch ($type) {
                        case 'image/*':
                            $smarty->assign('capturedevice', 'camera');
                            break;
                    }
                }
            }
        }
    }

234
235
236
    return $smarty->fetch('artefact:file:form/filebrowser.tpl');
}

237
function pieform_element_filebrowser_get_groupinfo($group) {
238
    require_once('group.php');
239
240
241
242
243
244
    $groupinfo = array(
        'roles' => group_get_role_info($group),
        'perms' => group_get_default_artefact_permissions($group),
        'perm'  => array(),
    );
    foreach (current($groupinfo['perms']) as $k => $v) {
245
        $groupinfo['perm'][$k] = get_string('filepermission.' . $k, 'artefact.file');
246
247
248
249
250
    }
    return $groupinfo;
}


251
252
253
function pieform_element_filebrowser_get_path($folder) {
    $path = array();
    if ($folder) {
254
255
        $artefact = artefact_instance_from_id($folder);
        $folders = ArtefactTypeFileBase::artefactchooser_folder_data($artefact)->data;
256
257
258
259
260
261
262
        $f = $folder;
        while ($f) {
            $path[] = (object) array('title' => $folders[$f]->title, 'id' => $f);
            $f = $folders[$f]->parent;
        }
    }

263
    $path[] = (object) array('title' => get_string('home', 'artefact.file'), 'id' => 0);
264
265
266
    return $path;
}

267

268
function pieform_element_filebrowser_build_path($form, $element, $folder, $owner=null, $ownerid=null) {
269
270
271
    if (!$form->submitted_by_js()) {
        return;
    }
272
    $querybase = $element['page'] . (strpos($element['page'], '?') === false ? '?' : '&');
273

274
275
276
277
278
    $path = pieform_element_filebrowser_get_path($folder);
    $foldername = $path[0]->title;

    $smarty = smarty_core();
    $smarty->assign('path', array_reverse($path));
279
280
    $smarty->assign('owner', $owner);
    $smarty->assign('ownerid', $ownerid);
281
    $smarty->assign('querybase', $querybase);
282
283
284
    return array('html' => $smarty->fetch('artefact:file:form/folderpath.tpl'), 'foldername' => $foldername);
}

285

286

287
function pieform_element_filebrowser_build_filelist($form, $element, $folder, $highlight=null, $user=null, $group=null, $institution=null) {
288
    require_once('license.php');
289
290
291
292
293
    if (!$form->submitted_by_js()) {
        // We're going to rebuild the page from scratch anyway.
        return;
    }

294
295
    global $USER;

296
    $smarty = smarty_core();
297
    $userid = null;
298
    if (is_null($institution) && is_null($group) && is_null($user)) {
299
300
301
302
303
304
305
306
        // See if the filebrowser has indicated it's a group element
        if (!empty($element['group'])) {
            $group = $element['group'];
        }
        else {
            // otherwise check if the form knows it's in a group setting
            $group = $form->get_property('group');
        }
307
308
309
310
311
312
313
314
315
        // See if the filebrowser has indicated it's an institution element
        if (!empty($element['institution'])) {
            $institution = $element['institution'];
        }
        else {
            // otherwise check if the form knows it's in an institution setting
            $institution = $form->get_property('institution');
        }
        $userid = ($group || $institution) ? null : $USER->get('id');
316
    }
317

318
    if ($user || $userid) {
319
320
321
322
        $userid = $USER->get('id');
        $smarty->assign('owner', 'user');
        $smarty->assign('ownerid', $userid);
    }
323
324
325
326
    else if ($institution) {
        $smarty->assign('owner', 'institution');
        $smarty->assign('ownerid', $institution);
    }
327
328
329
330
    else {
        $smarty->assign('owner', 'group');
        $smarty->assign('ownerid', $group);
    }
331

332
333
    $editable = (int) $element['config']['edit'];
    $selectable = (int) $element['config']['select'];
334
    $selectfolders = (int) !empty($element['config']['selectfolders']);
335
    $publishing = (int) !empty($element['config']['publishing']);
336
337
    $showtags = !empty($element['config']['tag']) ? (int) $userid : 0;
    $editmeta = (int) ($userid && !$editable && !empty($element['config']['tag']));
338
339
340
    $querybase = $element['page'] . (strpos($element['page'], '?') === false ? '?' : '&');
    $prefix = $form->get_name() . '_' . $element['name'];

341
342
    $filters = isset($element['filters']) ? $element['filters'] : null;
    $filedata = ArtefactTypeFileBase::get_my_files_data($folder, $userid, $group, $institution, $filters);
343
344
345
346
347
348
    // Only allow 'Download folder content as zip' link if theres some kind of content (file or subfolder with content)
    $addzipdownloadlink = false;
    foreach ($filedata as $k => $v) {
        if (empty($v->isparent) && ($v->artefacttype != 'folder' || ($v->artefacttype == 'folder' && !empty($v->childcount)))) {
            $addzipdownloadlink = true;
        }
349
350
351
        if ($v->artefacttype == 'image' || $v->artefacttype == 'profileicon') {
            $v->icon .= '&time=' . time();
        }
352
    }
353

354
    $smarty->assign('downloadfolderaszip', $addzipdownloadlink);
355
356
    $smarty->assign('edit', -1);
    $smarty->assign('highlight', $highlight);
357
358
    $smarty->assign('editable', $editable);
    $smarty->assign('selectable', $selectable);
359
    $smarty->assign('selectfolders', $selectfolders);
360
    $smarty->assign('publishing', $publishing);
361
362
    $smarty->assign('showtags', $showtags);
    $smarty->assign('editmeta', $editmeta);
363
    $smarty->assign('filelist', $filedata);
364
365
    $smarty->assign('querybase', $querybase);
    $smarty->assign('prefix', $prefix);
366

367
368
369
370
371
372
373
374
375
376
    $params = 'folder=' . ($folder === null ? 0 : $folder);
    if ($group !== null) {
        $params .= '&group=' . $group;
    }
    if ($institution !== null) {
        $params .= '&institution=' . $institution;
    }

    $smarty->assign('folderparams', $params);

377
378
379
380
381
382
    return array(
        'data' => $filedata,
        'html' => $smarty->fetch('artefact:file:form/filelist.tpl'),
    );
}

383

384
function pieform_element_filebrowser_configure_tabs($viewowner, $prefix) {
385
386
387
388
389
390
391
392
393
394
395
    if ($viewowner['type'] == 'institution' && $viewowner['id'] == 'mahara') {
        // No filebrowser tabs for site views
        return null;
    }

    $tabs = array();
    $subtabs = array();

    $upload = null;
    $selectedsubtab = null;
    if ($viewowner['type'] == 'institution') {
396
        $selectedtab = param_variable($prefix . '_owner', 'institution');
397
398
399
400
        $upload = $selectedtab == 'institution';
        $tabs['institution'] = get_string('institutionfiles', 'admin');
    }
    else if ($viewowner['type'] == 'group') {
401
        $selectedtab = param_variable($prefix . '_owner', 'group');
402
        $upload = $selectedtab == 'group';
403
        $tabs['user'] = get_string('myfiles', 'artefact.file');
404
405
406
407
        $tabs['group'] = get_string('groupfiles', 'artefact.file');
    }
    else { // $viewowner['type'] == 'user'
        global $USER;
408
        $selectedtab = param_variable($prefix . '_owner', 'user');
409
410
411
412
413
        $upload = $selectedtab == 'user';
        $tabs['user'] = get_string('myfiles', 'artefact.file');
        if ($groups = $USER->get('grouproles')) {
            $tabs['group'] = get_string('groupfiles', 'artefact.file');
            require_once(get_config('libroot') . 'group.php');
414
            $groups = group_get_user_groups($USER->get('id'));
415
            if ($selectedtab == 'group') {
416
                if (!$selectedsubtab = (int) param_variable($prefix . '_ownerid', 0)) {
417
418
419
420
421
422
423
424
425
                    $selectedsubtab = $groups[0]->id;
                }
                foreach ($groups as &$g) {
                    $subtabs[$g->id] = $g->name;
                }
            }
        }
        if ($institutions = $USER->get('institutions')) {
            $tabs['institution'] = get_string('institutionfiles', 'admin');
426
            $institutions = get_records_select_array('institution', 'name IN ('
427
428
                . join(',', array_map('db_quote', array_keys($institutions))) . ')');
            if ($selectedtab == 'institution') {
429
                if (!$selectedsubtab = param_variable($prefix . '_ownerid', '')) {
430
431
432
433
434
435
436
437
438
439
                    $selectedsubtab = $institutions[0]->name;
                }
                $selectedsubtab = hsc($selectedsubtab);
                foreach ($institutions as &$i) {
                    $subtabs[$i->name] = $i->displayname;
                }
            }
        }
    }
    $tabs['site'] = get_string('sitefiles', 'admin');
440
441
442
443
444
445
446
    return array(
        'tabs'    => $tabs,
        'subtabs' => $subtabs,
        'owner'   => $selectedtab,
        'ownerid' => $viewowner['type'] == 'group' ? $viewowner['id'] : $selectedsubtab,
        'upload'  => $upload
    );
447
}
448

449

450
function pieform_element_filebrowser_get_value(Pieform $form, $element) {
451
452
453
    $prefix = $form->get_name() . '_' . $element['name'];


454
455
456
457
458
459
460
461
    // Cancel edit a file artefact
    // This value only available when the filebrowser was submitted by non-js web browser
    $canceledit = param_variable($prefix . '_canceledit', null);
    if (!empty($canceledit)) {
        redirect($element['page']);
    }


462
463
464
465
466
    // The value of this element is the list of selected artefact ids
    $selected = param_variable($prefix . '_selected', null);
    if (is_array($selected)) {
        $selected = array_keys($selected);
    }
467
468


469
    // Process filebrowser actions that must occur before normal form validation and
470
471
    // which can safely occur without affecting the element's value
    $result = pieform_element_filebrowser_doupdate($form, $element);
472

473
474
475
476
477
478
479
480
481
    if (is_array($result)) {
        // We did something.  If js, replace the filebrowser now and
        // don't continue form submission.
        if (!isset($result['folder'])) {
            $result['folder'] = $element['folder'];
        }
        if ($form->submitted_by_js()) {
            $replacehtml = false; // Don't replace the entire form when replying with json data.
            $result['formelement'] = $prefix;
482
            if (!empty($result['error'])) {
483
                $result['formelementerror'] = $prefix . '.callback';
Richard Mansfield's avatar
Richard Mansfield committed
484
            }
485
            else {
486
                $result['formelementsuccess'] = $prefix . '.callback';
487
            }
488
            $form->json_reply(empty($result['error']) ? PIEFORM_OK : PIEFORM_ERR, $result, $replacehtml);
489
        }
490

491
492
493
494
495
496
497
498
499
500
501
502
503
        // Not js. Add some params & redirect back to the page
        $params = array();
        if (!empty($result['folder'])) {
            $params[] = 'folder=' . $result['folder'];
        }
        if (!empty($result['edit'])) {
            $params[] = 'edit=' . $result['edit'];
        }
        if (!empty($result['highlight'])) {
            $params[] = 'file=' . $result['highlight'];
        }
        if (!empty($result['browse'])) {
            $params[] = 'browse=1';
504
        }
505

506
        $result['goto'] = $element['page'];
507
        if (!empty($params)) {
508
509
510
511
512
513
514
515
516
            $result['goto'] .= (strpos($element['page'], '?') === false ? '?' : '&') . join('&', $params);
        }

        if (empty($result['select']) && empty($result['unselect'])) {
            $form->reply(empty($result['error']) ? PIEFORM_OK : PIEFORM_ERR, $result);
        }

        // If we got to this point, the doupdate function couldn't select or unselect a file,
        // so we need to let it go through to the form's submit function to deal with.
517
        if (!empty($result['select'])) {
518
519
            if ($element['config']['selectone']) {
                $selected = array($result['select']);
520
            }
521
522
            else {
                $selected = is_array($selected) ? $selected : array();
523
524
525
                if (!in_array($result['select'], $selected)) {
                    $selected[] = $result['select'];
                }
526
            }
527
        }
528
        else if (!empty($result['unselect'])) {
529
            $selected = is_array($selected) ? array_diff($selected, array($result['unselect'])) : array();
530
        }
531
    }
532

533
    if (is_array($selected) && !empty($selected)) {
534
        if (!empty($element['config']['selectone'])) {
535
536
537
            return $selected[0];
        }
        return $selected;
538
    }
539
    return null;
540
541
}

542

543
544
545
546
547
548
549
550
/**
 * This function handles filebrowser actions, such as uploading files, deleting files, creating folders, etc.
 * It piggybacks on the surrounding pieform but bypasses the normal Pieforms validation process.
 *
 * @param Pieform $form
 * @param array $element
 * @return mixed
 */
Richard Mansfield's avatar
Richard Mansfield committed
551
function pieform_element_filebrowser_doupdate(Pieform $form, $element) {
552
    require_once('license.php');
553
554
    $result = null;

555
556
    $prefix = $form->get_name() . '_' . $element['name'];

557
558
559
560
561
562
563
564
565
566
567
568
    // Since this is executed before normal pieforms validation, we'll redundantly call the validation here
    try {
        $sesskey = param_variable('sesskey', null);
        pieform_validate($form, array('sesskey' => $sesskey));
    }
    catch (Exception $e) {
        return array(
            'error'   => true,
            'message' => $e->getMessage(),
        );
    }

569
    $delete = param_variable($prefix . '_delete', null);
Richard Mansfield's avatar
Richard Mansfield committed
570
571
572
    if (is_array($delete)) {
        $keys = array_keys($delete);
        return pieform_element_filebrowser_delete($form, $element, (int) ($keys[0]));
573
    }
Richard Mansfield's avatar
Richard Mansfield committed
574

575
576
577
578
579
580
581
582
    $resizeonuploaduserenable = param_variable($prefix . '_resizeonuploaduserenable', null);
    if (!empty($resizeonuploaduserenable)) {
        $resizeimage = 1;
    }
    else {
        $resizeimage = 0;
    }

583
    $update = param_variable($prefix . '_update', null);
Richard Mansfield's avatar
Richard Mansfield committed
584
    if (is_array($update)) {
585
586
        $keys = array_keys($update);
        $artefactid = (int) ($keys[0]);
587
        $edit_title = param_variable($prefix . '_edit_title');
588
589
        $namelength = strlen($edit_title);
        if (!$namelength) {
590
            return array(
591
                'edit'    => $artefactid,
592
                'error'   => true,
593
                'message' => get_string('filenamefieldisrequired1', 'artefact.file')
594
595
            );
        }
596
597
        else if ($namelength > 1024) {
            return array(
598
                'edit'    => $artefactid,
599
600
601
602
                'error'   => true,
                'message' => get_string('nametoolong', 'artefact.file'),
            );
        }
603
        $data = array(
604
            'artefact'    => $artefactid,
Richard Mansfield's avatar
Richard Mansfield committed
605
            'title'       => $edit_title,
606
            'description' => param_variable($prefix . '_edit_description'),
607
            'tags'        => param_variable($prefix . '_edit_tags', ''),
Richard Mansfield's avatar
Richard Mansfield committed
608
            'folder'      => $element['folder'],
609
            'allowcomments' => param_boolean($prefix . '_edit_allowcomments'),
610
            'orientation'  => param_variable($prefix . '_edit_orientation'),
611
        );
612
613
614
615
616
617
618
619
620
        if (get_config('licensemetadata')) {
            $data = array_merge($data, array(
                'license'     => license_coalesce(null,
                    param_variable($prefix . '_edit_license'),
                    param_variable($prefix . '_edit_license_other', null)),
                'licensor'    => param_variable($prefix . '_edit_licensor'),
                'licensorurl' => param_variable($prefix . '_edit_licensorurl'),
            ));
        }
621
622
        if ($form->get_property('group')) {
            $data['permissions']  = array('admin' => (object) array('view' => true, 'edit' => true, 'republish' => true));
623
            foreach ($_POST as $k => $v) {
624
                if (preg_match('/^' . $prefix . '_permission:([a-z]+):([a-z]+)$/', $k, $m)) {
625
                    if (!isset($data['permissions'][$m[1]])) {
626
                        $data['permissions'][$m[1]] = new stdClass();
627
                    }
628
                    $data['permissions'][$m[1]]->{$m[2]} = (bool) $v;
629
630
631
                }
            }
        }
Richard Mansfield's avatar
Richard Mansfield committed
632
        return pieform_element_filebrowser_update($form, $element, $data);
633
    }
Richard Mansfield's avatar
Richard Mansfield committed
634

635
    $move = param_variable($prefix . '_move', null);
Richard Mansfield's avatar
Richard Mansfield committed
636
637
638
    if (!empty($move)) {
        return pieform_element_filebrowser_move($form, $element, array(
            'artefact'  => (int) $move,
639
            'newparent' => param_integer($prefix . '_moveto'),
Richard Mansfield's avatar
Richard Mansfield committed
640
            'folder'    => $element['folder'],
641
        ));
642
    }
Richard Mansfield's avatar
Richard Mansfield committed
643

644
    $createfolder = param_variable($prefix . '_createfolder', null);
Richard Mansfield's avatar
Richard Mansfield committed
645
    if (!empty($createfolder)) {
646
647
648
        $createfolder_name = param_variable($prefix . '_createfolder_name');
        $namelength = strlen($createfolder_name);
        if (!$namelength) {
649
650
651
652
            return array(
                'error'   => true,
                'message' => get_string('foldernamerequired', 'artefact.file'),
            );
653
        }
654
655
656
657
658
659
        else if ($namelength > 1024) {
            return array(
                'error'   => true,
                'message' => get_string('nametoolong', 'artefact.file'),
            );
        }
Richard Mansfield's avatar
Richard Mansfield committed
660
661
662
        return pieform_element_filebrowser_createfolder($form, $element, array(
            'title'  => $createfolder_name,
            'folder' => $element['folder'],
663
        ));
664
    }
Richard Mansfield's avatar
Richard Mansfield committed
665

666
667
    // {$prefix}_upload is set in all browsers except safari when javascript is
    // on (and set in all browsers when it's not)
668
    $upload = param_variable($prefix . '_upload', null);
Richard Mansfield's avatar
Richard Mansfield committed
669
    if (!empty($upload)) {
670
        if (empty($_FILES['userfile']['name'])) {
671
672
673
            return array(
                'error'   => true,
                'message' => get_string('filenamefieldisrequired', 'artefact.file'),
674
                'browse'  => 1,
675
            );
676
        }
677
678
679
680
681
682
683
684
685
686
687
688
        else if (is_array($_FILES['userfile']['name'])) {
            foreach ($_FILES['userfile']['name'] as $filename) {
                if (empty($filename)) {
                    // TODO, how to specify which file is in error...
                    return array(
                        'error'   => true,
                        'message' => get_string('filenamefieldisrequired', 'artefact.file'),
                        'browse'  => 1,
                    );
                }
            }
        }
689
690
691
    }

    if (!empty($_FILES['userfile']['name'])) {
692
        if (!is_array($_FILES['userfile']['name'])) {
693
694
            if (param_exists('_userfile') && is_array(param_array('_userfile'))) {
                $userfile = param_array('_userfile');
695
                // renaming file for drag and drop
696
697
                $_FILES['userfile']['name'] = $userfile['name'];
                $_FILES['userfile']['type'] = $userfile['type'];
698
            }
699
            if (strlen($_FILES['userfile']['name']) > 1024) {
700
                http_response_code(403);
701
702
703
704
705
706
                return array(
                    'error'   => true,
                    'message' => get_string('nametoolong', 'artefact.file'),
                );
            }
            else if ($element['config']['uploadagreement'] && !param_boolean($prefix . '_notice', false)) {
707
                http_response_code(403);
708
709
710
711
712
713
                return array(
                    'error'   => true,
                    'message' => get_string('youmustagreetothecopyrightnotice', 'artefact.file'),
                    'browse'  => 1,
                );
            }
714
            $data = array(
715
716
717
718
                'userfile'         => $_FILES['userfile'],
                'uploadnumber'     => param_integer($prefix . '_uploadnumber'),
                'uploadfolder'     => $element['folder'] ? $element['folder'] : null,
                'uploadfoldername' => param_variable($prefix . '_foldername'),
719
                'resizeonuploaduserenable' => $resizeimage,
720
            );
721
722
723
724
725
726
727
728
729
730
            if (get_config('licensemetadata') && param_variable('dropzone')) {
                $data = array_merge($data, array(
                    'license'     => license_coalesce(null,
                        param_variable($prefix . '_license'),
                        param_variable($prefix . '_license_other', null)),
                    'licensor'    => param_variable($prefix . '_licensor'),
                    'licensorurl' => param_variable($prefix . '_licensorurl'),
                ));
            }
            else if (get_config('licensemetadata')) {
731
732
733
734
735
736
737
738
739
                $data = array_merge($data, array(
                    'license'     => license_coalesce(null,
                        param_variable($prefix . '_edit_license'),
                        param_variable($prefix . '_edit_license_other', null)),
                    'licensor'    => param_variable($prefix . '_edit_licensor'),
                    'licensorurl' => param_variable($prefix . '_edit_licensorurl'),
                ));
            }
            $result = pieform_element_filebrowser_upload($form, $element, $data);
740
741
742
743
744
745
746
747
748
749
750
            // If it's a non-js upload, automatically select the newly uploaded file.
            $result['browse'] = 1;
            if (!$form->submitted_by_js() && !$result['error'] && !empty($element['config']['select'])) {
                if (isset($element['selectcallback']) && is_callable($element['selectcallback'])) {
                    $element['selectcallback']($result['highlight']);
                }
                else {
                    $result['select'] = $result['highlight'];
                }
            }
            return $result;
751
        }
752
753
754
755
756
757
758
        else if (!empty($_FILES['userfile']['name'][0])) {
            if ($element['config']['uploadagreement'] && !param_boolean($prefix . '_notice', false)) {
                return array(
                    'error'   => true,
                    'message' => get_string('youmustagreetothecopyrightnotice', 'artefact.file'),
                    'browse'  => 1,
                );
759
            }
760
761
762
763
764
765
766
767
768
            $result = array('multiuploads' => array());
            $size = sizeof($_FILES['userfile']['name']);
            for ($i = 0; $i < $size; $i ++) {
                if (strlen($_FILES['userfile']['name'][$i]) > 1024) {
                    return array(
                        'error'   => true,
                        'message' => get_string('nametoolong', 'artefact.file'),
                    );
                }
769
                $data = array(
770
771
772
773
774
                    'userfile'         => $_FILES['userfile'],
                    'userfileindex'    => $i,
                    'uploadnumber'     => param_integer($prefix . '_uploadnumber') - ($size - $i - 1),
                    'uploadfolder'     => $element['folder'] ? $element['folder'] : null,
                    'uploadfoldername' => param_variable($prefix . '_foldername'),
775
                    'resizeonuploaduserenable' => $resizeimage,
776
777
778
779
780
781
782
783
784
785
786
                );
                if (get_config('licensemetadata')) {
                    $data = array_merge($data, array(
                        'license'     => license_coalesce(null,
                            param_variable($prefix . '_license'),
                            param_variable($prefix . '_license_other', null)),
                        'licensor'    => param_variable($prefix . '_licensor'),
                        'licensorurl' => param_variable($prefix . '_licensorurl'),
                    ));
                }
                $result['multiuploads'][$i] = pieform_element_filebrowser_upload($form, $element, $data);
787
788
789
790
791
792
793
794
795
796
797
798
                // TODO, what to do here...
                // If it's a non-js upload, automatically select the newly uploaded file.
                $result['multiuploads'][$i]['browse'] = 1;
                if (!$form->submitted_by_js() && !$result['multiuploads'][$i]['error'] && !empty($element['config']['select'])) {
                    if (isset($element['selectcallback']) && is_callable($element['selectcallback'])) {
                        $element['selectcallback']($result['multiuploads'][$i]['highlight']);
                    }
                    else {
                        $result['multiuploads'][$i]['select'] = $result['multiuploads'][$i]['highlight'];
                    }
                }
                $result['multiuploads'][$i]['folder'] = $element['folder'];
799
            }
800
            return $result;
801
        }
802
    }
Richard Mansfield's avatar
Richard Mansfield committed
803

804
805
806
807
808
809
810
    if (!$form->submitted_by_js()) {

        $select = param_variable($prefix . '_select', null);
        if (is_array($select)) {
            $keys = array_keys($select);
            $add = (int) $keys[0];
            if (isset($element['selectcallback']) && is_callable($element['selectcallback'])) {
811
812
813
814
815
816
817
818
819
820
                try {
                    $element['selectcallback']($add);
                }
                catch (ArtefactNotFoundException $e) {
                    $result = array(
                        'error' => true,
                        'message' => get_string('selectingfailed', 'artefact.file'),
                    );
                    return $result;
                }
821
822
823
824
825
826
827
            }
            else {
                $result['select'] = $add;
            }
            $result['message'] = get_string('fileadded', 'artefact.file');
            $result['browse'] = 1;
            return $result;
828
829
        }

830
831
832
833
834
        $unselect = param_variable($prefix . '_unselect', null);
        if (is_array($unselect)) {
            $keys = array_keys($unselect);
            $del = (int) $keys[0];
            if (isset($element['unselectcallback']) && is_callable($element['unselectcallback'])) {
835
836
837
838
839
840
841
842
843
844
                try {
                    $element['unselectcallback']($del);
                }
                catch (ArtefactNotFoundException $e) {
                    $result = array(
                        'error' => true,
                        'message' => get_string('removingfailed', 'artefact.file'),
                    );
                    return $result;
                }
845
846
847
848
849
850
            }
            else {
                $result['unselect'] = $del;
            }
            $result['message'] = get_string('fileremoved', 'artefact.file');
            return $result;
851
        }
852
853
854
855
856
857

        $edit = param_variable($prefix . '_edit', null);
        if (is_array($edit)) {
            $keys = array_keys($edit);
            $result['edit'] = (int) $keys[0];
            return $result;
858
859
        }

860
861
862
863
        if (param_variable('browse', 0) && !param_variable($prefix . '_cancelbrowse', 0)) {
            $result['browse'] = 1;
            return $result;
        }
864
865
866

    }

867
868
    $changeowner = param_variable($prefix . '_changeowner', null);
    if (!empty($changeowner)) {
869
        $result = pieform_element_filebrowser_changeowner($form, $element);
870
871
872
873
        $result['browse'] = 1;
        return $result;
    }

874
    $newfolder = param_variable($prefix . '_changefolder', null);
Richard Mansfield's avatar
Richard Mansfield committed
875
    if (!is_null($newfolder) && is_numeric($newfolder)) {
876
        $result = pieform_element_filebrowser_changefolder($form, $element, $newfolder);
877
        $result['browse'] = 1;
Richard Mansfield's avatar
Richard Mansfield committed
878
879
        $result['folder'] = $newfolder;
        return $result;
880
881
882
883
    }

}

884

885
function pieform_element_filebrowser_upload(Pieform $form, $element, $data) {
886
887
    global $USER;

888
    $parentfolder     = $data['uploadfolder'] ? (int) $data['uploadfolder'] : null;
889
    $institution      = !empty($element['institution']) ? $element['institution'] : $form->get_property('institution');
890
    $group            = !empty($element['group']) ? $element['group'] : $form->get_property('group');
891
892
893
894
895
    if (get_config('licensemetadata')) {
        $license          = $data['license'];
        $licensor         = $data['licensor'];
        $licensorurl      = $data['licensorurl'];
    }
896
897
898
899
900
    $uploadnumber     = (int) $data['uploadnumber'];
    $editable         = (int) $element['config']['edit'];
    $selectable       = (int) $element['config']['select'];
    $querybase        = $element['page'] . (strpos($element['page'], '?') === false ? '?' : '&');
    $prefix           = $form->get_name() . '_' . $element['name'];
901
    $userfileindex    = isset($data['userfileindex']) ? $data['userfileindex'] : null;
902
903
904
    $resizeonuploadenable = get_config_plugin('artefact', 'file', 'resizeonuploadenable');
    $resizeonuploaduseroption = get_config_plugin('artefact', 'file', 'resizeonuploaduseroption');
    $resizeonuploaduserenable = (int) $data['resizeonuploaduserenable'];
905
906

    $result = array('error' => false, 'uploadnumber' => $uploadnumber);
907

908
909
910
    if ($parentfolder == 0) {
        $parentfolder = null;
    }
911

912
    $data             = new stdClass();
913
    $data->parent     = $parentfolder;
914
    $data->owner = $data->group = $data->institution = null;
915
916
917
918
919
    if (get_config('licensemetadata')) {
        $data->license    = $license;
        $data->licensor   = $licensor;
        $data->licensorurl= $licensorurl;
    }
920

921
922
923
924
925
926
927
    if ($parentfolder) {
        $parentartefact = artefact_instance_from_id($parentfolder);
        if (!$USER->can_edit_artefact($parentartefact)) {
            $result['error'] = true;
            $result['message'] = get_string('cannoteditfolder', 'artefact.file');
            return $result;
        }
928
929
930
931
932
        else if ($parentartefact->get('locked')) {
            $result['error'] = true;
            $result['message'] = get_string('cannoteditfoldersubmitted', 'artefact.file');
            return $result;
        }
933
934
935
936
        $parentfoldername = $parentartefact->get('title');
    }
    else {
        $parentfoldername = null;
937
938
    }
    if ($institution) {
939
940
941
942
943
        if (!$USER->can_edit_institution($institution)) {
            $result['error'] = true;
            $result['message'] = get_string('notadminforinstitution', 'admin');
            return $result;
        }
944
        $data->institution = $institution;
945
946
    }
    else if ($group) {
947
948
949
        if (!group_within_edit_window($group)) {
            return array('error' => true, 'message' => get_string('cannoteditfolder', 'artefact.file'));
        }
950
        if (!$parentfolder) {
951
952
            if (!pieform_element_filebrowser_edit_group_folder($group, 0)) {
                return array('error' => true, 'message' => get_string('cannoteditfolder', 'artefact.file'));
953
954
955
            }
        }
        $data->group = $group;
956
957
    }
    else {
958
959
960
961
962
        $data->owner = $USER->get('id');
    }

    $data->container = 0;

963
964
965
966
967
968
    if (isset($userfileindex)) {
        $originalname = $_FILES['userfile']['name'][$userfileindex];
    }
    else {
        $originalname = $_FILES['userfile']['name'];
    }
969
970
971
    $originalname = $originalname ? basename($originalname) : get_string('file', 'artefact.file');
    $data->title = ArtefactTypeFileBase::get_new_file_title($originalname, $parentfolder, $data->owner, $group, $institution);

972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
    // Overwrite image file with resized version if required
    $resized = false;
    $resizeattempted = false;
    // resize specified if (resizing is enabled AND user has enabled resizing) OR (resizing is enabled AND user is not given an option to enable/disable)
    if (($resizeonuploadenable && $resizeonuploaduserenable) || ($resizeonuploadenable && !$resizeonuploaduseroption)) {

        require_once('file.php');
        require_once('imageresizer.php');

        $file = $_FILES['userfile'];
        if (isset($userfileindex)) {
            $tmpname = $file['tmp_name'][$userfileindex];
        }
        else {
            $tmpname = $file['tmp_name'];
        }
        if (is_image_file($tmpname)) {
            $imageinfo = getimagesize($tmpname);
            $mimetype = $imageinfo['mime'];
            $width    = $imageinfo[0];
            $height   = $imageinfo[1];
            $bmptypes = array('image/bmp', 'image/x-bmp', 'image/ms-bmp', 'image/x-ms-bmp');

            // resize image if necessary
            $resizeonuploadmaxwidth  = get_config_plugin('artefact', 'file', 'resizeonuploadmaxwidth');
            $resizeonuploadmaxheight = get_config_plugin('artefact', 'file', 'resizeonuploadmaxheight');

            // Don't support bmps for now
            if (($width > $resizeonuploadmaxwidth || $height > $resizeonuploadmaxheight) && !in_array($mimetype, $bmptypes)) {
                $resizeattempted = true;
                $imgrs = new ImageResizer($tmpname, $mimetype);
                $img = $imgrs->get_image();
                if (!empty($img)) {
                    $imgrs->resize_image(array('w' => $resizeonuploadmaxwidth, 'h' => $resizeonuploadmaxheight), $mimetype); //auto
                    $saveresize = $imgrs->save_image($tmpname, $mimetype, 85);
                    if (!$saveresize) {
                        return array('error' => true, 'message' => get_string('problemresizing', 'artefact.file'));
                    }
                    $resized = true;
                }
            }
        }
    }

1016
    try {
1017
        $newid = ArtefactTypeFile::save_uploaded_file('userfile', $data, $userfileindex, $resized);
1018
1019
1020
    }
    catch (QuotaExceededException $e) {
        prepare_upload_failed_message($result, $e, $parentfoldername, $originalname);
1021
        // update the file listing
Hugh Davenport's avatar
Hugh Davenport committed
1022
1023
1024
1025
1026
1027
1028
1029
1030
        if (defined('GROUP')) {
            $group = group_current_group();
            $result['quota'] = $group->quota;
            $result['quotaused'] = $group->quotaused;
        }
        else {
            $result['quota'] = $USER->get('quota');
            $result['quotaused'] = $USER->get('quotaused');
        }