diff --git a/files/externallib.php b/files/externallib.php index f2b0ab6f92d26..0759a51f0ce88 100644 --- a/files/externallib.php +++ b/files/externallib.php @@ -272,11 +272,24 @@ public static function upload($contextid, $component, $filearea, $itemid, $filep $filepath = '/'; } + // Only allow uploads to draft or private areas (private is deprecated but still supported) + if (!($fileinfo['component'] == 'user' and in_array($fileinfo['filearea'], array('private', 'draft')))) { + throw new coding_exception('File can be uploaded to user private or draft areas only'); + } else { + $component = 'user'; + $filearea = $fileinfo['filearea']; + } + + $itemid = 0; if (isset($fileinfo['itemid'])) { + $itemid = $fileinfo['itemid']; + } + if ($filearea == 'draft' && $itemid <= 0) { + // Generate a draft area for the files. + $itemid = file_get_unused_draft_itemid(); + } else if ($filearea == 'private') { // TODO MDL-31116 in user private area, itemid is always 0. $itemid = 0; - } else { - throw new coding_exception('itemid cannot be empty'); } // We need to preserve backword compatibility. Context id is no more a required. @@ -287,13 +300,8 @@ public static function upload($contextid, $component, $filearea, $itemid, $filep // Get and validate context. $context = self::get_context_from_params($fileinfo); self::validate_context($context); - - if (!($fileinfo['component'] == 'user' and $fileinfo['filearea'] == 'private')) { - throw new coding_exception('File can be uploaded to user private area only'); - } else { - // TODO MDL-31116 hard-coded to use user_private area. - $component = 'user'; - $filearea = 'private'; + if (($fileinfo['component'] == 'user' and $fileinfo['filearea'] == 'private')) { + debugging('Uploading directly to user private files area is deprecated. Upload to a draft area and then move the files with core_user::add_files_to_private_files'); } $browser = get_file_browser(); diff --git a/user/externallib.php b/user/externallib.php index bbaa87ae9f142..787ddb5ada069 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -926,6 +926,68 @@ public static function user_description($additionalfields = array()) { return new external_single_structure($userfields); } + /** + * Returns description of method parameters + * + * @return external_function_parameters + * @since Moodle 2.6 + */ + public static function add_user_private_files_parameters() { + return new external_function_parameters( + array( + 'draftid' => new external_value(PARAM_INT, 'draft area id') + ) + ); + } + + /** + * Copy files from a draft area to users private files area. + * + * @param int $draftid Id of a draft area containing files. + * @return array An array of warnings + * @since Moodle 2.6 + */ + public static function add_user_private_files($draftid) { + global $CFG, $USER, $DB; + + require_once($CFG->dirroot . "/user/lib.php"); + $params = self::validate_parameters(self::add_user_private_files_parameters(), array('draftid'=>$draftid)); + + if (isguestuser()) { + throw new invalid_parameter_exception('Guest users cannot upload files'); + } + + $context = context_user::instance($USER->id); + require_capability('moodle/user:manageownfiles', $context); + + $maxbytes = $CFG->userquota; + $maxareabytes = $CFG->userquota; + if (has_capability('moodle/user:ignoreuserquota', $context)) { + $maxbytes = USER_CAN_IGNORE_FILE_SIZE_LIMITS; + $maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED; + } + + $options = array('subdirs' => 1, + 'maxbytes' => $maxbytes, + 'maxfiles' => -1, + 'accepted_types' => '*', + 'areamaxbytes' => $maxareabytes); + + file_save_draft_area_files($draftid, $context->id, 'user', 'private', 0, $options); + + return null; + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 2.2 + */ + public static function add_user_private_files_returns() { + return null; + } + } /** diff --git a/user/tests/externallib_test.php b/user/tests/externallib_test.php index f58271e62fd39..011cc71650d6c 100644 --- a/user/tests/externallib_test.php +++ b/user/tests/externallib_test.php @@ -30,6 +30,7 @@ require_once($CFG->dirroot . '/webservice/tests/helpers.php'); require_once($CFG->dirroot . '/user/externallib.php'); +require_once($CFG->dirroot . '/files/externallib.php'); class core_user_externallib_testcase extends externallib_advanced_testcase { @@ -667,4 +668,48 @@ public function test_update_users() { $this->setExpectedException('required_capability_exception'); core_user_external::update_users(array($user1)); } + + /** + * Test add_user_private_files + */ + public function test_add_user_private_files() { + global $USER, $CFG, $DB; + + $this->resetAfterTest(true); + + $context = context_system::instance(); + $roleid = $this->assignUserCapability('moodle/user:manageownfiles', $context->id); + + $context = context_user::instance($USER->id); + $contextid = $context->id; + $component = "user"; + $filearea = "draft"; + $itemid = 0; + $filepath = "/"; + $filename = "Simple.txt"; + $filecontent = base64_encode("Let us create a nice simple file"); + $contextlevel = null; + $instanceid = null; + $browser = get_file_browser(); + + // Call the files api to create a file. + $draftfile = core_files_external::upload($contextid, $component, $filearea, $itemid, $filepath, + $filename, $filecontent, $contextlevel, $instanceid); + + $draftid = $draftfile['itemid']; + // Make sure the file was created. + $file = $browser->get_file_info($context, $component, $filearea, $draftid, $filepath, $filename); + $this->assertNotEmpty($file); + + // Make sure the file does not exist in the user private files. + $file = $browser->get_file_info($context, $component, 'private', 0, $filepath, $filename); + $this->assertEmpty($file); + + // Call the external function. + core_user_external::add_user_private_files($draftid); + + // Make sure the file was added to the user private files. + $file = $browser->get_file_info($context, $component, 'private', 0, $filepath, $filename); + $this->assertNotEmpty($file); + } }