MDL-59268 mod_workshop: New WS mod_workshop_get_user_plan
authorJuan Leyva <juanleyvadelgado@gmail.com>
Fri, 16 Jun 2017 10:24:41 +0000 (11:24 +0100)
committerJuan Leyva <juanleyvadelgado@gmail.com>
Mon, 24 Jul 2017 16:02:21 +0000 (18:02 +0200)
mod/workshop/classes/external.php
mod/workshop/db/services.php
mod/workshop/tests/external_test.php
mod/workshop/version.php

index 52fe32a..788fb37 100644 (file)
@@ -231,4 +231,138 @@ class mod_workshop_external extends external_api {
 
         return new external_single_structure($structure);
     }
+
+    /**
+     * Describes the parameters for get_user_plan.
+     *
+     * @return external_external_function_parameters
+     * @since Moodle 3.4
+     */
+    public static function get_user_plan_parameters() {
+        return new external_function_parameters (
+            array(
+                'workshopid' => new external_value(PARAM_INT, 'Workshop instance id.'),
+                'userid' => new external_value(PARAM_INT, 'User id (empty or 0 for current user).', VALUE_DEFAULT, 0),
+            )
+        );
+    }
+
+    /**
+     * Return the planner information for the given user.
+     *
+     * @param int $workshopid workshop instance id
+     * @param int $userid user id
+     * @return array of warnings and the user plan
+     * @since Moodle 3.4
+     * @throws  moodle_exception
+     */
+    public static function get_user_plan($workshopid, $userid = 0) {
+        global $USER;
+
+        $params = array(
+            'workshopid' => $workshopid,
+            'userid' => $userid,
+        );
+        $params = self::validate_parameters(self::get_user_plan_parameters(), $params);
+
+        list($workshop, $course, $cm, $context) = self::validate_workshop($params['workshopid']);
+
+        // Extra checks so only users with permissions can view other users plans.
+        if (empty($params['userid']) || $params['userid'] == $USER->id) {
+            $userid = $USER->id;
+        } else {
+            require_capability('moodle/course:manageactivities', $context);
+            $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
+            core_user::require_active_user($user);
+            if (!$workshop->check_group_membership($user->id)) {
+                throw new moodle_exception('notingroup');
+            }
+            $userid = $user->id;
+        }
+
+        // Get the user plan information ready for external functions.
+        $userplan = new workshop_user_plan($workshop, $userid);
+        $userplan = array('phases' => $userplan->phases, 'examples' => $userplan->get_examples());
+        foreach ($userplan['phases'] as $phasecode => $phase) {
+            $phase->code = $phasecode;
+            $userplan['phases'][$phasecode] = (array) $phase;
+            foreach ($userplan['phases'][$phasecode]['tasks'] as $taskcode => $task) {
+                $task->code = $taskcode;
+                if ($task->link instanceof moodle_url) {
+                    $task->link = $task->link->out(false);
+                }
+                $userplan['phases'][$phasecode]['tasks'][$taskcode] = (array) $task;
+            }
+            foreach ($userplan['phases'][$phasecode]['actions'] as $actioncode => $action) {
+                if ($action->url instanceof moodle_url) {
+                    $action->url = $action->url->out(false);
+                }
+                $userplan['phases'][$phasecode]['actions'][$actioncode] = (array) $action;
+            }
+        }
+
+        $result['userplan'] = $userplan;
+        $result['warnings'] = array();
+        return $result;
+    }
+
+    /**
+     * Describes the get_user_plan return value.
+     *
+     * @return external_single_structure
+     * @since Moodle 3.4
+     */
+    public static function get_user_plan_returns() {
+        return new external_single_structure(
+            array(
+                'userplan' => new external_single_structure(
+                    array(
+                        'phases' => new external_multiple_structure(
+                            new external_single_structure(
+                                array(
+                                    'code' => new external_value(PARAM_INT, 'Phase code.'),
+                                    'title' => new external_value(PARAM_NOTAGS, 'Phase title.'),
+                                    'active' => new external_value(PARAM_BOOL, 'Whether is the active task.'),
+                                    'tasks' => new external_multiple_structure(
+                                        new external_single_structure(
+                                            array(
+                                                'code' => new external_value(PARAM_ALPHA, 'Task code.'),
+                                                'title' => new external_value(PARAM_RAW, 'Task title.'),
+                                                'link' => new external_value(PARAM_URL, 'Link to task.'),
+                                                'details' => new external_value(PARAM_RAW, 'Task details.', VALUE_OPTIONAL),
+                                                'completed' => new external_value(PARAM_NOTAGS,
+                                                    'Completion information (maybe empty, maybe a boolean or generic info.'),
+                                            )
+                                        )
+                                    ),
+                                    'actions' => new external_multiple_structure(
+                                        new external_single_structure(
+                                            array(
+                                                'type' => new external_value(PARAM_ALPHA, 'Action type.', VALUE_OPTIONAL),
+                                                'label' => new external_value(PARAM_RAW, 'Action label.', VALUE_OPTIONAL),
+                                                'url' => new external_value(PARAM_URL, 'Link to action.'),
+                                                'method' => new external_value(PARAM_ALPHA, 'Get or post.', VALUE_OPTIONAL),
+                                            )
+                                        )
+                                    ),
+                                )
+                            )
+                        ),
+                        'examples' => new external_multiple_structure(
+                            new external_single_structure(
+                                array(
+                                    'id' => new external_value(PARAM_INT, 'Example submission id.'),
+                                    'title' => new external_value(PARAM_RAW, 'Example submission title.'),
+                                    'assessmentid' => new external_value(PARAM_INT, 'Example submission assessment id.'),
+                                    'grade' => new external_value(PARAM_FLOAT, 'The submission grade.'),
+                                    'gradinggrade' => new external_value(PARAM_FLOAT, 'The assessment grade.'),
+                                )
+                            )
+                        ),
+                    )
+                ),
+                'warnings' => new external_warnings(),
+            )
+        );
+    }
 }
index 0da25d2..f86b53f 100644 (file)
@@ -45,4 +45,12 @@ $functions = array(
         'capabilities'  => 'mod/workshop:view',
         'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
     ),
+    'mod_workshop_get_user_plan' => array(
+        'classname'     => 'mod_workshop_external',
+        'methodname'    => 'get_user_plan',
+        'description'   => 'Return the planner information for the given user.',
+        'type'          => 'read',
+        'capabilities'  => 'mod/workshop:view',
+        'services'      => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+    ),
 );
index 0156a3e..8d7f407 100644 (file)
@@ -280,4 +280,74 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase {
         $this->assertFalse($result['assessingallowed']);
         $this->assertFalse($result['assessingexamplesallowed']);
     }
+
+    /**
+     * Test mod_workshop_get_user_plan for students.
+     */
+    public function test_mod_workshop_get_user_plan_student() {
+
+        self::setUser($this->student);
+        $result = mod_workshop_external::get_user_plan($this->workshop->id);
+        $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
+
+        $this->assertCount(0, $result['userplan']['examples']);  // No examples given.
+        $this->assertCount(5, $result['userplan']['phases']);  // Always 5 phases.
+        $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']);  // First phase always setup.
+        $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
+
+        // Switch phase.
+        $workshop = new workshop($this->workshop, $this->cm, $this->course);
+        $workshop->switch_phase(workshop::PHASE_SUBMISSION);
+
+        $result = mod_workshop_external::get_user_plan($this->workshop->id);
+        $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
+
+        $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
+        $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
+    }
+
+    /**
+     * Test mod_workshop_get_user_plan for teachers.
+     */
+    public function test_mod_workshop_get_user_plan_teacher() {
+        global $DB;
+
+        self::setUser($this->teacher);
+        $result = mod_workshop_external::get_user_plan($this->workshop->id);
+        $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
+
+        $this->assertCount(0, $result['userplan']['examples']);  // No examples given.
+        $this->assertCount(5, $result['userplan']['phases']);  // Always 5 phases.
+        $this->assertEquals(workshop::PHASE_SETUP, $result['userplan']['phases'][0]['code']);  // First phase always setup.
+        $this->assertTrue($result['userplan']['phases'][0]['active']); // First phase "Setup" active in new workshops.
+        $this->assertCount(4, $result['userplan']['phases'][0]['tasks']);  // For new empty workshops, always 4 tasks.
+
+        foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
+            if ($task['code'] == 'intro' || $task['code'] == 'instructauthors') {
+                $this->assertEquals(1, $task['completed']);
+            } else {
+                $this->assertEmpty($task['completed']);
+            }
+        }
+
+        // Do some of the tasks asked - switch phase.
+        $workshop = new workshop($this->workshop, $this->cm, $this->course);
+        $workshop->switch_phase(workshop::PHASE_SUBMISSION);
+
+        $result = mod_workshop_external::get_user_plan($this->workshop->id);
+        $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
+        foreach ($result['userplan']['phases'][0]['tasks'] as $task) {
+            if ($task['code'] == 'intro' || $task['code'] == 'instructauthors' || $task['code'] == 'switchtonextphase') {
+                $this->assertEquals(1, $task['completed']);
+            } else {
+                $this->assertEmpty($task['completed']);
+            }
+        }
+
+        $result = mod_workshop_external::get_user_plan($this->workshop->id);
+        $result = external_api::clean_returnvalue(mod_workshop_external::get_user_plan_returns(), $result);
+
+        $this->assertEquals(workshop::PHASE_SUBMISSION, $result['userplan']['phases'][1]['code']);
+        $this->assertTrue($result['userplan']['phases'][1]['active']); // We are now in submission phase.
+    }
 }
index 1de474e..68fff48 100644 (file)
@@ -24,7 +24,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version   = 2017051502;        // The current module version (YYYYMMDDXX)
+$plugin->version   = 2017051503;        // 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.