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 data generator.
19 *
20 * @package    core_competency
21 * @category   test
22 * @copyright  2015 Frédéric Massart - FMCorz.net
23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26use core_competency\competency;
27use core_competency\competency_framework;
28use core_competency\course_competency;
29use core_competency\course_module_competency;
30use core_competency\evidence;
31use core_competency\external;
32use core_competency\plan;
33use core_competency\plan_competency;
34use core_competency\related_competency;
35use core_competency\template;
36use core_competency\template_cohort;
37use core_competency\template_competency;
38use core_competency\user_competency;
39use core_competency\user_competency_course;
40use core_competency\user_competency_plan;
41use core_competency\user_evidence;
42use core_competency\user_evidence_competency;
43
44
45defined('MOODLE_INTERNAL') || die();
46
47global $CFG;
48require_once($CFG->libdir . '/grade/grade_scale.php');
49
50/**
51 * Competency data generator class.
52 *
53 * @package    core_competency
54 * @category   test
55 * @copyright  2015 Frédéric Massart - FMCorz.net
56 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
57 */
58class core_competency_generator extends component_generator_base {
59
60    /** @var int Number of created competencies. */
61    protected $competencycount = 0;
62
63    /** @var int Number of created frameworks. */
64    protected $frameworkcount = 0;
65
66    /** @var int Number of created plans. */
67    protected $plancount = 0;
68
69    /** @var int Number of created templates. */
70    protected $templatecount = 0;
71
72    /** @var int Number of created user_evidence. */
73    protected $userevidencecount = 0;
74
75    /** @var stdClass Scale that we might need. */
76    protected $scale;
77
78    /**
79     * Reset process.
80     *
81     * Do not call directly.
82     *
83     * @return void
84     */
85    public function reset() {
86        $this->competencycount = 0;
87        $this->frameworkcount = 0;
88        $this->scale = null;
89    }
90
91    /**
92     * Create a new competency.
93     *
94     * @param array|stdClass $record
95     * @return competency
96     */
97    public function create_competency($record = null) {
98        $this->competencycount++;
99        $i = $this->competencycount;
100        $record = (object) $record;
101
102        if (!isset($record->competencyframeworkid)) {
103            throw new coding_exception('The competencyframeworkid value is required.');
104        }
105        if (!isset($record->shortname)) {
106            $record->shortname = "Competency shortname $i";
107        }
108        if (!isset($record->idnumber)) {
109            $record->idnumber = "cmp{$i}";
110        }
111        if (!isset($record->description)) {
112            $record->description = "Competency $i description ";
113        }
114        if (!isset($record->descriptionformat)) {
115            $record->descriptionformat = FORMAT_HTML;
116        }
117        if (!isset($record->scaleconfiguration) && isset($record->scaleid)) {
118            $record->scaleconfiguration = json_encode($this->make_default_scale_configuration($record->scaleid));
119        }
120        if (isset($record->scaleconfiguration)
121                && (is_array($record->scaleconfiguration) || is_object($record->scaleconfiguration))) {
122            // Conveniently encode the config.
123            $record->scaleconfiguration = json_encode($record->scaleconfiguration);
124        }
125
126        $competency = new competency(0, $record);
127        $competency->create();
128
129        return $competency;
130    }
131
132    /**
133     * Create a new framework.
134     *
135     * @param array|stdClass $record
136     * @return competency_framework
137     */
138    public function create_framework($record = null) {
139        $generator = phpunit_util::get_data_generator();
140        $this->frameworkcount++;
141        $i = $this->frameworkcount;
142        $record = (object) $record;
143
144        if (!isset($record->shortname)) {
145            $record->shortname = "Framework shortname $i";
146        }
147        if (!isset($record->idnumber)) {
148            $record->idnumber = "frm{$i}";
149        }
150        if (!isset($record->description)) {
151            $record->description = "Framework $i description ";
152        }
153        if (!isset($record->descriptionformat)) {
154            $record->descriptionformat = FORMAT_HTML;
155        }
156        if (!isset($record->visible)) {
157            $record->visible = 1;
158        }
159        if (!isset($record->scaleid)) {
160            if (isset($record->scaleconfiguration)) {
161                throw new coding_exception('Scale configuration must be provided with a scale.');
162            }
163            if (!$this->scale) {
164                $this->scale = $generator->create_scale(array('scale' => 'A,B,C,D'));
165            }
166            $record->scaleid = $this->scale->id;
167        }
168        if (!isset($record->scaleconfiguration)) {
169            $record->scaleconfiguration = json_encode($this->make_default_scale_configuration($record->scaleid));
170        }
171        if (is_array($record->scaleconfiguration) || is_object($record->scaleconfiguration)) {
172            // Conveniently encode the config.
173            $record->scaleconfiguration = json_encode($record->scaleconfiguration);
174        }
175        if (!isset($record->contextid)) {
176            $record->contextid = context_system::instance()->id;
177        }
178
179        $framework = new competency_framework(0, $record);
180        $framework->create();
181
182        return $framework;
183    }
184
185    /**
186     * Create a related competency.
187     *
188     * @param array|stdClass $record
189     * @return related_competency
190     */
191    public function create_related_competency($record = null) {
192        $record = (object) $record;
193
194        if (!isset($record->competencyid)) {
195            throw new coding_exception('Property competencyid is required.');
196        }
197        if (!isset($record->relatedcompetencyid)) {
198            throw new coding_exception('Property relatedcompetencyid is required.');
199        }
200
201        $relation = related_competency::get_relation($record->competencyid, $record->relatedcompetencyid);
202        if ($relation->get('id')) {
203            throw new coding_exception('Relation already exists');
204        }
205        $relation->create();
206
207        return $relation;
208    }
209
210    /**
211     * Create a template.
212     *
213     * @param array|stdClass $record
214     * @return template
215     */
216    public function create_template($record = null) {
217        $this->templatecount++;
218        $i = $this->templatecount;
219        $record = (object) $record;
220
221        if (!isset($record->shortname)) {
222            $record->shortname = "Template shortname $i";
223        }
224        if (!isset($record->description)) {
225            $record->description = "Template $i description ";
226        }
227        if (!isset($record->contextid)) {
228            $record->contextid = context_system::instance()->id;
229        }
230
231        $template = new template(0, $record);
232        $template->create();
233
234        return $template;
235    }
236
237    /**
238     * Create a template competency.
239     *
240     * @param array|stdClass $record
241     * @return template_competency
242     */
243    public function create_template_competency($record = null) {
244        $record = (object) $record;
245
246        if (!isset($record->competencyid)) {
247            throw new coding_exception('Property competencyid is required.');
248        }
249        if (!isset($record->templateid)) {
250            throw new coding_exception('Property templateid is required.');
251        }
252
253        $relation = new template_competency(0, $record);
254        $relation->create();
255
256        return $relation;
257    }
258
259    /**
260     * Create a new user competency.
261     *
262     * @param array|stdClass $record
263     * @return user_competency
264     */
265    public function create_user_competency($record = null) {
266        $record = (object) $record;
267
268        if (!isset($record->userid)) {
269            throw new coding_exception('The userid value is required.');
270        }
271        if (!isset($record->competencyid)) {
272            throw new coding_exception('The competencyid value is required.');
273        }
274
275        $usercompetency = new user_competency(0, $record);
276        $usercompetency->create();
277
278        return $usercompetency;
279    }
280
281    /**
282     * Create a new plan.
283     *
284     * @param array|stdClass $record
285     * @return plan
286     */
287    public function create_plan($record = null) {
288        $this->plancount++;
289        $i = $this->plancount;
290        $record = (object) $record;
291
292        if (!isset($record->name)) {
293            $record->name = "Plan shortname $i";
294        }
295        if (!isset($record->description)) {
296            $record->description = "Plan $i description";
297        }
298        if (!isset($record->descriptionformat)) {
299            $record->descriptionformat = FORMAT_HTML;
300        }
301        if (!isset($record->userid)) {
302            throw new coding_exception('The userid value is required.');
303        }
304
305        $plan = new plan(0, $record);
306        $plan->create();
307
308        return $plan;
309    }
310
311    /**
312     * Create a new user competency course.
313     *
314     * @param array|stdClass $record
315     * @return user_competency_course
316     */
317    public function create_user_competency_course($record = null) {
318        $record = (object) $record;
319
320        if (!isset($record->userid)) {
321            throw new coding_exception('The userid value is required.');
322        }
323        if (!isset($record->competencyid)) {
324            throw new coding_exception('The competencyid value is required.');
325        }
326
327        if (!isset($record->courseid)) {
328            throw new coding_exception('The courseid value is required.');
329        }
330
331        $usercompetencycourse = new user_competency_course(0, $record);
332        $usercompetencycourse->create();
333
334        return $usercompetencycourse;
335    }
336
337    /**
338     * Create a new user competency plan.
339     *
340     * @param array|stdClass $record
341     * @return user_competency_plan
342     */
343    public function create_user_competency_plan($record = null) {
344        $record = (object) $record;
345
346        if (!isset($record->userid)) {
347            throw new coding_exception('The userid value is required.');
348        }
349        if (!isset($record->competencyid)) {
350            throw new coding_exception('The competencyid value is required.');
351        }
352
353        if (!isset($record->planid)) {
354            throw new coding_exception('The planid value is required.');
355        }
356
357        if (!isset($record->sortorder)) {
358            $record->sortorder = 0;
359        }
360
361        $usercompetencyplan = new user_competency_plan(0, $record);
362        $usercompetencyplan->create();
363
364        return $usercompetencyplan;
365    }
366
367    /**
368     * Create a new plan competency.
369     *
370     * @param array|stdClass $record
371     * @return plan_competency
372     */
373    public function create_plan_competency($record = null) {
374        $record = (object) $record;
375
376        if (!isset($record->planid)) {
377            throw new coding_exception('The planid value is required.');
378        }
379        if (!isset($record->competencyid)) {
380            throw new coding_exception('The competencyid value is required.');
381        }
382
383        $plancompetency = new plan_competency(0, $record);
384        $plancompetency->create();
385
386        return $plancompetency;
387    }
388
389    /**
390     * Create a new template cohort.
391     *
392     * @param array|stdClass $record
393     * @return template_cohort
394     */
395    public function create_template_cohort($record = null) {
396        $record = (object) $record;
397
398        if (!isset($record->templateid)) {
399            throw new coding_exception('The templateid value is required.');
400        }
401        if (!isset($record->cohortid)) {
402            throw new coding_exception('The cohortid value is required.');
403        }
404
405        $tplcohort = new template_cohort(0, $record);
406        $tplcohort->create();
407
408        return $tplcohort;
409    }
410
411    /**
412     * Create a new evidence.
413     *
414     * @param array|stdClass $record
415     * @return evidence
416     */
417    public function create_evidence($record = null) {
418        $record = (object) $record;
419
420        if (!isset($record->usercompetencyid)) {
421            throw new coding_exception('The usercompetencyid value is required.');
422        }
423        if (!isset($record->action) && !isset($record->grade)) {
424            $record->action = evidence::ACTION_LOG;
425        }
426        if (!isset($record->action)) {
427            throw new coding_exception('The action value is required with a grade.');
428        }
429
430        if (!isset($record->contextid)) {
431            $record->contextid = context_system::instance()->id;
432        }
433        if (!isset($record->descidentifier)) {
434            $record->descidentifier = 'invalidevidencedesc';
435        }
436        if (!isset($record->desccomponent)) {
437            $record->desccomponent = 'core_competency';
438        }
439        $evidence = new evidence(0, $record);
440        $evidence->create();
441
442        return $evidence;
443    }
444
445    /**
446     * Create a new course competency.
447     *
448     * @param array|stdClass $record
449     * @return user_competency
450     */
451    public function create_course_competency($record = null) {
452        $record = (object) $record;
453
454        if (!isset($record->courseid)) {
455            throw new coding_exception('The courseid value is required.');
456        }
457        if (!isset($record->competencyid)) {
458            throw new coding_exception('The competencyid value is required.');
459        }
460
461        $cc = new course_competency(0, $record);
462        $cc->create();
463
464        return $cc;
465    }
466
467    /**
468     * Create a new course module competency.
469     *
470     * @param array|stdClass $record
471     * @return course_module_competency
472     */
473    public function create_course_module_competency($record = null) {
474        $record = (object) $record;
475
476        if (!isset($record->cmid)) {
477            throw new coding_exception('The cmid value is required.');
478        }
479        if (!isset($record->competencyid)) {
480            throw new coding_exception('The competencyid value is required.');
481        }
482
483        $cc = new course_module_competency(0, $record);
484        $cc->create();
485
486        return $cc;
487    }
488
489    /**
490     * Create a new user_evidence.
491     *
492     * @param array|stdClass $record
493     * @return evidence
494     */
495    public function create_user_evidence($record = null) {
496        $this->userevidencecount++;
497        $i = $this->userevidencecount;
498        $record = (object) $record;
499
500        if (!isset($record->userid)) {
501            throw new coding_exception('The userid value is required.');
502        }
503        if (!isset($record->name)) {
504            $record->name = "Evidence $i name";
505        }
506        if (!isset($record->description)) {
507            $record->description = "Evidence $i description";
508        }
509        if (!isset($record->descriptionformat)) {
510            $record->descriptionformat = FORMAT_HTML;
511        }
512
513        $ue = new user_evidence(0, $record);
514        $ue->create();
515
516        return $ue;
517    }
518
519    /**
520     * Create a new user_evidence_comp.
521     *
522     * @param array|stdClass $record
523     * @return evidence
524     */
525    public function create_user_evidence_competency($record = null) {
526        $record = (object) $record;
527
528        if (!isset($record->userevidenceid)) {
529            throw new coding_exception('The userevidenceid value is required.');
530        }
531        if (!isset($record->competencyid)) {
532            throw new coding_exception('The competencyid value is required.');
533        }
534
535        $uec = new user_evidence_competency(0, $record);
536        $uec->create();
537
538        return $uec;
539    }
540
541    /**
542     * Make a default scale configuration.
543     *
544     * The last and second-last item will be flagged proficient. The
545     * second-last item will be flagged as default.
546     *
547     * @param int $scaleid The scale ID.
548     * @return array Configuration as array.
549     */
550    protected function make_default_scale_configuration($scaleid) {
551        $scale = grade_scale::fetch(array('id' => $scaleid));
552        $values = $scale->load_items();
553
554        foreach ($values as $key => $value) {
555            // Add a key (make the first value 1).
556            $values[$key] = array('id' => $key + 1, 'name' => $value);
557        }
558
559        if (count($values) < 2) {
560            throw new coding_exception('Please provide the scale configuration for one-item scales.');
561        }
562
563        $scaleconfig = array();
564
565        // Last item is proficient.
566        $item = array_pop($values);
567        array_unshift($scaleconfig, array(
568            'id' => $item['id'],
569            'proficient' => 1
570        ));
571
572        // Second-last item is default and proficient.
573        $item = array_pop($values);
574        array_unshift($scaleconfig, array(
575            'id' => $item['id'],
576            'scaledefault' => 1,
577            'proficient' => 1
578        ));
579
580        // Add the scale ID.
581        array_unshift($scaleconfig, array('scaleid' => $scaleid));
582
583        return $scaleconfig;
584    }
585
586}
587
588