Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403]
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 * External files API 20 * 21 * @package core_files 22 * @category external 23 * @copyright 2010 Dongsheng Cai 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 use core_external\external_api; 28 use core_external\external_function_parameters; 29 use core_external\external_multiple_structure; 30 use core_external\external_single_structure; 31 use core_external\external_value; 32 33 defined('MOODLE_INTERNAL') || die(); 34 35 require_once("{$CFG->libdir}/filelib.php"); 36 37 /** 38 * Files external functions 39 * 40 * @package core_files 41 * @category external 42 * @copyright 2011 Jerome Mouneyrac 43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 44 * @since Moodle 2.2 45 */ 46 class core_files_external extends external_api { 47 48 /** 49 * Returns description of get_files parameters 50 * 51 * @return external_function_parameters 52 * @since Moodle 2.2 53 */ 54 public static function get_files_parameters() { 55 return new external_function_parameters([ 56 'contextid' => new external_value(PARAM_INT, 'context id Set to -1 to use contextlevel and instanceid.'), 57 'component' => new external_value(PARAM_TEXT, 'component'), 58 'filearea' => new external_value(PARAM_TEXT, 'file area'), 59 'itemid' => new external_value(PARAM_INT, 'associated id'), 60 'filepath' => new external_value(PARAM_PATH, 'file path'), 61 'filename' => new external_value(PARAM_TEXT, 'file name'), 62 'modified' => new external_value( 63 PARAM_INT, 64 'timestamp to return files changed after this time.', 65 VALUE_DEFAULT, 66 null 67 ), 68 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level for the file location.', VALUE_DEFAULT, null), 69 'instanceid' => new external_value(PARAM_INT, 'The instance id for where the file is located.', VALUE_DEFAULT, null), 70 ]); 71 } 72 73 /** 74 * Return moodle files listing 75 * 76 * @param int $contextid context id 77 * @param int $component component 78 * @param int $filearea file area 79 * @param int $itemid item id 80 * @param string $filepath file path 81 * @param string $filename file name 82 * @param int $modified timestamp to return files changed after this time. 83 * @param string $contextlevel The context level for the file location. 84 * @param int $instanceid The instance id for where the file is located. 85 * @return array 86 * @since Moodle 2.9 Returns additional fields (timecreated, filesize, author, license) 87 * @since Moodle 2.2 88 */ 89 public static function get_files($contextid, $component, $filearea, $itemid, $filepath, $filename, $modified = null, 90 $contextlevel = null, $instanceid = null) { 91 92 $parameters = [ 93 'contextid' => $contextid, 94 'component' => $component, 95 'filearea' => $filearea, 96 'itemid' => $itemid, 97 'filepath' => $filepath, 98 'filename' => $filename, 99 'modified' => $modified, 100 'contextlevel' => $contextlevel, 101 'instanceid' => $instanceid, 102 ]; 103 $fileinfo = self::validate_parameters(self::get_files_parameters(), $parameters); 104 105 $browser = get_file_browser(); 106 107 // We need to preserve backwards compatibility. Zero will use the system context and minus one will 108 // use the addtional parameters to determine the context. 109 // TODO MDL-40489 get_context_from_params should handle this logic. 110 if ($fileinfo['contextid'] == 0) { 111 $context = context_system::instance(); 112 } else { 113 if ($fileinfo['contextid'] == -1) { 114 $fileinfo['contextid'] = null; 115 } 116 $context = self::get_context_from_params($fileinfo); 117 } 118 self::validate_context($context); 119 120 if (empty($fileinfo['component'])) { 121 $fileinfo['component'] = null; 122 } 123 if (empty($fileinfo['filearea'])) { 124 $fileinfo['filearea'] = null; 125 } 126 if (empty($fileinfo['filename'])) { 127 $fileinfo['filename'] = null; 128 } 129 if (empty($fileinfo['filepath'])) { 130 $fileinfo['filepath'] = null; 131 } 132 133 $return = array(); 134 $return['parents'] = array(); 135 $return['files'] = array(); 136 $list = array(); 137 138 if ($file = $browser->get_file_info( 139 $context, $fileinfo['component'], $fileinfo['filearea'], $fileinfo['itemid'], 140 $fileinfo['filepath'], $fileinfo['filename'])) { 141 $level = $file->get_parent(); 142 while ($level) { 143 $params = $level->get_params(); 144 $params['filename'] = $level->get_visible_name(); 145 array_unshift($return['parents'], $params); 146 $level = $level->get_parent(); 147 } 148 $children = $file->get_children(); 149 foreach ($children as $child) { 150 151 $params = $child->get_params(); 152 $timemodified = $child->get_timemodified(); 153 $timecreated = $child->get_timecreated(); 154 155 if ($child->is_directory()) { 156 if ((is_null($modified)) or ($modified < $timemodified)) { 157 $node = [ 158 'contextid' => $params['contextid'], 159 'component' => $params['component'], 160 'filearea' => $params['filearea'], 161 'itemid' => $params['itemid'], 162 'filepath' => $params['filepath'], 163 'filename' => $child->get_visible_name(), 164 'url' => null, 165 'isdir' => true, 166 'timemodified' => $timemodified, 167 'timecreated' => $timecreated, 168 'filesize' => 0, 169 'author' => null, 170 'license' => null, 171 ]; 172 $list[] = $node; 173 } 174 } else { 175 if ((is_null($modified)) or ($modified < $timemodified)) { 176 $node = [ 177 'contextid' => $params['contextid'], 178 'component' => $params['component'], 179 'filearea' => $params['filearea'], 180 'itemid' => $params['itemid'], 181 'filepath' => $params['filepath'], 182 'filename' => $child->get_visible_name(), 183 'url' => $child->get_url(), 184 'isdir' => false, 185 'timemodified' => $timemodified, 186 'timecreated' => $timecreated, 187 'filesize' => $child->get_filesize(), 188 'author' => $child->get_author(), 189 'license' => $child->get_license(), 190 ]; 191 $list[] = $node; 192 } 193 } 194 } 195 } 196 $return['files'] = $list; 197 return $return; 198 } 199 200 /** 201 * Returns description of get_files returns 202 * 203 * @return external_single_structure 204 * @since Moodle 2.9 Returns additional fields for files (timecreated, filesize, author, license) 205 * @since Moodle 2.2 206 */ 207 public static function get_files_returns() { 208 return new external_single_structure([ 209 'parents' => new external_multiple_structure( 210 new external_single_structure([ 211 'contextid' => new external_value(PARAM_INT, ''), 212 'component' => new external_value(PARAM_COMPONENT, ''), 213 'filearea' => new external_value(PARAM_AREA, ''), 214 'itemid' => new external_value(PARAM_INT, ''), 215 'filepath' => new external_value(PARAM_TEXT, ''), 216 'filename' => new external_value(PARAM_TEXT, ''), 217 ]) 218 ), 219 'files' => new external_multiple_structure( 220 new external_single_structure([ 221 'contextid' => new external_value(PARAM_INT, ''), 222 'component' => new external_value(PARAM_COMPONENT, ''), 223 'filearea' => new external_value(PARAM_AREA, ''), 224 'itemid' => new external_value(PARAM_INT, ''), 225 'filepath' => new external_value(PARAM_TEXT, ''), 226 'filename' => new external_value(PARAM_TEXT, ''), 227 'isdir' => new external_value(PARAM_BOOL, ''), 228 'url' => new external_value(PARAM_TEXT, ''), 229 'timemodified' => new external_value(PARAM_INT, ''), 230 'timecreated' => new external_value(PARAM_INT, 'Time created', VALUE_OPTIONAL), 231 'filesize' => new external_value(PARAM_INT, 'File size', VALUE_OPTIONAL), 232 'author' => new external_value(PARAM_TEXT, 'File owner', VALUE_OPTIONAL), 233 'license' => new external_value(PARAM_TEXT, 'File license', VALUE_OPTIONAL), 234 ]) 235 ), 236 ]); 237 } 238 239 /** 240 * Returns description of upload parameters 241 * 242 * @return external_function_parameters 243 * @since Moodle 2.2 244 */ 245 public static function upload_parameters() { 246 return new external_function_parameters([ 247 'contextid' => new external_value(PARAM_INT, 'context id', VALUE_DEFAULT, null), 248 'component' => new external_value(PARAM_COMPONENT, 'component'), 249 'filearea' => new external_value(PARAM_AREA, 'file area'), 250 'itemid' => new external_value(PARAM_INT, 'associated id'), 251 'filepath' => new external_value(PARAM_PATH, 'file path'), 252 'filename' => new external_value(PARAM_FILE, 'file name'), 253 'filecontent' => new external_value(PARAM_TEXT, 'file content'), 254 'contextlevel' => new external_value( 255 PARAM_ALPHA, 256 'The context level to put the file in, 257 (block, course, coursecat, system, user, module)', 258 VALUE_DEFAULT, 259 null 260 ), 261 'instanceid' => new external_value(PARAM_INT, 'The Instance id of item associated 262 with the context level', VALUE_DEFAULT, null), 263 ]); 264 } 265 266 /** 267 * Uploading a file to moodle 268 * 269 * @param int $contextid context id 270 * @param string $component component 271 * @param string $filearea file area 272 * @param int $itemid item id 273 * @param string $filepath file path 274 * @param string $filename file name 275 * @param string $filecontent file content 276 * @param string $contextlevel Context level (block, course, coursecat, system, user or module) 277 * @param int $instanceid Instance id of the item associated with the context level 278 * @return array 279 * @since Moodle 2.2 280 */ 281 public static function upload( 282 $contextid, 283 $component, 284 $filearea, 285 $itemid, 286 $filepath, 287 $filename, 288 $filecontent, 289 $contextlevel, 290 $instanceid 291 ) { 292 global $USER, $CFG; 293 294 $fileinfo = self::validate_parameters(self::upload_parameters(), [ 295 'contextid' => $contextid, 'component' => $component, 'filearea' => $filearea, 'itemid' => $itemid, 296 'filepath' => $filepath, 'filename' => $filename, 'filecontent' => $filecontent, 'contextlevel' => $contextlevel, 297 'instanceid' => $instanceid, 298 ]); 299 300 if (!isset($fileinfo['filecontent'])) { 301 throw new moodle_exception('nofile'); 302 } 303 // Saving file. 304 $dir = make_temp_directory('wsupload'); 305 306 if (empty($fileinfo['filename'])) { 307 $filename = uniqid('wsupload', true).'_'.time().'.tmp'; 308 } else { 309 $filename = $fileinfo['filename']; 310 } 311 312 if (file_exists($dir.$filename)) { 313 $savedfilepath = $dir.uniqid('m').$filename; 314 } else { 315 $savedfilepath = $dir.$filename; 316 } 317 318 file_put_contents($savedfilepath, base64_decode($fileinfo['filecontent'])); 319 @chmod($savedfilepath, $CFG->filepermissions); 320 unset($fileinfo['filecontent']); 321 322 if (!empty($fileinfo['filepath'])) { 323 $filepath = $fileinfo['filepath']; 324 } else { 325 $filepath = '/'; 326 } 327 328 // Only allow uploads to draft area. 329 if (!($fileinfo['component'] == 'user' and $fileinfo['filearea'] == 'draft')) { 330 throw new coding_exception('File can be uploaded to user draft area only'); 331 } else { 332 $component = 'user'; 333 $filearea = $fileinfo['filearea']; 334 } 335 336 $itemid = 0; 337 if (isset($fileinfo['itemid'])) { 338 $itemid = $fileinfo['itemid']; 339 } 340 if ($filearea == 'draft' && $itemid <= 0) { 341 // Generate a draft area for the files. 342 $itemid = file_get_unused_draft_itemid(); 343 } else if ($filearea == 'private') { 344 // TODO MDL-31116 in user private area, itemid is always 0. 345 $itemid = 0; 346 } 347 348 // We need to preserve backword compatibility. Context id is no more a required. 349 if (empty($fileinfo['contextid'])) { 350 unset($fileinfo['contextid']); 351 } 352 353 // Get and validate context. 354 $context = self::get_context_from_params($fileinfo); 355 self::validate_context($context); 356 if (($fileinfo['component'] == 'user' and $fileinfo['filearea'] == 'private')) { 357 throw new moodle_exception('privatefilesupload'); 358 } 359 360 $browser = get_file_browser(); 361 362 // Check existing file. 363 if ($file = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, $filename)) { 364 throw new moodle_exception('fileexist'); 365 } 366 367 // Move file to filepool. 368 if ($dir = $browser->get_file_info($context, $component, $filearea, $itemid, $filepath, '.')) { 369 $info = $dir->create_file_from_pathname($filename, $savedfilepath); 370 $params = $info->get_params(); 371 unlink($savedfilepath); 372 return [ 373 'contextid' => $params['contextid'], 374 'component' => $params['component'], 375 'filearea' => $params['filearea'], 376 'itemid' => $params['itemid'], 377 'filepath' => $params['filepath'], 378 'filename' => $params['filename'], 379 'url' => $info->get_url(), 380 ]; 381 } else { 382 throw new moodle_exception('nofile'); 383 } 384 } 385 386 /** 387 * Returns description of upload returns 388 * 389 * @return external_single_structure 390 * @since Moodle 2.2 391 */ 392 public static function upload_returns() { 393 return new external_single_structure([ 394 'contextid' => new external_value(PARAM_INT, ''), 395 'component' => new external_value(PARAM_COMPONENT, ''), 396 'filearea' => new external_value(PARAM_AREA, ''), 397 'itemid' => new external_value(PARAM_INT, ''), 398 'filepath' => new external_value(PARAM_TEXT, ''), 399 'filename' => new external_value(PARAM_FILE, ''), 400 'url' => new external_value(PARAM_TEXT, ''), 401 ]); 402 } 403 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body