Differences Between: [Versions 400 and 403] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_course\external; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 use context_user; 22 use core_calendar_external; 23 use core_course_external; 24 use core_external\external_api; 25 use core_external\external_function_parameters; 26 use core_external\external_multiple_structure; 27 use core_external\external_single_structure; 28 use core_external\external_value; 29 30 require_once("{$CFG->dirroot}/calendar/externallib.php"); 31 require_once("{$CFG->dirroot}/course/externallib.php"); 32 33 /** 34 * Class for fetching courses which have action event(s) and match given filter parameters. 35 * 36 * @package core_course 37 * @copyright 2022 Michael Hawkins <michaelh@moodle.com> 38 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 39 */ 40 class get_enrolled_courses_with_action_events_by_timeline_classification extends external_api { 41 42 /** 43 * Returns the description of method parameters. 44 * 45 * @return external_function_parameters 46 */ 47 public static function execute_parameters(): external_function_parameters { 48 return new external_function_parameters( 49 [ 50 'classification' => new external_value(PARAM_ALPHA, 'future, inprogress, or past'), 51 'limit' => new external_value(PARAM_INT, 'Result set limit', VALUE_DEFAULT, 0), 52 'offset' => new external_value(PARAM_INT, 'Result set offset', VALUE_DEFAULT, 0), 53 'sort' => new external_value(PARAM_TEXT, 'Sort string', VALUE_DEFAULT, null), 54 'customfieldname' => new external_value(PARAM_ALPHANUMEXT, 'Used when classification = customfield', 55 VALUE_DEFAULT, null), 56 'customfieldvalue' => new external_value(PARAM_RAW, 'Used when classification = customfield', 57 VALUE_DEFAULT, null), 58 'searchvalue' => new external_value(PARAM_RAW, 'The value a user wishes to search against', 59 VALUE_DEFAULT, null), 60 'eventsfrom' => new external_value(PARAM_INT, 'Optional starting timestamp for action events', 61 VALUE_DEFAULT, null), 62 'eventsto' => new external_value(PARAM_INT, 'Optional ending timestamp for action events', 63 VALUE_DEFAULT, null), 64 ] 65 ); 66 } 67 68 /** 69 * Get courses matching the given timeline classification which have action event(s). 70 * 71 * Fetches courses by timeline classification which have at least one action event within the specified filtering. 72 * 73 * @param string $classification past, inprogress, or future 74 * @param int $limit Number of courses with events to attempt to fetch 75 * @param int $offset Offset the full course set before timeline classification is applied 76 * @param string $sort SQL sort string for results 77 * @param string $customfieldname Custom field name used when when classification is customfield 78 * @param string $customfieldvalue Custom field value used when when classification is customfield 79 * @param string $searchvalue Text search being applied 80 * @param int $eventsfrom The start timestamp (inclusive) to search from for action events in the course 81 * @param int $eventsto The end timestamp (inclusive) to search to for action events in the course 82 * @return array list of courses and any warnings 83 */ 84 public static function execute( 85 string $classification, 86 int $limit = 0, 87 int $offset = 0, 88 string $sort = null, 89 string $customfieldname = null, 90 string $customfieldvalue = null, 91 string $searchvalue = null, 92 int $eventsfrom = null, 93 int $eventsto = null 94 ): array { 95 global $USER; 96 97 self::validate_context(context_user::instance($USER->id)); 98 99 $params = self::validate_parameters( 100 self::execute_parameters(), 101 [ 102 'classification' => $classification, 103 'limit' => $limit, 104 'offset' => $offset, 105 'sort' => $sort, 106 'customfieldname' => $customfieldname, 107 'customfieldvalue' => $customfieldvalue, 108 'searchvalue' => $searchvalue, 109 'eventsfrom' => $eventsfrom, 110 'eventsto' => $eventsto, 111 ] 112 ); 113 114 $classification = $params['classification']; 115 $limit = $params['limit']; 116 $offset = $params['offset']; 117 $sort = $params['sort']; 118 $customfieldname = $params['customfieldname']; 119 $customfieldvalue = $params['customfieldvalue']; 120 $searchvalue = clean_param($params['searchvalue'], PARAM_TEXT); 121 $eventsfrom = $params['eventsfrom']; 122 $eventsto = $params['eventsto']; 123 $morecoursestofetch = true; 124 $morecoursespossible = true; 125 $coursesfinal = []; 126 127 do { 128 // Fetch courses. 129 [ 130 'courses' => $coursesfetched, 131 'nextoffset' => $offset, 132 ] = core_course_external::get_enrolled_courses_by_timeline_classification($classification, $limit, 133 $offset, $sort, $customfieldname, $customfieldvalue, $searchvalue); 134 135 $courseids = array_column($coursesfetched, 'id'); 136 $coursesfetched = array_combine($courseids, $coursesfetched); 137 138 if (!empty($courseids)) { 139 // Need to check this to know how many are expected (since it is possible for this to be less than the limit). 140 $numcoursesfetched = count($courseids); 141 $numfetchedwithevents = 0; 142 143 // If less courses are fetched than we requested, we know it is not possible for more courses to be available. 144 if ($numcoursesfetched < $limit) { 145 $morecoursestofetch = false; 146 $morecoursespossible = false; 147 } 148 149 // Try to fetch one action event within the time/search parameters for each course. 150 $events = core_calendar_external::get_calendar_action_events_by_courses($courseids, $eventsfrom, $eventsto, 1, 151 $searchvalue); 152 153 foreach ($events->groupedbycourse as $courseevents) { 154 $courseid = $courseevents->courseid; 155 156 // Only include courses which contain at least one event. 157 if (empty($courseevents->events)) { 158 unset($coursesfetched[$courseid]); 159 } else { 160 $numfetchedwithevents++; 161 } 162 } 163 164 // Add courses with events to the final course list in order. 165 $coursesfinal = array_merge($coursesfinal, $coursesfetched); 166 167 // If any courses did not have events, adjust the limit so we can attempt to fetch as many as are still required. 168 if ($numfetchedwithevents < $numcoursesfetched) { 169 $limit -= $numfetchedwithevents; 170 } else { 171 // If we have found as many courses as required or are available, no need to attempt fetching more. 172 $morecoursestofetch = false; 173 } 174 } else { 175 $morecoursestofetch = false; 176 $morecoursespossible = false; 177 } 178 179 } while ($morecoursestofetch); 180 181 static $isrecursivecall = false; 182 $morecoursesavailable = false; 183 184 // Recursively call this method to check if at least one more course is available if we know that is a possibility. 185 if (!$isrecursivecall && $morecoursespossible) { 186 // Prevent infinite recursion. 187 $isrecursivecall = true; 188 189 $additionalcourses = self::execute( 190 $classification, 1, $offset, $sort, $customfieldname, $customfieldvalue, $searchvalue, $eventsfrom, $eventsto 191 ); 192 193 if (!empty($additionalcourses['courses'])) { 194 $morecoursesavailable = true; 195 } 196 } 197 198 return [ 199 'courses' => $coursesfinal, 200 'nextoffset' => $offset, 201 'morecoursesavailable' => $morecoursesavailable, 202 ]; 203 } 204 205 /** 206 * Returns description of method result value. 207 * 208 * @return \core_external\external_description 209 */ 210 public static function execute_returns(): external_single_structure { 211 return new external_single_structure( 212 [ 213 'courses' => new external_multiple_structure(course_summary_exporter::get_read_structure(), 'Course'), 214 'nextoffset' => new external_value(PARAM_INT, 'Offset for the next request'), 215 'morecoursesavailable' => new external_value(PARAM_BOOL, 216 'Whether more courses with events exist within the provided parameters'), 217 ] 218 ); 219 } 220 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body