Commit | Line | Data |
---|---|---|
4317f92f | 1 | <?php |
10d53fd3 DC |
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 | ||
67233725 DC |
17 | /** |
18 | * This plugin is used to access files on server file system | |
19 | * | |
20 | * @since 2.0 | |
21 | * @package repository_filesystem | |
22 | * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | require_once($CFG->dirroot . '/repository/lib.php'); | |
26 | require_once($CFG->libdir . '/filelib.php'); | |
27 | ||
fdcf5320 | 28 | /** |
29 | * repository_filesystem class | |
67233725 | 30 | * |
fdcf5320 | 31 | * Create a repository from your local filesystem |
32 | * *NOTE* for security issue, we use a fixed repository path | |
33 | * which is %moodledata%/repository | |
34 | * | |
d078f6d3 | 35 | * @package repository |
67233725 | 36 | * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} |
d078f6d3 | 37 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later |
fdcf5320 | 38 | */ |
520de343 | 39 | class repository_filesystem extends repository { |
67233725 DC |
40 | |
41 | /** | |
42 | * Constructor | |
43 | * | |
44 | * @param int $repositoryid repository ID | |
45 | * @param int $context context ID | |
46 | * @param array $options | |
47 | */ | |
447c7a19 | 48 | public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { |
fdcf5320 | 49 | global $CFG; |
520de343 | 50 | parent::__construct($repositoryid, $context, $options); |
873f2e0f DC |
51 | $root = $CFG->dataroot.'/repository/'; |
52 | $subdir = $this->get_option('fs_path'); | |
53 | $this->root_path = $root . $subdir . '/'; | |
e437618b | 54 | if (!empty($options['ajax'])) { |
fdcf5320 | 55 | if (!is_dir($this->root_path)) { |
8512eebe | 56 | $created = mkdir($this->root_path, $CFG->directorypermissions, true); |
520de343 | 57 | $ret = array(); |
58 | $ret['msg'] = get_string('invalidpath', 'repository_filesystem'); | |
59 | $ret['nosearch'] = true; | |
93e9aa27 | 60 | if ($options['ajax'] && !$created) { |
fdcf5320 | 61 | echo json_encode($ret); |
62 | exit; | |
520de343 | 63 | } |
64 | } | |
520de343 | 65 | } |
66 | } | |
67 | public function get_listing($path = '', $page = '') { | |
390baf46 | 68 | global $CFG, $OUTPUT; |
520de343 | 69 | $list = array(); |
70 | $list['list'] = array(); | |
71 | // process breacrumb trail | |
72 | $list['path'] = array( | |
5bdf63cc | 73 | array('name'=>get_string('root', 'repository_filesystem'), 'path'=>'') |
520de343 | 74 | ); |
75 | $trail = ''; | |
76 | if (!empty($path)) { | |
77 | $parts = explode('/', $path); | |
78 | if (count($parts) > 1) { | |
79 | foreach ($parts as $part) { | |
4a9aff79 | 80 | if (!empty($part)) { |
81 | $trail .= ('/'.$part); | |
82 | $list['path'][] = array('name'=>$part, 'path'=>$trail); | |
83 | } | |
520de343 | 84 | } |
85 | } else { | |
86 | $list['path'][] = array('name'=>$path, 'path'=>$path); | |
87 | } | |
88 | $this->root_path .= ($path.'/'); | |
89 | } | |
520de343 | 90 | $list['manage'] = false; |
520de343 | 91 | $list['dynload'] = true; |
520de343 | 92 | $list['nologin'] = true; |
520de343 | 93 | $list['nosearch'] = true; |
7355640a MG |
94 | // retrieve list of files and directories and sort them |
95 | $fileslist = array(); | |
96 | $dirslist = array(); | |
520de343 | 97 | if ($dh = opendir($this->root_path)) { |
98 | while (($file = readdir($dh)) != false) { | |
99 | if ( $file != '.' and $file !='..') { | |
7355640a MG |
100 | if (is_file($this->root_path.$file)) { |
101 | $fileslist[] = $file; | |
520de343 | 102 | } else { |
7355640a | 103 | $dirslist[] = $file; |
520de343 | 104 | } |
105 | } | |
106 | } | |
107 | } | |
7355640a MG |
108 | collatorlib::asort($fileslist, collatorlib::SORT_STRING); |
109 | collatorlib::asort($dirslist, collatorlib::SORT_STRING); | |
110 | // fill the $list['list'] | |
111 | foreach ($dirslist as $file) { | |
112 | if (!empty($path)) { | |
113 | $current_path = $path . '/'. $file; | |
114 | } else { | |
115 | $current_path = $file; | |
116 | } | |
117 | $list['list'][] = array( | |
118 | 'title' => $file, | |
119 | 'children' => array(), | |
120 | 'datecreated' => filectime($this->root_path.$file), | |
121 | 'datemodified' => filemtime($this->root_path.$file), | |
122 | 'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false), | |
123 | 'path' => $current_path | |
124 | ); | |
125 | } | |
126 | foreach ($fileslist as $file) { | |
127 | $list['list'][] = array( | |
128 | 'title' => $file, | |
129 | 'source' => $path.'/'.$file, | |
130 | 'size' => filesize($this->root_path.$file), | |
131 | 'datecreated' => filectime($this->root_path.$file), | |
132 | 'datemodified' => filemtime($this->root_path.$file), | |
133 | 'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file, 90))->out(false), | |
134 | 'icon' => $OUTPUT->pix_url(file_extension_icon($file, 24))->out(false) | |
135 | ); | |
136 | } | |
fb4ee704 | 137 | $list['list'] = array_filter($list['list'], array($this, 'filter')); |
520de343 | 138 | return $list; |
139 | } | |
520de343 | 140 | public function check_login() { |
141 | return true; | |
142 | } | |
520de343 | 143 | public function print_login() { |
144 | return true; | |
145 | } | |
520de343 | 146 | public function global_search() { |
147 | return false; | |
148 | } | |
67233725 | 149 | |
951d2d55 DC |
150 | /** |
151 | * Return file path | |
152 | * @return array | |
153 | */ | |
520de343 | 154 | public function get_file($file, $title = '') { |
155 | global $CFG; | |
156 | if ($file{0} == '/') { | |
157 | $file = $this->root_path.substr($file, 1, strlen($file)-1); | |
951d2d55 DC |
158 | } else { |
159 | $file = $this->root_path.$file; | |
520de343 | 160 | } |
161 | // this is a hack to prevent move_to_file deleteing files | |
162 | // in local repository | |
163 | $CFG->repository_no_delete = true; | |
85b5ed5d | 164 | return array('path'=>$file, 'url'=>''); |
520de343 | 165 | } |
166 | ||
d6453211 DC |
167 | /** |
168 | * Return the source information | |
169 | * | |
170 | * @param stdClass $filepath | |
171 | * @return string|null | |
172 | */ | |
173 | public function get_file_source_info($filepath) { | |
174 | return $filepath; | |
175 | } | |
176 | ||
520de343 | 177 | public function logout() { |
178 | return true; | |
179 | } | |
180 | ||
181 | public static function get_instance_option_names() { | |
93e9aa27 | 182 | return array('fs_path'); |
520de343 | 183 | } |
184 | ||
b2f8adf4 | 185 | public function set_option($options = array()) { |
186 | $options['fs_path'] = clean_param($options['fs_path'], PARAM_PATH); | |
187 | $ret = parent::set_option($options); | |
188 | return $ret; | |
189 | } | |
8e5af6cf | 190 | |
4a126f17 | 191 | public static function instance_config_form($mform) { |
49d20def | 192 | global $CFG, $PAGE; |
8e5af6cf | 193 | if (has_capability('moodle/site:config', get_system_context())) { |
49d20def DC |
194 | $path = $CFG->dataroot . '/repository/'; |
195 | if (!is_dir($path)) { | |
8512eebe | 196 | mkdir($path, $CFG->directorypermissions, true); |
93e9aa27 | 197 | } |
49d20def DC |
198 | if ($handle = opendir($path)) { |
199 | $fieldname = get_string('path', 'repository_filesystem'); | |
200 | $choices = array(); | |
201 | while (false !== ($file = readdir($handle))) { | |
202 | if (is_dir($path.$file) && $file != '.' && $file!= '..') { | |
203 | $choices[$file] = $file; | |
204 | $fieldname = ''; | |
205 | } | |
206 | } | |
207 | if (empty($choices)) { | |
208 | $mform->addElement('static', '', '', get_string('nosubdir', 'repository_filesystem', $path)); | |
6b172cdc | 209 | $mform->addElement('hidden', 'fs_path', ''); |
49d20def DC |
210 | } else { |
211 | $mform->addElement('select', 'fs_path', $fieldname, $choices); | |
212 | $mform->addElement('static', null, '', get_string('information','repository_filesystem', $path)); | |
213 | } | |
214 | closedir($handle); | |
873f2e0f | 215 | } |
49d20def DC |
216 | } else { |
217 | $mform->addElement('static', null, '', get_string('nopermissions', 'error', get_string('configplugin', 'repository_filesystem'))); | |
218 | return false; | |
93e9aa27 | 219 | } |
93e9aa27 | 220 | } |
8e5af6cf | 221 | |
49d20def DC |
222 | public static function create($type, $userid, $context, $params, $readonly=0) { |
223 | global $PAGE; | |
8e5af6cf | 224 | if (has_capability('moodle/site:config', get_system_context())) { |
49d20def DC |
225 | return parent::create($type, $userid, $context, $params, $readonly); |
226 | } else { | |
8e5af6cf | 227 | require_capability('moodle/site:config', get_system_context()); |
49d20def DC |
228 | return false; |
229 | } | |
230 | } | |
6b172cdc DC |
231 | public static function instance_form_validation($mform, $data, $errors) { |
232 | if (empty($data['fs_path'])) { | |
233 | $errors['fs_path'] = get_string('invalidadminsettingname', 'error', 'fs_path'); | |
234 | } | |
235 | return $errors; | |
236 | } | |
67233725 DC |
237 | |
238 | /** | |
239 | * User cannot use the external link to dropbox | |
240 | * | |
241 | * @return int | |
242 | */ | |
243 | public function supported_returntypes() { | |
244 | return FILE_INTERNAL | FILE_REFERENCE; | |
245 | } | |
246 | ||
247 | /** | |
0b2bfbd1 | 248 | * Returns information about file in this repository by reference |
67233725 DC |
249 | * {@link repository::get_file_reference()} |
250 | * {@link repository::get_file()} | |
251 | * | |
0b2bfbd1 MG |
252 | * Returns null if file not found or is not readable |
253 | * | |
67233725 | 254 | * @param stdClass $reference file reference db record |
0b2bfbd1 MG |
255 | * @return stdClass|null contains one of the following: |
256 | * - 'contenthash' and 'filesize' | |
257 | * - 'filepath' | |
258 | * - 'handle' | |
259 | * - 'content' | |
67233725 DC |
260 | */ |
261 | public function get_file_by_reference($reference) { | |
262 | $ref = $reference->reference; | |
263 | if ($ref{0} == '/') { | |
264 | $filepath = $this->root_path.substr($ref, 1, strlen($ref)-1); | |
265 | } else { | |
266 | $filepath = $this->root_path.$ref; | |
267 | } | |
0b2bfbd1 MG |
268 | if (file_exists($filepath) && is_readable($filepath)) { |
269 | return (object)array('filepath' => $filepath); | |
270 | } else { | |
271 | return null; | |
272 | } | |
67233725 DC |
273 | } |
274 | ||
275 | /** | |
0b2bfbd1 MG |
276 | * Repository method to serve the referenced file |
277 | * | |
278 | * @see send_stored_file | |
67233725 | 279 | * |
0b2bfbd1 | 280 | * @param stored_file $storedfile the file that contains the reference |
67233725 DC |
281 | * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) |
282 | * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only | |
283 | * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin | |
284 | * @param array $options additional options affecting the file serving | |
285 | */ | |
286 | public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { | |
287 | $reference = $storedfile->get_reference(); | |
288 | if ($reference{0} == '/') { | |
289 | $file = $this->root_path.substr($reference, 1, strlen($reference)-1); | |
290 | } else { | |
291 | $file = $this->root_path.$reference; | |
292 | } | |
0b2bfbd1 MG |
293 | if (is_readable($file)) { |
294 | $filename = $storedfile->get_filename(); | |
295 | if ($options && isset($options['filename'])) { | |
296 | $filename = $options['filename']; | |
297 | } | |
298 | $dontdie = ($options && isset($options['dontdie'])); | |
299 | send_file($file, $filename, $lifetime , $filter, false, $forcedownload, '', $dontdie); | |
300 | } else { | |
301 | send_file_not_found(); | |
302 | } | |
67233725 | 303 | } |
520de343 | 304 | } |