���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/external.php.tar
���ѧ٧ѧ�
home3/cpr76684/public_html/Aem/mod/scorm/classes/external.php 0000644 00000115774 15151252334 0017700 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * SCORM module external API * * @package mod_scorm * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ use core_course\external\helper_for_get_mods_by_courses; defined('MOODLE_INTERNAL') || die; require_once($CFG->libdir . '/externallib.php'); require_once($CFG->dirroot . '/mod/scorm/lib.php'); require_once($CFG->dirroot . '/mod/scorm/locallib.php'); /** * SCORM module external functions * * @package mod_scorm * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ class mod_scorm_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.0 */ public static function view_scorm_parameters() { return new external_function_parameters( array( 'scormid' => new external_value(PARAM_INT, 'scorm instance id') ) ); } /** * Trigger the course module viewed event. * * @param int $scormid the scorm instance id * @return array of warnings and status result * @since Moodle 3.0 * @throws moodle_exception */ public static function view_scorm($scormid) { global $DB, $CFG; require_once($CFG->dirroot . '/mod/scorm/lib.php'); $params = self::validate_parameters(self::view_scorm_parameters(), array( 'scormid' => $scormid )); $warnings = array(); // Request and permission validation. $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($scorm, 'scorm'); $context = context_module::instance($cm->id); self::validate_context($context); // Call the scorm/lib API. scorm_view($scorm, $course, $cm, $context); $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_scorm_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Describes the parameters for get_scorm_attempt_count. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_scorm_attempt_count_parameters() { return new external_function_parameters( array( 'scormid' => new external_value(PARAM_INT, 'SCORM instance id'), 'userid' => new external_value(PARAM_INT, 'User id'), 'ignoremissingcompletion' => new external_value(PARAM_BOOL, 'Ignores attempts that haven\'t reported a grade/completion', VALUE_DEFAULT, false), ) ); } /** * Return the number of attempts done by a user in the given SCORM. * * @param int $scormid the scorm id * @param int $userid the user id * @param bool $ignoremissingcompletion ignores attempts that haven't reported a grade/completion * @return array of warnings and the attempts count * @since Moodle 3.0 */ public static function get_scorm_attempt_count($scormid, $userid, $ignoremissingcompletion = false) { global $USER, $DB; $params = self::validate_parameters(self::get_scorm_attempt_count_parameters(), array('scormid' => $scormid, 'userid' => $userid, 'ignoremissingcompletion' => $ignoremissingcompletion)); $attempts = array(); $warnings = array(); $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('scorm', $scorm->id); $context = context_module::instance($cm->id); self::validate_context($context); $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/scorm:viewreport', $context); } // If the SCORM is not open this function will throw exceptions. scorm_require_available($scorm); $attemptscount = scorm_get_attempt_count($user->id, $scorm, false, $params['ignoremissingcompletion']); $result = array(); $result['attemptscount'] = $attemptscount; $result['warnings'] = $warnings; return $result; } /** * Describes the get_scorm_attempt_count return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_scorm_attempt_count_returns() { return new external_single_structure( array( 'attemptscount' => new external_value(PARAM_INT, 'Attempts count'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_scorm_scoes. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_scorm_scoes_parameters() { return new external_function_parameters( array( 'scormid' => new external_value(PARAM_INT, 'scorm instance id'), 'organization' => new external_value(PARAM_RAW, 'organization id', VALUE_DEFAULT, '') ) ); } /** * Returns a list containing all the scoes data related to the given scorm id * * @param int $scormid the scorm id * @param string $organization the organization id * @return array warnings and the scoes data * @since Moodle 3.0 */ public static function get_scorm_scoes($scormid, $organization = '') { global $DB; $params = self::validate_parameters(self::get_scorm_scoes_parameters(), array('scormid' => $scormid, 'organization' => $organization)); $scoes = array(); $warnings = array(); $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('scorm', $scorm->id); $context = context_module::instance($cm->id); self::validate_context($context); // Check settings / permissions to view the SCORM. scorm_require_available($scorm, true, $context); if (!$scoes = scorm_get_scoes($scorm->id, $params['organization'])) { // Function scorm_get_scoes return false, not an empty array. $scoes = array(); } else { $scoreturnstructure = self::get_scorm_scoes_returns(); foreach ($scoes as $sco) { $extradata = array(); foreach ($sco as $element => $value) { // Check if the element is extra data (not a basic SCO element). if (!isset($scoreturnstructure->keys['scoes']->content->keys[$element])) { $extradata[] = array( 'element' => $element, 'value' => $value ); } } $sco->extradata = $extradata; } } $result = array(); $result['scoes'] = $scoes; $result['warnings'] = $warnings; return $result; } /** * Describes the get_scorm_scoes return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_scorm_scoes_returns() { return new external_single_structure( array( 'scoes' => new external_multiple_structure( new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'sco id'), 'scorm' => new external_value(PARAM_INT, 'scorm id'), 'manifest' => new external_value(PARAM_NOTAGS, 'manifest id'), 'organization' => new external_value(PARAM_NOTAGS, 'organization id'), 'parent' => new external_value(PARAM_NOTAGS, 'parent'), 'identifier' => new external_value(PARAM_NOTAGS, 'identifier'), 'launch' => new external_value(PARAM_NOTAGS, 'launch file'), 'scormtype' => new external_value(PARAM_ALPHA, 'scorm type (asset, sco)'), 'title' => new external_value(PARAM_NOTAGS, 'sco title'), 'sortorder' => new external_value(PARAM_INT, 'sort order'), 'extradata' => new external_multiple_structure( new external_single_structure( array( 'element' => new external_value(PARAM_RAW, 'element name'), 'value' => new external_value(PARAM_RAW, 'element value') ) ), 'Additional SCO data', VALUE_OPTIONAL ) ), 'SCORM SCO data' ) ), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_scorm_user_data. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_scorm_user_data_parameters() { return new external_function_parameters( array( 'scormid' => new external_value(PARAM_INT, 'scorm instance id'), 'attempt' => new external_value(PARAM_INT, 'attempt number') ) ); } /** * Retrieves user tracking and SCO data and default SCORM values * * @param int $scormid the scorm id * @param int $attempt the attempt number * @return array warnings and the scoes data * @throws moodle_exception * @since Moodle 3.0 */ public static function get_scorm_user_data($scormid, $attempt) { global $CFG, $DB; $params = self::validate_parameters(self::get_scorm_user_data_parameters(), array('scormid' => $scormid, 'attempt' => $attempt)); $data = array(); $warnings = array(); $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('scorm', $scorm->id); $context = context_module::instance($cm->id); self::validate_context($context); scorm_require_available($scorm, true, $context); $scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR)); if (!file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'lib.php')) { $scorm->version = 'scorm_12'; } require_once($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'lib.php'); if ($scoes = scorm_get_scoes($scorm->id)) { $def = new stdClass(); $user = new stdClass(); foreach ($scoes as $sco) { $def->{$sco->id} = new stdClass(); $user->{$sco->id} = new stdClass(); // We force mode normal, this can be override by the client at any time. $def->{$sco->id} = get_scorm_default($user->{$sco->id}, $scorm, $sco->id, $params['attempt'], 'normal'); $userdata = array(); $defaultdata = array(); foreach ((array) $user->{$sco->id} as $key => $val) { $userdata[] = array( 'element' => $key, 'value' => $val ); } foreach ($def->{$sco->id} as $key => $val) { $defaultdata[] = array( 'element' => $key, 'value' => $val ); } $data[] = array( 'scoid' => $sco->id, 'userdata' => $userdata, 'defaultdata' => $defaultdata, ); } } $result = array(); $result['data'] = $data; $result['warnings'] = $warnings; return $result; } /** * Describes the get_scorm_user_data return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_scorm_user_data_returns() { return new external_single_structure( array( 'data' => new external_multiple_structure( new external_single_structure( array( 'scoid' => new external_value(PARAM_INT, 'sco id'), 'userdata' => new external_multiple_structure( new external_single_structure( array( 'element' => new external_value(PARAM_RAW, 'element name'), 'value' => new external_value(PARAM_RAW, 'element value') ) ) ), 'defaultdata' => new external_multiple_structure( new external_single_structure( array( 'element' => new external_value(PARAM_RAW, 'element name'), 'value' => new external_value(PARAM_RAW, 'element value') ) ) ), ), 'SCO data' ) ), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for insert_scorm_tracks. * * @return external_function_parameters * @since Moodle 3.0 */ public static function insert_scorm_tracks_parameters() { return new external_function_parameters( array( 'scoid' => new external_value(PARAM_INT, 'SCO id'), 'attempt' => new external_value(PARAM_INT, 'attempt number'), 'tracks' => new external_multiple_structure( new external_single_structure( array( 'element' => new external_value(PARAM_RAW, 'element name'), 'value' => new external_value(PARAM_RAW, 'element value') ) ) ), ) ); } /** * Saves a SCORM tracking record. * It will overwrite any existing tracking data for this attempt. * Validation should be performed before running the function to ensure the user will not lose any existing attempt data. * * @param int $scoid the SCO id * @param string $attempt the attempt number * @param array $tracks the track records to be stored * @return array warnings and the scoes data * @throws moodle_exception * @since Moodle 3.0 */ public static function insert_scorm_tracks($scoid, $attempt, $tracks) { global $USER, $DB; $params = self::validate_parameters(self::insert_scorm_tracks_parameters(), array('scoid' => $scoid, 'attempt' => $attempt, 'tracks' => $tracks)); $trackids = array(); $warnings = array(); $sco = scorm_get_sco($params['scoid'], SCO_ONLY); if (!$sco) { throw new moodle_exception('cannotfindsco', 'scorm'); } $scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('scorm', $scorm->id); $context = context_module::instance($cm->id); self::validate_context($context); // Check settings / permissions to view the SCORM. require_capability('mod/scorm:savetrack', $context); // Check settings / permissions to view the SCORM. scorm_require_available($scorm); foreach ($params['tracks'] as $track) { $element = $track['element']; $value = $track['value']; $trackid = scorm_insert_track($USER->id, $scorm->id, $sco->id, $params['attempt'], $element, $value, $scorm->forcecompleted); if ($trackid) { $trackids[] = $trackid; } else { $warnings[] = array( 'item' => 'scorm', 'itemid' => $scorm->id, 'warningcode' => 1, 'message' => 'Element: ' . $element . ' was not saved' ); } } $result = array(); $result['trackids'] = $trackids; $result['warnings'] = $warnings; return $result; } /** * Describes the insert_scorm_tracks return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function insert_scorm_tracks_returns() { return new external_single_structure( array( 'trackids' => new external_multiple_structure(new external_value(PARAM_INT, 'track id')), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_scorm_sco_tracks. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_scorm_sco_tracks_parameters() { return new external_function_parameters( array( 'scoid' => new external_value(PARAM_INT, 'sco id'), 'userid' => new external_value(PARAM_INT, 'user id'), 'attempt' => new external_value(PARAM_INT, 'attempt number (0 for last attempt)', VALUE_DEFAULT, 0) ) ); } /** * Retrieves SCO tracking data for the given user id and attempt number * * @param int $scoid the sco id * @param int $userid the user id * @param int $attempt the attempt number * @return array warnings and the scoes data * @since Moodle 3.0 */ public static function get_scorm_sco_tracks($scoid, $userid, $attempt = 0) { global $USER, $DB; $params = self::validate_parameters(self::get_scorm_sco_tracks_parameters(), array('scoid' => $scoid, 'userid' => $userid, 'attempt' => $attempt)); $tracks = array(); $warnings = array(); $sco = scorm_get_sco($params['scoid'], SCO_ONLY); if (!$sco) { throw new moodle_exception('cannotfindsco', 'scorm'); } $scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST); $cm = get_coursemodule_from_instance('scorm', $scorm->id); $context = context_module::instance($cm->id); self::validate_context($context); $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/scorm:viewreport', $context); } scorm_require_available($scorm, true, $context); if (empty($params['attempt'])) { $params['attempt'] = scorm_get_last_attempt($scorm->id, $user->id); } $attempted = false; if ($scormtracks = scorm_get_tracks($sco->id, $params['userid'], $params['attempt'])) { // Check if attempted. if ($scormtracks->status != '') { $attempted = true; foreach ($scormtracks as $element => $value) { $tracks[] = array( 'element' => $element, 'value' => $value, ); } } } if (!$attempted) { $warnings[] = array( 'item' => 'attempt', 'itemid' => $params['attempt'], 'warningcode' => 'notattempted', 'message' => get_string('notattempted', 'scorm') ); } $result = array(); $result['data']['attempt'] = $params['attempt']; $result['data']['tracks'] = $tracks; $result['warnings'] = $warnings; return $result; } /** * Describes the get_scorm_sco_tracks return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_scorm_sco_tracks_returns() { return new external_single_structure( array( 'data' => new external_single_structure( array( 'attempt' => new external_value(PARAM_INT, 'Attempt number'), 'tracks' => new external_multiple_structure( new external_single_structure( array( 'element' => new external_value(PARAM_RAW, 'Element name'), 'value' => new external_value(PARAM_RAW, 'Element value') ), 'Tracks data' ) ), ), 'SCO data' ), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_scorms_by_courses. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_scorms_by_courses_parameters() { return new external_function_parameters ( array( 'courseids' => new external_multiple_structure( new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() ), ) ); } /** * Returns a list of scorms in a provided list of courses, * if no list is provided all scorms that the user can view will be returned. * * @param array $courseids the course ids * @return array the scorm details * @since Moodle 3.0 */ public static function get_scorms_by_courses($courseids = array()) { global $CFG; $returnedscorms = array(); $warnings = array(); $params = self::validate_parameters(self::get_scorms_by_courses_parameters(), array('courseids' => $courseids)); $courses = array(); if (empty($params['courseids'])) { $courses = enrol_get_my_courses(); $params['courseids'] = array_keys($courses); } // Ensure there are courseids to loop through. if (!empty($params['courseids'])) { list($courses, $warnings) = external_util::validate_courses($params['courseids'], $courses); // Get the scorms in this course, this function checks users visibility permissions. // We can avoid then additional validate_context calls. $scorms = get_all_instances_in_courses("scorm", $courses); $fs = get_file_storage(); foreach ($scorms as $scorm) { $context = context_module::instance($scorm->coursemodule); // Entry to return. $module = helper_for_get_mods_by_courses::standard_coursemodule_element_values($scorm, 'mod_scorm'); // Check if the SCORM open and return warnings if so. list($open, $openwarnings) = scorm_get_availability_status($scorm, true, $context); if (!$open) { foreach ($openwarnings as $warningkey => $warningdata) { $warnings[] = array( 'item' => 'scorm', 'itemid' => $scorm->id, 'warningcode' => $warningkey, 'message' => get_string($warningkey, 'scorm', $warningdata) ); } } else { $module['packagesize'] = 0; // SCORM size. if ($scorm->scormtype === SCORM_TYPE_LOCAL or $scorm->scormtype === SCORM_TYPE_LOCALSYNC) { if ($packagefile = $fs->get_file($context->id, 'mod_scorm', 'package', 0, '/', $scorm->reference)) { $module['packagesize'] = $packagefile->get_filesize(); // Download URL. $module['packageurl'] = moodle_url::make_webservice_pluginfile_url( $context->id, 'mod_scorm', 'package', 0, '/', $scorm->reference)->out(false); } } $module['protectpackagedownloads'] = get_config('scorm', 'protectpackagedownloads'); $viewablefields = array('version', 'maxgrade', 'grademethod', 'whatgrade', 'maxattempt', 'forcecompleted', 'forcenewattempt', 'lastattemptlock', 'displayattemptstatus', 'displaycoursestructure', 'sha1hash', 'md5hash', 'revision', 'launch', 'skipview', 'hidebrowse', 'hidetoc', 'nav', 'navpositionleft', 'navpositiontop', 'auto', 'popup', 'width', 'height', 'timeopen', 'timeclose', 'scormtype', 'reference'); // Check additional permissions for returning optional private settings. if (has_capability('moodle/course:manageactivities', $context)) { $additionalfields = array('updatefreq', 'options', 'completionstatusrequired', 'completionscorerequired', 'completionstatusallscos', 'autocommit', 'timemodified'); $viewablefields = array_merge($viewablefields, $additionalfields); } foreach ($viewablefields as $field) { $module[$field] = $scorm->{$field}; } } $returnedscorms[] = $module; } } $result = array(); $result['scorms'] = $returnedscorms; $result['warnings'] = $warnings; return $result; } /** * Describes the get_scorms_by_courses return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_scorms_by_courses_returns() { return new external_single_structure( array( 'scorms' => new external_multiple_structure( new external_single_structure(array_merge( helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(), [ 'packagesize' => new external_value(PARAM_INT, 'SCORM zip package size', VALUE_OPTIONAL), 'packageurl' => new external_value(PARAM_URL, 'SCORM zip package URL', VALUE_OPTIONAL), 'version' => new external_value(PARAM_NOTAGS, 'SCORM version (SCORM_12, SCORM_13, SCORM_AICC)', VALUE_OPTIONAL), 'maxgrade' => new external_value(PARAM_INT, 'Max grade', VALUE_OPTIONAL), 'grademethod' => new external_value(PARAM_INT, 'Grade method', VALUE_OPTIONAL), 'whatgrade' => new external_value(PARAM_INT, 'What grade', VALUE_OPTIONAL), 'maxattempt' => new external_value(PARAM_INT, 'Maximum number of attemtps', VALUE_OPTIONAL), 'forcecompleted' => new external_value(PARAM_BOOL, 'Status current attempt is forced to "completed"', VALUE_OPTIONAL), 'forcenewattempt' => new external_value(PARAM_INT, 'Controls re-entry behaviour', VALUE_OPTIONAL), 'lastattemptlock' => new external_value(PARAM_BOOL, 'Prevents to launch new attempts once finished', VALUE_OPTIONAL), 'displayattemptstatus' => new external_value(PARAM_INT, 'How to display attempt status', VALUE_OPTIONAL), 'displaycoursestructure' => new external_value(PARAM_BOOL, 'Display contents structure', VALUE_OPTIONAL), 'sha1hash' => new external_value(PARAM_NOTAGS, 'Package content or ext path hash', VALUE_OPTIONAL), 'md5hash' => new external_value(PARAM_NOTAGS, 'MD5 Hash of package file', VALUE_OPTIONAL), 'revision' => new external_value(PARAM_INT, 'Revison number', VALUE_OPTIONAL), 'launch' => new external_value(PARAM_INT, 'First content to launch', VALUE_OPTIONAL), 'skipview' => new external_value(PARAM_INT, 'How to skip the content structure page', VALUE_OPTIONAL), 'hidebrowse' => new external_value(PARAM_BOOL, 'Disable preview mode?', VALUE_OPTIONAL), 'hidetoc' => new external_value(PARAM_INT, 'How to display the SCORM structure in player', VALUE_OPTIONAL), 'nav' => new external_value(PARAM_INT, 'Show navigation buttons', VALUE_OPTIONAL), 'navpositionleft' => new external_value(PARAM_INT, 'Navigation position left', VALUE_OPTIONAL), 'navpositiontop' => new external_value(PARAM_INT, 'Navigation position top', VALUE_OPTIONAL), 'auto' => new external_value(PARAM_BOOL, 'Auto continue?', VALUE_OPTIONAL), 'popup' => new external_value(PARAM_INT, 'Display in current or new window', VALUE_OPTIONAL), 'width' => new external_value(PARAM_INT, 'Frame width', VALUE_OPTIONAL), 'height' => new external_value(PARAM_INT, 'Frame height', VALUE_OPTIONAL), 'timeopen' => new external_value(PARAM_INT, 'Available from', VALUE_OPTIONAL), 'timeclose' => new external_value(PARAM_INT, 'Available to', VALUE_OPTIONAL), 'scormtype' => new external_value(PARAM_ALPHA, 'SCORM type', VALUE_OPTIONAL), 'reference' => new external_value(PARAM_NOTAGS, 'Reference to the package', VALUE_OPTIONAL), 'protectpackagedownloads' => new external_value(PARAM_BOOL, 'Protect package downloads?', VALUE_OPTIONAL), 'updatefreq' => new external_value(PARAM_INT, 'Auto-update frequency for remote packages', VALUE_OPTIONAL), 'options' => new external_value(PARAM_RAW, 'Additional options', VALUE_OPTIONAL), 'completionstatusrequired' => new external_value(PARAM_INT, 'Status passed/completed required?', VALUE_OPTIONAL), 'completionscorerequired' => new external_value(PARAM_INT, 'Minimum score required', VALUE_OPTIONAL), 'completionstatusallscos' => new external_value(PARAM_INT, 'Require all scos to return completion status', VALUE_OPTIONAL), 'autocommit' => new external_value(PARAM_BOOL, 'Save track data automatically?', VALUE_OPTIONAL), 'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL), ] ), 'SCORM') ), 'warnings' => new external_warnings(), ) ); } /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.1 */ public static function launch_sco_parameters() { return new external_function_parameters( array( 'scormid' => new external_value(PARAM_INT, 'SCORM instance id'), 'scoid' => new external_value(PARAM_INT, 'SCO id (empty for launching the first SCO)', VALUE_DEFAULT, 0) ) ); } /** * Trigger the course module viewed event. * * @param int $scormid the SCORM instance id * @param int $scoid the SCO id * @return array of warnings and status result * @since Moodle 3.1 * @throws moodle_exception */ public static function launch_sco($scormid, $scoid = 0) { global $DB, $CFG; require_once($CFG->libdir . '/completionlib.php'); $params = self::validate_parameters(self::launch_sco_parameters(), array( 'scormid' => $scormid, 'scoid' => $scoid )); $warnings = array(); // Request and permission validation. $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($scorm, 'scorm'); $context = context_module::instance($cm->id); self::validate_context($context); // If the SCORM is not open this function will throw exceptions. scorm_require_available($scorm); if (!empty($params['scoid']) and !($sco = scorm_get_sco($params['scoid'], SCO_ONLY))) { throw new moodle_exception('cannotfindsco', 'scorm'); } // Mark module viewed. $completion = new completion_info($course); $completion->set_module_viewed($cm); list($sco, $scolaunchurl) = scorm_get_sco_and_launch_url($scorm, $params['scoid'], $context); // Trigger the SCO launched event. scorm_launch_sco($scorm, $sco, $cm, $context, $scolaunchurl); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Returns description of method result value * * @return external_description * @since Moodle 3.1 */ public static function launch_sco_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Describes the parameters for get_scorm_access_information. * * @return external_external_function_parameters * @since Moodle 3.7 */ public static function get_scorm_access_information_parameters() { return new external_function_parameters ( array( 'scormid' => new external_value(PARAM_INT, 'scorm instance id.') ) ); } /** * Return access information for a given scorm. * * @param int $scormid scorm instance id * @return array of warnings and the access information * @since Moodle 3.7 * @throws moodle_exception */ public static function get_scorm_access_information($scormid) { global $DB; $params = self::validate_parameters(self::get_scorm_access_information_parameters(), array('scormid' => $scormid)); // Request and permission validation. $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($scorm, 'scorm'); $context = context_module::instance($cm->id); self::validate_context($context); $result = array(); // Return all the available capabilities. $capabilities = load_capability_def('mod_scorm'); foreach ($capabilities as $capname => $capdata) { // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules. $field = 'can' . str_replace('mod/scorm:', '', $capname); $result[$field] = has_capability($capname, $context); } $result['warnings'] = array(); return $result; } /** * Describes the get_scorm_access_information return value. * * @return external_single_structure * @since Moodle 3.7 */ public static function get_scorm_access_information_returns() { $structure = array( 'warnings' => new external_warnings() ); $capabilities = load_capability_def('mod_scorm'); foreach ($capabilities as $capname => $capdata) { // Get fields like cansubmit so it is consistent with the access_information function implemented in other modules. $field = 'can' . str_replace('mod/scorm:', '', $capname); $structure[$field] = new external_value(PARAM_BOOL, 'Whether the user has the capability ' . $capname . ' allowed.', VALUE_OPTIONAL); } return new external_single_structure($structure); } } home3/cpr76684/public_html/Aem/mod/book/classes/external.php 0000644 00000021642 15151265175 0017504 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Book external API * * @package mod_book * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ use core_course\external\helper_for_get_mods_by_courses; defined('MOODLE_INTERNAL') || die; require_once("$CFG->libdir/externallib.php"); /** * Book external functions * * @package mod_book * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ class mod_book_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.0 */ public static function view_book_parameters() { return new external_function_parameters( array( 'bookid' => new external_value(PARAM_INT, 'book instance id'), 'chapterid' => new external_value(PARAM_INT, 'chapter id', VALUE_DEFAULT, 0) ) ); } /** * Simulate the book/view.php web interface page: trigger events, completion, etc... * * @param int $bookid the book instance id * @param int $chapterid the book chapter id * @return array of warnings and status result * @since Moodle 3.0 * @throws moodle_exception */ public static function view_book($bookid, $chapterid = 0) { global $DB, $CFG; require_once($CFG->dirroot . "/mod/book/lib.php"); require_once($CFG->dirroot . "/mod/book/locallib.php"); $params = self::validate_parameters(self::view_book_parameters(), array( 'bookid' => $bookid, 'chapterid' => $chapterid )); $bookid = $params['bookid']; $chapterid = $params['chapterid']; $warnings = array(); // Request and permission validation. $book = $DB->get_record('book', array('id' => $bookid), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($book, 'book'); $context = context_module::instance($cm->id); self::validate_context($context); require_capability('mod/book:read', $context); $chapters = book_preload_chapters($book); $firstchapterid = 0; $lastchapterid = 0; foreach ($chapters as $ch) { if ($ch->hidden) { continue; } if (!$firstchapterid) { $firstchapterid = $ch->id; } $lastchapterid = $ch->id; } if (!$chapterid) { // Trigger the module viewed events since we are displaying the book. book_view($book, null, false, $course, $cm, $context); $chapterid = $firstchapterid; } // Check if book is empty (warning). if (!$chapterid) { $warnings[] = array( 'item' => 'book', 'itemid' => $book->id, 'warningcode' => '1', 'message' => get_string('nocontent', 'mod_book') ); } else { $chapter = $DB->get_record('book_chapters', array('id' => $chapterid, 'bookid' => $book->id)); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); if (!$chapter or ($chapter->hidden and !$viewhidden)) { throw new moodle_exception('errorchapter', 'mod_book'); } // Trigger the chapter viewed event. $islastchapter = ($chapter->id == $lastchapterid) ? true : false; book_view($book, $chapter, $islastchapter, $course, $cm, $context); } $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_book_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Describes the parameters for get_books_by_courses. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_books_by_courses_parameters() { return new external_function_parameters ( array( 'courseids' => new external_multiple_structure( new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() ), ) ); } /** * Returns a list of books in a provided list of courses, * if no list is provided all books that the user can view will be returned. * * @param array $courseids the course ids * @return array of books details * @since Moodle 3.0 */ public static function get_books_by_courses($courseids = array()) { $returnedbooks = array(); $warnings = array(); $params = self::validate_parameters(self::get_books_by_courses_parameters(), array('courseids' => $courseids)); $courses = array(); if (empty($params['courseids'])) { $courses = enrol_get_my_courses(); $params['courseids'] = array_keys($courses); } // Ensure there are courseids to loop through. if (!empty($params['courseids'])) { list($courses, $warnings) = external_util::validate_courses($params['courseids'], $courses); // Get the books in this course, this function checks users visibility permissions. // We can avoid then additional validate_context calls. $books = get_all_instances_in_courses("book", $courses); foreach ($books as $book) { // Entry to return. $bookdetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values($book, 'mod_book'); $bookdetails['numbering'] = $book->numbering; $bookdetails['navstyle'] = $book->navstyle; $bookdetails['customtitles'] = $book->customtitles; if (has_capability('moodle/course:manageactivities', context_module::instance($book->coursemodule))) { $bookdetails['revision'] = $book->revision; $bookdetails['timecreated'] = $book->timecreated; $bookdetails['timemodified'] = $book->timemodified; } $returnedbooks[] = $bookdetails; } } $result = array(); $result['books'] = $returnedbooks; $result['warnings'] = $warnings; return $result; } /** * Describes the get_books_by_courses return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_books_by_courses_returns() { return new external_single_structure( array( 'books' => new external_multiple_structure( new external_single_structure(array_merge( helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(), [ 'numbering' => new external_value(PARAM_INT, 'Book numbering configuration'), 'navstyle' => new external_value(PARAM_INT, 'Book navigation style configuration'), 'customtitles' => new external_value(PARAM_INT, 'Book custom titles type'), 'revision' => new external_value(PARAM_INT, 'Book revision', VALUE_OPTIONAL), 'timecreated' => new external_value(PARAM_INT, 'Time of creation', VALUE_OPTIONAL), 'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL), ] ), 'Books') ), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/tag/classes/external.php 0000644 00000065424 15151265357 0016556 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Contains class core_tag_external * * @package core_tag * @copyright 2015 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/externallib.php"); require_once("$CFG->dirroot/webservice/externallib.php"); /** * Tags-related web services * * @package core_tag * @copyright 2015 Marina Glancy * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core_tag_external extends external_api { /** * Parameters for function update_tags() * * @return external_function_parameters */ public static function update_tags_parameters() { return new external_function_parameters( array( 'tags' => new external_multiple_structure( new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'tag id'), 'rawname' => new external_value(PARAM_RAW, 'tag raw name (may contain capital letters)', VALUE_OPTIONAL), 'description' => new external_value(PARAM_RAW, 'tag description', VALUE_OPTIONAL), 'descriptionformat' => new external_value(PARAM_INT, 'tag description format', VALUE_OPTIONAL), 'flag' => new external_value(PARAM_INT, 'flag', VALUE_OPTIONAL), 'official' => new external_value(PARAM_INT, '(deprecated, use isstandard) whether this flag is standard', VALUE_OPTIONAL), 'isstandard' => new external_value(PARAM_INT, 'whether this flag is standard', VALUE_OPTIONAL), ) ) ) ) ); } /** * Update tags * * @param array $tags */ public static function update_tags($tags) { global $CFG, $PAGE, $DB; // Validate and normalize parameters. $tags = self::validate_parameters(self::update_tags_parameters(), array('tags' => $tags)); $systemcontext = context_system::instance(); $canmanage = has_capability('moodle/tag:manage', $systemcontext); $canedit = has_capability('moodle/tag:edit', $systemcontext); $warnings = array(); if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } $renderer = $PAGE->get_renderer('core'); foreach ($tags['tags'] as $tag) { $tag = (array)$tag; if (array_key_exists('rawname', $tag)) { $tag['rawname'] = clean_param($tag['rawname'], PARAM_TAG); if (empty($tag['rawname'])) { unset($tag['rawname']); } } if (!$canmanage) { // User without manage capability can not change any fields except for descriptions. $tag = array_intersect_key($tag, array('id' => 1, 'description' => 1, 'descriptionformat' => 1)); } if (!$canedit) { // User without edit capability can not change description. $tag = array_diff_key($tag, array('description' => 1, 'descriptionformat' => 1)); } if (count($tag) <= 1) { $warnings[] = array( 'item' => $tag['id'], 'warningcode' => 'nothingtoupdate', 'message' => get_string('nothingtoupdate', 'core_tag') ); continue; } if (!$tagobject = core_tag_tag::get($tag['id'], '*')) { $warnings[] = array( 'item' => $tag['id'], 'warningcode' => 'tagnotfound', 'message' => get_string('tagnotfound', 'error') ); continue; } // First check if new tag name is allowed. if (!empty($tag['rawname']) && ($existing = core_tag_tag::get_by_name($tagobject->tagcollid, $tag['rawname']))) { if ($existing->id != $tag['id']) { $warnings[] = array( 'item' => $tag['id'], 'warningcode' => 'namesalreadybeeingused', 'message' => get_string('namesalreadybeeingused', 'core_tag') ); continue; } } if (array_key_exists('official', $tag)) { // Parameter 'official' deprecated and replaced with 'isstandard'. $tag['isstandard'] = $tag['official'] ? 1 : 0; unset($tag['official']); } if (isset($tag['flag'])) { if ($tag['flag']) { $tagobject->flag(); } else { $tagobject->reset_flag(); } unset($tag['flag']); } unset($tag['id']); if (count($tag)) { $tagobject->update($tag); } } return array('warnings' => $warnings); } /** * Return structure for update_tag() * * @return external_description */ public static function update_tags_returns() { return new external_single_structure( array( 'warnings' => new external_warnings() ) ); } /** * Parameters for function get_tags() * * @return external_function_parameters */ public static function get_tags_parameters() { return new external_function_parameters( array( 'tags' => new external_multiple_structure( new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'tag id'), ) ) ) ) ); } /** * Get tags by their ids * * @param array $tags */ public static function get_tags($tags) { global $CFG, $PAGE, $DB; // Validate and normalize parameters. $tags = self::validate_parameters(self::get_tags_parameters(), array('tags' => $tags)); $systemcontext = context_system::instance(); self::validate_context($systemcontext); $canmanage = has_capability('moodle/tag:manage', $systemcontext); $canedit = has_capability('moodle/tag:edit', $systemcontext); $return = array(); $warnings = array(); if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } $renderer = $PAGE->get_renderer('core'); foreach ($tags['tags'] as $tag) { $tag = (array)$tag; if (!$tagobject = $DB->get_record('tag', array('id' => $tag['id']))) { $warnings[] = array( 'item' => $tag['id'], 'warningcode' => 'tagnotfound', 'message' => get_string('tagnotfound', 'error') ); continue; } $tagoutput = new \core_tag\output\tag($tagobject); // Do not return some information to users without permissions. $rv = $tagoutput->export_for_template($renderer); if (!$canmanage) { if (!$canedit) { unset($rv->isstandard); unset($rv->official); } unset($rv->flag); } $return[] = $rv; } return array('tags' => $return, 'warnings' => $warnings); } /** * Return structure for get_tag() * * @return external_description */ public static function get_tags_returns() { return new external_single_structure( array( 'tags' => new external_multiple_structure( new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'tag id'), 'tagcollid' => new external_value(PARAM_INT, 'tag collection id'), 'name' => new external_value(PARAM_TAG, 'name'), 'rawname' => new external_value(PARAM_RAW, 'tag raw name (may contain capital letters)'), 'description' => new external_value(PARAM_RAW, 'tag description'), 'descriptionformat' => new external_format_value(PARAM_INT, VALUE_REQUIRED, 'tag description format'), 'flag' => new external_value(PARAM_INT, 'flag', VALUE_OPTIONAL), 'official' => new external_value(PARAM_INT, 'whether this flag is standard (deprecated, use isstandard)', VALUE_OPTIONAL), 'isstandard' => new external_value(PARAM_INT, 'whether this flag is standard', VALUE_OPTIONAL), 'viewurl' => new external_value(PARAM_URL, 'URL to view'), ), 'information about one tag') ), 'warnings' => new external_warnings() ) ); } /** * Parameters for function get_tagindex() * * @return external_function_parameters */ public static function get_tagindex_parameters() { return new external_function_parameters( array( 'tagindex' => new external_single_structure(array( 'tag' => new external_value(PARAM_TAG, 'tag name'), 'tc' => new external_value(PARAM_INT, 'tag collection id'), 'ta' => new external_value(PARAM_INT, 'tag area id'), 'excl' => new external_value(PARAM_BOOL, 'exlusive mode for this tag area', VALUE_OPTIONAL, 0), 'from' => new external_value(PARAM_INT, 'context id where the link was displayed', VALUE_OPTIONAL, 0), 'ctx' => new external_value(PARAM_INT, 'context id where to search for items', VALUE_OPTIONAL, 0), 'rec' => new external_value(PARAM_INT, 'search in the context recursive', VALUE_OPTIONAL, 1), 'page' => new external_value(PARAM_INT, 'page number (0-based)', VALUE_OPTIONAL, 0), ), 'parameters') ) ); } /** * Get tags by their ids * * @param array $params */ public static function get_tagindex($params) { global $PAGE; // Validate and normalize parameters. $tagindex = self::validate_parameters( self::get_tagindex_parameters(), array('tagindex' => $params)); $params = $tagindex['tagindex'] + array( 'excl' => 0, 'from' => 0, 'ctx' => 0, 'rec' => 1, 'page' => 0 ); // Login to the course / module if applicable. $context = $params['ctx'] ? context::instance_by_id($params['ctx']) : context_system::instance(); self::validate_context($context); $tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*', MUST_EXIST); $tagareas = core_tag_collection::get_areas($params['tc']); $tagindex = $tag->get_tag_index($tagareas[$params['ta']], $params['excl'], $params['from'], $params['ctx'], $params['rec'], $params['page']); $renderer = $PAGE->get_renderer('core'); return $tagindex->export_for_template($renderer); } /** * Return structure for get_tag() * * @return external_description */ public static function get_tagindex_returns() { return new external_single_structure( array( 'tagid' => new external_value(PARAM_INT, 'tag id'), 'ta' => new external_value(PARAM_INT, 'tag area id'), 'component' => new external_value(PARAM_COMPONENT, 'component'), 'itemtype' => new external_value(PARAM_NOTAGS, 'itemtype'), 'nextpageurl' => new external_value(PARAM_URL, 'URL for the next page', VALUE_OPTIONAL), 'prevpageurl' => new external_value(PARAM_URL, 'URL for the next page', VALUE_OPTIONAL), 'exclusiveurl' => new external_value(PARAM_URL, 'URL for exclusive link', VALUE_OPTIONAL), 'exclusivetext' => new external_value(PARAM_TEXT, 'text for exclusive link', VALUE_OPTIONAL), 'title' => new external_value(PARAM_RAW, 'title'), 'content' => new external_value(PARAM_RAW, 'title'), 'hascontent' => new external_value(PARAM_INT, 'whether the content is present'), 'anchor' => new external_value(PARAM_TEXT, 'name of anchor', VALUE_OPTIONAL), ), 'tag index' ); } /** * Parameters for function get_tagindex_per_area() * * @return external_function_parameters * @since Moodle 3.7 */ public static function get_tagindex_per_area_parameters() { return new external_function_parameters( array( 'tagindex' => new external_single_structure(array( 'id' => new external_value(PARAM_INT, 'tag id', VALUE_OPTIONAL, 0), 'tag' => new external_value(PARAM_TAG, 'tag name', VALUE_OPTIONAL, ''), 'tc' => new external_value(PARAM_INT, 'tag collection id', VALUE_OPTIONAL, 0), 'ta' => new external_value(PARAM_INT, 'tag area id', VALUE_OPTIONAL, 0), 'excl' => new external_value(PARAM_BOOL, 'exlusive mode for this tag area', VALUE_OPTIONAL, 0), 'from' => new external_value(PARAM_INT, 'context id where the link was displayed', VALUE_OPTIONAL, 0), 'ctx' => new external_value(PARAM_INT, 'context id where to search for items', VALUE_OPTIONAL, 0), 'rec' => new external_value(PARAM_INT, 'search in the context recursive', VALUE_OPTIONAL, 1), 'page' => new external_value(PARAM_INT, 'page number (0-based)', VALUE_OPTIONAL, 0), ), 'parameters') ) ); } /** * Returns the tag index per multiple areas if requested. * * @param array $params Tag index required information. * @throws moodle_exception * @since Moodle 3.7 */ public static function get_tagindex_per_area($params) { global $CFG, $PAGE; // Validate and normalize parameters. $tagindex = self::validate_parameters( self::get_tagindex_per_area_parameters(), array('tagindex' => $params)); $params = $tagindex['tagindex'] + array( // Force defaults. 'id' => 0, 'tag' => '', 'tc' => 0, 'ta' => 0, 'excl' => 0, 'from' => 0, 'ctx' => 0, 'rec' => 1, 'page' => 0, ); if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } if (!empty($params['tag'])) { if (empty($params['tc'])) { // Tag name specified but tag collection was not. Try to guess it. $tags = core_tag_tag::guess_by_name($params['tag'], '*'); if (count($tags) > 1) { // It is in more that one collection, do not display. throw new moodle_exception('Tag is in more that one collection, please indicate one.'); } else if (count($tags) == 1) { $tag = reset($tags); } } else { if (!$tag = core_tag_tag::get_by_name($params['tc'], $params['tag'], '*')) { // Not found in collection. throw new moodle_exception('notagsfound', 'tag'); } } } else if (!empty($params['id'])) { $tag = core_tag_tag::get($params['id'], '*'); } if (empty($tag)) { throw new moodle_exception('notagsfound', 'tag'); } // Login to the course / module if applicable. $context = !empty($params['ctx']) ? context::instance_by_id($params['ctx']) : context_system::instance(); self::validate_context($context); $tag = core_tag_tag::get_by_name($params['tc'], $tag->name, '*', MUST_EXIST); $tagareas = core_tag_collection::get_areas($params['tc']); $tagareaid = $params['ta']; $exclusivemode = 0; // Find all areas in this collection and their items tagged with this tag. if ($tagareaid) { $tagareas = array($tagareas[$tagareaid]); } if (!$tagareaid && count($tagareas) == 1) { // Automatically set "exclusive" mode for tag collection with one tag area only. $params['excl'] = 1; } $renderer = $PAGE->get_renderer('core'); $result = array(); foreach ($tagareas as $ta) { $tagindex = $tag->get_tag_index($ta, $params['excl'], $params['from'], $params['ctx'], $params['rec'], $params['page']); if (!empty($tagindex->hascontent)) { $result[] = $tagindex->export_for_template($renderer); } } return $result; } /** * Return structure for get_tagindex_per_area * * @return external_description * @since Moodle 3.7 */ public static function get_tagindex_per_area_returns() { return new external_multiple_structure( self::get_tagindex_returns() ); } /** * Returns description of get_tag_areas() parameters. * * @return external_function_parameters * @since Moodle 3.7 */ public static function get_tag_areas_parameters() { return new external_function_parameters(array()); } /** * Retrieves existing tag areas. * * @return array an array of warnings and objects containing the plugin information * @throws moodle_exception * @since Moodle 3.7 */ public static function get_tag_areas() { global $CFG, $PAGE; if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } $context = context_system::instance(); self::validate_context($context); $PAGE->set_context($context); // Needed by internal APIs. $output = $PAGE->get_renderer('core'); $areas = core_tag_area::get_areas(); $exportedareas = array(); foreach ($areas as $itemtype => $component) { foreach ($component as $area) { // Move optional fields not part of the DB table to otherdata. $locked = false; if (isset($area->locked)) { $locked = $area->locked; unset($area->locked); } $exporter = new \core_tag\external\tag_area_exporter($area, array('locked' => $locked)); $exportedareas[] = $exporter->export($output); } } return array( 'areas' => $exportedareas, 'warnings' => array(), ); } /** * Returns description of get_tag_areas() result value. * * @return external_description * @since Moodle 3.7 */ public static function get_tag_areas_returns() { return new external_single_structure( array( 'areas' => new external_multiple_structure( \core_tag\external\tag_area_exporter::get_read_structure() ), 'warnings' => new external_warnings(), ) ); } /** * Returns description of get_tag_collections() parameters. * * @return external_function_parameters * @since Moodle 3.7 */ public static function get_tag_collections_parameters() { return new external_function_parameters(array()); } /** * Retrieves existing tag collections. * * @return array an array of warnings and tag collections * @throws moodle_exception * @since Moodle 3.7 */ public static function get_tag_collections() { global $CFG, $PAGE; if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } $context = context_system::instance(); self::validate_context($context); $PAGE->set_context($context); // Needed by internal APIs. $output = $PAGE->get_renderer('core'); $collections = core_tag_collection::get_collections(); $exportedcollections = array(); foreach ($collections as $collection) { $exporter = new \core_tag\external\tag_collection_exporter($collection); $exportedcollections[] = $exporter->export($output); } return array( 'collections' => $exportedcollections, 'warnings' => array(), ); } /** * Returns description of get_tag_collections() result value. * * @return external_description * @since Moodle 3.7 */ public static function get_tag_collections_returns() { return new external_single_structure( array( 'collections' => new external_multiple_structure( \core_tag\external\tag_collection_exporter::get_read_structure() ), 'warnings' => new external_warnings(), ) ); } /** * Returns description of get_tag_cloud() parameters. * * @return external_function_parameters * @since Moodle 3.7 */ public static function get_tag_cloud_parameters() { return new external_function_parameters( array( 'tagcollid' => new external_value(PARAM_INT, 'Tag collection id.', VALUE_DEFAULT, 0), 'isstandard' => new external_value(PARAM_BOOL, 'Whether to return only standard tags.', VALUE_DEFAULT, false), 'limit' => new external_value(PARAM_INT, 'Maximum number of tags to retrieve.', VALUE_DEFAULT, 150), 'sort' => new external_value(PARAM_ALPHA, 'Sort order for display (id, name, rawname, count, flag, isstandard, tagcollid).', VALUE_DEFAULT, 'name'), 'search' => new external_value(PARAM_RAW, 'Search string.', VALUE_DEFAULT, ''), 'fromctx' => new external_value(PARAM_INT, 'Context id where this tag cloud is displayed.', VALUE_DEFAULT, 0), 'ctx' => new external_value(PARAM_INT, 'Only retrieve tag instances in this context.', VALUE_DEFAULT, 0), 'rec' => new external_value(PARAM_INT, 'Retrieve tag instances in the $ctx context and it\'s children.', VALUE_DEFAULT, 1), ) ); } /** * Retrieves a tag cloud for display. * * @param int $tagcollid tag collection id * @param bool $isstandard return only standard tags * @param int $limit maximum number of tags to retrieve, tags are sorted by the instance count * descending here regardless of $sort parameter * @param string $sort sort order for display, default 'name' - tags will be sorted after they are retrieved * @param string $search search string * @param int $fromctx context id where this tag cloud is displayed * @param int $ctx only retrieve tag instances in this context * @param int $rec retrieve tag instances in the $ctx context and it's children (default 1) * @return array an array of warnings and tag cloud information and items * @throws moodle_exception * @since Moodle 3.7 */ public static function get_tag_cloud($tagcollid = 0, $isstandard = false, $limit = 150, $sort = 'name', $search = '', $fromctx = 0, $ctx = 0, $rec = 1) { global $CFG, $PAGE; $params = self::validate_parameters(self::get_tag_cloud_parameters(), array( 'tagcollid' => $tagcollid, 'isstandard' => $isstandard, 'limit' => $limit, 'sort' => $sort, 'search' => $search, 'fromctx' => $fromctx, 'ctx' => $ctx, 'rec' => $rec, ) ); if (empty($CFG->usetags)) { throw new moodle_exception('tagsaredisabled', 'tag'); } $context = context_system::instance(); self::validate_context($context); $PAGE->set_context($context); // Needed by internal APIs. $output = $PAGE->get_renderer('core'); $tagcloud = core_tag_collection::get_tag_cloud($params['tagcollid'], $params['isstandard'], $params['limit'], $params['sort'], $params['search'], $params['fromctx'], $params['ctx'], $params['rec']); $result = $tagcloud->export_for_template($output); $result->warnings = array(); return (array) $result; } /** * Returns description of get_tag_cloud() result value. * * @return external_description * @since Moodle 3.7 */ public static function get_tag_cloud_returns() { return new external_single_structure( array( 'tags' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_TAG, 'Tag name.'), 'viewurl' => new external_value(PARAM_RAW, 'URL to view the tag index.'), 'flag' => new external_value(PARAM_BOOL, 'Whether the tag is flagged as inappropriate.', VALUE_OPTIONAL), 'isstandard' => new external_value(PARAM_BOOL, 'Whether is a standard tag or not.', VALUE_OPTIONAL), 'count' => new external_value(PARAM_INT, 'Number of tag instances.', VALUE_OPTIONAL), 'size' => new external_value(PARAM_INT, 'Proportional size to display the tag.', VALUE_OPTIONAL), ), 'Tags.' ) ), 'tagscount' => new external_value(PARAM_INT, 'Number of tags returned.'), 'totalcount' => new external_value(PARAM_INT, 'Total count of tags.'), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/comment/classes/external.php 0000644 00000034714 15152003637 0017433 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * External comment API * * @package core_comment * @category external * @copyright Costantino Cito <ccito@cvaconsulting.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 2.9 */ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/externallib.php"); require_once("$CFG->dirroot/comment/lib.php"); /** * External comment API functions * * @package core_comment * @category external * @copyright Costantino Cito <ccito@cvaconsulting.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 2.9 */ class core_comment_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 2.9 */ public static function get_comments_parameters() { return new external_function_parameters( array( 'contextlevel' => new external_value(PARAM_ALPHA, 'contextlevel system, course, user...'), 'instanceid' => new external_value(PARAM_INT, 'the Instance id of item associated with the context level'), 'component' => new external_value(PARAM_COMPONENT, 'component'), 'itemid' => new external_value(PARAM_INT, 'associated id'), 'area' => new external_value(PARAM_AREA, 'string comment area', VALUE_DEFAULT, ''), 'page' => new external_value(PARAM_INT, 'page number (0 based)', VALUE_DEFAULT, 0), 'sortdirection' => new external_value(PARAM_ALPHA, 'Sort direction: ASC or DESC', VALUE_DEFAULT, 'DESC'), ) ); } /** * Return a list of comments * * @param string $contextlevel ('system, course, user', etc..) * @param int $instanceid * @param string $component the name of the component * @param int $itemid the item id * @param string $area comment area * @param int $page page number * @param string $sortdirection sort direction * @return array of comments and warnings * @since Moodle 2.9 */ public static function get_comments($contextlevel, $instanceid, $component, $itemid, $area = '', $page = 0, $sortdirection = 'DESC') { global $CFG; $warnings = array(); $arrayparams = array( 'contextlevel' => $contextlevel, 'instanceid' => $instanceid, 'component' => $component, 'itemid' => $itemid, 'area' => $area, 'page' => $page, 'sortdirection' => $sortdirection, ); $params = self::validate_parameters(self::get_comments_parameters(), $arrayparams); $sortdirection = strtoupper($params['sortdirection']); $directionallowedvalues = array('ASC', 'DESC'); if (!in_array($sortdirection, $directionallowedvalues)) { throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' . 'allowed values are: ' . implode(',', $directionallowedvalues)); } $context = self::get_context_from_params($params); self::validate_context($context); require_capability('moodle/comment:view', $context); $args = new stdClass; $args->context = $context; $args->area = $params['area']; $args->itemid = $params['itemid']; $args->component = $params['component']; $commentobject = new comment($args); $comments = $commentobject->get_comments($params['page'], $sortdirection); // False means no permissions to see comments. if ($comments === false) { throw new moodle_exception('nopermissions', 'error', '', 'view comments'); } $options = array('blanktarget' => true); foreach ($comments as $key => $comment) { list($comments[$key]->content, $comments[$key]->format) = external_format_text($comment->content, $comment->format, $context->id, $params['component'], '', 0, $options); } $results = array( 'comments' => $comments, 'count' => $commentobject->count(), 'perpage' => (!empty($CFG->commentsperpage)) ? $CFG->commentsperpage : 15, 'canpost' => $commentobject->can_post(), 'warnings' => $warnings ); return $results; } /** * Returns description of method result value * * @return external_description * @since Moodle 2.9 */ public static function get_comments_returns() { return new external_single_structure( array( 'comments' => new external_multiple_structure( self::get_comment_structure(), 'List of comments' ), 'count' => new external_value(PARAM_INT, 'Total number of comments.', VALUE_OPTIONAL), 'perpage' => new external_value(PARAM_INT, 'Number of comments per page.', VALUE_OPTIONAL), 'canpost' => new external_value(PARAM_BOOL, 'Whether the user can post in this comment area.', VALUE_OPTIONAL), 'warnings' => new external_warnings() ) ); } /** * Helper to get the structure of a single comment. * * @return external_single_structure the comment structure. */ protected static function get_comment_structure() { return new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'Comment ID'), 'content' => new external_value(PARAM_RAW, 'The content text formatted'), 'format' => new external_format_value('content'), 'timecreated' => new external_value(PARAM_INT, 'Time created (timestamp)'), 'strftimeformat' => new external_value(PARAM_NOTAGS, 'Time format'), 'profileurl' => new external_value(PARAM_URL, 'URL profile'), 'fullname' => new external_value(PARAM_NOTAGS, 'fullname'), 'time' => new external_value(PARAM_NOTAGS, 'Time in human format'), 'avatar' => new external_value(PARAM_RAW, 'HTML user picture'), 'userid' => new external_value(PARAM_INT, 'User ID'), 'delete' => new external_value(PARAM_BOOL, 'Permission to delete=true/false', VALUE_OPTIONAL) ), 'comment' ); } /** * Returns description of method parameters for the add_comments method. * * @return external_function_parameters * @since Moodle 3.8 */ public static function add_comments_parameters() { return new external_function_parameters( [ 'comments' => new external_multiple_structure( new external_single_structure( [ 'contextlevel' => new external_value(PARAM_ALPHA, 'contextlevel system, course, user...'), 'instanceid' => new external_value(PARAM_INT, 'the id of item associated with the contextlevel'), 'component' => new external_value(PARAM_COMPONENT, 'component'), 'content' => new external_value(PARAM_RAW, 'component'), 'itemid' => new external_value(PARAM_INT, 'associated id'), 'area' => new external_value(PARAM_AREA, 'string comment area', VALUE_DEFAULT, ''), ] ) ) ] ); } /** * Add a comment or comments. * * @param array $comments the array of comments to create. * @return array the array containing those comments created. * @throws comment_exception * @since Moodle 3.8 */ public static function add_comments($comments) { global $CFG, $SITE; if (empty($CFG->usecomments)) { throw new comment_exception('commentsnotenabled', 'moodle'); } $params = self::validate_parameters(self::add_comments_parameters(), ['comments' => $comments]); // Validate every intended comment before creating anything, storing the validated comment for use below. foreach ($params['comments'] as $index => $comment) { $context = self::get_context_from_params($comment); self::validate_context($context); list($context, $course, $cm) = get_context_info_array($context->id); if ($context->id == SYSCONTEXTID) { $course = $SITE; } // Initialising comment object. $args = new stdClass(); $args->context = $context; $args->course = $course; $args->cm = $cm; $args->component = $comment['component']; $args->itemid = $comment['itemid']; $args->area = $comment['area']; $manager = new comment($args); if (!$manager->can_post()) { throw new comment_exception('nopermissiontocomment'); } $params['comments'][$index]['preparedcomment'] = $manager; } // Create the comments. $results = []; foreach ($params['comments'] as $comment) { $manager = $comment['preparedcomment']; $newcomment = $manager->add($comment['content']); $newcomment->delete = true; // USER created the comment, so they can delete it. $results[] = $newcomment; } return $results; } /** * Returns description of method result value for the add_comments method. * * @return external_description * @since Moodle 3.8 */ public static function add_comments_returns() { return new external_multiple_structure( self::get_comment_structure() ); } /** * Returns description of method parameters for the delete_comments() method. * * @return external_function_parameters * @since Moodle 3.8 */ public static function delete_comments_parameters() { return new external_function_parameters( [ 'comments' => new external_multiple_structure( new external_value(PARAM_INT, 'id of the comment', VALUE_DEFAULT, 0) ) ] ); } /** * Deletes a comment or comments. * * @param array $comments array of comment ids to be deleted * @return array * @throws comment_exception * @since Moodle 3.8 */ public static function delete_comments(array $comments) { global $CFG, $DB, $USER, $SITE; if (empty($CFG->usecomments)) { throw new comment_exception('commentsnotenabled', 'moodle'); } $params = self::validate_parameters(self::delete_comments_parameters(), ['comments' => $comments]); $commentids = $params['comments']; list($insql, $inparams) = $DB->get_in_or_equal($commentids); $commentrecords = $DB->get_records_select('comments', "id {$insql}", $inparams); // If one or more of the records could not be found, report this and fail early. if (count($commentrecords) != count($comments)) { $invalidcomments = array_diff($commentids, array_column($commentrecords, 'id')); $invalidcommentsstr = implode(',', $invalidcomments); throw new comment_exception("One or more comments could not be found by id: $invalidcommentsstr"); } // Make sure we can delete every one of the comments before actually doing so. $comments = []; // Holds the comment objects, for later deletion. foreach ($commentrecords as $commentrecord) { // Validate the context. list($context, $course, $cm) = get_context_info_array($commentrecord->contextid); if ($context->id == SYSCONTEXTID) { $course = $SITE; } self::validate_context($context); // Make sure the user is allowed to delete the comment. $args = new stdClass; $args->context = $context; $args->course = $course; $args->cm = $cm; $args->component = $commentrecord->component; $args->itemid = $commentrecord->itemid; $args->area = $commentrecord->commentarea; $manager = new comment($args); if (!$manager->can_delete($commentrecord)) { throw new comment_exception('nopermissiontodelentry'); } // User is allowed to delete it, so store the comment object, for use below in final deletion. $comments[$commentrecord->id] = $manager; } // All comments can be deleted by the user. Make it so. foreach ($comments as $commentid => $comment) { $comment->delete($commentid); } return []; } /** * Returns description of method result value for the delete_comments() method. * * @return external_description * @since Moodle 3.8 */ public static function delete_comments_returns() { return new external_warnings(); } } home3/cpr76684/public_html/Aem/auth/classes/external.php 0000644 00000034170 15152114127 0016723 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Auth external API * * @package core_auth * @category external * @copyright 2016 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.2 */ defined('MOODLE_INTERNAL') || die; require_once($CFG->libdir . '/externallib.php'); require_once($CFG->libdir . '/authlib.php'); /** * Auth external functions * * @package core_auth * @category external * @copyright 2016 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.2 */ class core_auth_external extends external_api { /** * Describes the parameters for confirm_user. * * @return external_function_parameters * @since Moodle 3.2 */ public static function confirm_user_parameters() { return new external_function_parameters( array( 'username' => new external_value(core_user::get_property_type('username'), 'User name'), 'secret' => new external_value(core_user::get_property_type('secret'), 'Confirmation secret'), ) ); } /** * Confirm a user account. * * @param string $username user name * @param string $secret confirmation secret (random string) used for validating the confirm request * @return array warnings and success status (true if the user was confirmed, false if he was already confirmed) * @since Moodle 3.2 * @throws moodle_exception */ public static function confirm_user($username, $secret) { global $PAGE; $warnings = array(); $params = self::validate_parameters( self::confirm_user_parameters(), array( 'username' => $username, 'secret' => $secret, ) ); $context = context_system::instance(); $PAGE->set_context($context); if (!$authplugin = signup_get_user_confirmation_authplugin()) { throw new moodle_exception('confirmationnotenabled'); } $confirmed = $authplugin->user_confirm($username, $secret); if ($confirmed == AUTH_CONFIRM_ALREADY) { $success = false; $warnings[] = array( 'item' => 'user', 'itemid' => 0, 'warningcode' => 'alreadyconfirmed', 'message' => s(get_string('alreadyconfirmed')) ); } else if ($confirmed == AUTH_CONFIRM_OK) { $success = true; } else { throw new moodle_exception('invalidconfirmdata'); } $result = array( 'success' => $success, 'warnings' => $warnings, ); return $result; } /** * Describes the confirm_user return value. * * @return external_single_structure * @since Moodle 3.2 */ public static function confirm_user_returns() { return new external_single_structure( array( 'success' => new external_value(PARAM_BOOL, 'True if the user was confirmed, false if he was already confirmed'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for request_password_reset. * * @return external_function_parameters * @since Moodle 3.4 */ public static function request_password_reset_parameters() { return new external_function_parameters( array( 'username' => new external_value(core_user::get_property_type('username'), 'User name', VALUE_DEFAULT, ''), 'email' => new external_value(core_user::get_property_type('email'), 'User email', VALUE_DEFAULT, ''), ) ); } /** * Requests a password reset. * * @param string $username user name * @param string $email user email * @return array warnings and success status (including notices and errors while processing) * @since Moodle 3.4 * @throws moodle_exception */ public static function request_password_reset($username = '', $email = '') { global $CFG, $PAGE; require_once($CFG->dirroot . '/login/lib.php'); $warnings = array(); $params = self::validate_parameters( self::request_password_reset_parameters(), array( 'username' => $username, 'email' => $email, ) ); $context = context_system::instance(); $PAGE->set_context($context); // Needed by format_string calls. // Check if an alternate forgotten password method is set. if (!empty($CFG->forgottenpasswordurl)) { throw new moodle_exception('cannotmailconfirm'); } $errors = core_login_validate_forgot_password_data($params); if (!empty($errors)) { $status = 'dataerror'; $notice = ''; foreach ($errors as $itemname => $message) { $warnings[] = array( 'item' => $itemname, 'itemid' => 0, 'warningcode' => 'fielderror', 'message' => s($message) ); } } else { list($status, $notice, $url) = core_login_process_password_reset($params['username'], $params['email']); } return array( 'status' => $status, 'notice' => $notice, 'warnings' => $warnings, ); } /** * Describes the request_password_reset return value. * * @return external_single_structure * @since Moodle 3.4 */ public static function request_password_reset_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_ALPHANUMEXT, 'The returned status of the process: dataerror: Error in the sent data (username or email). More information in warnings field. emailpasswordconfirmmaybesent: Email sent or not (depends on user found in database). emailpasswordconfirmnotsent: Failure, user not found. emailpasswordconfirmnoemail: Failure, email not found. emailalreadysent: Email already sent. emailpasswordconfirmsent: User pending confirmation. emailresetconfirmsent: Email sent. '), 'notice' => new external_value(PARAM_RAW, 'Important information for the user about the process.'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for the digital minor check. * * @return external_function_parameters * @since Moodle 3.4 */ public static function is_minor_parameters() { return new external_function_parameters( array( 'age' => new external_value(PARAM_INT, 'Age'), 'country' => new external_value(PARAM_ALPHA, 'Country of residence'), ) ); } /** * Requests a check if a user is digital minor. * * @param int $age User age * @param string $country Country of residence * @return array status (true if the user is a minor, false otherwise) * @since Moodle 3.4 * @throws moodle_exception */ public static function is_minor($age, $country) { global $CFG, $PAGE; require_once($CFG->dirroot . '/login/lib.php'); $params = self::validate_parameters( self::is_minor_parameters(), array( 'age' => $age, 'country' => $country, ) ); if (!array_key_exists($params['country'], get_string_manager()->get_list_of_countries())) { throw new invalid_parameter_exception('Invalid value for country parameter (value: '. $params['country'] .')'); } $context = context_system::instance(); $PAGE->set_context($context); // Check if verification of age and location (minor check) is enabled. if (!\core_auth\digital_consent::is_age_digital_consent_verification_enabled()) { throw new moodle_exception('nopermissions', 'error', '', get_string('agelocationverificationdisabled', 'error')); } $status = \core_auth\digital_consent::is_minor($params['age'], $params['country']); return array( 'status' => $status ); } /** * Describes the is_minor return value. * * @return external_single_structure * @since Moodle 3.4 */ public static function is_minor_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'True if the user is considered to be a digital minor, false if not') ) ); } /** * Describes the parameters for is_age_digital_consent_verification_enabled. * * @return external_function_parameters * @since Moodle 3.3 */ public static function is_age_digital_consent_verification_enabled_parameters() { return new external_function_parameters(array()); } /** * Checks if age digital consent verification is enabled. * * @return array status (true if digital consent verification is enabled, false otherwise.) * @since Moodle 3.3 * @throws moodle_exception */ public static function is_age_digital_consent_verification_enabled() { global $PAGE; $context = context_system::instance(); $PAGE->set_context($context); $status = false; // Check if verification is enabled. if (\core_auth\digital_consent::is_age_digital_consent_verification_enabled()) { $status = true; } return array( 'status' => $status ); } /** * Describes the is_age_digital_consent_verification_enabled return value. * * @return external_single_structure * @since Moodle 3.3 */ public static function is_age_digital_consent_verification_enabled_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'True if digital consent verification is enabled, false otherwise.') ) ); } /** * Describes the parameters for resend_confirmation_email. * * @return external_function_parameters * @since Moodle 3.6 */ public static function resend_confirmation_email_parameters() { return new external_function_parameters( array( 'username' => new external_value(core_user::get_property_type('username'), 'Username.'), 'password' => new external_value(core_user::get_property_type('password'), 'Plain text password.'), 'redirect' => new external_value(PARAM_LOCALURL, 'Redirect the user to this site url after confirmation.', VALUE_DEFAULT, ''), ) ); } /** * Requests resend the confirmation email. * * @param string $username user name * @param string $password plain text password * @param string $redirect redirect the user to this site url after confirmation * @return array warnings and success status * @since Moodle 3.6 * @throws moodle_exception */ public static function resend_confirmation_email($username, $password, $redirect = '') { global $PAGE; $warnings = array(); $params = self::validate_parameters( self::resend_confirmation_email_parameters(), array( 'username' => $username, 'password' => $password, 'redirect' => $redirect, ) ); $context = context_system::instance(); $PAGE->set_context($context); // Need by internal APIs. $username = trim(core_text::strtolower($params['username'])); $password = $params['password']; if (is_restored_user($username)) { throw new moodle_exception('restoredaccountresetpassword', 'webservice'); } $user = authenticate_user_login($username, $password); if (empty($user)) { throw new moodle_exception('invalidlogin'); } if ($user->confirmed) { throw new moodle_exception('alreadyconfirmed'); } // Check if we should redirect the user once the user is confirmed. $confirmationurl = null; if (!empty($params['redirect'])) { // Pass via moodle_url to fix thinks like admin links. $redirect = new moodle_url($params['redirect']); $confirmationurl = new moodle_url('/login/confirm.php', array('redirect' => $redirect->out())); } $status = send_confirmation_email($user, $confirmationurl); return array( 'status' => $status, 'warnings' => $warnings, ); } /** * Describes the resend_confirmation_email return value. * * @return external_single_structure * @since Moodle 3.6 */ public static function resend_confirmation_email_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'True if the confirmation email was sent, false otherwise.'), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/mod/resource/classes/external.php 0000644 00000016536 15152154525 0020404 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Resource external API * * @package mod_resource * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ use core_course\external\helper_for_get_mods_by_courses; defined('MOODLE_INTERNAL') || die; require_once("$CFG->libdir/externallib.php"); /** * Resource external functions * * @package mod_resource * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ class mod_resource_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.0 */ public static function view_resource_parameters() { return new external_function_parameters( array( 'resourceid' => new external_value(PARAM_INT, 'resource instance id') ) ); } /** * Simulate the resource/view.php web interface page: trigger events, completion, etc... * * @param int $resourceid the resource instance id * @return array of warnings and status result * @since Moodle 3.0 * @throws moodle_exception */ public static function view_resource($resourceid) { global $DB, $CFG; require_once($CFG->dirroot . "/mod/resource/lib.php"); $params = self::validate_parameters(self::view_resource_parameters(), array( 'resourceid' => $resourceid )); $warnings = array(); // Request and permission validation. $resource = $DB->get_record('resource', array('id' => $params['resourceid']), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($resource, 'resource'); $context = context_module::instance($cm->id); self::validate_context($context); require_capability('mod/resource:view', $context); // Call the resource/lib API. resource_view($resource, $course, $cm, $context); $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_resource_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Describes the parameters for get_resources_by_courses. * * @return external_function_parameters * @since Moodle 3.3 */ public static function get_resources_by_courses_parameters() { return new external_function_parameters ( array( 'courseids' => new external_multiple_structure( new external_value(PARAM_INT, 'Course id'), 'Array of course ids', VALUE_DEFAULT, array() ), ) ); } /** * Returns a list of files in a provided list of courses. * If no list is provided all files that the user can view will be returned. * * @param array $courseids course ids * @return array of warnings and files * @since Moodle 3.3 */ public static function get_resources_by_courses($courseids = array()) { $warnings = array(); $returnedresources = array(); $params = array( 'courseids' => $courseids, ); $params = self::validate_parameters(self::get_resources_by_courses_parameters(), $params); $mycourses = array(); if (empty($params['courseids'])) { $mycourses = enrol_get_my_courses(); $params['courseids'] = array_keys($mycourses); } // Ensure there are courseids to loop through. if (!empty($params['courseids'])) { list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses); // Get the resources in this course, this function checks users visibility permissions. // We can avoid then additional validate_context calls. $resources = get_all_instances_in_courses("resource", $courses); foreach ($resources as $resource) { $context = context_module::instance($resource->coursemodule); helper_for_get_mods_by_courses::format_name_and_intro($resource, 'mod_resource'); $resource->contentfiles = external_util::get_area_files($context->id, 'mod_resource', 'content'); $returnedresources[] = $resource; } } $result = array( 'resources' => $returnedresources, 'warnings' => $warnings ); return $result; } /** * Describes the get_resources_by_courses return value. * * @return external_single_structure * @since Moodle 3.3 */ public static function get_resources_by_courses_returns() { return new external_single_structure( array( 'resources' => new external_multiple_structure( new external_single_structure(array_merge( helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(), [ 'contentfiles' => new external_files('Files in the content'), 'tobemigrated' => new external_value(PARAM_INT, 'Whether this resource was migrated'), 'legacyfiles' => new external_value(PARAM_INT, 'Legacy files flag'), 'legacyfileslast' => new external_value(PARAM_INT, 'Legacy files last control flag'), 'display' => new external_value(PARAM_INT, 'How to display the resource'), 'displayoptions' => new external_value(PARAM_RAW, 'Display options (width, height)'), 'filterfiles' => new external_value(PARAM_INT, 'If filters should be applied to the resource content'), 'revision' => new external_value(PARAM_INT, 'Incremented when after each file changes, to avoid cache'), 'timemodified' => new external_value(PARAM_INT, 'Last time the resource was modified'), ] )) ), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/question/classes/external.php 0000644 00000032107 15152250153 0017627 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * External question API * * @package core_question * @category external * @copyright 2016 Pau Ferrer <pau@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/externallib.php"); require_once($CFG->dirroot . '/question/engine/lib.php'); require_once($CFG->dirroot . '/question/engine/datalib.php'); require_once($CFG->libdir . '/questionlib.php'); /** * Question external functions * * @package core_question * @category external * @copyright 2016 Pau Ferrer <pau@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ class core_question_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.1 */ public static function update_flag_parameters() { return new external_function_parameters( array( 'qubaid' => new external_value(PARAM_INT, 'the question usage id.'), 'questionid' => new external_value(PARAM_INT, 'the question id'), 'qaid' => new external_value(PARAM_INT, 'the question_attempt id'), 'slot' => new external_value(PARAM_INT, 'the slot number within the usage'), 'checksum' => new external_value(PARAM_ALPHANUM, 'computed checksum with the last three arguments and the users username'), 'newstate' => new external_value(PARAM_BOOL, 'the new state of the flag. true = flagged') ) ); } /** * Update the flag state of a question attempt. * * @param int $qubaid the question usage id. * @param int $questionid the question id. * @param int $qaid the question_attempt id. * @param int $slot the slot number within the usage. * @param string $checksum checksum, as computed by {@link get_toggle_checksum()} * corresponding to the last three arguments and the users username. * @param bool $newstate the new state of the flag. true = flagged. * @return array (success infos and fail infos) * @since Moodle 3.1 */ public static function update_flag($qubaid, $questionid, $qaid, $slot, $checksum, $newstate) { global $CFG, $DB; $params = self::validate_parameters(self::update_flag_parameters(), array( 'qubaid' => $qubaid, 'questionid' => $questionid, 'qaid' => $qaid, 'slot' => $slot, 'checksum' => $checksum, 'newstate' => $newstate ) ); $warnings = array(); self::validate_context(context_system::instance()); // The checksum will be checked to provide security flagging other users questions. question_flags::update_flag($params['qubaid'], $params['questionid'], $params['qaid'], $params['slot'], $params['checksum'], $params['newstate']); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Returns description of method result value * * @return external_description * @since Moodle 3.1 */ public static function update_flag_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Returns description of method parameters. * * @return external_function_parameters. * @deprecated since Moodle 4.0 * @see \qbank_tagquestion\external\qbank_tagquestion_external * @todo Final deprecation on Moodle 4.4 MDL-72438 */ public static function submit_tags_form_parameters() { return new external_function_parameters([ 'questionid' => new external_value(PARAM_INT, 'The question id'), 'contextid' => new external_value(PARAM_INT, 'The editing context id'), 'formdata' => new external_value(PARAM_RAW, 'The data from the tag form'), ]); } /** * Handles the tags form submission. * * @param int $questionid The question id. * @param int $contextid The editing context id. * @param string $formdata The question tag form data in a URI encoded param string * @return array The created or modified question tag * @deprecated since Moodle 4.0 * @see \qbank_tagquestion\external\qbank_tagquestion_external * @todo Final deprecation on Moodle 4.4 MDL-72438 */ public static function submit_tags_form($questionid, $contextid, $formdata) { global $DB, $CFG; $data = []; $result = ['status' => false]; // Parameter validation. $params = self::validate_parameters(self::submit_tags_form_parameters(), [ 'questionid' => $questionid, 'contextid' => $contextid, 'formdata' => $formdata ]); $editingcontext = \context::instance_by_id($contextid); self::validate_context($editingcontext); parse_str($params['formdata'], $data); if (!$question = $DB->get_record_sql(' SELECT q.*, qc.contextid FROM {question} q JOIN {question_categories} qc ON qc.id = q.category WHERE q.id = ?', [$questionid])) { throw new \moodle_exception('questiondoesnotexist', 'question'); } require_once($CFG->libdir . '/questionlib.php'); $cantag = question_has_capability_on($question, 'tag'); $questioncontext = \context::instance_by_id($question->contextid); $contexts = new \core_question\local\bank\question_edit_contexts($editingcontext); $formoptions = [ 'editingcontext' => $editingcontext, 'questioncontext' => $questioncontext, 'contexts' => $contexts->all() ]; $mform = new \qbank_tagquestion\form\tags_form(null, $formoptions, 'post', '', null, $cantag, $data); if ($validateddata = $mform->get_data()) { if ($cantag) { if (isset($validateddata->tags)) { // Due to a mform bug, if there's no tags set on the tag element, it submits the name as the value. // The only way to discover is checking if the tag element is an array. $tags = is_array($validateddata->tags) ? $validateddata->tags : []; core_tag_tag::set_item_tags('core_question', 'question', $validateddata->id, $questioncontext, $tags); $result['status'] = true; } if (isset($validateddata->coursetags)) { $coursetags = is_array($validateddata->coursetags) ? $validateddata->coursetags : []; core_tag_tag::set_item_tags('core_question', 'question', $validateddata->id, $editingcontext->get_course_context(false), $coursetags); $result['status'] = true; } } } return $result; } /** * Returns description of method result value. * * @deprecated since Moodle 4.0 * @see \qbank_tagquestion\external\qbank_tagquestion_external * @todo Final deprecation on Moodle 4.4 MDL-72438 */ public static function submit_tags_form_returns() { return new external_single_structure([ 'status' => new external_value(PARAM_BOOL, 'status: true if success') ]); } /** * Marking the method as deprecated. * * @return bool * @todo Final deprecation on Moodle 4.4 MDL-72438 */ public static function submit_tags_form_is_deprecated() { return true; } /** * Returns description of method parameters. * * @return external_function_parameters. */ public static function get_random_question_summaries_parameters() { return new external_function_parameters([ 'categoryid' => new external_value(PARAM_INT, 'Category id to find random questions'), 'includesubcategories' => new external_value(PARAM_BOOL, 'Include the subcategories in the search'), 'tagids' => new external_multiple_structure( new external_value(PARAM_INT, 'Tag id') ), 'contextid' => new external_value(PARAM_INT, 'Context id that the questions will be rendered in (used for exporting)'), 'limit' => new external_value(PARAM_INT, 'Maximum number of results to return', VALUE_DEFAULT, 0), 'offset' => new external_value(PARAM_INT, 'Number of items to skip from the begging of the result set', VALUE_DEFAULT, 0) ]); } /** * Gets the list of random questions for the given criteria. The questions * will be exported in a summaries format and won't include all of the * question data. * * @param int $categoryid Category id to find random questions * @param bool $includesubcategories Include the subcategories in the search * @param int[] $tagids Only include questions with these tags * @param int $contextid The context id where the questions will be rendered * @param int $limit Maximum number of results to return * @param int $offset Number of items to skip from the beginning of the result set. * @return array The list of questions and total question count. */ public static function get_random_question_summaries( $categoryid, $includesubcategories, $tagids, $contextid, $limit = 0, $offset = 0 ) { global $DB, $PAGE; // Parameter validation. $params = self::validate_parameters( self::get_random_question_summaries_parameters(), [ 'categoryid' => $categoryid, 'includesubcategories' => $includesubcategories, 'tagids' => $tagids, 'contextid' => $contextid, 'limit' => $limit, 'offset' => $offset ] ); $categoryid = $params['categoryid']; $includesubcategories = $params['includesubcategories']; $tagids = $params['tagids']; $contextid = $params['contextid']; $limit = $params['limit']; $offset = $params['offset']; $context = \context::instance_by_id($contextid); self::validate_context($context); $categorycontextid = $DB->get_field('question_categories', 'contextid', ['id' => $categoryid], MUST_EXIST); $categorycontext = \context::instance_by_id($categorycontextid); $editcontexts = new \core_question\local\bank\question_edit_contexts($categorycontext); // The user must be able to view all questions in the category that they are requesting. $editcontexts->require_cap('moodle/question:viewall'); $loader = new \core_question\local\bank\random_question_loader(new qubaid_list([])); // Only load the properties we require from the DB. $properties = \core_question\external\question_summary_exporter::get_mandatory_properties(); $questions = $loader->get_questions($categoryid, $includesubcategories, $tagids, $limit, $offset, $properties); $totalcount = $loader->count_questions($categoryid, $includesubcategories, $tagids); $renderer = $PAGE->get_renderer('core'); $formattedquestions = array_map(function($question) use ($context, $renderer) { $exporter = new \core_question\external\question_summary_exporter($question, ['context' => $context]); return $exporter->export($renderer); }, $questions); return [ 'totalcount' => $totalcount, 'questions' => $formattedquestions ]; } /** * Returns description of method result value. */ public static function get_random_question_summaries_returns() { return new external_single_structure([ 'totalcount' => new external_value(PARAM_INT, 'total number of questions in result set'), 'questions' => new external_multiple_structure( \core_question\external\question_summary_exporter::get_read_structure() ) ]); } } home3/cpr76684/public_html/Aem/mod/quiz/classes/external.php 0000644 00000254336 15152263065 0017547 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Quiz external API * * @package mod_quiz * @category external * @copyright 2016 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ use core_course\external\helper_for_get_mods_by_courses; defined('MOODLE_INTERNAL') || die; require_once($CFG->libdir . '/externallib.php'); require_once($CFG->dirroot . '/mod/quiz/locallib.php'); /** * Quiz external functions * * @package mod_quiz * @category external * @copyright 2016 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.1 */ class mod_quiz_external extends external_api { /** * Describes the parameters for get_quizzes_by_courses. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_quizzes_by_courses_parameters() { return new external_function_parameters ( array( 'courseids' => new external_multiple_structure( new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() ), ) ); } /** * Returns a list of quizzes in a provided list of courses, * if no list is provided all quizzes that the user can view will be returned. * * @param array $courseids Array of course ids * @return array of quizzes details * @since Moodle 3.1 */ public static function get_quizzes_by_courses($courseids = array()) { global $USER; $warnings = array(); $returnedquizzes = array(); $params = array( 'courseids' => $courseids, ); $params = self::validate_parameters(self::get_quizzes_by_courses_parameters(), $params); $mycourses = array(); if (empty($params['courseids'])) { $mycourses = enrol_get_my_courses(); $params['courseids'] = array_keys($mycourses); } // Ensure there are courseids to loop through. if (!empty($params['courseids'])) { list($courses, $warnings) = external_util::validate_courses($params['courseids'], $mycourses); // Get the quizzes in this course, this function checks users visibility permissions. // We can avoid then additional validate_context calls. $quizzes = get_all_instances_in_courses("quiz", $courses); foreach ($quizzes as $quiz) { $context = context_module::instance($quiz->coursemodule); // Update quiz with override information. $quiz = quiz_update_effective_access($quiz, $USER->id); // Entry to return. $quizdetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values( $quiz, 'mod_quiz', 'mod/quiz:view', 'mod/quiz:view'); if (has_capability('mod/quiz:view', $context)) { $quizdetails['introfiles'] = external_util::get_area_files($context->id, 'mod_quiz', 'intro', false, false); $viewablefields = array('timeopen', 'timeclose', 'attempts', 'timelimit', 'grademethod', 'decimalpoints', 'questiondecimalpoints', 'sumgrades', 'grade', 'preferredbehaviour'); // Sometimes this function returns just empty. $hasfeedback = quiz_has_feedback($quiz); $quizdetails['hasfeedback'] = (!empty($hasfeedback)) ? 1 : 0; $timenow = time(); $quizobj = quiz::create($quiz->id, $USER->id); $accessmanager = new quiz_access_manager($quizobj, $timenow, has_capability('mod/quiz:ignoretimelimits', $context, null, false)); // Fields the user could see if have access to the quiz. if (!$accessmanager->prevent_access()) { $quizdetails['hasquestions'] = (int) $quizobj->has_questions(); $quizdetails['autosaveperiod'] = get_config('quiz', 'autosaveperiod'); $additionalfields = array('attemptonlast', 'reviewattempt', 'reviewcorrectness', 'reviewmarks', 'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer', 'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'overduehandling', 'graceperiod', 'canredoquestions', 'allowofflineattempts'); $viewablefields = array_merge($viewablefields, $additionalfields); // Any course module fields that previously existed in quiz. $quizdetails['completionpass'] = $quizobj->get_cm()->completionpassgrade; } // Fields only for managers. if (has_capability('moodle/course:manageactivities', $context)) { $additionalfields = array('shuffleanswers', 'timecreated', 'timemodified', 'password', 'subnet'); $viewablefields = array_merge($viewablefields, $additionalfields); } foreach ($viewablefields as $field) { $quizdetails[$field] = $quiz->{$field}; } } $returnedquizzes[] = $quizdetails; } } $result = array(); $result['quizzes'] = $returnedquizzes; $result['warnings'] = $warnings; return $result; } /** * Describes the get_quizzes_by_courses return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_quizzes_by_courses_returns() { return new external_single_structure( array( 'quizzes' => new external_multiple_structure( new external_single_structure(array_merge( helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(true), [ 'timeopen' => new external_value(PARAM_INT, 'The time when this quiz opens. (0 = no restriction.)', VALUE_OPTIONAL), 'timeclose' => new external_value(PARAM_INT, 'The time when this quiz closes. (0 = no restriction.)', VALUE_OPTIONAL), 'timelimit' => new external_value(PARAM_INT, 'The time limit for quiz attempts, in seconds.', VALUE_OPTIONAL), 'overduehandling' => new external_value(PARAM_ALPHA, 'The method used to handle overdue attempts. \'autosubmit\', \'graceperiod\' or \'autoabandon\'.', VALUE_OPTIONAL), 'graceperiod' => new external_value(PARAM_INT, 'The amount of time (in seconds) after the time limit runs out during which attempts can still be submitted, if overduehandling is set to allow it.', VALUE_OPTIONAL), 'preferredbehaviour' => new external_value(PARAM_ALPHANUMEXT, 'The behaviour to ask questions to use.', VALUE_OPTIONAL), 'canredoquestions' => new external_value(PARAM_INT, 'Allows students to redo any completed question within a quiz attempt.', VALUE_OPTIONAL), 'attempts' => new external_value(PARAM_INT, 'The maximum number of attempts a student is allowed.', VALUE_OPTIONAL), 'attemptonlast' => new external_value(PARAM_INT, 'Whether subsequent attempts start from the answer to the previous attempt (1) or start blank (0).', VALUE_OPTIONAL), 'grademethod' => new external_value(PARAM_INT, 'One of the values QUIZ_GRADEHIGHEST, QUIZ_GRADEAVERAGE, QUIZ_ATTEMPTFIRST or QUIZ_ATTEMPTLAST.', VALUE_OPTIONAL), 'decimalpoints' => new external_value(PARAM_INT, 'Number of decimal points to use when displaying grades.', VALUE_OPTIONAL), 'questiondecimalpoints' => new external_value(PARAM_INT, 'Number of decimal points to use when displaying question grades. (-1 means use decimalpoints.)', VALUE_OPTIONAL), 'reviewattempt' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. This is a bit field, decoded by the mod_quiz_display_options class. It is formed by ORing together the constants defined there.', VALUE_OPTIONAL), 'reviewcorrectness' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewmarks' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewspecificfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewgeneralfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewrightanswer' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewoverallfeedback' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'questionsperpage' => new external_value(PARAM_INT, 'How often to insert a page break when editing the quiz, or when shuffling the question order.', VALUE_OPTIONAL), 'navmethod' => new external_value(PARAM_ALPHA, 'Any constraints on how the user is allowed to navigate around the quiz. Currently recognised values are \'free\' and \'seq\'.', VALUE_OPTIONAL), 'shuffleanswers' => new external_value(PARAM_INT, 'Whether the parts of the question should be shuffled, in those question types that support it.', VALUE_OPTIONAL), 'sumgrades' => new external_value(PARAM_FLOAT, 'The total of all the question instance maxmarks.', VALUE_OPTIONAL), 'grade' => new external_value(PARAM_FLOAT, 'The total that the quiz overall grade is scaled to be out of.', VALUE_OPTIONAL), 'timecreated' => new external_value(PARAM_INT, 'The time when the quiz was added to the course.', VALUE_OPTIONAL), 'timemodified' => new external_value(PARAM_INT, 'Last modified time.', VALUE_OPTIONAL), 'password' => new external_value(PARAM_RAW, 'A password that the student must enter before starting or continuing a quiz attempt.', VALUE_OPTIONAL), 'subnet' => new external_value(PARAM_RAW, 'Used to restrict the IP addresses from which this quiz can be attempted. The format is as requried by the address_in_subnet function.', VALUE_OPTIONAL), 'browsersecurity' => new external_value(PARAM_ALPHANUMEXT, 'Restriciton on the browser the student must use. E.g. \'securewindow\'.', VALUE_OPTIONAL), 'delay1' => new external_value(PARAM_INT, 'Delay that must be left between the first and second attempt, in seconds.', VALUE_OPTIONAL), 'delay2' => new external_value(PARAM_INT, 'Delay that must be left between the second and subsequent attempt, in seconds.', VALUE_OPTIONAL), 'showuserpicture' => new external_value(PARAM_INT, 'Option to show the user\'s picture during the attempt and on the review page.', VALUE_OPTIONAL), 'showblocks' => new external_value(PARAM_INT, 'Whether blocks should be shown on the attempt.php and review.php pages.', VALUE_OPTIONAL), 'completionattemptsexhausted' => new external_value(PARAM_INT, 'Mark quiz complete when the student has exhausted the maximum number of attempts', VALUE_OPTIONAL), 'completionpass' => new external_value(PARAM_INT, 'Whether to require passing grade', VALUE_OPTIONAL), 'allowofflineattempts' => new external_value(PARAM_INT, 'Whether to allow the quiz to be attempted offline in the mobile app', VALUE_OPTIONAL), 'autosaveperiod' => new external_value(PARAM_INT, 'Auto-save delay', VALUE_OPTIONAL), 'hasfeedback' => new external_value(PARAM_INT, 'Whether the quiz has any non-blank feedback text', VALUE_OPTIONAL), 'hasquestions' => new external_value(PARAM_INT, 'Whether the quiz has questions', VALUE_OPTIONAL), ] )) ), 'warnings' => new external_warnings(), ) ); } /** * Utility function for validating a quiz. * * @param int $quizid quiz instance id * @return array array containing the quiz, course, context and course module objects * @since Moodle 3.1 */ protected static function validate_quiz($quizid) { global $DB; // Request and permission validation. $quiz = $DB->get_record('quiz', array('id' => $quizid), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($quiz, 'quiz'); $context = context_module::instance($cm->id); self::validate_context($context); return array($quiz, $course, $cm, $context); } /** * Describes the parameters for view_quiz. * * @return external_function_parameters * @since Moodle 3.1 */ public static function view_quiz_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), ) ); } /** * Trigger the course module viewed event and update the module completion status. * * @param int $quizid quiz instance id * @return array of warnings and status result * @since Moodle 3.1 * @throws moodle_exception */ public static function view_quiz($quizid) { global $DB; $params = self::validate_parameters(self::view_quiz_parameters(), array('quizid' => $quizid)); $warnings = array(); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); // Trigger course_module_viewed event and completion. quiz_view($quiz, $course, $cm, $context); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Describes the view_quiz return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function view_quiz_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_user_attempts. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_user_attempts_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'userid' => new external_value(PARAM_INT, 'user id, empty for current user', VALUE_DEFAULT, 0), 'status' => new external_value(PARAM_ALPHA, 'quiz status: all, finished or unfinished', VALUE_DEFAULT, 'finished'), 'includepreviews' => new external_value(PARAM_BOOL, 'whether to include previews or not', VALUE_DEFAULT, false), ) ); } /** * Return a list of attempts for the given quiz and user. * * @param int $quizid quiz instance id * @param int $userid user id * @param string $status quiz status: all, finished or unfinished * @param bool $includepreviews whether to include previews or not * @return array of warnings and the list of attempts * @since Moodle 3.1 * @throws invalid_parameter_exception */ public static function get_user_attempts($quizid, $userid = 0, $status = 'finished', $includepreviews = false) { global $DB, $USER; $warnings = array(); $params = array( 'quizid' => $quizid, 'userid' => $userid, 'status' => $status, 'includepreviews' => $includepreviews, ); $params = self::validate_parameters(self::get_user_attempts_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); if (!in_array($params['status'], array('all', 'finished', 'unfinished'))) { throw new invalid_parameter_exception('Invalid status value'); } // Default value for userid. if (empty($params['userid'])) { $params['userid'] = $USER->id; } $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/quiz:viewreports', $context); } // Update quiz with override information. $quiz = quiz_update_effective_access($quiz, $params['userid']); $attempts = quiz_get_user_attempts($quiz->id, $user->id, $params['status'], $params['includepreviews']); $attemptresponse = []; foreach ($attempts as $attempt) { $reviewoptions = quiz_get_review_options($quiz, $attempt, $context); if (!has_capability('mod/quiz:viewreports', $context) && ($reviewoptions->marks < question_display_options::MARK_AND_MAX || $attempt->state != quiz_attempt::FINISHED)) { // Blank the mark if the teacher does not allow it. $attempt->sumgrades = null; } $attemptresponse[] = $attempt; } $result = array(); $result['attempts'] = $attemptresponse; $result['warnings'] = $warnings; return $result; } /** * Describes a single attempt structure. * * @return external_single_structure the attempt structure */ private static function attempt_structure() { return new external_single_structure( array( 'id' => new external_value(PARAM_INT, 'Attempt id.', VALUE_OPTIONAL), 'quiz' => new external_value(PARAM_INT, 'Foreign key reference to the quiz that was attempted.', VALUE_OPTIONAL), 'userid' => new external_value(PARAM_INT, 'Foreign key reference to the user whose attempt this is.', VALUE_OPTIONAL), 'attempt' => new external_value(PARAM_INT, 'Sequentially numbers this students attempts at this quiz.', VALUE_OPTIONAL), 'uniqueid' => new external_value(PARAM_INT, 'Foreign key reference to the question_usage that holds the details of the the question_attempts that make up this quiz attempt.', VALUE_OPTIONAL), 'layout' => new external_value(PARAM_RAW, 'Attempt layout.', VALUE_OPTIONAL), 'currentpage' => new external_value(PARAM_INT, 'Attempt current page.', VALUE_OPTIONAL), 'preview' => new external_value(PARAM_INT, 'Whether is a preview attempt or not.', VALUE_OPTIONAL), 'state' => new external_value(PARAM_ALPHA, 'The current state of the attempts. \'inprogress\', \'overdue\', \'finished\' or \'abandoned\'.', VALUE_OPTIONAL), 'timestart' => new external_value(PARAM_INT, 'Time when the attempt was started.', VALUE_OPTIONAL), 'timefinish' => new external_value(PARAM_INT, 'Time when the attempt was submitted. 0 if the attempt has not been submitted yet.', VALUE_OPTIONAL), 'timemodified' => new external_value(PARAM_INT, 'Last modified time.', VALUE_OPTIONAL), 'timemodifiedoffline' => new external_value(PARAM_INT, 'Last modified time via webservices.', VALUE_OPTIONAL), 'timecheckstate' => new external_value(PARAM_INT, 'Next time quiz cron should check attempt for state changes. NULL means never check.', VALUE_OPTIONAL), 'sumgrades' => new external_value(PARAM_FLOAT, 'Total marks for this attempt.', VALUE_OPTIONAL), 'gradednotificationsenttime' => new external_value(PARAM_INT, 'Time when the student was notified that manual grading of their attempt was complete.', VALUE_OPTIONAL), ) ); } /** * Describes the get_user_attempts return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_user_attempts_returns() { return new external_single_structure( array( 'attempts' => new external_multiple_structure(self::attempt_structure()), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_user_best_grade. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_user_best_grade_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'userid' => new external_value(PARAM_INT, 'user id', VALUE_DEFAULT, 0), ) ); } /** * Get the best current grade for the given user on a quiz. * * @param int $quizid quiz instance id * @param int $userid user id * @return array of warnings and the grade information * @since Moodle 3.1 */ public static function get_user_best_grade($quizid, $userid = 0) { global $DB, $USER, $CFG; require_once($CFG->libdir . '/gradelib.php'); $warnings = array(); $params = array( 'quizid' => $quizid, 'userid' => $userid, ); $params = self::validate_parameters(self::get_user_best_grade_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); // Default value for userid. if (empty($params['userid'])) { $params['userid'] = $USER->id; } $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/quiz:viewreports', $context); } $result = array(); // This code was mostly copied from mod/quiz/view.php. We need to make the web service logic consistent. // Get this user's attempts. $attempts = quiz_get_user_attempts($quiz->id, $user->id, 'all'); $canviewgrade = false; if ($attempts) { if ($USER->id != $user->id) { // No need to check the permission here. We did it at by require_capability('mod/quiz:viewreports', $context). $canviewgrade = true; } else { // Work out which columns we need, taking account what data is available in each attempt. [$notused, $alloptions] = quiz_get_combined_reviewoptions($quiz, $attempts); $canviewgrade = $alloptions->marks >= question_display_options::MARK_AND_MAX; } } $grade = $canviewgrade ? quiz_get_best_grade($quiz, $user->id) : null; if ($grade === null) { $result['hasgrade'] = false; } else { $result['hasgrade'] = true; $result['grade'] = $grade; } // Inform user of the grade to pass if non-zero. $gradinginfo = grade_get_grades($course->id, 'mod', 'quiz', $quiz->id, $user->id); if (!empty($gradinginfo->items)) { $item = $gradinginfo->items[0]; if ($item && grade_floats_different($item->gradepass, 0)) { $result['gradetopass'] = $item->gradepass; } } $result['warnings'] = $warnings; return $result; } /** * Describes the get_user_best_grade return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_user_best_grade_returns() { return new external_single_structure( array( 'hasgrade' => new external_value(PARAM_BOOL, 'Whether the user has a grade on the given quiz.'), 'grade' => new external_value(PARAM_FLOAT, 'The grade (only if the user has a grade).', VALUE_OPTIONAL), 'gradetopass' => new external_value(PARAM_FLOAT, 'The grade to pass the quiz (only if set).', VALUE_OPTIONAL), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_combined_review_options. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_combined_review_options_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'userid' => new external_value(PARAM_INT, 'user id (empty for current user)', VALUE_DEFAULT, 0), ) ); } /** * Combines the review options from a number of different quiz attempts. * * @param int $quizid quiz instance id * @param int $userid user id (empty for current user) * @return array of warnings and the review options * @since Moodle 3.1 */ public static function get_combined_review_options($quizid, $userid = 0) { global $DB, $USER; $warnings = array(); $params = array( 'quizid' => $quizid, 'userid' => $userid, ); $params = self::validate_parameters(self::get_combined_review_options_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); // Default value for userid. if (empty($params['userid'])) { $params['userid'] = $USER->id; } $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/quiz:viewreports', $context); } $attempts = quiz_get_user_attempts($quiz->id, $user->id, 'all', true); $result = array(); $result['someoptions'] = []; $result['alloptions'] = []; list($someoptions, $alloptions) = quiz_get_combined_reviewoptions($quiz, $attempts); foreach (array('someoptions', 'alloptions') as $typeofoption) { foreach ($$typeofoption as $key => $value) { $result[$typeofoption][] = array( "name" => $key, "value" => (!empty($value)) ? $value : 0 ); } } $result['warnings'] = $warnings; return $result; } /** * Describes the get_combined_review_options return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_combined_review_options_returns() { return new external_single_structure( array( 'someoptions' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'option name'), 'value' => new external_value(PARAM_INT, 'option value'), ) ) ), 'alloptions' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'option name'), 'value' => new external_value(PARAM_INT, 'option value'), ) ) ), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for start_attempt. * * @return external_function_parameters * @since Moodle 3.1 */ public static function start_attempt_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ), 'forcenew' => new external_value(PARAM_BOOL, 'Whether to force a new attempt or not.', VALUE_DEFAULT, false), ) ); } /** * Starts a new attempt at a quiz. * * @param int $quizid quiz instance id * @param array $preflightdata preflight required data (like passwords) * @param bool $forcenew Whether to force a new attempt or not. * @return array of warnings and the attempt basic data * @since Moodle 3.1 * @throws moodle_quiz_exception */ public static function start_attempt($quizid, $preflightdata = array(), $forcenew = false) { global $DB, $USER; $warnings = array(); $attempt = array(); $params = array( 'quizid' => $quizid, 'preflightdata' => $preflightdata, 'forcenew' => $forcenew, ); $params = self::validate_parameters(self::start_attempt_parameters(), $params); $forcenew = $params['forcenew']; list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $quizobj = quiz::create($cm->instance, $USER->id); // Check questions. if (!$quizobj->has_questions()) { throw new moodle_quiz_exception($quizobj, 'noquestionsfound'); } // Create an object to manage all the other (non-roles) access rules. $timenow = time(); $accessmanager = $quizobj->get_access_manager($timenow); // Validate permissions for creating a new attempt and start a new preview attempt if required. list($currentattemptid, $attemptnumber, $lastattempt, $messages, $page) = quiz_validate_new_attempt($quizobj, $accessmanager, $forcenew, -1, false); // Check access. if (!$quizobj->is_preview_user() && $messages) { // Create warnings with the exact messages. foreach ($messages as $message) { $warnings[] = array( 'item' => 'quiz', 'itemid' => $quiz->id, 'warningcode' => '1', 'message' => clean_text($message, PARAM_TEXT) ); } } else { if ($accessmanager->is_preflight_check_required($currentattemptid)) { // Need to do some checks before allowing the user to continue. $provideddata = array(); foreach ($params['preflightdata'] as $data) { $provideddata[$data['name']] = $data['value']; } $errors = $accessmanager->validate_preflight_check($provideddata, [], $currentattemptid); if (!empty($errors)) { throw new moodle_quiz_exception($quizobj, array_shift($errors)); } // Pre-flight check passed. $accessmanager->notify_preflight_check_passed($currentattemptid); } if ($currentattemptid) { if ($lastattempt->state == quiz_attempt::OVERDUE) { throw new moodle_quiz_exception($quizobj, 'stateoverdue'); } else { throw new moodle_quiz_exception($quizobj, 'attemptstillinprogress'); } } $offlineattempt = WS_SERVER ? true : false; $attempt = quiz_prepare_and_start_new_attempt($quizobj, $attemptnumber, $lastattempt, $offlineattempt); } $result = array(); $result['attempt'] = $attempt; $result['warnings'] = $warnings; return $result; } /** * Describes the start_attempt return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function start_attempt_returns() { return new external_single_structure( array( 'attempt' => self::attempt_structure(), 'warnings' => new external_warnings(), ) ); } /** * Utility function for validating a given attempt * * @param array $params array of parameters including the attemptid and preflight data * @param bool $checkaccessrules whether to check the quiz access rules or not * @param bool $failifoverdue whether to return error if the attempt is overdue * @return array containing the attempt object and access messages * @throws moodle_quiz_exception * @since Moodle 3.1 */ protected static function validate_attempt($params, $checkaccessrules = true, $failifoverdue = true) { global $USER; $attemptobj = quiz_attempt::create($params['attemptid']); $context = context_module::instance($attemptobj->get_cm()->id); self::validate_context($context); // Check that this attempt belongs to this user. if ($attemptobj->get_userid() != $USER->id) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'notyourattempt'); } // General capabilities check. $ispreviewuser = $attemptobj->is_preview_user(); if (!$ispreviewuser) { $attemptobj->require_capability('mod/quiz:attempt'); } // Check the access rules. $accessmanager = $attemptobj->get_access_manager(time()); $messages = array(); if ($checkaccessrules) { // If the attempt is now overdue, or abandoned, deal with that. $attemptobj->handle_if_time_expired(time(), true); $messages = $accessmanager->prevent_access(); if (!$ispreviewuser && $messages) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'attempterror'); } } // Attempt closed?. if ($attemptobj->is_finished()) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'attemptalreadyclosed'); } else if ($failifoverdue && $attemptobj->get_state() == quiz_attempt::OVERDUE) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'stateoverdue'); } // User submitted data (like the quiz password). if ($accessmanager->is_preflight_check_required($attemptobj->get_attemptid())) { $provideddata = array(); foreach ($params['preflightdata'] as $data) { $provideddata[$data['name']] = $data['value']; } $errors = $accessmanager->validate_preflight_check($provideddata, [], $params['attemptid']); if (!empty($errors)) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), array_shift($errors)); } // Pre-flight check passed. $accessmanager->notify_preflight_check_passed($params['attemptid']); } if (isset($params['page'])) { // Check if the page is out of range. if ($params['page'] != $attemptobj->force_page_number_into_range($params['page'])) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'Invalid page number'); } // Prevent out of sequence access. if (!$attemptobj->check_page_access($params['page'])) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'Out of sequence access'); } // Check slots. $slots = $attemptobj->get_slots($params['page']); if (empty($slots)) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noquestionsfound'); } } return array($attemptobj, $messages); } /** * Describes a single question structure. * * @return external_single_structure the question data. Some fields may not be returned depending on the quiz display settings. * @since Moodle 3.1 * @since Moodle 3.2 blockedbyprevious parameter added. */ private static function question_structure() { return new external_single_structure( array( 'slot' => new external_value(PARAM_INT, 'slot number'), 'type' => new external_value(PARAM_ALPHANUMEXT, 'question type, i.e: multichoice'), 'page' => new external_value(PARAM_INT, 'page of the quiz this question appears on'), 'html' => new external_value(PARAM_RAW, 'the question rendered'), 'responsefileareas' => new external_multiple_structure( new external_single_structure( array( 'area' => new external_value(PARAM_NOTAGS, 'File area name'), 'files' => new external_files('Response files for the question', VALUE_OPTIONAL), ) ), 'Response file areas including files', VALUE_OPTIONAL ), 'sequencecheck' => new external_value(PARAM_INT, 'the number of real steps in this attempt', VALUE_OPTIONAL), 'lastactiontime' => new external_value(PARAM_INT, 'the timestamp of the most recent step in this question attempt', VALUE_OPTIONAL), 'hasautosavedstep' => new external_value(PARAM_BOOL, 'whether this question attempt has autosaved data', VALUE_OPTIONAL), 'flagged' => new external_value(PARAM_BOOL, 'whether the question is flagged or not'), 'number' => new external_value(PARAM_INT, 'question ordering number in the quiz', VALUE_OPTIONAL), 'state' => new external_value(PARAM_ALPHA, 'the state where the question is in. It will not be returned if the user cannot see it due to the quiz display correctness settings.', VALUE_OPTIONAL), 'status' => new external_value(PARAM_RAW, 'current formatted state of the question', VALUE_OPTIONAL), 'blockedbyprevious' => new external_value(PARAM_BOOL, 'whether the question is blocked by the previous question', VALUE_OPTIONAL), 'mark' => new external_value(PARAM_RAW, 'the mark awarded. It will be returned only if the user is allowed to see it.', VALUE_OPTIONAL), 'maxmark' => new external_value(PARAM_FLOAT, 'the maximum mark possible for this question attempt. It will be returned only if the user is allowed to see it.', VALUE_OPTIONAL), 'settings' => new external_value(PARAM_RAW, 'Question settings (JSON encoded).', VALUE_OPTIONAL), ), 'The question data. Some fields may not be returned depending on the quiz display settings.' ); } /** * Return questions information for a given attempt. * * @param quiz_attempt $attemptobj the quiz attempt object * @param bool $review whether if we are in review mode or not * @param mixed $page string 'all' or integer page number * @return array array of questions including data */ private static function get_attempt_questions_data(quiz_attempt $attemptobj, $review, $page = 'all') { global $PAGE; $questions = array(); $contextid = $attemptobj->get_quizobj()->get_context()->id; $displayoptions = $attemptobj->get_display_options($review); $renderer = $PAGE->get_renderer('mod_quiz'); $contextid = $attemptobj->get_quizobj()->get_context()->id; foreach ($attemptobj->get_slots($page) as $slot) { $qtype = $attemptobj->get_question_type_name($slot); $qattempt = $attemptobj->get_question_attempt($slot); $questiondef = $qattempt->get_question(true); // Get response files (for questions like essay that allows attachments). $responsefileareas = []; foreach (question_bank::get_qtype($qtype)->response_file_areas() as $area) { if ($files = $attemptobj->get_question_attempt($slot)->get_last_qt_files($area, $contextid)) { $responsefileareas[$area]['area'] = $area; $responsefileareas[$area]['files'] = []; foreach ($files as $file) { $responsefileareas[$area]['files'][] = array( 'filename' => $file->get_filename(), 'fileurl' => $qattempt->get_response_file_url($file), 'filesize' => $file->get_filesize(), 'filepath' => $file->get_filepath(), 'mimetype' => $file->get_mimetype(), 'timemodified' => $file->get_timemodified(), ); } } } // Check display settings for question. $settings = $questiondef->get_question_definition_for_external_rendering($qattempt, $displayoptions); $question = array( 'slot' => $slot, 'type' => $qtype, 'page' => $attemptobj->get_question_page($slot), 'flagged' => $attemptobj->is_question_flagged($slot), 'html' => $attemptobj->render_question($slot, $review, $renderer) . $PAGE->requires->get_end_code(), 'responsefileareas' => $responsefileareas, 'sequencecheck' => $qattempt->get_sequence_check_count(), 'lastactiontime' => $qattempt->get_last_step()->get_timecreated(), 'hasautosavedstep' => $qattempt->has_autosaved_step(), 'settings' => !empty($settings) ? json_encode($settings) : null, ); if ($attemptobj->is_real_question($slot)) { $question['number'] = $attemptobj->get_question_number($slot); $showcorrectness = $displayoptions->correctness && $qattempt->has_marks(); if ($showcorrectness) { $question['state'] = (string) $attemptobj->get_question_state($slot); } $question['status'] = $attemptobj->get_question_status($slot, $displayoptions->correctness); $question['blockedbyprevious'] = $attemptobj->is_blocked_by_previous_question($slot); } if ($displayoptions->marks >= question_display_options::MAX_ONLY) { $question['maxmark'] = $qattempt->get_max_mark(); } if ($displayoptions->marks >= question_display_options::MARK_AND_MAX) { $question['mark'] = $attemptobj->get_question_mark($slot); } if ($attemptobj->check_page_access($attemptobj->get_question_page($slot), false)) { $questions[] = $question; } } return $questions; } /** * Describes the parameters for get_attempt_data. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_attempt_data_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'page' => new external_value(PARAM_INT, 'page number'), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Returns information for the given attempt page for a quiz attempt in progress. * * @param int $attemptid attempt id * @param int $page page number * @param array $preflightdata preflight required data (like passwords) * @return array of warnings and the attempt data, next page, message and questions * @since Moodle 3.1 * @throws moodle_quiz_exceptions */ public static function get_attempt_data($attemptid, $page, $preflightdata = array()) { global $PAGE; $warnings = array(); $params = array( 'attemptid' => $attemptid, 'page' => $page, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::get_attempt_data_parameters(), $params); list($attemptobj, $messages) = self::validate_attempt($params); if ($attemptobj->is_last_page($params['page'])) { $nextpage = -1; } else { $nextpage = $params['page'] + 1; } // TODO: Remove the code once the long-term solution (MDL-76728) has been applied. // Set a default URL to stop the debugging output. $PAGE->set_url('/fake/url'); $result = array(); $result['attempt'] = $attemptobj->get_attempt(); $result['messages'] = $messages; $result['nextpage'] = $nextpage; $result['warnings'] = $warnings; $result['questions'] = self::get_attempt_questions_data($attemptobj, false, $params['page']); return $result; } /** * Describes the get_attempt_data return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_attempt_data_returns() { return new external_single_structure( array( 'attempt' => self::attempt_structure(), 'messages' => new external_multiple_structure( new external_value(PARAM_TEXT, 'access message'), 'access messages, will only be returned for users with mod/quiz:preview capability, for other users this method will throw an exception if there are messages'), 'nextpage' => new external_value(PARAM_INT, 'next page number'), 'questions' => new external_multiple_structure(self::question_structure()), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_attempt_summary. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_attempt_summary_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Returns a summary of a quiz attempt before it is submitted. * * @param int $attemptid attempt id * @param int $preflightdata preflight required data (like passwords) * @return array of warnings and the attempt summary data for each question * @since Moodle 3.1 */ public static function get_attempt_summary($attemptid, $preflightdata = array()) { $warnings = array(); $params = array( 'attemptid' => $attemptid, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::get_attempt_summary_parameters(), $params); list($attemptobj, $messages) = self::validate_attempt($params, true, false); $result = array(); $result['warnings'] = $warnings; $result['questions'] = self::get_attempt_questions_data($attemptobj, false, 'all'); return $result; } /** * Describes the get_attempt_summary return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_attempt_summary_returns() { return new external_single_structure( array( 'questions' => new external_multiple_structure(self::question_structure()), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for save_attempt. * * @return external_function_parameters * @since Moodle 3.1 */ public static function save_attempt_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'data' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_RAW, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'the data to be saved' ), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Processes save requests during the quiz. This function is intended for the quiz auto-save feature. * * @param int $attemptid attempt id * @param array $data the data to be saved * @param array $preflightdata preflight required data (like passwords) * @return array of warnings and execution result * @since Moodle 3.1 */ public static function save_attempt($attemptid, $data, $preflightdata = array()) { global $DB, $USER; $warnings = array(); $params = array( 'attemptid' => $attemptid, 'data' => $data, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::save_attempt_parameters(), $params); // Add a page, required by validate_attempt. list($attemptobj, $messages) = self::validate_attempt($params); // Prevent functions like file_get_submitted_draft_itemid() or form library requiring a sesskey for WS requests. if (WS_SERVER || PHPUNIT_TEST) { $USER->ignoresesskey = true; } $transaction = $DB->start_delegated_transaction(); // Create the $_POST object required by the question engine. $_POST = array(); foreach ($data as $element) { $_POST[$element['name']] = $element['value']; // Some deep core functions like file_get_submitted_draft_itemid() also requires $_REQUEST to be filled. $_REQUEST[$element['name']] = $element['value']; } $timenow = time(); // Update the timemodifiedoffline field. $attemptobj->set_offline_modified_time($timenow); $attemptobj->process_auto_save($timenow); $transaction->allow_commit(); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Describes the save_attempt return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function save_attempt_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for process_attempt. * * @return external_function_parameters * @since Moodle 3.1 */ public static function process_attempt_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'data' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_RAW, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'the data to be saved', VALUE_DEFAULT, array() ), 'finishattempt' => new external_value(PARAM_BOOL, 'whether to finish or not the attempt', VALUE_DEFAULT, false), 'timeup' => new external_value(PARAM_BOOL, 'whether the WS was called by a timer when the time is up', VALUE_DEFAULT, false), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Process responses during an attempt at a quiz and also deals with attempts finishing. * * @param int $attemptid attempt id * @param array $data the data to be saved * @param bool $finishattempt whether to finish or not the attempt * @param bool $timeup whether the WS was called by a timer when the time is up * @param array $preflightdata preflight required data (like passwords) * @return array of warnings and the attempt state after the processing * @since Moodle 3.1 */ public static function process_attempt($attemptid, $data, $finishattempt = false, $timeup = false, $preflightdata = array()) { global $USER; $warnings = array(); $params = array( 'attemptid' => $attemptid, 'data' => $data, 'finishattempt' => $finishattempt, 'timeup' => $timeup, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::process_attempt_parameters(), $params); // Do not check access manager rules and evaluate fail if overdue. $attemptobj = quiz_attempt::create($params['attemptid']); $failifoverdue = !($attemptobj->get_quizobj()->get_quiz()->overduehandling == 'graceperiod'); list($attemptobj, $messages) = self::validate_attempt($params, false, $failifoverdue); // Prevent functions like file_get_submitted_draft_itemid() or form library requiring a sesskey for WS requests. if (WS_SERVER || PHPUNIT_TEST) { $USER->ignoresesskey = true; } // Create the $_POST object required by the question engine. $_POST = array(); foreach ($params['data'] as $element) { $_POST[$element['name']] = $element['value']; $_REQUEST[$element['name']] = $element['value']; } $timenow = time(); $finishattempt = $params['finishattempt']; $timeup = $params['timeup']; $result = array(); // Update the timemodifiedoffline field. $attemptobj->set_offline_modified_time($timenow); $result['state'] = $attemptobj->process_attempt($timenow, $finishattempt, $timeup, 0); $result['warnings'] = $warnings; return $result; } /** * Describes the process_attempt return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function process_attempt_returns() { return new external_single_structure( array( 'state' => new external_value(PARAM_ALPHANUMEXT, 'state: the new attempt state: inprogress, finished, overdue, abandoned'), 'warnings' => new external_warnings(), ) ); } /** * Validate an attempt finished for review. The attempt would be reviewed by a user or a teacher. * * @param array $params Array of parameters including the attemptid * @return array containing the attempt object and display options * @since Moodle 3.1 * @throws moodle_exception * @throws moodle_quiz_exception */ protected static function validate_attempt_review($params) { $attemptobj = quiz_attempt::create($params['attemptid']); $attemptobj->check_review_capability(); $displayoptions = $attemptobj->get_display_options(true); if ($attemptobj->is_own_attempt()) { if (!$attemptobj->is_finished()) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'attemptclosed'); } else if (!$displayoptions->attempt) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noreview', null, '', $attemptobj->cannot_review_message()); } } else if (!$attemptobj->is_review_allowed()) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noreviewattempt'); } return array($attemptobj, $displayoptions); } /** * Describes the parameters for get_attempt_review. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_attempt_review_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'page' => new external_value(PARAM_INT, 'page number, empty for all the questions in all the pages', VALUE_DEFAULT, -1), ) ); } /** * Returns review information for the given finished attempt, can be used by users or teachers. * * @param int $attemptid attempt id * @param int $page page number, empty for all the questions in all the pages * @return array of warnings and the attempt data, feedback and questions * @since Moodle 3.1 * @throws moodle_exception * @throws moodle_quiz_exception */ public static function get_attempt_review($attemptid, $page = -1) { global $PAGE; $warnings = array(); $params = array( 'attemptid' => $attemptid, 'page' => $page, ); $params = self::validate_parameters(self::get_attempt_review_parameters(), $params); list($attemptobj, $displayoptions) = self::validate_attempt_review($params); if ($params['page'] !== -1) { $page = $attemptobj->force_page_number_into_range($params['page']); } else { $page = 'all'; } // Prepare the output. $result = array(); $result['attempt'] = $attemptobj->get_attempt(); $result['questions'] = self::get_attempt_questions_data($attemptobj, true, $page, true); $result['additionaldata'] = array(); // Summary data (from behaviours). $summarydata = $attemptobj->get_additional_summary_data($displayoptions); foreach ($summarydata as $key => $data) { // This text does not need formatting (no need for external_format_[string|text]). $result['additionaldata'][] = array( 'id' => $key, 'title' => $data['title'], $attemptobj->get_quizobj()->get_context()->id, 'content' => $data['content'], ); } // Feedback if there is any, and the user is allowed to see it now. $grade = quiz_rescale_grade($attemptobj->get_attempt()->sumgrades, $attemptobj->get_quiz(), false); $feedback = $attemptobj->get_overall_feedback($grade); if ($displayoptions->overallfeedback && $feedback) { $result['additionaldata'][] = array( 'id' => 'feedback', 'title' => get_string('feedback', 'quiz'), 'content' => $feedback, ); } $result['grade'] = $grade; $result['warnings'] = $warnings; return $result; } /** * Describes the get_attempt_review return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_attempt_review_returns() { return new external_single_structure( array( 'grade' => new external_value(PARAM_RAW, 'grade for the quiz (or empty or "notyetgraded")'), 'attempt' => self::attempt_structure(), 'additionaldata' => new external_multiple_structure( new external_single_structure( array( 'id' => new external_value(PARAM_ALPHANUMEXT, 'id of the data'), 'title' => new external_value(PARAM_TEXT, 'data title'), 'content' => new external_value(PARAM_RAW, 'data content'), ) ) ), 'questions' => new external_multiple_structure(self::question_structure()), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for view_attempt. * * @return external_function_parameters * @since Moodle 3.1 */ public static function view_attempt_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'page' => new external_value(PARAM_INT, 'page number'), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Trigger the attempt viewed event. * * @param int $attemptid attempt id * @param int $page page number * @param array $preflightdata preflight required data (like passwords) * @return array of warnings and status result * @since Moodle 3.1 */ public static function view_attempt($attemptid, $page, $preflightdata = array()) { $warnings = array(); $params = array( 'attemptid' => $attemptid, 'page' => $page, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::view_attempt_parameters(), $params); list($attemptobj, $messages) = self::validate_attempt($params); // Log action. $attemptobj->fire_attempt_viewed_event(); // Update attempt page, throwing an exception if $page is not valid. if (!$attemptobj->set_currentpage($params['page'])) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'Out of sequence access'); } $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Describes the view_attempt return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function view_attempt_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for view_attempt_summary. * * @return external_function_parameters * @since Moodle 3.1 */ public static function view_attempt_summary_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), 'preflightdata' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_ALPHANUMEXT, 'data name'), 'value' => new external_value(PARAM_RAW, 'data value'), ) ), 'Preflight required data (like passwords)', VALUE_DEFAULT, array() ) ) ); } /** * Trigger the attempt summary viewed event. * * @param int $attemptid attempt id * @param array $preflightdata preflight required data (like passwords) * @return array of warnings and status result * @since Moodle 3.1 */ public static function view_attempt_summary($attemptid, $preflightdata = array()) { $warnings = array(); $params = array( 'attemptid' => $attemptid, 'preflightdata' => $preflightdata, ); $params = self::validate_parameters(self::view_attempt_summary_parameters(), $params); list($attemptobj, $messages) = self::validate_attempt($params); // Log action. $attemptobj->fire_attempt_summary_viewed_event(); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Describes the view_attempt_summary return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function view_attempt_summary_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for view_attempt_review. * * @return external_function_parameters * @since Moodle 3.1 */ public static function view_attempt_review_parameters() { return new external_function_parameters ( array( 'attemptid' => new external_value(PARAM_INT, 'attempt id'), ) ); } /** * Trigger the attempt reviewed event. * * @param int $attemptid attempt id * @return array of warnings and status result * @since Moodle 3.1 */ public static function view_attempt_review($attemptid) { $warnings = array(); $params = array( 'attemptid' => $attemptid, ); $params = self::validate_parameters(self::view_attempt_review_parameters(), $params); list($attemptobj, $displayoptions) = self::validate_attempt_review($params); // Log action. $attemptobj->fire_attempt_reviewed_event(); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Describes the view_attempt_review return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function view_attempt_review_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for view_quiz. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_quiz_feedback_for_grade_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'grade' => new external_value(PARAM_FLOAT, 'the grade to check'), ) ); } /** * Get the feedback text that should be show to a student who got the given grade in the given quiz. * * @param int $quizid quiz instance id * @param float $grade the grade to check * @return array of warnings and status result * @since Moodle 3.1 * @throws moodle_exception */ public static function get_quiz_feedback_for_grade($quizid, $grade) { global $DB; $params = array( 'quizid' => $quizid, 'grade' => $grade, ); $params = self::validate_parameters(self::get_quiz_feedback_for_grade_parameters(), $params); $warnings = array(); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $result = array(); $result['feedbacktext'] = ''; $result['feedbacktextformat'] = FORMAT_MOODLE; $feedback = quiz_feedback_record_for_grade($params['grade'], $quiz); if (!empty($feedback->feedbacktext)) { list($text, $format) = external_format_text($feedback->feedbacktext, $feedback->feedbacktextformat, $context->id, 'mod_quiz', 'feedback', $feedback->id); $result['feedbacktext'] = $text; $result['feedbacktextformat'] = $format; $feedbackinlinefiles = external_util::get_area_files($context->id, 'mod_quiz', 'feedback', $feedback->id); if (!empty($feedbackinlinefiles)) { $result['feedbackinlinefiles'] = $feedbackinlinefiles; } } $result['warnings'] = $warnings; return $result; } /** * Describes the get_quiz_feedback_for_grade return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_quiz_feedback_for_grade_returns() { return new external_single_structure( array( 'feedbacktext' => new external_value(PARAM_RAW, 'the comment that corresponds to this grade (empty for none)'), 'feedbacktextformat' => new external_format_value('feedbacktext', VALUE_OPTIONAL), 'feedbackinlinefiles' => new external_files('feedback inline files', VALUE_OPTIONAL), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_quiz_access_information. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_quiz_access_information_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id') ) ); } /** * Return access information for a given quiz. * * @param int $quizid quiz instance id * @return array of warnings and the access information * @since Moodle 3.1 * @throws moodle_quiz_exception */ public static function get_quiz_access_information($quizid) { global $DB, $USER; $warnings = array(); $params = array( 'quizid' => $quizid ); $params = self::validate_parameters(self::get_quiz_access_information_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $result = array(); // Capabilities first. $result['canattempt'] = has_capability('mod/quiz:attempt', $context);; $result['canmanage'] = has_capability('mod/quiz:manage', $context);; $result['canpreview'] = has_capability('mod/quiz:preview', $context);; $result['canreviewmyattempts'] = has_capability('mod/quiz:reviewmyattempts', $context);; $result['canviewreports'] = has_capability('mod/quiz:viewreports', $context);; // Access manager now. $quizobj = quiz::create($cm->instance, $USER->id); $ignoretimelimits = has_capability('mod/quiz:ignoretimelimits', $context, null, false); $timenow = time(); $accessmanager = new quiz_access_manager($quizobj, $timenow, $ignoretimelimits); $result['accessrules'] = $accessmanager->describe_rules(); $result['activerulenames'] = $accessmanager->get_active_rule_names(); $result['preventaccessreasons'] = $accessmanager->prevent_access(); $result['warnings'] = $warnings; return $result; } /** * Describes the get_quiz_access_information return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_quiz_access_information_returns() { return new external_single_structure( array( 'canattempt' => new external_value(PARAM_BOOL, 'Whether the user can do the quiz or not.'), 'canmanage' => new external_value(PARAM_BOOL, 'Whether the user can edit the quiz settings or not.'), 'canpreview' => new external_value(PARAM_BOOL, 'Whether the user can preview the quiz or not.'), 'canreviewmyattempts' => new external_value(PARAM_BOOL, 'Whether the users can review their previous attempts or not.'), 'canviewreports' => new external_value(PARAM_BOOL, 'Whether the user can view the quiz reports or not.'), 'accessrules' => new external_multiple_structure( new external_value(PARAM_TEXT, 'rule description'), 'list of rules'), 'activerulenames' => new external_multiple_structure( new external_value(PARAM_PLUGIN, 'rule plugin names'), 'list of active rules'), 'preventaccessreasons' => new external_multiple_structure( new external_value(PARAM_TEXT, 'access restriction description'), 'list of reasons'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_attempt_access_information. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_attempt_access_information_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id'), 'attemptid' => new external_value(PARAM_INT, 'attempt id, 0 for the user last attempt if exists', VALUE_DEFAULT, 0), ) ); } /** * Return access information for a given attempt in a quiz. * * @param int $quizid quiz instance id * @param int $attemptid attempt id, 0 for the user last attempt if exists * @return array of warnings and the access information * @since Moodle 3.1 * @throws moodle_quiz_exception */ public static function get_attempt_access_information($quizid, $attemptid = 0) { global $DB, $USER; $warnings = array(); $params = array( 'quizid' => $quizid, 'attemptid' => $attemptid, ); $params = self::validate_parameters(self::get_attempt_access_information_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $attempttocheck = 0; if (!empty($params['attemptid'])) { $attemptobj = quiz_attempt::create($params['attemptid']); if ($attemptobj->get_userid() != $USER->id) { throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'notyourattempt'); } $attempttocheck = $attemptobj->get_attempt(); } // Access manager now. $quizobj = quiz::create($cm->instance, $USER->id); $ignoretimelimits = has_capability('mod/quiz:ignoretimelimits', $context, null, false); $timenow = time(); $accessmanager = new quiz_access_manager($quizobj, $timenow, $ignoretimelimits); $attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'finished', true); $lastfinishedattempt = end($attempts); if ($unfinishedattempt = quiz_get_user_attempt_unfinished($quiz->id, $USER->id)) { $attempts[] = $unfinishedattempt; // Check if the attempt is now overdue. In that case the state will change. $quizobj->create_attempt_object($unfinishedattempt)->handle_if_time_expired(time(), false); if ($unfinishedattempt->state != quiz_attempt::IN_PROGRESS and $unfinishedattempt->state != quiz_attempt::OVERDUE) { $lastfinishedattempt = $unfinishedattempt; } } $numattempts = count($attempts); if (!$attempttocheck) { $attempttocheck = $unfinishedattempt ? $unfinishedattempt : $lastfinishedattempt; } $result = array(); $result['isfinished'] = $accessmanager->is_finished($numattempts, $lastfinishedattempt); $result['preventnewattemptreasons'] = $accessmanager->prevent_new_attempt($numattempts, $lastfinishedattempt); if ($attempttocheck) { $endtime = $accessmanager->get_end_time($attempttocheck); $result['endtime'] = ($endtime === false) ? 0 : $endtime; $attemptid = $unfinishedattempt ? $unfinishedattempt->id : null; $result['ispreflightcheckrequired'] = $accessmanager->is_preflight_check_required($attemptid); } $result['warnings'] = $warnings; return $result; } /** * Describes the get_attempt_access_information return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_attempt_access_information_returns() { return new external_single_structure( array( 'endtime' => new external_value(PARAM_INT, 'When the attempt must be submitted (determined by rules).', VALUE_OPTIONAL), 'isfinished' => new external_value(PARAM_BOOL, 'Whether there is no way the user will ever be allowed to attempt.'), 'ispreflightcheckrequired' => new external_value(PARAM_BOOL, 'whether a check is required before the user starts/continues his attempt.', VALUE_OPTIONAL), 'preventnewattemptreasons' => new external_multiple_structure( new external_value(PARAM_TEXT, 'access restriction description'), 'list of reasons'), 'warnings' => new external_warnings(), ) ); } /** * Describes the parameters for get_quiz_required_qtypes. * * @return external_function_parameters * @since Moodle 3.1 */ public static function get_quiz_required_qtypes_parameters() { return new external_function_parameters ( array( 'quizid' => new external_value(PARAM_INT, 'quiz instance id') ) ); } /** * Return the potential question types that would be required for a given quiz. * Please note that for random question types we return the potential question types in the category choosen. * * @param int $quizid quiz instance id * @return array of warnings and the access information * @since Moodle 3.1 * @throws moodle_quiz_exception */ public static function get_quiz_required_qtypes($quizid) { global $DB, $USER; $warnings = array(); $params = array( 'quizid' => $quizid ); $params = self::validate_parameters(self::get_quiz_required_qtypes_parameters(), $params); list($quiz, $course, $cm, $context) = self::validate_quiz($params['quizid']); $quizobj = quiz::create($cm->instance, $USER->id); $quizobj->preload_questions(); $quizobj->load_questions(); // Question types used. $result = array(); $result['questiontypes'] = $quizobj->get_all_question_types_used(true); $result['warnings'] = $warnings; return $result; } /** * Describes the get_quiz_required_qtypes return value. * * @return external_single_structure * @since Moodle 3.1 */ public static function get_quiz_required_qtypes_returns() { return new external_single_structure( array( 'questiontypes' => new external_multiple_structure( new external_value(PARAM_PLUGIN, 'question type'), 'list of question types used in the quiz'), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/blocks/classes/external.php 0000644 00000032234 15152541531 0017241 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Blocks external API * * @package core_block * @category external * @copyright 2017 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.3 */ defined('MOODLE_INTERNAL') || die; require_once("$CFG->libdir/externallib.php"); require_once("$CFG->dirroot/my/lib.php"); /** * Blocks external functions * * @package core_block * @category external * @copyright 2015 Juan Leyva <juan@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.3 */ class core_block_external extends external_api { /** * Returns a block structure. * * @return external_single_structure a block single structure. * @since Moodle 3.6 */ private static function get_block_structure() { return new external_single_structure( array( 'instanceid' => new external_value(PARAM_INT, 'Block instance id.'), 'name' => new external_value(PARAM_PLUGIN, 'Block name.'), 'region' => new external_value(PARAM_ALPHANUMEXT, 'Block region.'), 'positionid' => new external_value(PARAM_INT, 'Position id.'), 'collapsible' => new external_value(PARAM_BOOL, 'Whether the block is collapsible.'), 'dockable' => new external_value(PARAM_BOOL, 'Whether the block is dockable.'), 'weight' => new external_value(PARAM_INT, 'Used to order blocks within a region.', VALUE_OPTIONAL), 'visible' => new external_value(PARAM_BOOL, 'Whether the block is visible.', VALUE_OPTIONAL), 'contents' => new external_single_structure( array( 'title' => new external_value(PARAM_RAW, 'Block title.'), 'content' => new external_value(PARAM_RAW, 'Block contents.'), 'contentformat' => new external_format_value('content'), 'footer' => new external_value(PARAM_RAW, 'Block footer.'), 'files' => new external_files('Block files.'), ), 'Block contents (if required).', VALUE_OPTIONAL ), 'configs' => new external_multiple_structure( new external_single_structure( array( 'name' => new external_value(PARAM_RAW, 'Name.'), 'value' => new external_value(PARAM_RAW, 'JSON encoded representation of the config value.'), 'type' => new external_value(PARAM_ALPHA, 'Type (instance or plugin).'), ) ), 'Block instance and plugin configuration settings.', VALUE_OPTIONAL ), ), 'Block information.' ); } /** * Convenience function for getting all the blocks of the current $PAGE. * * @param bool $includeinvisible Whether to include not visible blocks or not * @param bool $returncontents Whether to return the block contents * @return array Block information * @since Moodle 3.6 */ private static function get_all_current_page_blocks($includeinvisible = false, $returncontents = false) { global $PAGE, $OUTPUT; // Set page URL to a fake URL to avoid errors. $PAGE->set_url(new \moodle_url('/webservice/core_block_external/')); // Load the block instances for all the regions. $PAGE->blocks->load_blocks($includeinvisible); $PAGE->blocks->create_all_block_instances(); $allblocks = array(); $blocks = $PAGE->blocks->get_content_for_all_regions($OUTPUT); foreach ($blocks as $region => $regionblocks) { $regioninstances = $PAGE->blocks->get_blocks_for_region($region); // Index block instances to retrieve required info. $blockinstances = array(); foreach ($regioninstances as $ri) { $blockinstances[$ri->instance->id] = $ri; } foreach ($regionblocks as $bc) { $block = [ 'instanceid' => $bc->blockinstanceid, 'name' => $blockinstances[$bc->blockinstanceid]->instance->blockname, 'region' => $region, 'positionid' => $bc->blockpositionid, 'collapsible' => (bool) $bc->collapsible, 'dockable' => (bool) $bc->dockable, 'weight' => $blockinstances[$bc->blockinstanceid]->instance->weight, 'visible' => $blockinstances[$bc->blockinstanceid]->instance->visible, ]; if ($returncontents) { $block['contents'] = (array) $blockinstances[$bc->blockinstanceid]->get_content_for_external($OUTPUT); } $configs = (array) $blockinstances[$bc->blockinstanceid]->get_config_for_external(); foreach ($configs as $type => $data) { foreach ((array) $data as $name => $value) { $block['configs'][] = [ 'name' => $name, 'value' => json_encode($value), // Always JSON encode, we may receive non-scalar values. 'type' => $type, ]; } } $allblocks[] = $block; } } return $allblocks; } /** * Returns description of get_course_blocks parameters. * * @return external_function_parameters * @since Moodle 3.3 */ public static function get_course_blocks_parameters() { return new external_function_parameters( array( 'courseid' => new external_value(PARAM_INT, 'course id'), 'returncontents' => new external_value(PARAM_BOOL, 'Whether to return the block contents.', VALUE_DEFAULT, false), ) ); } /** * Returns blocks information for a course. * * @param int $courseid The course id * @param bool $returncontents Whether to return the block contents * @return array Blocks list and possible warnings * @throws moodle_exception * @since Moodle 3.3 */ public static function get_course_blocks($courseid, $returncontents = false) { global $PAGE; $warnings = array(); $params = self::validate_parameters(self::get_course_blocks_parameters(), ['courseid' => $courseid, 'returncontents' => $returncontents]); $course = get_course($params['courseid']); $context = context_course::instance($course->id); self::validate_context($context); // Specific layout for frontpage course. if ($course->id == SITEID) { $PAGE->set_pagelayout('frontpage'); $PAGE->set_pagetype('site-index'); } else { $PAGE->set_pagelayout('course'); // Ensure course format is set (view course/view.php). $course->format = course_get_format($course)->get_format(); $PAGE->set_pagetype('course-view-' . $course->format); } $allblocks = self::get_all_current_page_blocks(false, $params['returncontents']); return array( 'blocks' => $allblocks, 'warnings' => $warnings ); } /** * Returns description of get_course_blocks result values. * * @return external_single_structure * @since Moodle 3.3 */ public static function get_course_blocks_returns() { return new external_single_structure( array( 'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the course.'), 'warnings' => new external_warnings(), ) ); } /** * Returns description of get_dashboard_blocks parameters. * * @return external_function_parameters * @since Moodle 3.6 */ public static function get_dashboard_blocks_parameters() { return new external_function_parameters( array( 'userid' => new external_value(PARAM_INT, 'User id (optional), default is current user.', VALUE_DEFAULT, 0), 'returncontents' => new external_value(PARAM_BOOL, 'Whether to return the block contents.', VALUE_DEFAULT, false), 'mypage' => new external_value(PARAM_TEXT, 'What my page to return blocks of', VALUE_DEFAULT, MY_PAGE_DEFAULT), ) ); } /** * Returns blocks information for the given user dashboard. * * @param int $userid The user id to retrieve the blocks from, optional, default is to current user. * @param bool $returncontents Whether to return the block contents * @param string $mypage The page to get blocks of within my * @return array Blocks list and possible warnings * @throws moodle_exception * @since Moodle 3.6 */ public static function get_dashboard_blocks($userid = 0, $returncontents = false, $mypage = MY_PAGE_DEFAULT) { global $CFG, $USER, $PAGE; require_once($CFG->dirroot . '/my/lib.php'); $warnings = array(); $params = self::validate_parameters(self::get_dashboard_blocks_parameters(), ['userid' => $userid, 'returncontents' => $returncontents, 'mypage' => $mypage]); $userid = $params['userid']; if (empty($userid)) { $userid = $USER->id; } if ($USER->id != $userid) { // We must check if the current user can view other users dashboard. require_capability('moodle/site:config', context_system::instance()); $user = core_user::get_user($userid, '*', MUST_EXIST); core_user::require_active_user($user); } $context = context_user::instance($userid);; self::validate_context($context); $currentpage = null; if ($params['mypage'] === MY_PAGE_DEFAULT) { $currentpage = my_get_page($userid); } else if ($params['mypage'] === MY_PAGE_COURSES) { $currentpage = my_get_page($userid, MY_PAGE_PUBLIC, MY_PAGE_COURSES); } if (!$currentpage) { throw new moodle_exception('mymoodlesetup'); } $PAGE->set_context($context); $PAGE->set_pagelayout('mydashboard'); $PAGE->set_pagetype('my-index'); $PAGE->blocks->add_region('content'); // Need to add this special regition to retrieve the central blocks. $PAGE->set_subpage($currentpage->id); // Load the block instances in the current $PAGE for all the regions. $returninvisible = has_capability('moodle/my:manageblocks', $context) ? true : false; $allblocks = self::get_all_current_page_blocks($returninvisible, $params['returncontents']); // Temporary hack to be removed in 4.1. // Return always the course overview block so old versions of the app can list the user courses. if ($mypage == MY_PAGE_DEFAULT && core_useragent::is_moodle_app()) { $myoverviewfound = false; foreach ($allblocks as $block) { if ($block['name'] == 'myoverview' && $block['visible']) { $myoverviewfound = true; break; } } if (!$myoverviewfound) { // Include a course overview fake block. $allblocks[] = [ 'instanceid' => 0, 'name' => 'myoverview', 'region' => 'forced', 'positionid' => null, 'collapsible' => true, 'dockable' => false, 'weight' => 0, 'visible' => true, ]; } } // End of the hack to be removed in 4.1 see MDL-73670. return array( 'blocks' => $allblocks, 'warnings' => $warnings ); } /** * Returns description of get_dashboard_blocks result values. * * @return external_single_structure * @since Moodle 3.6 */ public static function get_dashboard_blocks_returns() { return new external_single_structure( array( 'blocks' => new external_multiple_structure(self::get_block_structure(), 'List of blocks in the dashboard.'), 'warnings' => new external_warnings(), ) ); } } home3/cpr76684/public_html/Aem/filter/classes/external.php 0000644 00000011751 15152647120 0017253 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * This is the external API for the filter component. * * @package core_filters * @copyright 2017 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_filters; defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir . '/externallib.php'); require_once($CFG->libdir . '/filterlib.php'); use external_api; use external_function_parameters; use external_value; use external_single_structure; use external_multiple_structure; use external_warnings; use Exception; /** * This is the external API for the filter component. * * @copyright 2017 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class external extends external_api { /** * Returns description of get_available_in_context() parameters. * * @return external_function_parameters * @since Moodle 3.4 */ public static function get_available_in_context_parameters() { return new external_function_parameters ( array( 'contexts' => new external_multiple_structure( new external_single_structure( array( 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level where the filters are: (coursecat, course, module)'), 'instanceid' => new external_value(PARAM_INT, 'The instance id of item associated with the context.') ) ), 'The list of contexts to check.' ), ) ); } /** * Returns the filters available in the given contexts. * * @param array $contexts the list of contexts to check * @return array with the filters information and warnings * @since Moodle 3.4 */ public static function get_available_in_context($contexts) { $params = self::validate_parameters(self::get_available_in_context_parameters(), array('contexts' => $contexts)); $filters = $warnings = array(); foreach ($params['contexts'] as $contextinfo) { try { $context = self::get_context_from_params($contextinfo); self::validate_context($context); $contextinfo['contextid'] = $context->id; } catch (Exception $e) { $warnings[] = array( 'item' => 'context', 'itemid' => $contextinfo['instanceid'], 'warningcode' => $e->getCode(), 'message' => $e->getMessage(), ); continue; } $contextfilters = filter_get_available_in_context($context); foreach ($contextfilters as $filter) { $filters[] = array_merge($contextinfo, (array) $filter); } } return array( 'filters' => $filters, 'warnings' => $warnings, ); } /** * Returns description of get_available_in_context() result value. * * @return external_single_structure * @since Moodle 3.4 */ public static function get_available_in_context_returns() { return new external_single_structure( array( 'filters' => new external_multiple_structure( new external_single_structure( array( 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level where the filters are: (coursecat, course, module).'), 'instanceid' => new external_value(PARAM_INT, 'The instance id of item associated with the context.'), 'contextid' => new external_value(PARAM_INT, 'The context id.'), 'filter' => new external_value(PARAM_PLUGIN, 'Filter plugin name.'), 'localstate' => new external_value(PARAM_INT, 'Filter state: 1 for on, -1 for off, 0 if inherit.'), 'inheritedstate' => new external_value(PARAM_INT, '1 or 0 to use when localstate is set to inherit.'), ) ), 'Available filters' ), 'warnings' => new external_warnings(), ) ); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�