Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}