external.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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. * Completion external API
  18. *
  19. * @package core_completion
  20. * @category external
  21. * @copyright 2015 Juan Leyva <juan@moodle.com>
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. * @since Moodle 2.9
  24. */
  25. defined('MOODLE_INTERNAL') || die;
  26. require_once("$CFG->libdir/externallib.php");
  27. require_once("$CFG->libdir/completionlib.php");
  28. /**
  29. * Completion external functions
  30. *
  31. * @package core_completion
  32. * @category external
  33. * @copyright 2015 Juan Leyva <juan@moodle.com>
  34. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35. * @since Moodle 2.9
  36. */
  37. class core_completion_external extends external_api {
  38. /**
  39. * Describes the parameters for update_activity_completion_status_manually.
  40. *
  41. * @return external_external_function_parameters
  42. * @since Moodle 2.9
  43. */
  44. public static function update_activity_completion_status_manually_parameters() {
  45. return new external_function_parameters (
  46. array(
  47. 'cmid' => new external_value(PARAM_INT, 'course module id'),
  48. 'completed' => new external_value(PARAM_BOOL, 'activity completed or not'),
  49. )
  50. );
  51. }
  52. /**
  53. * Update completion status for the current user in an activity, only for activities with manual tracking.
  54. * @param int $cmid Course module id
  55. * @param bool $completed Activity completed or not
  56. * @return array Result and possible warnings
  57. * @since Moodle 2.9
  58. * @throws moodle_exception
  59. */
  60. public static function update_activity_completion_status_manually($cmid, $completed) {
  61. // Validate and normalize parameters.
  62. $params = self::validate_parameters(self::update_activity_completion_status_manually_parameters(),
  63. array('cmid' => $cmid, 'completed' => $completed));
  64. $cmid = $params['cmid'];
  65. $completed = $params['completed'];
  66. $warnings = array();
  67. $context = context_module::instance($cmid);
  68. self::validate_context($context);
  69. list($course, $cm) = get_course_and_cm_from_cmid($cmid);
  70. // Set up completion object and check it is enabled.
  71. $completion = new completion_info($course);
  72. if (!$completion->is_enabled()) {
  73. throw new moodle_exception('completionnotenabled', 'completion');
  74. }
  75. // Check completion state is manual.
  76. if ($cm->completion != COMPLETION_TRACKING_MANUAL) {
  77. throw new moodle_exception('cannotmanualctrack', 'error');
  78. }
  79. $targetstate = ($completed) ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE;
  80. $completion->update_state($cm, $targetstate);
  81. $result = array();
  82. $result['status'] = true;
  83. $result['warnings'] = $warnings;
  84. return $result;
  85. }
  86. /**
  87. * Describes the update_activity_completion_status_manually return value.
  88. *
  89. * @return external_single_structure
  90. * @since Moodle 2.9
  91. */
  92. public static function update_activity_completion_status_manually_returns() {
  93. return new external_single_structure(
  94. array(
  95. 'status' => new external_value(PARAM_BOOL, 'status, true if success'),
  96. 'warnings' => new external_warnings(),
  97. )
  98. );
  99. }
  100. /**
  101. * Returns description of method parameters
  102. *
  103. * @return external_function_parameters
  104. * @since Moodle 2.9
  105. */
  106. public static function get_activities_completion_status_parameters() {
  107. return new external_function_parameters(
  108. array(
  109. 'courseid' => new external_value(PARAM_INT, 'Course ID'),
  110. 'userid' => new external_value(PARAM_INT, 'User ID'),
  111. )
  112. );
  113. }
  114. /**
  115. * Get Activities completion status
  116. *
  117. * @param int $courseid ID of the Course
  118. * @param int $userid ID of the User
  119. * @return array of activities progress and warnings
  120. * @throws moodle_exception
  121. * @since Moodle 2.9
  122. * @throws moodle_exception
  123. */
  124. public static function get_activities_completion_status($courseid, $userid) {
  125. global $CFG, $USER;
  126. require_once($CFG->libdir . '/grouplib.php');
  127. $warnings = array();
  128. $arrayparams = array(
  129. 'courseid' => $courseid,
  130. 'userid' => $userid,
  131. );
  132. $params = self::validate_parameters(self::get_activities_completion_status_parameters(), $arrayparams);
  133. $course = get_course($params['courseid']);
  134. $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
  135. core_user::require_active_user($user);
  136. $context = context_course::instance($course->id);
  137. self::validate_context($context);
  138. // Check that current user have permissions to see this user's activities.
  139. if ($user->id != $USER->id) {
  140. require_capability('report/progress:view', $context);
  141. if (!groups_user_groups_visible($course, $user->id)) {
  142. // We are not in the same group!
  143. throw new moodle_exception('accessdenied', 'admin');
  144. }
  145. }
  146. $completion = new completion_info($course);
  147. $activities = $completion->get_activities();
  148. $progresses = $completion->get_progress_all();
  149. $userprogress = $progresses[$user->id];
  150. $results = array();
  151. foreach ($activities as $activity) {
  152. // Check if current user has visibility on this activity.
  153. if (!$activity->uservisible) {
  154. continue;
  155. }
  156. // Get progress information and state.
  157. if (array_key_exists($activity->id, $userprogress->progress)) {
  158. $thisprogress = $userprogress->progress[$activity->id];
  159. $state = $thisprogress->completionstate;
  160. $timecompleted = $thisprogress->timemodified;
  161. } else {
  162. $state = COMPLETION_INCOMPLETE;
  163. $timecompleted = 0;
  164. }
  165. $results[] = array(
  166. 'cmid' => $activity->id,
  167. 'modname' => $activity->modname,
  168. 'instance' => $activity->instance,
  169. 'state' => $state,
  170. 'timecompleted' => $timecompleted,
  171. 'tracking' => $activity->completion
  172. );
  173. }
  174. $results = array(
  175. 'statuses' => $results,
  176. 'warnings' => $warnings
  177. );
  178. return $results;
  179. }
  180. /**
  181. * Returns description of method result value
  182. *
  183. * @return external_description
  184. * @since Moodle 2.9
  185. */
  186. public static function get_activities_completion_status_returns() {
  187. return new external_single_structure(
  188. array(
  189. 'statuses' => new external_multiple_structure(
  190. new external_single_structure(
  191. array(
  192. 'cmid' => new external_value(PARAM_INT, 'comment ID'),
  193. 'modname' => new external_value(PARAM_PLUGIN, 'activity module name'),
  194. 'instance' => new external_value(PARAM_INT, 'instance ID'),
  195. 'state' => new external_value(PARAM_INT, 'completion state value:
  196. 0 means incomplete, 1 complete,
  197. 2 complete pass, 3 complete fail'),
  198. 'timecompleted' => new external_value(PARAM_INT, 'timestamp for completed activity'),
  199. 'tracking' => new external_value(PARAM_INT, 'type of tracking:
  200. 0 means none, 1 manual, 2 automatic'),
  201. ), 'Activity'
  202. ), 'List of activities status'
  203. ),
  204. 'warnings' => new external_warnings()
  205. )
  206. );
  207. }
  208. /**
  209. * Returns description of method parameters
  210. *
  211. * @return external_function_parameters
  212. * @since Moodle 2.9
  213. */
  214. public static function get_course_completion_status_parameters() {
  215. return new external_function_parameters(
  216. array(
  217. 'courseid' => new external_value(PARAM_INT, 'Course ID'),
  218. 'userid' => new external_value(PARAM_INT, 'User ID'),
  219. )
  220. );
  221. }
  222. /**
  223. * Get Course completion status
  224. *
  225. * @param int $courseid ID of the Course
  226. * @param int $userid ID of the User
  227. * @return array of course completion status and warnings
  228. * @since Moodle 2.9
  229. * @throws moodle_exception
  230. */
  231. public static function get_course_completion_status($courseid, $userid) {
  232. global $CFG, $USER;
  233. require_once($CFG->libdir . '/grouplib.php');
  234. $warnings = array();
  235. $arrayparams = array(
  236. 'courseid' => $courseid,
  237. 'userid' => $userid,
  238. );
  239. $params = self::validate_parameters(self::get_course_completion_status_parameters(), $arrayparams);
  240. $course = get_course($params['courseid']);
  241. $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
  242. core_user::require_active_user($user);
  243. $context = context_course::instance($course->id);
  244. self::validate_context($context);
  245. // Can current user see user's course completion status?
  246. // This check verifies if completion is enabled because $course is mandatory.
  247. if (!completion_can_view_data($user->id, $course)) {
  248. throw new moodle_exception('cannotviewreport');
  249. }
  250. // The previous function doesn't check groups.
  251. if ($user->id != $USER->id) {
  252. if (!groups_user_groups_visible($course, $user->id)) {
  253. // We are not in the same group!
  254. throw new moodle_exception('accessdenied', 'admin');
  255. }
  256. }
  257. $info = new completion_info($course);
  258. // Check this user is enroled.
  259. if (!$info->is_tracked_user($user->id)) {
  260. if ($USER->id == $user->id) {
  261. throw new moodle_exception('notenroled', 'completion');
  262. } else {
  263. throw new moodle_exception('usernotenroled', 'completion');
  264. }
  265. }
  266. $completions = $info->get_completions($user->id);
  267. if (empty($completions)) {
  268. throw new moodle_exception('nocriteriaset', 'completion');
  269. }
  270. // Load course completion.
  271. $completionparams = array(
  272. 'userid' => $user->id,
  273. 'course' => $course->id,
  274. );
  275. $ccompletion = new completion_completion($completionparams);
  276. $completionrows = array();
  277. // Loop through course criteria.
  278. foreach ($completions as $completion) {
  279. $criteria = $completion->get_criteria();
  280. $completionrow = array();
  281. $completionrow['type'] = $criteria->criteriatype;
  282. $completionrow['title'] = $criteria->get_title();
  283. $completionrow['status'] = $completion->get_status();
  284. $completionrow['complete'] = $completion->is_complete();
  285. $completionrow['timecompleted'] = $completion->timecompleted;
  286. $completionrow['details'] = $criteria->get_details($completion);
  287. $completionrows[] = $completionrow;
  288. }
  289. $result = array(
  290. 'completed' => $info->is_course_complete($user->id),
  291. 'aggregation' => $info->get_aggregation_method(),
  292. 'completions' => $completionrows
  293. );
  294. $results = array(
  295. 'completionstatus' => $result,
  296. 'warnings' => $warnings
  297. );
  298. return $results;
  299. }
  300. /**
  301. * Returns description of method result value
  302. *
  303. * @return external_description
  304. * @since Moodle 2.9
  305. */
  306. public static function get_course_completion_status_returns() {
  307. return new external_single_structure(
  308. array(
  309. 'completionstatus' => new external_single_structure(
  310. array(
  311. 'completed' => new external_value(PARAM_BOOL, 'true if the course is complete, false otherwise'),
  312. 'aggregation' => new external_value(PARAM_INT, 'aggregation method 1 means all, 2 means any'),
  313. 'completions' => new external_multiple_structure(
  314. new external_single_structure(
  315. array(
  316. 'type' => new external_value(PARAM_INT, 'Completion criteria type'),
  317. 'title' => new external_value(PARAM_TEXT, 'Completion criteria Title'),
  318. 'status' => new external_value(PARAM_NOTAGS, 'Completion status (Yes/No) a % or number'),
  319. 'complete' => new external_value(PARAM_BOOL, 'Completion status (true/false)'),
  320. 'timecompleted' => new external_value(PARAM_INT, 'Timestamp for criteria completetion'),
  321. 'details' => new external_single_structure(
  322. array(
  323. 'type' => new external_value(PARAM_TEXT, 'Type description'),
  324. 'criteria' => new external_value(PARAM_RAW, 'Criteria description'),
  325. 'requirement' => new external_value(PARAM_TEXT, 'Requirement description'),
  326. 'status' => new external_value(PARAM_RAW, 'Status description, can be anything'),
  327. ), 'details'),
  328. ), 'Completions'
  329. ), ''
  330. )
  331. ), 'Course status'
  332. ),
  333. 'warnings' => new external_warnings()
  334. ), 'Course completion status'
  335. );
  336. }
  337. /**
  338. * Describes the parameters for mark_course_self_completed.
  339. *
  340. * @return external_external_function_parameters
  341. * @since Moodle 3.0
  342. */
  343. public static function mark_course_self_completed_parameters() {
  344. return new external_function_parameters (
  345. array(
  346. 'courseid' => new external_value(PARAM_INT, 'Course ID')
  347. )
  348. );
  349. }
  350. /**
  351. * Update the course completion status for the current user (if course self-completion is enabled).
  352. *
  353. * @param int $courseid Course id
  354. * @return array Result and possible warnings
  355. * @since Moodle 3.0
  356. * @throws moodle_exception
  357. */
  358. public static function mark_course_self_completed($courseid) {
  359. global $USER;
  360. $warnings = array();
  361. $params = self::validate_parameters(self::mark_course_self_completed_parameters(),
  362. array('courseid' => $courseid));
  363. $course = get_course($params['courseid']);
  364. $context = context_course::instance($course->id);
  365. self::validate_context($context);
  366. // Set up completion object and check it is enabled.
  367. $completion = new completion_info($course);
  368. if (!$completion->is_enabled()) {
  369. throw new moodle_exception('completionnotenabled', 'completion');
  370. }
  371. if (!$completion->is_tracked_user($USER->id)) {
  372. throw new moodle_exception('nottracked', 'completion');
  373. }
  374. $completion = $completion->get_completion($USER->id, COMPLETION_CRITERIA_TYPE_SELF);
  375. // Self completion criteria not enabled.
  376. if (!$completion) {
  377. throw new moodle_exception('noselfcompletioncriteria', 'completion');
  378. }
  379. // Check if the user has already marked himself as complete.
  380. if ($completion->is_complete()) {
  381. throw new moodle_exception('useralreadymarkedcomplete', 'completion');
  382. }
  383. // Mark the course complete.
  384. $completion->mark_complete();
  385. $result = array();
  386. $result['status'] = true;
  387. $result['warnings'] = $warnings;
  388. return $result;
  389. }
  390. /**
  391. * Describes the mark_course_self_completed return value.
  392. *
  393. * @return external_single_structure
  394. * @since Moodle 3.0
  395. */
  396. public static function mark_course_self_completed_returns() {
  397. return new external_single_structure(
  398. array(
  399. 'status' => new external_value(PARAM_BOOL, 'status, true if success'),
  400. 'warnings' => new external_warnings(),
  401. )
  402. );
  403. }
  404. }