From 82b2cd7d19b5edc6bc2fc0390e159cf2ef07546d Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Fri, 3 Feb 2017 16:31:41 +0100 Subject: [PATCH] MDL-57820 mod_feedback: New WS mod_feedback_get_analysis --- mod/feedback/classes/external.php | 127 +++++++++++++++++++++++++++ mod/feedback/db/services.php | 8 ++ mod/feedback/tests/external_test.php | 59 +++++++++++++ mod/feedback/version.php | 2 +- 4 files changed, 195 insertions(+), 1 deletion(-) diff --git a/mod/feedback/classes/external.php b/mod/feedback/classes/external.php index 19d686a5c6a..c3fa0c43810 100644 --- a/mod/feedback/classes/external.php +++ b/mod/feedback/classes/external.php @@ -704,4 +704,131 @@ class mod_feedback_external extends external_api { ) ); } + + /** + * Describes the parameters for get_analysis. + * + * @return external_function_parameters + * @since Moodle 3.3 + */ + public static function get_analysis_parameters() { + return new external_function_parameters ( + array( + 'feedbackid' => new external_value(PARAM_INT, 'Feedback instance id'), + 'groupid' => new external_value(PARAM_INT, 'Group id, 0 means that the function will determine the user group', + VALUE_DEFAULT, 0), + ) + ); + } + + /** + * Retrieves the feedback analysis. + * + * @param array $feedbackid feedback instance id + * @return array of warnings and launch information + * @since Moodle 3.3 + */ + public static function get_analysis($feedbackid, $groupid = 0) { + global $PAGE; + + $params = array('feedbackid' => $feedbackid, 'groupid' => $groupid); + $params = self::validate_parameters(self::get_analysis_parameters(), $params); + $warnings = $itemsdata = array(); + + list($feedback, $course, $cm, $context) = self::validate_feedback($params['feedbackid']); + + // Check permissions. + $feedbackstructure = new mod_feedback_structure($feedback, $cm); + if (!$feedbackstructure->can_view_analysis()) { + throw new required_capability_exception($context, 'mod/feedback:viewanalysepage', 'nopermission', ''); + } + + if (!empty($params['groupid'])) { + $groupid = $params['groupid']; + // Determine is the group is visible to user. + if (!groups_group_visible($groupid, $course, $cm)) { + throw new moodle_exception('notingroup'); + } + } else { + // Check to see if groups are being used here. + if ($groupmode = groups_get_activity_groupmode($cm)) { + $groupid = groups_get_activity_group($cm); + // Determine is the group is visible to user (this is particullary for the group 0 -> all groups). + if (!groups_group_visible($groupid, $course, $cm)) { + throw new moodle_exception('notingroup'); + } + } else { + $groupid = 0; + } + } + + // Summary data. + $summary = new mod_feedback\output\summary($feedbackstructure, $groupid); + $summarydata = $summary->export_for_template($PAGE->get_renderer('core')); + + $checkanonymously = true; + if ($groupid > 0 AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES) { + $completedcount = $feedbackstructure->count_completed_responses($groupid); + if ($completedcount < FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP) { + $checkanonymously = false; + } + } + + if ($checkanonymously) { + // Get the items of the feedback. + $items = $feedbackstructure->get_items(true); + foreach ($items as $item) { + $itemobj = feedback_get_item_class($item->typ); + $itemnumber = empty($item->itemnr) ? null : $item->itemnr; + unset($item->itemnr); // Added by the function, not part of the record. + $exporter = new feedback_item_exporter($item, array('context' => $context, 'itemnumber' => $itemnumber)); + + $itemsdata[] = array( + 'item' => $exporter->export($PAGE->get_renderer('core')), + 'data' => $itemobj->get_analysed_for_external($item, $groupid), + ); + } + } else { + $warnings[] = array( + 'item' => 'feedback', + 'itemid' => $feedback->id, + 'warningcode' => 'insufficientresponsesforthisgroup', + 'message' => s(get_string('insufficient_responses_for_this_group', 'feedback')) + ); + } + + $result = array( + 'completedcount' => $summarydata->completedcount, + 'itemscount' => $summarydata->itemscount, + 'itemsdata' => $itemsdata, + 'warnings' => $warnings + ); + return $result; + } + + /** + * Describes the get_analysis return value. + * + * @return external_single_structure + * @since Moodle 3.3 + */ + public static function get_analysis_returns() { + return new external_single_structure( + array( + 'completedcount' => new external_value(PARAM_INT, 'Number of completed submissions.'), + 'itemscount' => new external_value(PARAM_INT, 'Number of items (questions).'), + 'itemsdata' => new external_multiple_structure( + new external_single_structure( + array( + 'item' => feedback_item_exporter::get_read_structure(), + 'data' => new external_multiple_structure( + new external_value(PARAM_RAW, 'The analysis data (can be json encoded)') + ), + ) + ) + ), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/mod/feedback/db/services.php b/mod/feedback/db/services.php index bcfbdd82cac..8665261084c 100644 --- a/mod/feedback/db/services.php +++ b/mod/feedback/db/services.php @@ -93,4 +93,12 @@ $functions = array( 'capabilities' => 'mod/feedback:complete', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_feedback_get_analysis' => array( + 'classname' => 'mod_feedback_external', + 'methodname' => 'get_analysis', + 'description' => 'Retrieves the feedback analysis.', + 'type' => 'read', + 'capabilities' => 'mod/feedback:viewanalysepage', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/feedback/tests/external_test.php b/mod/feedback/tests/external_test.php index d095243ee8b..837d38505c9 100644 --- a/mod/feedback/tests/external_test.php +++ b/mod/feedback/tests/external_test.php @@ -531,4 +531,63 @@ class mod_feedback_external_testcase extends externallib_advanced_testcase { $itemsaved = $DB->get_field('feedback_value', 'value', array('item' => $itemid)); $this->assertEquals('b', $itemsaved); } + + /** + * Test get_analysis. + */ + public function test_get_analysis() { + // Test user with full capabilities. + $this->setUser($this->student); + + // Create a very simple feedback. + $feedbackgenerator = $this->getDataGenerator()->get_plugin_generator('mod_feedback'); + $numericitem = $feedbackgenerator->create_item_numeric($this->feedback); + $textfielditem = $feedbackgenerator->create_item_textfield($this->feedback); + + $pagedata = [ + ['name' => $numericitem->typ .'_'. $numericitem->id, 'value' => 5], + ['name' => $textfielditem->typ .'_'. $textfielditem->id, 'value' => 'abc'], + ]; + // Process the feedback, there is only one page so the feedback will be completed. + $result = mod_feedback_external::process_page($this->feedback->id, 0, $pagedata); + $result = external_api::clean_returnvalue(mod_feedback_external::process_page_returns(), $result); + $this->assertTrue($result['completed']); + + // Retrieve analysis. + $this->setUser($this->teacher); + $result = mod_feedback_external::get_analysis($this->feedback->id); + $result = external_api::clean_returnvalue(mod_feedback_external::get_analysis_returns(), $result); + $this->assertEquals(1, $result['completedcount']); // 1 feedback completed. + $this->assertEquals(2, $result['itemscount']); // 2 items in the feedback. + $this->assertCount(2, $result['itemsdata']); + $this->assertCount(1, $result['itemsdata'][0]['data']); // There are 1 response per item. + $this->assertCount(1, $result['itemsdata'][1]['data']); + // Check we receive the info the students filled. + foreach ($result['itemsdata'] as $data) { + if ($data['item']['id'] == $numericitem->id) { + $this->assertEquals(5, $data['data'][0]); + } else { + $this->assertEquals('abc', $data['data'][0]); + } + } + + // Create another user / response. + $anotherstudent = self::getDataGenerator()->create_user(); + $this->getDataGenerator()->enrol_user($anotherstudent->id, $this->course->id, $this->studentrole->id, 'manual'); + $this->setUser($anotherstudent); + + // Process the feedback, there is only one page so the feedback will be completed. + $result = mod_feedback_external::process_page($this->feedback->id, 0, $pagedata); + $result = external_api::clean_returnvalue(mod_feedback_external::process_page_returns(), $result); + $this->assertTrue($result['completed']); + + // Retrieve analysis. + $this->setUser($this->teacher); + $result = mod_feedback_external::get_analysis($this->feedback->id); + $result = external_api::clean_returnvalue(mod_feedback_external::get_analysis_returns(), $result); + $this->assertEquals(2, $result['completedcount']); // 2 feedback completed. + $this->assertEquals(2, $result['itemscount']); + $this->assertCount(2, $result['itemsdata'][0]['data']); // There are 2 responses per item. + $this->assertCount(2, $result['itemsdata'][1]['data']); + } } diff --git a/mod/feedback/version.php b/mod/feedback/version.php index 9ef23d3d329..6a9250fdffc 100644 --- a/mod/feedback/version.php +++ b/mod/feedback/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016120508; // The current module version (Date: YYYYMMDDXX) +$plugin->version = 2016120509; // The current module version (Date: YYYYMMDDXX) $plugin->requires = 2016112900; // Requires this Moodle version $plugin->component = 'mod_feedback'; // Full name of the plugin (used for diagnostics) $plugin->cron = 0;