MDL-27586 fix file_browser access control
[moodle.git] / lib / filebrowser / file_info_context_module.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
19 /**
20  * Utility class for browsing of module files.
21  *
22  * @package    core
23  * @subpackage filebrowser
24  * @copyright  2008 Petr Skoda (http://skodak.org)
25  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 defined('MOODLE_INTERNAL') || die();
30 /**
31  * Represents a module context in the tree navigated by @see{file_browser}.
32  *
33  * @package    core
34  * @subpackage filebrowser
35  * @copyright  2008 Petr Skoda (http://skodak.org)
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class file_info_context_module extends file_info {
39     protected $course;
40     protected $cm;
41     protected $modname;
42     protected $areas;
44     public function __construct($browser, $context, $course, $cm, $modname) {
45         global $CFG;
47         parent::__construct($browser, $context);
48         $this->course  = $course;
49         $this->cm      = $cm;
50         $this->modname = $modname;
52         include_once("$CFG->dirroot/mod/$modname/lib.php");
54         //find out all supported areas
55         $functionname     = 'mod_'.$modname.'_get_file_areas';
56         $functionname_old = $modname.'_get_file_areas';
58         if (function_exists($functionname)) {
59             $this->areas = $functionname($course, $cm, $context);
60         } else if (function_exists($functionname_old)) {
61             $this->areas = $functionname_old($course, $cm, $context);
62         } else {
63             $this->areas = array();
64         }
65         unset($this->areas['intro']); // hardcoded, ignore attempts to override it
66     }
68     /**
69      * Return information about this specific context level
70      *
71      * @param $component
72      * @param $filearea
73      * @param $itemid
74      * @param $filepath
75      * @param $filename
76      */
77     public function get_file_info($component, $filearea, $itemid, $filepath, $filename) {
78         // try to emulate require_login() tests here
79         if (!isloggedin()) {
80             return null;
81         }
83         $coursecontext = get_course_context($this->context);
84         if (!$this->course->visible and !has_capability('moodle/course:viewhiddencourses', $coursecontext)) {
85             return null;
86         }
88         if (!is_viewing($this->context) and !is_enrolled($this->context)) {
89             // no peaking here if not enrolled or inspector
90             return null;
91         }
93         $modinfo = get_fast_modinfo($this->course);
94         $cminfo = $modinfo->get_cm($this->cm->id);
95         if (!$cminfo->uservisible) {
96             // activity hidden sorry
97             return null;
98         }
100         if (empty($component)) {
101             return $this;
102         }
104         if ($component == 'mod_'.$this->modname and $filearea === 'intro') {
105             return $this->get_area_intro($itemid, $filepath, $filename);
106         } else if ($component == 'backup' and $filearea === 'activity') {
107             return $this->get_area_backup($itemid, $filepath, $filename);
108         }
110         $functionname     = 'mod_'.$this->modname.'_get_file_info';
111         $functionname_old = $this->modname.'_get_file_info';
113         if (function_exists($functionname)) {
114             return $functionname($this->browser, $this->areas, $this->course, $this->cm, $this->context, $filearea, $itemid, $filepath, $filename);
115         } else if (function_exists($functionname_old)) {
116             return $functionname_old($this->browser, $this->areas, $this->course, $this->cm, $this->context, $filearea, $itemid, $filepath, $filename);
117         }
119         return null;
120     }
122     protected function get_area_intro($itemid, $filepath, $filename) {
123         global $CFG;
125         if (!plugin_supports('mod', $this->modname, FEATURE_MOD_INTRO, true) or !has_capability('moodle/course:managefiles', $this->context)) {
126             return null;
127         }
129         $fs = get_file_storage();
131         $filepath = is_null($filepath) ? '/' : $filepath;
132         $filename = is_null($filename) ? '.' : $filename;
133         if (!$storedfile = $fs->get_file($this->context->id, 'mod_'.$this->modname, 'intro', 0, $filepath, $filename)) {
134             if ($filepath === '/' and $filename === '.') {
135                 $storedfile = new virtual_root_file($this->context->id, 'mod_'.$this->modname, 'intro', 0);
136             } else {
137                 // not found
138                 return null;
139             }
140         }
142         $urlbase = $CFG->wwwroot.'/pluginfile.php';
143         return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('moduleintro'), false, true, true, false);
144     }
146     protected function get_area_backup($itemid, $filepath, $filename) {
147         global $CFG;
149         if (!has_capability('moodle/backup:backupactivity', $this->context)) {
150             return null;
151         }
153         $fs = get_file_storage();
155         $filepath = is_null($filepath) ? '/' : $filepath;
156         $filename = is_null($filename) ? '.' : $filename;
157         if (!$storedfile = $fs->get_file($this->context->id, 'backup', 'activity', 0, $filepath, $filename)) {
158             if ($filepath === '/' and $filename === '.') {
159                 $storedfile = new virtual_root_file($this->context->id, 'backup', 'activity', 0);
160             } else {
161                 // not found
162                 return null;
163             }
164         }
166         $downloadable = has_capability('moodle/backup:downloadfile', $this->context);
167         $uploadable   = has_capability('moodle/restore:uploadfile', $this->context);
169         $urlbase = $CFG->wwwroot.'/pluginfile.php';
170         return new file_info_stored($this->browser, $this->context, $storedfile, $urlbase, get_string('activitybackup', 'repository'), false, $downloadable, $uploadable, false);
171     }
173     /**
174      * Returns localised visible name.
175      * @return string
176      */
177     public function get_visible_name() {
178         return $this->cm->name.' ('.get_string('modulename', $this->cm->modname).')';
179     }
181     /**
182      * Can I add new files or directories?
183      * @return bool
184      */
185     public function is_writable() {
186         return false;
187     }
189     /**
190      * Is this empty area?
191      *
192      * @return bool
193      */
194     public function is_empty_area() {
195         if ($child = $this->get_area_backup(0, '/', '.')) {
196             if (!$child->is_empty_area()) {
197                 return false;
198             }
199         }
200         if ($child = $this->get_area_intro(0, '/', '.')) {
201             if (!$child->is_empty_area()) {
202                 return false;
203             }
204         }
206         foreach ($this->areas as $area=>$desctiption) {
207             if ($child = $this->get_file_info('mod_'.$this->modname, $area, null, null, null)) {
208                 if (!$child->is_empty_area()) {
209                     return false;
210                 }
211             }
212         }
214         return true;
215     }
217     /**
218      * Is directory?
219      * @return bool
220      */
221     public function is_directory() {
222         return true;
223     }
225     /**
226      * Returns list of children.
227      * @return array of file_info instances
228      */
229     public function get_children() {
230         $children = array();
232         if ($child = $this->get_area_backup(0, '/', '.')) {
233             $children[] = $child;
234         }
235         if ($child = $this->get_area_intro(0, '/', '.')) {
236             $children[] = $child;
237         }
239         foreach ($this->areas as $area=>$desctiption) {
240             if ($child = $this->get_file_info('mod_'.$this->modname, $area, null, null, null)) {
241                 $children[] = $child;
242             }
243         }
245         return $children;
246     }
248     /**
249      * Returns parent file_info instance
250      * @return file_info or null for root
251      */
252     public function get_parent() {
253         $pcid = get_parent_contextid($this->context);
254         $parent = get_context_instance_by_id($pcid);
255         return $this->browser->get_file_info($parent);
256     }