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 /** 18 * Competency rule points based. 19 * 20 * @package core_competency 21 * @copyright 2015 Frédéric Massart - FMCorz.net 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_competency; 26 defined('MOODLE_INTERNAL') || die(); 27 28 use coding_exception; 29 use lang_string; 30 31 32 /** 33 * Competency rule points based class. 34 * 35 * This rule matches when related competencies contribute for a required number of points. 36 * 37 * @package core_competency 38 * @copyright 2015 Frédéric Massart - FMCorz.net 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class competency_rule_points extends competency_rule { 42 43 /** 44 * Get the rule config. 45 * 46 * @return mixed 47 */ 48 protected function get_config() { 49 $config = parent::get_config(); 50 return json_decode($config); 51 } 52 53 /** 54 * Whether or not the rule is matched. 55 * 56 * @param user_competency $usercompetency The user competency. 57 * @return bool 58 */ 59 public function matches(user_competency $usercompetency) { 60 global $DB; 61 62 $config = $this->get_config(); 63 $pointsrequired = $config->base->points; 64 65 // Index by competency ID and extract required. 66 $compsrules = array(); 67 $requiredids = array(); 68 foreach ($config->competencies as $comp) { 69 $compsrules[$comp->id] = $comp; 70 if ($comp->required) { 71 $requiredids[$comp->id] = $comp->id; 72 } 73 } 74 75 // Find all the user competency records. 76 list($insql, $params) = $DB->get_in_or_equal(array_keys($compsrules), SQL_PARAMS_NAMED); 77 $sql = "userid = :userid 78 AND proficiency = :proficiency 79 AND competencyid $insql"; 80 $params['userid'] = $usercompetency->get('userid'); 81 $params['proficiency'] = 1; 82 $ucs = user_competency::get_records_select($sql, $params, '', 'competencyid'); 83 84 // Check that all the required are found. 85 if (!empty($requiredids)) { 86 $unmetrequired = array_diff_key($requiredids, $ucs); 87 if (!empty($unmetrequired)) { 88 return false; 89 } 90 } 91 92 // Check that we have enough points. 93 $points = 0; 94 foreach ($compsrules as $compid => $comp) { 95 if (array_key_exists($compid, $ucs)) { 96 $points += $comp->points; 97 } 98 } 99 100 return $points >= $pointsrequired; 101 } 102 103 /** 104 * Validate the rule config. 105 * 106 * @param string $value The value to validate. 107 * @return bool 108 */ 109 public function validate_config($value) { 110 $compids = array(); 111 $config = json_decode($value); 112 if ($config === null || !isset($config->base) || !isset($config->competencies)) { 113 return false; 114 } 115 116 if (!isset($config->base->points)) { 117 return false; 118 } 119 120 try { 121 $requiredpoints = validate_param($config->base->points, PARAM_INT); 122 } catch (\invalid_parameter_exception $e) { 123 return false; 124 } 125 126 if ($requiredpoints < 1) { 127 return false; 128 } 129 130 $totalpoints = 0; 131 132 // Validate the competency info. 133 foreach ($config->competencies as $competency) { 134 135 // Cannot include self. 136 if ($competency->id == $this->competency->get('id')) { 137 return false; 138 } 139 140 // Check for duplicates. 141 if (in_array($competency->id, $compids)) { 142 return false; 143 } 144 145 // Check for required fields. 146 if (!isset($competency->id) 147 || !isset($competency->points) 148 || !isset($competency->required)) { 149 return false; 150 } 151 152 // Validate the parameters. 153 try { 154 validate_param($competency->id, PARAM_INT); 155 $points = validate_param($competency->points, PARAM_INT); 156 validate_param($competency->required, PARAM_BOOL); 157 } catch (\invalid_parameter_exception $e) { 158 return false; 159 } 160 161 $totalpoints += $points; 162 if ($points < 0) { 163 return false; 164 } 165 166 $compids[] = $competency->id; 167 } 168 169 // No competencies, that's strange. 170 if (empty($compids)) { 171 return false; 172 } 173 174 // Impossible to reach the points required. 175 if ($requiredpoints > $totalpoints) { 176 return false; 177 } 178 179 // Check that all the competencies are children of the competency. 180 // We may want to relax this check at a later stage if we want to allow competencies 181 // to be linked throughout the whole framework. 182 return $this->competency->is_parent_of($compids); 183 } 184 185 /** 186 * The name of the rule. 187 * 188 * @return lang_string 189 */ 190 public static function get_name() { 191 return new lang_string('pointsrequiredaremet', 'core_competency'); 192 } 193 194 /** 195 * Migrate rule config when duplicate competency based on mapping competencies ids. 196 * 197 * @param string $config the config rule of a competency 198 * @param array $mappings array that match the old competency ids with the new competencies 199 * @return string 200 */ 201 public static function migrate_config($config, $mappings) { 202 $ruleconfig = json_decode($config, true); 203 if (is_array($ruleconfig)) { 204 foreach ($ruleconfig['competencies'] as $key => $rulecomp) { 205 $rulecmpid = $rulecomp['id']; 206 if (array_key_exists($rulecmpid, $mappings)) { 207 $ruleconfig['competencies'][$key]['id'] = $mappings[$rulecmpid]->get('id'); 208 } else { 209 throw new coding_exception("The competency id is not found in the matchids."); 210 } 211 } 212 } else { 213 throw new coding_exception("Invalid JSON config rule."); 214 } 215 216 return json_encode($ruleconfig); 217 } 218 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body