MDL-59243 mod_workshop: New WS mod_workshop_add_submission
authorJuan Leyva <juanleyvadelgado@gmail.com>
Tue, 20 Jun 2017 15:43:57 +0000 (16:43 +0100)
committerJuan Leyva <juanleyvadelgado@gmail.com>
Wed, 6 Sep 2017 12:00:17 +0000 (14:00 +0200)
mod/workshop/classes/external.php
mod/workshop/db/services.php
mod/workshop/tests/external_test.php
mod/workshop/version.php

index 2e5d554..30585b9 100644 (file)
@@ -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()
+        ));
+    }
 }
index 8e362d8..5a19f66 100644 (file)
@@ -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)
+    ),
 );
index c6974b8..d97e783 100644 (file)
@@ -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']);
+    }
 }
index fadef54..5788945 100644 (file)
@@ -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.