Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
/**
19
 * Utility class for browsing of course files.
20
 *
21
 * @package    core_files
22
 * @copyright  2008 Petr Skoda (http://skodak.org)
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
/**
29
 * Represents a course context in the tree navigated by {@link file_browser}.
30
 *
31
 * @package    core_files
32
 * @copyright  2008 Petr Skoda (http://skodak.org)
33
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
class file_info_context_course extends file_info {
36
    /** @var stdClass course object */
37
    protected $course;
38
 
39
    /** @var file_info_context_module[] cached child modules. See {@link get_child_module()} */
40
    protected $childrenmodules = [];
41
 
42
    /**
43
     * Constructor
44
     *
45
     * @param file_browser $browser file browser instance
46
     * @param stdClass $context context object
47
     * @param stdClass $course course object
48
     */
49
    public function __construct($browser, $context, $course) {
50
        parent::__construct($browser, $context);
51
        $this->course   = $course;
52
    }
53
 
54
    /**
55
     * Return information about this specific context level
56
     *
57
     * @param string $component component
58
     * @param string $filearea file area
59
     * @param int $itemid item ID
60
     * @param string $filepath file path
61
     * @param string $filename file name
62
     * @return file_info|null file_info instance or null if not found or access not allowed
63
     */
64
    public function get_file_info($component, $filearea, $itemid, $filepath, $filename) {
65
        // try to emulate require_login() tests here
66
        if (!isloggedin()) {
67
            return null;
68
        }
69
 
70
        if (!$this->course->visible and !has_capability('moodle/course:viewhiddencourses', $this->context)) {
71
            return null;
72
        }
73
 
74
        if (!is_viewing($this->context) and !$this->browser->is_enrolled($this->course->id)) {
75
            // no peaking here if not enrolled or inspector
76
            return null;
77
        }
78
 
79
        if (empty($component)) {
80
            return $this;
81
        }
82
 
83
        $methodname = "get_area_{$component}_{$filearea}";
84
 
85
        if (method_exists($this, $methodname)) {
86
            return $this->$methodname($itemid, $filepath, $filename);
87
        }
88
 
89
        return null;
90
    }
91
 
92
    /**
93
     * Returns list of areas inside this course
94
     *
95
     * @param string $extensions Only return areas that have files with these extensions
96
     * @param bool $returnemptyfolders return all areas always, if true it will ignore the previous argument
97
     * @return array
98
     */
99
    protected function get_course_areas($extensions = '*', $returnemptyfolders = false) {
100
        global $DB;
101
 
102
        $allareas = [
103
            'course_summary',
104
            'course_overviewfiles',
105
            'course_section',
106
            'backup_section',
107
            'backup_course',
108
            'backup_automated',
109
            'course_legacy'
110
        ];
111
 
112
        if ($returnemptyfolders) {
113
            return $allareas;
114
        }
115
 
116
        $params1 = ['contextid' => $this->context->id, 'emptyfilename' => '.'];
117
        $sql1 = "SELECT " . $DB->sql_concat('f.component', "'_'", 'f.filearea') . "
118
            FROM {files} f
119
            WHERE f.filename <> :emptyfilename AND f.contextid = :contextid ";
120
        $sql3 = ' GROUP BY f.component, f.filearea';
121
        list($sql2, $params2) = $this->build_search_files_sql($extensions);
122
        $areaswithfiles = $DB->get_fieldset_sql($sql1 . $sql2 . $sql3, array_merge($params1, $params2));
123
 
124
        return array_intersect($allareas, $areaswithfiles);
125
    }
126
 
127
    /**
128
     * Gets a stored file for the course summary filearea directory
129
     *
130
     * @param int $itemid item ID
131
     * @param string $filepath file path
132
     * @param string $filename file name
133
     * @return file_info|null file_info instance or null if not found or access not allowed
134
     */
135
    protected function get_area_course_summary($itemid, $filepath, $filename) {
136
        global $CFG;
137
 
138
        if (!has_capability('moodle/course:update', $this->context)) {
139
            return null;
140
        }
141
        if (is_null($itemid)) {
142
            return $this;
143
        }
144
 
145
        $fs = get_file_storage();
146
 
147
        $filepath = is_null($filepath) ? '/' : $filepath;
148
        $filename = is_null($filename) ? '.' : $filename;
149
        if (!$storedfile = $fs->get_file($this->context->id, 'course', 'summary', 0, $filepath, $filename)) {
150
            if ($filepath === '/' and $filename === '.') {
151
                $storedfile = new virtual_root_file($this->context->id, 'course', 'summary', 0);
152
            } else {
153
                // not found
154
                return null;
155
            }
156
        }
157
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
158
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('areacourseintro', 'repository'), false, true, true, false);
159
    }
160
 
161
    /**
162
     * Gets a stored file for the course images filearea directory
163
     *
164
     * @param int $itemid item ID
165
     * @param string $filepath file path
166
     * @param string $filename file name
167
     * @return file_info|null file_info instance or null if not found or access not allowed
168
     */
169
    protected function get_area_course_overviewfiles($itemid, $filepath, $filename) {
170
        global $CFG;
171
 
172
        if (!has_capability('moodle/course:update', $this->context)) {
173
            return null;
174
        }
175
        if (is_null($itemid)) {
176
            return $this;
177
        }
178
 
179
        $fs = get_file_storage();
180
 
181
        $filepath = is_null($filepath) ? '/' : $filepath;
182
        $filename = is_null($filename) ? '.' : $filename;
183
        if (!$storedfile = $fs->get_file($this->context->id, 'course', 'overviewfiles', 0, $filepath, $filename)) {
184
            if ($filepath === '/' and $filename === '.') {
185
                $storedfile = new virtual_root_file($this->context->id, 'course', 'overviewfiles', 0);
186
            } else {
187
                // not found
188
                return null;
189
            }
190
        }
191
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
192
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('areacourseoverviewfiles', 'repository'), false, true, true, false);
193
    }
194
 
195
    /**
196
     * Gets a stored file for the course section filearea directory
197
     *
198
     * @param int $itemid item ID
199
     * @param string $filepath file path
200
     * @param string $filename file name
201
     * @return file_info|null file_info instance or null if not found or access not allowed
202
     */
203
    protected function get_area_course_section($itemid, $filepath, $filename) {
204
        global $CFG, $DB;
205
 
206
        if (!has_capability('moodle/course:update', $this->context)) {
207
            return null;
208
        }
209
 
210
        if (empty($itemid)) {
211
            // list all sections
212
            return new file_info_area_course_section($this->browser, $this->context, $this->course, $this);
213
        }
214
 
215
        if (!$section = $DB->get_record('course_sections', array('course'=>$this->course->id, 'id'=>$itemid))) {
216
            return null; // does not exist
217
        }
218
 
219
        $fs = get_file_storage();
220
 
221
        $filepath = is_null($filepath) ? '/' : $filepath;
222
        $filename = is_null($filename) ? '.' : $filename;
223
        if (!$storedfile = $fs->get_file($this->context->id, 'course', 'section', $itemid, $filepath, $filename)) {
224
            if ($filepath === '/' and $filename === '.') {
225
                $storedfile = new virtual_root_file($this->context->id, 'course', 'section', $itemid);
226
            } else {
227
                // not found
228
                return null;
229
            }
230
        }
231
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
232
        require_once($CFG->dirroot.'/course/lib.php');
233
        $sectionname = get_section_name($this->course, $section);
234
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, $sectionname, true, true, true, false);
235
    }
236
 
237
    /**
238
     * Gets a stored file for the course legacy filearea directory
239
     *
240
     * @param int $itemid item ID
241
     * @param string $filepath file path
242
     * @param string $filename file name
243
     * @return file_info|null file_info instance or null if not found or access not allowed
244
     */
245
    protected function get_area_course_legacy($itemid, $filepath, $filename) {
246
        if (!has_capability('moodle/course:managefiles', $this->context)) {
247
            return null;
248
        }
249
 
250
        if ($this->course->id != SITEID and $this->course->legacyfiles != 2) {
251
            // bad luck, legacy course files not used any more
252
        }
253
 
254
        if (is_null($itemid)) {
255
            return $this;
256
        }
257
 
258
        $fs = get_file_storage();
259
 
260
        $filepath = is_null($filepath) ? '/' : $filepath;
261
        $filename = is_null($filename) ? '.' : $filename;
262
        if (!$storedfile = $fs->get_file($this->context->id, 'course', 'legacy', 0, $filepath, $filename)) {
263
            if ($filepath === '/' and $filename === '.') {
264
                $storedfile = new virtual_root_file($this->context->id, 'course', 'legacy', 0);
265
            } else {
266
                // not found
267
                return null;
268
            }
269
        }
270
 
271
        return new file_info_area_course_legacy($this->browser, $this->context, $storedfile);
272
    }
273
 
274
    /**
275
     * Gets a stored file for the backup course filearea directory
276
     *
277
     * @param int $itemid item ID
278
     * @param string $filepath file path
279
     * @param string $filename file name
280
     * @return file_info|null file_info instance or null if not found or access not allowed
281
     */
282
    protected function get_area_backup_course($itemid, $filepath, $filename) {
283
        global $CFG;
284
 
285
        if (!has_capability('moodle/backup:backupcourse', $this->context) and !has_capability('moodle/restore:restorecourse', $this->context)) {
286
            return null;
287
        }
288
        if (is_null($itemid)) {
289
            return $this;
290
        }
291
 
292
        $fs = get_file_storage();
293
 
294
        $filepath = is_null($filepath) ? '/' : $filepath;
295
        $filename = is_null($filename) ? '.' : $filename;
296
        if (!$storedfile = $fs->get_file($this->context->id, 'backup', 'course', 0, $filepath, $filename)) {
297
            if ($filepath === '/' and $filename === '.') {
298
                $storedfile = new virtual_root_file($this->context->id, 'backup', 'course', 0);
299
            } else {
300
                // not found
301
                return null;
302
            }
303
        }
304
 
305
        $downloadable = has_capability('moodle/backup:downloadfile', $this->context);
306
        $uploadable   = has_capability('moodle/restore:uploadfile', $this->context);
307
 
308
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
309
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('coursebackup', 'repository'), false, $downloadable, $uploadable, false);
310
    }
311
 
312
    /**
313
     * Gets a stored file for the automated backup filearea directory
314
     *
315
     * @param int $itemid item ID
316
     * @param string $filepath file path
317
     * @param string $filename file name
318
     * @return file_info|null
319
     */
320
    protected function get_area_backup_automated($itemid, $filepath, $filename) {
321
        global $CFG;
322
 
323
        if (!has_capability('moodle/restore:viewautomatedfilearea', $this->context)) {
324
            return null;
325
        }
326
        if (is_null($itemid)) {
327
            return $this;
328
        }
329
 
330
        $fs = get_file_storage();
331
 
332
        $filepath = is_null($filepath) ? '/' : $filepath;
333
        $filename = is_null($filename) ? '.' : $filename;
334
        if (!$storedfile = $fs->get_file($this->context->id, 'backup', 'automated', 0, $filepath, $filename)) {
335
            if ($filepath === '/' and $filename === '.') {
336
                $storedfile = new virtual_root_file($this->context->id, 'backup', 'automated', 0);
337
            } else {
338
                // not found
339
                return null;
340
            }
341
        }
342
 
343
        // Automated backup files are only downloadable if the user has both 'backup:downloadfile and 'restore:userinfo'.
344
        $downloadable = has_capability('moodle/backup:downloadfile', $this->context) &&
345
                        has_capability('moodle/restore:userinfo', $this->context);
346
        $uploadable   = false;
347
 
348
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
349
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('automatedbackup', 'repository'), true, $downloadable, $uploadable, false);
350
    }
351
 
352
    /**
353
     * Gets a stored file for the backup section filearea directory
354
     *
355
     * @param int $itemid item ID
356
     * @param string $filepath file path
357
     * @param string $filename file name
358
     * @return file_info|null file_info instance or null if not found or access not allowed
359
     */
360
    protected function get_area_backup_section($itemid, $filepath, $filename) {
361
        global $CFG, $DB;
362
 
363
        if (!has_capability('moodle/backup:backupcourse', $this->context) and !has_capability('moodle/restore:restorecourse', $this->context)) {
364
            return null;
365
        }
366
 
367
        if (empty($itemid)) {
368
            // list all sections
369
            return new file_info_area_backup_section($this->browser, $this->context, $this->course, $this);
370
        }
371
 
372
        if (!$section = $DB->get_record('course_sections', array('course'=>$this->course->id, 'id'=>$itemid))) {
373
            return null; // does not exist
374
        }
375
 
376
        $fs = get_file_storage();
377
 
378
        $filepath = is_null($filepath) ? '/' : $filepath;
379
        $filename = is_null($filename) ? '.' : $filename;
380
        if (!$storedfile = $fs->get_file($this->context->id, 'backup', 'section', $itemid, $filepath, $filename)) {
381
            if ($filepath === '/' and $filename === '.') {
382
                $storedfile = new virtual_root_file($this->context->id, 'backup', 'section', $itemid);
383
            } else {
384
                // not found
385
                return null;
386
            }
387
        }
388
 
389
        $downloadable = has_capability('moodle/backup:downloadfile', $this->context);
390
        $uploadable   = has_capability('moodle/restore:uploadfile', $this->context);
391
 
392
        $urlbase = $CFG->wwwroot.'/pluginfile.php';
393
        return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, $section->id, true, $downloadable, $uploadable, false);
394
    }
395
 
396
    /**
397
     * Returns localised visible name.
398
     *
399
     * @return string
400
     */
401
    public function get_visible_name() {
402
        return ($this->course->id == SITEID) ? get_string('frontpage', 'admin') : format_string(get_course_display_name_for_list($this->course), true, array('context'=>$this->context));
403
    }
404
 
405
    /**
406
     * Whether or not new files or directories can be added
407
     *
408
     * @return bool
409
     */
410
    public function is_writable() {
411
        return false;
412
    }
413
 
414
    /**
415
     * Whether or not this is a directory
416
     *
417
     * @return bool
418
     */
419
    public function is_directory() {
420
        return true;
421
    }
422
 
423
    /**
424
     * Returns list of children.
425
     *
426
     * @return array of file_info instances
427
     */
428
    public function get_children() {
429
        return $this->get_filtered_children('*', false, true);
430
    }
431
 
432
    /**
433
     * Returns the child module if it is accessible by the current user
434
     *
435
     * @param cm_info|int $cm
436
     * @return file_info_context_module|null
437
     */
438
    protected function get_child_module($cm) {
439
        $cmid = is_object($cm) ? $cm->id : $cm;
440
        if (!array_key_exists($cmid, $this->childrenmodules)) {
441
            $this->childrenmodules[$cmid] = null;
442
            if (!($cm instanceof cm_info)) {
443
                $cms = get_fast_modinfo($this->course)->cms;
444
                $cm = array_key_exists($cmid, $cms) ? $cms[$cmid] : null;
445
            }
446
            if ($cm && $cm->uservisible) {
447
                $this->childrenmodules[$cmid] = new file_info_context_module($this->browser,
448
                    $cm->context, $this->course, $cm, $cm->modname);
449
            }
450
        }
451
        return $this->childrenmodules[$cmid];
452
    }
453
 
454
    /**
455
     * Help function to return files matching extensions or their count
456
     *
457
     * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
458
     * @param bool|int $countonly if false returns the children, if an int returns just the
459
     *    count of children but stops counting when $countonly number of children is reached
460
     * @param bool $returnemptyfolders if true returns items that don't have matching files inside
461
     * @return array|int array of file_info instances or the count
462
     */
463
    private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) {
464
        $children = array();
465
 
466
        $courseareas = $this->get_course_areas($extensions, $returnemptyfolders);
467
        foreach ($courseareas as $areaname) {
468
            $area = explode('_', $areaname, 2);
469
            if ($child = $this->get_file_info($area[0], $area[1], 0, '/', '.')) {
470
                $children[] = $child;
471
                if (($countonly !== false) && count($children) >= $countonly) {
472
                    return $countonly;
473
                }
474
            }
475
        }
476
 
477
        $cnt = count($children);
478
        if (!has_capability('moodle/course:managefiles', $this->context)) {
479
            // 'managefiles' capability is checked in every activity module callback.
480
            // Don't even waste time on retrieving the modules if we can't browse the files anyway
481
        } else {
482
            if ($returnemptyfolders) {
483
                $modinfo = get_fast_modinfo($this->course);
484
                foreach ($modinfo->cms as $cminfo) {
485
                    if ($child = $this->get_child_module($cminfo)) {
486
                        $children[] = $child;
487
                        $cnt++;
488
                    }
489
                }
490
            } else if ($moduleareas = $this->get_module_areas_with_files($extensions)) {
491
                // We found files in some of the modules.
492
                // Create array of children modules ordered with the same way as cms in modinfo.
493
                $modulechildren = array_fill_keys(array_keys(get_fast_modinfo($this->course)->get_cms()), null);
494
                foreach ($moduleareas as $area) {
495
                    if ($modulechildren[$area->cmid]) {
496
                        // We already found non-empty area within the same module, do not analyse other areas.
497
                        continue;
498
                    }
499
                    if ($child = $this->get_child_module($area->cmid)) {
500
                        if ($child->get_file_info($area->component, $area->filearea, $area->itemid, null, null)) {
501
                            $modulechildren[$area->cmid] = $child;
502
                            $cnt++;
503
                            if (($countonly !== false) && $cnt >= $countonly) {
504
                                return $cnt;
505
                            }
506
                        }
507
                    }
508
                }
509
                $children = array_merge($children, array_values(array_filter($modulechildren)));
510
            }
511
        }
512
 
513
        if ($countonly !== false) {
514
            return count($children);
515
        }
516
        return $children;
517
    }
518
 
519
    /**
520
     * Returns list of areas inside the course modules that have files with the given extension
521
     *
522
     * @param string $extensions
523
     * @return array
524
     */
525
    protected function get_module_areas_with_files($extensions = '*') {
526
        global $DB;
527
 
528
        $params1 = ['contextid' => $this->context->id,
529
            'emptyfilename' => '.',
530
            'contextlevel' => CONTEXT_MODULE,
531
            'course' => $this->course->id];
532
        $ctxfieldsas = context_helper::get_preload_record_columns_sql('ctx');
533
        $ctxfields = implode(', ', array_keys(context_helper::get_preload_record_columns('ctx')));
534
        $sql1 = "SELECT
535
                    ctx.id AS contextid,
536
                    f.component,
537
                    f.filearea,
538
                    f.itemid,
539
                    ctx.instanceid AS cmid,
540
                    {$ctxfieldsas}
541
            FROM {files} f
542
            INNER JOIN {context} ctx ON ctx.id = f.contextid
543
            INNER JOIN {course_modules} cm ON cm.id = ctx.instanceid
544
            WHERE f.filename <> :emptyfilename
545
              AND cm.course = :course
546
              AND ctx.contextlevel = :contextlevel";
547
        $sql3 = "
548
            GROUP BY ctx.id, f.component, f.filearea, f.itemid, {$ctxfields}
549
            ORDER BY ctx.id, f.component, f.filearea, f.itemid";
550
        list($sql2, $params2) = $this->build_search_files_sql($extensions);
551
        $areas = [];
552
        if ($rs = $DB->get_recordset_sql($sql1. $sql2 . $sql3, array_merge($params1, $params2))) {
553
            foreach ($rs as $record) {
554
                context_helper::preload_from_record($record);
555
                $areas[] = $record;
556
            }
557
            $rs->close();
558
        }
559
 
560
        // Sort areas so 'backup' and 'intro' are in the beginning of the list, they are the easiest to check access to.
561
        usort($areas, function($a, $b) {
562
            $aeasy = ($a->filearea === 'intro' && substr($a->component, 0, 4) === 'mod_') ||
563
                ($a->filearea === 'activity' && $a->component === 'backup');
564
            $beasy = ($b->filearea === 'intro' && substr($b->component, 0, 4) === 'mod_') ||
565
                ($b->filearea === 'activity' && $b->component === 'backup');
566
            return $aeasy == $beasy ? 0 : ($aeasy ? -1 : 1);
567
        });
568
        return $areas;
569
    }
570
 
571
    /**
572
     * Returns list of children which are either files matching the specified extensions
573
     * or folders that contain at least one such file.
574
     *
575
     * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
576
     * @return array of file_info instances
577
     */
578
    public function get_non_empty_children($extensions = '*') {
579
        return $this->get_filtered_children($extensions, false);
580
    }
581
 
582
    /**
583
     * Returns the number of children which are either files matching the specified extensions
584
     * or folders containing at least one such file.
585
     *
586
     * @param string|array $extensions, for example '*' or array('.gif','.jpg')
587
     * @param int $limit stop counting after at least $limit non-empty children are found
588
     * @return int
589
     */
590
    public function count_non_empty_children($extensions = '*', $limit = 1) {
591
        return $this->get_filtered_children($extensions, $limit);
592
    }
593
 
594
    /**
595
     * Returns parent file_info instance
596
     *
597
     * @return file_info or null for root
598
     */
599
    public function get_parent() {
600
        $parent = $this->context->get_parent_context();
601
        return $this->browser->get_file_info($parent);
602
    }
603
}
604
 
605
 
606
/**
607
 * Subclass of file_info_stored for files in the course files area.
608
 *
609
 * @package   core_files
610
 * @copyright 2008 Petr Skoda (http://skodak.org)
611
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
612
 */
613
class file_info_area_course_legacy extends file_info_stored {
614
    /**
615
     * Constructor
616
     *
617
     * @param file_browser $browser file browser instance
618
     * @param stdClass $context context object
619
     * @param stored_file $storedfile stored_file instance
620
     */
621
    public function __construct($browser, $context, $storedfile) {
622
        global $CFG;
623
        $urlbase = $CFG->wwwroot.'/file.php';
624
        parent::__construct($browser, $context, $storedfile, $urlbase, get_string('coursefiles'), false, true, true, false);
625
    }
626
 
627
    /**
628
     * Returns file download url
629
     *
630
     * @param bool $forcedownload whether or not force download
631
     * @param bool $https whether or not force https
632
     * @return string url
633
     */
634
    public function get_url($forcedownload=false, $https=false) {
635
        if (!$this->is_readable()) {
636
            return null;
637
        }
638
 
639
        if ($this->lf->is_directory()) {
640
            return null;
641
        }
642
 
643
        $filepath = $this->lf->get_filepath();
644
        $filename = $this->lf->get_filename();
645
        $courseid = $this->context->instanceid;
646
 
647
        $path = '/'.$courseid.$filepath.$filename;
648
 
649
        return file_encode_url($this->urlbase, $path, $forcedownload, $https);
650
    }
651
 
652
    /**
653
     * Returns list of children.
654
     *
655
     * @return array of file_info instances
656
     */
657
    public function get_children() {
658
        if (!$this->lf->is_directory()) {
659
            return array();
660
        }
661
 
662
        $result = array();
663
        $fs = get_file_storage();
664
 
665
        $storedfiles = $fs->get_directory_files($this->context->id, 'course', 'legacy', 0, $this->lf->get_filepath(), false, true, "filepath ASC, filename ASC");
666
        foreach ($storedfiles as $file) {
667
            $result[] = new file_info_area_course_legacy($this->browser, $this->context, $file);
668
        }
669
 
670
        return $result;
671
    }
672
 
673
    /**
674
     * Returns list of children which are either files matching the specified extensions
675
     * or folders that contain at least one such file.
676
     *
677
     * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
678
     * @return array of file_info instances
679
     */
680
    public function get_non_empty_children($extensions = '*') {
681
        if (!$this->lf->is_directory()) {
682
            return array();
683
        }
684
 
685
        $result = array();
686
        $fs = get_file_storage();
687
 
688
        $storedfiles = $fs->get_directory_files($this->context->id, 'course', 'legacy', 0,
689
                                                $this->lf->get_filepath(), false, true, "filepath, filename");
690
        foreach ($storedfiles as $file) {
691
            $extension = core_text::strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION));
692
            if ($file->is_directory() || $extensions === '*' || (!empty($extension) && in_array('.'.$extension, $extensions))) {
693
                $fileinfo = new file_info_area_course_legacy($this->browser, $this->context, $file, $this->urlbase, $this->topvisiblename,
694
                                                 $this->itemidused, $this->readaccess, $this->writeaccess, false);
695
                if (!$file->is_directory() || $fileinfo->count_non_empty_children($extensions)) {
696
                    $result[] = $fileinfo;
697
                }
698
            }
699
        }
700
 
701
        return $result;
702
    }
703
}
704
 
705
/**
706
 * Represents a course category context in the tree navigated by {@link file_browser}.
707
 *
708
 * @package    core_files
709
 * @copyright  2008 Petr Skoda (http://skodak.org)
710
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
711
 */
712
class file_info_area_course_section extends file_info {
713
    /** @var stdClass course object */
714
    protected $course;
715
    /** @var file_info_context_course course file info object */
716
    protected $courseinfo;
717
 
718
    /**
719
     * Constructor
720
     *
721
     * @param file_browser $browser file browser instance
722
     * @param stdClass $context context object
723
     * @param stdClass $course course object
724
     * @param file_info_context_course $courseinfo file info instance
725
     */
726
    public function __construct($browser, $context, $course, file_info_context_course $courseinfo) {
727
        parent::__construct($browser, $context);
728
        $this->course     = $course;
729
        $this->courseinfo = $courseinfo;
730
    }
731
 
732
    /**
733
     * Returns list of standard virtual file/directory identification.
734
     * The difference from stored_file parameters is that null values
735
     * are allowed in all fields
736
     *
737
     * @return array with keys contextid, filearea, itemid, filepath and filename
738
     */
739
    public function get_params() {
740
        return array('contextid' => $this->context->id,
741
                     'component' => 'course',
742
                     'filearea'  => 'section',
743
                     'itemid'    => null,
744
                     'filepath'  => null,
745
                     'filename'  => null);
746
    }
747
 
748
    /**
749
     * Returns localised visible name.
750
     *
751
     * @return string
752
     */
753
    public function get_visible_name() {
754
        //$format = $this->course->format;
755
        $sectionsname = get_string("coursesectionsummaries");
756
 
757
        return $sectionsname;
758
    }
759
 
760
    /**
761
     * Return whether or not new files or directories can be added
762
     *
763
     * @return bool
764
     */
765
    public function is_writable() {
766
        return false;
767
    }
768
 
769
    /**
770
     * Return whether or not this is a empty area
771
     *
772
     * @return bool
773
     */
774
    public function is_empty_area() {
775
        $fs = get_file_storage();
776
        return $fs->is_area_empty($this->context->id, 'course', 'section');
777
    }
778
 
779
    /**
780
     * Return whether or not this is a empty area
781
     *
782
     * @return bool
783
     */
784
    public function is_directory() {
785
        return true;
786
    }
787
 
788
    /**
789
     * Returns list of children.
790
     *
791
     * @return array of file_info instances
792
     */
793
    public function get_children() {
794
        global $DB;
795
 
796
        $children = array();
797
 
798
        $course_sections = $DB->get_records('course_sections', array('course'=>$this->course->id), 'section');
799
        foreach ($course_sections as $section) {
800
            if ($child = $this->courseinfo->get_file_info('course', 'section', $section->id, '/', '.')) {
801
                $children[] = $child;
802
            }
803
        }
804
 
805
        return $children;
806
    }
807
 
808
    /**
809
     * Returns the number of children which are either files matching the specified extensions
810
     * or folders containing at least one such file.
811
     *
812
     * @param string|array $extensions, for example '*' or array('.gif','.jpg')
813
     * @param int $limit stop counting after at least $limit non-empty children are found
814
     * @return int
815
     */
816
    public function count_non_empty_children($extensions = '*', $limit = 1) {
817
        global $DB;
818
        $params1 = array(
819
            'courseid' => $this->course->id,
820
            'contextid' => $this->context->id,
821
            'component' => 'course',
822
            'filearea' => 'section',
823
            'emptyfilename' => '.');
824
        $sql1 = "SELECT DISTINCT cs.id FROM {files} f, {course_sections} cs
825
            WHERE cs.course = :courseid
826
            AND f.contextid = :contextid
827
            AND f.component = :component
828
            AND f.filearea = :filearea
829
            AND f.itemid = cs.id
830
            AND f.filename <> :emptyfilename";
831
        list($sql2, $params2) = $this->build_search_files_sql($extensions);
832
        $rs = $DB->get_recordset_sql($sql1. ' '. $sql2, array_merge($params1, $params2));
833
        $cnt = 0;
834
        foreach ($rs as $record) {
835
            if ((++$cnt) >= $limit) {
836
                break;
837
            }
838
        }
839
        $rs->close();
840
        return $cnt;
841
    }
842
 
843
    /**
844
     * Returns parent file_info instance
845
     *
846
     * @return file_info|null file_info or null for root
847
     */
848
    public function get_parent() {
849
        return $this->courseinfo;
850
    }
851
}
852
 
853
 
854
/**
855
 * Implementation of course section backup area
856
 *
857
 * @package    core_files
858
 * @copyright  2008 Petr Skoda (http://skodak.org)
859
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
860
 */
861
class file_info_area_backup_section extends file_info {
862
    /** @var stdClass course object */
863
    protected $course;
864
    /** @var file_info_context_course course file info object */
865
    protected $courseinfo;
866
 
867
    /**
868
     * Constructor
869
     *
870
     * @param file_browser $browser file browser instance
871
     * @param stdClass $context context object
872
     * @param stdClass $course course object
873
     * @param file_info_context_course $courseinfo file info instance
874
     */
875
    public function __construct($browser, $context, $course, file_info_context_course $courseinfo) {
876
        parent::__construct($browser, $context);
877
        $this->course     = $course;
878
        $this->courseinfo = $courseinfo;
879
    }
880
 
881
    /**
882
     * Returns list of standard virtual file/directory identification.
883
     * The difference from stored_file parameters is that null values
884
     * are allowed in all fields
885
     *
886
     * @return array with keys contextid, component, filearea, itemid, filepath and filename
887
     */
888
    public function get_params() {
889
        return array('contextid' => $this->context->id,
890
                     'component' => 'backup',
891
                     'filearea'  => 'section',
892
                     'itemid'    => null,
893
                     'filepath'  => null,
894
                     'filename'  => null);
895
    }
896
 
897
    /**
898
     * Returns localised visible name.
899
     *
900
     * @return string
901
     */
902
    public function get_visible_name() {
903
        return get_string('sectionbackup', 'repository');
904
    }
905
 
906
    /**
907
     * Return whether or not new files and directories can be added
908
     *
909
     * @return bool
910
     */
911
    public function is_writable() {
912
        return false;
913
    }
914
 
915
    /**
916
     * Whether or not this is an empty area
917
     *
918
     * @return bool
919
     */
920
    public function is_empty_area() {
921
        $fs = get_file_storage();
922
        return $fs->is_area_empty($this->context->id, 'backup', 'section');
923
    }
924
 
925
    /**
926
     * Return whether or not this is a directory
927
     *
928
     * @return bool
929
     */
930
    public function is_directory() {
931
        return true;
932
    }
933
 
934
    /**
935
     * Returns list of children.
936
     *
937
     * @return array of file_info instances
938
     */
939
    public function get_children() {
940
        global $DB;
941
 
942
        $children = array();
943
 
944
        $course_sections = $DB->get_records('course_sections', array('course'=>$this->course->id), 'section');
945
        foreach ($course_sections as $section) {
946
            if ($child = $this->courseinfo->get_file_info('backup', 'section', $section->id, '/', '.')) {
947
                $children[] = $child;
948
            }
949
        }
950
 
951
        return $children;
952
    }
953
 
954
    /**
955
     * Returns the number of children which are either files matching the specified extensions
956
     * or folders containing at least one such file.
957
     *
958
     * @param string|array $extensions, for example '*' or array('.gif','.jpg')
959
     * @param int $limit stop counting after at least $limit non-empty children are found
960
     * @return int
961
     */
962
    public function count_non_empty_children($extensions = '*', $limit = 1) {
963
        global $DB;
964
        $params1 = array(
965
            'courseid' => $this->course->id,
966
            'contextid' => $this->context->id,
967
            'component' => 'backup',
968
            'filearea' => 'section',
969
            'emptyfilename' => '.');
970
        $sql1 = "SELECT DISTINCT cs.id AS sectionid FROM {files} f, {course_sections} cs
971
            WHERE cs.course = :courseid
972
            AND f.contextid = :contextid
973
            AND f.component = :component
974
            AND f.filearea = :filearea
975
            AND f.itemid = cs.id
976
            AND f.filename <> :emptyfilename";
977
        list($sql2, $params2) = $this->build_search_files_sql($extensions);
978
        $rs = $DB->get_recordset_sql($sql1. ' '. $sql2, array_merge($params1, $params2));
979
        $cnt = 0;
980
        foreach ($rs as $record) {
981
            if ((++$cnt) >= $limit) {
982
                break;
983
            }
984
        }
985
        $rs->close();
986
        return $cnt;
987
    }
988
 
989
    /**
990
     * Returns parent file_info instance
991
     *
992
     * @return file_info or null for root
993
     */
994
    public function get_parent() {
995
        return $this->browser->get_file_info($this->context);
996
    }
997
}