From 75516809d28ca13fb0eba3c45fb3e1b60ee2312f Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Thu, 1 Oct 2015 12:21:50 +0200 Subject: [PATCH] MDL-51629 mod_survey: New Web Service mod_survey_view_survey --- lib/db/services.php | 1 + mod/survey/classes/external.php | 65 +++++++++++++++++++ mod/survey/db/services.php | 10 ++- mod/survey/lib.php | 31 +++++++++ mod/survey/tests/externallib_test.php | 60 +++++++++++++++++ mod/survey/tests/lib_test.php | 92 +++++++++++++++++++++++++++ mod/survey/view.php | 36 +++-------- 7 files changed, 268 insertions(+), 27 deletions(-) create mode 100644 mod/survey/tests/lib_test.php diff --git a/lib/db/services.php b/lib/db/services.php index 490340134b4..f97f521db77 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1232,6 +1232,7 @@ $services = array( 'mod_scorm_get_scorm_attempt_count', 'mod_scorm_get_scorms_by_courses', 'mod_survey_get_surveys_by_courses', + 'mod_survey_view_survey', 'mod_page_view_page', 'mod_resource_view_resource', 'mod_folder_view_folder', diff --git a/mod/survey/classes/external.php b/mod/survey/classes/external.php index d7f4547c68e..1c9e3e31942 100644 --- a/mod/survey/classes/external.php +++ b/mod/survey/classes/external.php @@ -164,4 +164,69 @@ class mod_survey_external extends external_api { ); } + /** + * Returns description of method parameters + * + * @return external_function_parameters + * @since Moodle 3.0 + */ + public static function view_survey_parameters() { + return new external_function_parameters( + array( + 'surveyid' => new external_value(PARAM_INT, 'survey instance id') + ) + ); + } + + /** + * Trigger the course module viewed event and update the module completion status. + * + * @param int $surveyid the survey instance id + * @return array of warnings and status result + * @since Moodle 3.0 + * @throws moodle_exception + */ + public static function view_survey($surveyid) { + global $DB, $USER; + + $params = self::validate_parameters(self::view_survey_parameters(), + array( + 'surveyid' => $surveyid + )); + $warnings = array(); + + // Request and permission validation. + $survey = $DB->get_record('survey', array('id' => $params['surveyid']), '*', MUST_EXIST); + list($course, $cm) = get_course_and_cm_from_instance($survey, 'survey'); + + $context = context_module::instance($cm->id); + self::validate_context($context); + require_capability('mod/survey:participate', $context); + + $viewed = survey_already_done($survey->id, $USER->id) ? 'graph' : 'form'; + + // Trigger course_module_viewed event and completion. + survey_view($survey, $course, $cm, $context, $viewed); + + $result = array(); + $result['status'] = true; + $result['warnings'] = $warnings; + return $result; + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 3.0 + */ + public static function view_survey_returns() { + return new external_single_structure( + array( + 'status' => new external_value(PARAM_BOOL, 'status: true if success'), + 'warnings' => new external_warnings() + ) + ); + } + } diff --git a/mod/survey/db/services.php b/mod/survey/db/services.php index 4ab9a66e482..6e95ea8cdfd 100644 --- a/mod/survey/db/services.php +++ b/mod/survey/db/services.php @@ -35,5 +35,13 @@ $functions = array( if no courses are provided then all the survey instances the user has access to will be returned.', 'type' => 'read', 'capabilities' => '' - ) + ), + + 'mod_survey_view_survey' => array( + 'classname' => 'mod_survey_external', + 'methodname' => 'view_survey', + 'description' => 'Trigger the course module viewed event and update the module completion status.', + 'type' => 'write', + 'capabilities' => 'mod/survey:participate' + ), ); diff --git a/mod/survey/lib.php b/mod/survey/lib.php index 9ebae563dcc..b21402187b6 100644 --- a/mod/survey/lib.php +++ b/mod/survey/lib.php @@ -838,3 +838,34 @@ function survey_page_type_list($pagetype, $parentcontext, $currentcontext) { $module_pagetype = array('mod-survey-*'=>get_string('page-mod-survey-x', 'survey')); return $module_pagetype; } + +/** + * Mark the activity completed (if required) and trigger the course_module_viewed event. + * + * @param stdClass $survey survey object + * @param stdClass $course course object + * @param stdClass $cm course module object + * @param stdClass $context context object + * @param string $viewed which page viewed + * @since Moodle 3.0 + */ +function survey_view($survey, $course, $cm, $context, $viewed) { + + // Trigger course_module_viewed event. + $params = array( + 'context' => $context, + 'objectid' => $survey->id, + 'courseid' => $course->id, + 'other' => array('viewed' => $viewed) + ); + + $event = \mod_survey\event\course_module_viewed::create($params); + $event->add_record_snapshot('course_modules', $cm); + $event->add_record_snapshot('course', $course); + $event->add_record_snapshot('survey', $survey); + $event->trigger(); + + // Completion. + $completion = new completion_info($course); + $completion->set_module_viewed($cm); +} diff --git a/mod/survey/tests/externallib_test.php b/mod/survey/tests/externallib_test.php index 884ef452649..cdf16856d82 100644 --- a/mod/survey/tests/externallib_test.php +++ b/mod/survey/tests/externallib_test.php @@ -191,4 +191,64 @@ class mod_survey_external_testcase extends externallib_advanced_testcase { $this->assertFalse(isset($surveys['surveys'][0]['intro'])); } + /** + * Test view_survey + */ + public function test_view_survey() { + global $DB; + + // Test invalid instance id. + try { + mod_survey_external::view_survey(0); + $this->fail('Exception expected due to invalid mod_survey instance id.'); + } catch (moodle_exception $e) { + $this->assertEquals('invalidrecord', $e->errorcode); + } + + // Test not-enrolled user. + $usernotenrolled = self::getDataGenerator()->create_user(); + $this->setUser($usernotenrolled); + try { + mod_survey_external::view_survey($this->survey->id); + $this->fail('Exception expected due to not enrolled user.'); + } catch (moodle_exception $e) { + $this->assertEquals('requireloginerror', $e->errorcode); + } + + // Test user with full capabilities. + $this->setUser($this->student); + + // Trigger and capture the event. + $sink = $this->redirectEvents(); + + $result = mod_survey_external::view_survey($this->survey->id); + $result = external_api::clean_returnvalue(mod_survey_external::view_survey_returns(), $result); + $this->assertTrue($result['status']); + + $events = $sink->get_events(); + $this->assertCount(1, $events); + $event = array_shift($events); + + // Checking that the event contains the expected values. + $this->assertInstanceOf('\mod_survey\event\course_module_viewed', $event); + $this->assertEquals($this->context, $event->get_context()); + $moodlesurvey = new \moodle_url('/mod/survey/view.php', array('id' => $this->cm->id)); + $this->assertEquals($moodlesurvey, $event->get_url()); + $this->assertEventContextNotUsed($event); + $this->assertNotEmpty($event->get_name()); + + // Test user with no capabilities. + // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. + assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); + accesslib_clear_all_caches_for_unit_testing(); + + try { + mod_survey_external::view_survey($this->survey->id); + $this->fail('Exception expected due to missing capability.'); + } catch (moodle_exception $e) { + $this->assertEquals('nopermissions', $e->errorcode); + } + + } + } diff --git a/mod/survey/tests/lib_test.php b/mod/survey/tests/lib_test.php new file mode 100644 index 00000000000..3c6fd4c5466 --- /dev/null +++ b/mod/survey/tests/lib_test.php @@ -0,0 +1,92 @@ +. + +/** + * Unit tests for mod_survey lib + * + * @package mod_survey + * @category external + * @copyright 2015 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.0 + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Unit tests for mod_survey lib + * + * @package mod_survey + * @category external + * @copyright 2015 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.0 + */ +class mod_survey_lib_testcase extends advanced_testcase { + + /** + * Prepares things before this test case is initialised + * @return void + */ + public static function setUpBeforeClass() { + global $CFG; + require_once($CFG->dirroot . '/mod/survey/lib.php'); + } + + /** + * Test survey_view + * @return void + */ + public function test_survey_view() { + global $CFG; + + $CFG->enablecompletion = 1; + $this->resetAfterTest(); + + $this->setAdminUser(); + // Setup test data. + $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); + $survey = $this->getDataGenerator()->create_module('survey', array('course' => $course->id), + array('completion' => 2, 'completionview' => 1)); + $context = context_module::instance($survey->cmid); + $cm = get_coursemodule_from_instance('survey', $survey->id); + + // Trigger and capture the event. + $sink = $this->redirectEvents(); + + survey_view($survey, $course, $cm, $context, 'form'); + + $events = $sink->get_events(); + // 2 additional events thanks to completion. + $this->assertCount(3, $events); + $event = array_shift($events); + + // Checking that the event contains the expected values. + $this->assertInstanceOf('\mod_survey\event\course_module_viewed', $event); + $this->assertEquals($context, $event->get_context()); + $moodleurl = new \moodle_url('/mod/survey/view.php', array('id' => $cm->id)); + $this->assertEquals($moodleurl, $event->get_url()); + $this->assertEquals('form', $event->other['viewed']); + $this->assertEventContextNotUsed($event); + $this->assertNotEmpty($event->get_name()); + // Check completion status. + $completion = new completion_info($course); + $completiondata = $completion->get_data($cm); + $this->assertEquals(1, $completiondata->completionstate); + + } +} diff --git a/mod/survey/view.php b/mod/survey/view.php index dabc1b6f474..991dc1a079f 100644 --- a/mod/survey/view.php +++ b/mod/survey/view.php @@ -54,13 +54,17 @@ if (! $template = $DB->get_record("survey", array("id" => $survey->template))) { print_error('invalidtmptid', 'survey'); } -// Update 'viewed' state if required by completion system. -require_once($CFG->libdir . '/completionlib.php'); -$completion = new completion_info($course); -$completion->set_module_viewed($cm); - $showscales = ($template->name != 'ciqname'); +// Check the survey hasn't already been filled out. +$surveyalreadydone = survey_already_done($survey->id, $USER->id); +if ($surveyalreadydone) { + // Trigger course_module_viewed event and completion. + survey_view($survey, $course, $cm, $context, 'graph'); +} else { + survey_view($survey, $course, $cm, $context, 'form'); +} + $strsurvey = get_string("modulename", "survey"); $PAGE->set_title($survey->name); $PAGE->set_heading($course->fullname); @@ -91,18 +95,8 @@ if (!is_enrolled($context)) { echo $OUTPUT->notification(get_string("guestsnotallowed", "survey")); } +if ($surveyalreadydone) { -// Check the survey hasn't already been filled out. - -if (survey_already_done($survey->id, $USER->id)) { - $params = array( - 'objectid' => $survey->id, - 'context' => $context, - 'courseid' => $course->id, - 'other' => array('viewed' => 'graph') - ); - $event = \mod_survey\event\course_module_viewed::create($params); - $event->trigger(); $numusers = survey_count_responses($survey->id, $currentgroup, $groupingid); if ($showscales) { @@ -146,16 +140,6 @@ if (survey_already_done($survey->id, $USER->id)) { exit; } -// Start the survey form. -$params = array( - 'objectid' => $survey->id, - 'context' => $context, - 'courseid' => $course->id, - 'other' => array('viewed' => 'form') -); -$event = \mod_survey\event\course_module_viewed::create($params); -$event->trigger(); - echo "
"; echo '
'; echo "";