Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace core_xapi\external; 18 19 use core_xapi\local\statement; 20 use core_xapi\handler; 21 use core_xapi\xapi_exception; 22 use core_external\external_api; 23 use core_external\external_function_parameters; 24 use core_external\external_multiple_structure; 25 use core_external\external_value; 26 use core_component; 27 28 /** 29 * This is the external API for generic xAPI handling. 30 * 31 * @package core_xapi 32 * @since Moodle 3.9 33 * @copyright 2020 Ferran Recio 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class post_statement extends external_api { 37 38 /** 39 * Parameters for execute 40 * 41 * @return external_function_parameters 42 */ 43 public static function execute_parameters() { 44 return new external_function_parameters( 45 [ 46 'component' => new external_value(PARAM_COMPONENT, 'Component name', VALUE_REQUIRED), 47 'requestjson' => new external_value(PARAM_RAW, 'json object with all the statements to post', VALUE_REQUIRED) 48 ] 49 ); 50 } 51 52 /** 53 * Process a statement post request. 54 * 55 * @param string $component component name (frankenstyle) 56 * @param string $requestjson json object with all the statements to post 57 * @return bool[] storing acceptance of every statement 58 */ 59 public static function execute(string $component, string $requestjson): array { 60 61 $params = self::validate_parameters(self::execute_parameters(), array( 62 'component' => $component, 63 'requestjson' => $requestjson, 64 )); 65 $component = $params['component']; 66 $requestjson = $params['requestjson']; 67 68 static::validate_component($component); 69 70 $handler = handler::create($component); 71 72 $statements = self::get_statements_from_json($requestjson); 73 74 if (!self::check_statements_users($statements, $handler)) { 75 throw new xapi_exception('Statements actor is not the current user'); 76 } 77 78 $result = $handler->process_statements($statements); 79 80 // In case no statement is processed, an error must be returned. 81 if (count(array_filter($result)) == 0) { 82 throw new xapi_exception('No statement can be processed.'); 83 } 84 return $result; 85 } 86 87 /** 88 * Return for execute. 89 */ 90 public static function execute_returns() { 91 return new external_multiple_structure( 92 new external_value(PARAM_BOOL, 'If the statement is accepted'), 93 'List of statements storing acceptance results' 94 ); 95 } 96 97 /** 98 * Check component name. 99 * 100 * Note: this function is separated mainly for testing purposes to 101 * be overridden to fake components. 102 * 103 * @throws xapi_exception if component is not available 104 * @param string $component component name 105 */ 106 protected static function validate_component(string $component): void { 107 // Check that $component is a real component name. 108 $dir = core_component::get_component_directory($component); 109 if (!$dir) { 110 throw new xapi_exception("Component $component not available."); 111 } 112 } 113 114 /** 115 * Convert mulitple types of statement request into an array of statements. 116 * 117 * @throws xapi_exception if JSON cannot be parsed 118 * @param string $requestjson json encoded statements structure 119 * @return statement[] array of statements 120 */ 121 private static function get_statements_from_json(string $requestjson): array { 122 $request = json_decode($requestjson); 123 if ($request === null) { 124 throw new xapi_exception('JSON error: '.json_last_error_msg()); 125 } 126 $result = []; 127 if (is_array($request)) { 128 foreach ($request as $data) { 129 $result[] = statement::create_from_data($data); 130 } 131 } else { 132 $result[] = statement::create_from_data($request); 133 } 134 if (empty($result)) { 135 throw new xapi_exception('No statements detected'); 136 } 137 return $result; 138 } 139 140 /** 141 * Check that $USER is actor in all statements. 142 * 143 * @param statement[] $statements array of statements 144 * @param handler $handler specific xAPI handler 145 * @return bool if $USER is actor in all statements 146 */ 147 private static function check_statements_users(array $statements, handler $handler): bool { 148 global $USER; 149 150 foreach ($statements as $statement) { 151 if ($handler->supports_group_actors()) { 152 $users = $statement->get_all_users(); 153 if (!isset($users[$USER->id])) { 154 return false; 155 } 156 } else { 157 $user = $statement->get_user(); 158 if ($user->id != $USER->id) { 159 return false; 160 } 161 } 162 } 163 return true; 164 } 165 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body