From c2cf2450acc8417e2493fe2fcb920d9459da6167 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Tue, 20 Jun 2017 16:43:57 +0100 Subject: [PATCH] MDL-59243 mod_workshop: New WS mod_workshop_add_submission --- mod/workshop/classes/external.php | 111 ++++++++++++++++++++++++ mod/workshop/db/services.php | 8 ++ mod/workshop/tests/external_test.php | 122 +++++++++++++++++++++++++++ mod/workshop/version.php | 2 +- 4 files changed, 242 insertions(+), 1 deletion(-) diff --git a/mod/workshop/classes/external.php b/mod/workshop/classes/external.php index 2e5d5540ef2..30585b9e5f3 100644 --- a/mod/workshop/classes/external.php +++ b/mod/workshop/classes/external.php @@ -197,6 +197,7 @@ class mod_workshop_external extends external_api { if (is_null($result['assessingexamplesallowed'])) { $result['assessingexamplesallowed'] = false; } + $result['examplesassessed'] = $workshop->check_examples_assessed($USER->id); $result['warnings'] = array(); return $result; @@ -219,6 +220,8 @@ class mod_workshop_external extends external_api { 'Is the user allowed to create/edit his assessments?'), 'assessingexamplesallowed' => new external_value(PARAM_BOOL, 'Are reviewers allowed to create/edit their assessments of the example submissions?.'), + 'examplesassessed' => new external_value(PARAM_BOOL, + 'Whether the given user has assessed all his required examples (always true if there are no examples to assess).'), 'warnings' => new external_warnings() ); @@ -419,4 +422,112 @@ class mod_workshop_external extends external_api { ) ); } + + /** + * Returns the description of the external function parameters. + * + * @return external_function_parameters + * @since Moodle 3.4 + */ + public static function add_submission_parameters() { + return new external_function_parameters(array( + 'workshopid' => new external_value(PARAM_INT, 'Workshop id'), + 'title' => new external_value(PARAM_TEXT, 'Submission title'), + 'content' => new external_value(PARAM_RAW, 'Submission text content', VALUE_DEFAULT, ''), + 'contentformat' => new external_value(PARAM_INT, 'The format used for the content', VALUE_DEFAULT, FORMAT_MOODLE), + 'inlineattachmentsid' => new external_value(PARAM_INT, 'The draft file area id for inline attachments in the content', + VALUE_DEFAULT, 0), + 'attachmentsid' => new external_value(PARAM_INT, 'The draft file area id for attachments', VALUE_DEFAULT, 0), + )); + } + + /** + * Add a new submission to a given workshop. + * + * @param int $workshopid the workshop id + * @param string $title the submission title + * @param string $content the submission text content + * @param int $contentformat the format used for the content + * @param int $inlineattachmentsid the draft file area id for inline attachments in the content + * @param int $attachmentsid the draft file area id for attachments + * @return array Containing the new created submission id and warnings. + * @since Moodle 3.4 + * @throws moodle_exception + */ + public static function add_submission($workshopid, $title, $content = '', $contentformat = FORMAT_MOODLE, + $inlineattachmentsid = 0, $attachmentsid = 0) { + global $USER; + + $params = self::validate_parameters(self::add_submission_parameters(), array( + 'workshopid' => $workshopid, + 'title' => $title, + 'content' => $content, + 'contentformat' => $contentformat, + 'inlineattachmentsid' => $inlineattachmentsid, + 'attachmentsid' => $attachmentsid, + )); + $warnings = array(); + + // Get and validate the workshop. + list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']); + require_capability('mod/workshop:submit', $context); + + // Check if we can submit now. + $canaddsubmission = $workshop->creating_submission_allowed($USER->id); + $canaddsubmission = $canaddsubmission && $workshop->check_examples_assessed($USER->id); + if (!$canaddsubmission) { + throw new moodle_exception('nopermissions', 'error', '', 'add submission'); + } + + // Prepare the submission object. + $submission = new stdClass; + $submission->id = null; + $submission->cmid = $cm->id; + $submission->example = 0; + $submission->title = trim($params['title']); + $submission->content_editor = array( + 'text' => $params['content'], + 'format' => $params['contentformat'], + 'itemid' => $params['inlineattachmentsid'], + ); + $submission->attachment_filemanager = $params['attachmentsid']; + + if (empty($submission->title)) { + throw new moodle_exception('errorinvalidparam', 'webservice', '', 'title'); + } + + $errors = $workshop->validate_submission_data((array) $submission); + // We can get several errors, return them in warnings. + if (!empty($errors)) { + $submission->id = 0; + foreach ($errors as $itemname => $message) { + $warnings[] = array( + 'item' => $itemname, + 'itemid' => 0, + 'warningcode' => 'fielderror', + 'message' => s($message) + ); + } + } else { + $submission->id = $workshop->edit_submission($submission); + } + + return array( + 'submissionid' => $submission->id, + 'warnings' => $warnings + ); + } + + /** + * Returns the description of the external function return value. + * + * @return external_description + * @since Moodle 3.4 + */ + public static function add_submission_returns() { + return new external_single_structure(array( + 'submissionid' => new external_value(PARAM_INT, 'New workshop submission id (0 if it wasn\'t created).'), + 'warnings' => new external_warnings() + )); + } } diff --git a/mod/workshop/db/services.php b/mod/workshop/db/services.php index 8e362d8a77b..5a19f664288 100644 --- a/mod/workshop/db/services.php +++ b/mod/workshop/db/services.php @@ -61,4 +61,12 @@ $functions = array( 'capabilities' => 'mod/workshop:view', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_workshop_add_submission' => array( + 'classname' => 'mod_workshop_external', + 'methodname' => 'add_submission', + 'description' => 'Add a new submission to a given workshop.', + 'type' => 'write', + 'capabilities' => 'mod/workshop:submit', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/workshop/tests/external_test.php b/mod/workshop/tests/external_test.php index c6974b8be77..d97e7832a11 100644 --- a/mod/workshop/tests/external_test.php +++ b/mod/workshop/tests/external_test.php @@ -228,6 +228,7 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->assertFalse($result['modifyingsubmissionallowed']); $this->assertFalse($result['assessingallowed']); $this->assertFalse($result['assessingexamplesallowed']); + $this->assertTrue($result['examplesassessed']); // Switch phase. $workshop = new workshop($this->workshop, $this->cm, $this->course); @@ -239,6 +240,7 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->assertTrue($result['modifyingsubmissionallowed']); $this->assertFalse($result['assessingallowed']); $this->assertFalse($result['assessingexamplesallowed']); + $this->assertTrue($result['examplesassessed']); // Switch to next (to assessment). $workshop = new workshop($this->workshop, $this->cm, $this->course); @@ -250,6 +252,7 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->assertFalse($result['modifyingsubmissionallowed']); $this->assertTrue($result['assessingallowed']); $this->assertFalse($result['assessingexamplesallowed']); + $this->assertTrue($result['examplesassessed']); } /** @@ -412,4 +415,123 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->expectException('moodle_exception'); mod_workshop_external::view_workshop($this->workshop->id); } + + /** + * Test test_add_submission. + */ + public function test_add_submission() { + $fs = get_file_storage(); + + // Test user with full capabilities. + $this->setUser($this->student); + + $title = 'Submission title'; + $content = 'Submission contents'; + + // Create a file in a draft area for inline attachments. + $draftidinlineattach = file_get_unused_draft_itemid(); + $usercontext = context_user::instance($this->student->id); + $filenameimg = 'shouldbeanimage.txt'; + $filerecordinline = array( + 'contextid' => $usercontext->id, + 'component' => 'user', + 'filearea' => 'draft', + 'itemid' => $draftidinlineattach, + 'filepath' => '/', + 'filename' => $filenameimg, + ); + $fs->create_file_from_string($filerecordinline, 'image contents (not really)'); + + // Create a file in a draft area for regular attachments. + $draftidattach = file_get_unused_draft_itemid(); + $filerecordattach = $filerecordinline; + $attachfilename = 'attachment.txt'; + $filerecordattach['filename'] = $attachfilename; + $filerecordattach['itemid'] = $draftidattach; + $fs->create_file_from_string($filerecordattach, 'simple text attachment'); + + // Switch to submission phase. + $workshop = new workshop($this->workshop, $this->cm, $this->course); + $workshop->switch_phase(workshop::PHASE_SUBMISSION); + + $result = mod_workshop_external::add_submission($this->workshop->id, $title, $content, FORMAT_MOODLE, $draftidinlineattach, + $draftidattach); + $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); + $this->assertEmpty($result['warnings']); + + // Check submission created. + $submission = $workshop->get_submission_by_author($this->student->id); + $this->assertEquals($result['submissionid'], $submission->id); + $this->assertEquals($title, $submission->title); + $this->assertEquals($content, $submission->content); + + // Check files. + $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_content', $submission->id); + $this->assertCount(2, $contentfiles); + foreach ($contentfiles as $file) { + if ($file->is_directory()) { + continue; + } else { + $this->assertEquals($filenameimg, $file->get_filename()); + } + } + $contentfiles = $fs->get_area_files($this->context->id, 'mod_workshop', 'submission_attachment', $submission->id); + $this->assertCount(2, $contentfiles); + foreach ($contentfiles as $file) { + if ($file->is_directory()) { + continue; + } else { + $this->assertEquals($attachfilename, $file->get_filename()); + } + } + } + + /** + * Test test_add_submission invalid phase. + */ + public function test_add_submission_invalid_phase() { + $this->setUser($this->student); + + $this->expectException('moodle_exception'); + mod_workshop_external::add_submission($this->workshop->id, 'Test'); + } + + /** + * Test test_add_submission empty title. + */ + public function test_add_submission_empty_title() { + $this->setUser($this->student); + + // Switch to submission phase. + $workshop = new workshop($this->workshop, $this->cm, $this->course); + $workshop->switch_phase(workshop::PHASE_SUBMISSION); + + $this->expectException('moodle_exception'); + mod_workshop_external::add_submission($this->workshop->id, ''); + } + + /** + * Test test_add_submission already added. + */ + public function test_add_submission_already_added() { + $this->setUser($this->student); + + // Switch to submission phase. + $workshop = new workshop($this->workshop, $this->cm, $this->course); + $workshop->switch_phase(workshop::PHASE_SUBMISSION); + + // Create the submission. + $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission'); + $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); + + // Try to create it again. + $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission'); + $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); + $this->assertEquals(0, $result['submissionid']); + $this->assertCount(2, $result['warnings']); + $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']); + $this->assertEquals('content_editor', $result['warnings'][0]['item']); + $this->assertEquals('fielderror', $result['warnings'][1]['warningcode']); + $this->assertEquals('attachment_filemanager', $result['warnings'][1]['item']); + } } diff --git a/mod/workshop/version.php b/mod/workshop/version.php index fadef548fc9..5788945b0c8 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017051504; // The current module version (YYYYMMDDXX) +$plugin->version = 2017051505; // The current module version (YYYYMMDDXX) $plugin->requires = 2017050500; // Requires this Moodle version. $plugin->component = 'mod_workshop'; $plugin->cron = 60; // Give as a chance every minute.