8959fe95dca6cd52ee2e8e452dddc60d9199f1d8
[moodle.git] / admin / tool / lp / classes / api.php
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/>.
17 /**
18  * Class for loading/storing competency frameworks from the DB.
19  *
20  * @package    tool_lp
21  * @copyright  2015 Damyon Wiese
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
24 namespace tool_lp;
26 use stdClass;
27 use context_system;
28 use context_course;
29 use context_user;
30 use coding_exception;
31 use required_capability_exception;
33 /**
34  * Class for doing things with competency frameworks.
35  *
36  * @copyright  2015 Damyon Wiese
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class api {
41     /**
42      * Create a competency from a record containing all the data for the class.
43      *
44      * Requires tool/lp:competencymanage capability at the system context.
45      *
46      * @param stdClass $record Record containing all the data for an instance of the class.
47      * @return competency
48      */
49     public static function create_competency(stdClass $record) {
50         // First we do a permissions check.
51         require_capability('tool/lp:competencymanage', context_system::instance());
53         // OK - all set.
54         $competency = new competency(0, $record);
55         $id = $competency->create();
56         return $competency;
57     }
59     /**
60      * Delete a competency by id.
61      *
62      * Requires tool/lp:competencymanage capability at the system context.
63      *
64      * @param int $id The record to delete. This will delete alot of related data - you better be sure.
65      * @return boolean
66      */
67     public static function delete_competency($id) {
68         // First we do a permissions check.
69         require_capability('tool/lp:competencymanage', context_system::instance());
71         // OK - all set.
72         $competency = new competency();
73         $competency->set_id($id);
74         return $competency->delete();
75     }
77     /**
78      * Reorder this competency.
79      *
80      * Requires tool/lp:competencymanage capability at the system context.
81      *
82      * @param int $id The id of the competency to move.
83      * @return boolean
84      */
85     public static function move_down_competency($id) {
86         // First we do a permissions check.
87         require_capability('tool/lp:competencymanage', context_system::instance());
89         // Check the current one too.
90         $current = new competency($id);
92         $max = self::count_competencies(array('parentid' => $current->get_parentid(),
93                                              'competencyframeworkid' => $current->get_competencyframeworkid()));
94         if ($max > 0) {
95             $max--;
96         }
98         $sortorder = $current->get_sortorder();
99         if ($sortorder >= $max) {
100             return false;
101         }
102         $sortorder = $sortorder + 1;
103         $current->set_sortorder($sortorder);
105         $filters = array('parentid' => $current->get_parentid(),
106                          'competencyframeworkid' => $current->get_competencyframeworkid(),
107                          'sortorder' => $sortorder);
108         $children = self::list_competencies($filters, 'id');
109         foreach ($children as $needtoswap) {
110             $needtoswap->set_sortorder($sortorder - 1);
111             $needtoswap->update();
112         }
114         // OK - all set.
115         return $current->update();
116     }
118     /**
119      * Reorder this competency.
120      *
121      * Requires tool/lp:competencymanage capability at the system context.
122      *
123      * @param int $id The id of the competency to move.
124      * @return boolean
125      */
126     public static function move_up_competency($id) {
127         // First we do a permissions check.
128         require_capability('tool/lp:competencymanage', context_system::instance());
130         // Check the current one too.
131         $current = new competency($id);
133         $sortorder = $current->get_sortorder();
134         if ($sortorder == 0) {
135             return false;
136         }
138         $sortorder = $sortorder - 1;
139         $current->set_sortorder($sortorder);
141         $filters = array('parentid' => $current->get_parentid(),
142                          'competencyframeworkid' => $current->get_competencyframeworkid(),
143                          'sortorder' => $sortorder);
144         $children = self::list_competencies($filters, 'id');
145         foreach ($children as $needtoswap) {
146             $needtoswap->set_sortorder($sortorder + 1);
147             $needtoswap->update();
148         }
150         // OK - all set.
151         return $current->update();
152     }
154     /**
155      * Move this competency so it sits in a new parent.
156      *
157      * Requires tool/lp:competencymanage capability at the system context.
158      *
159      * @param int $id The id of the competency to move.
160      * @param int $newparentid The new parent id for the competency.
161      * @return boolean
162      */
163     public static function set_parent_competency($id, $newparentid) {
164         // First we do a permissions check.
165         require_capability('tool/lp:competencymanage', context_system::instance());
167         // This will throw an exception if the parent does not exist.
169         // Check the current one too.
170         $current = new competency($id);
171         $parentframeworkid = $current->get_competencyframeworkid();
172         $parentpath = '/0/';
173         if ($newparentid) {
174             $parent = new competency($newparentid);
175             $parentframeworkid = $parent->get_competencyframeworkid();
176             $parentpath = $parent->get_path();
177         }
179         if ($parentframeworkid != $current->get_competencyframeworkid()) {
180             // Only allow moving within the same framework.
181             throw new coding_exception('Moving competencies is only supported within the same framework.');
182         }
184         // If we are moving a node to a child of itself, promote all the child nodes by one level.
186         $newparents = explode('/', $parentpath);
187         if (in_array($current->get_id(), $newparents)) {
188             $filters = array('parentid' => $current->get_id(), 'competencyframeworkid' => $current->get_competencyframeworkid());
189             $children = self::list_competencies($filters, 'id');
191             foreach ($children as $child) {
192                 $child->set_parentid($current->get_parentid());
193                 $child->update();
194             }
195         }
197         $current->set_parentid($newparentid);
199         // OK - all set.
200         return $current->update();
201     }
203     /**
204      * Update the details for a competency.
205      *
206      * Requires tool/lp:competencymanage capability at the system context.
207      *
208      * @param stdClass $record The new details for the competency. Note - must contain an id that points to the competency to update.
209      * @return boolean
210      */
211     public static function update_competency($record) {
212         // First we do a permissions check.
213         require_capability('tool/lp:competencymanage', context_system::instance());
215         // Some things should not be changed in an update - they should use a more specific method.
216         $current = new competency($record->id);
217         $record->sortorder = $current->get_sortorder();
218         $record->parentid = $current->get_parentid();
219         $record->competencyframeworkid = $current->get_competencyframeworkid();
221         // OK - all set.
222         $competency = new competency(0, $record);
223         return $competency->update();
224     }
226     /**
227      * Read a the details for a single competency and return a record.
228      *
229      * Requires tool/lp:competencyread capability at the system context.
230      *
231      * @param int $id The id of the competency to read.
232      * @return stdClass
233      */
234     public static function read_competency($id) {
235         // First we do a permissions check.
236         $context = context_system::instance();
237         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
238              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
239         }
241         // OK - all set.
242         return new competency($id);
243     }
245     /**
246      * Perform a text search based and return all results and their parents.
247      *
248      * Requires tool/lp:competencyread capability at the system context.
249      *
250      * @param string $textsearch A string to search for.
251      * @param int $competencyframeworkid The id of the framework to limit the search.
252      * @return array of competencies
253      */
254     public static function search_competencies($textsearch, $competencyframeworkid) {
255         // First we do a permissions check.
256         $context = context_system::instance();
257         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
258              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
259         }
261         // OK - all set.
262         $competency = new competency();
263         return $competency->search($textsearch, $competencyframeworkid);
264     }
266     /**
267      * Perform a search based on the provided filters and return a paginated list of records.
268      *
269      * Requires tool/lp:competencyread capability at the system context.
270      *
271      * @param array $filters A list of filters to apply to the list.
272      * @param string $sort The column to sort on
273      * @param string $order ('ASC' or 'DESC')
274      * @param int $skip Number of records to skip (pagination)
275      * @param int $limit Max of records to return (pagination)
276      * @return array of competencies
277      */
278     public static function list_competencies($filters, $sort = '', $order = 'ASC', $skip = 0, $limit = 0) {
279         // First we do a permissions check.
280         $context = context_system::instance();
281         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
282              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
283         }
285         // OK - all set.
286         $competency = new competency();
287         return $competency->get_records($filters, $sort, $order, $skip, $limit);
288     }
290     /**
291      * Perform a search based on the provided filters and return a paginated list of records.
292      *
293      * Requires tool/lp:competencyread capability at the system context.
294      *
295      * @param array $filters A list of filters to apply to the list.
296      * @return int
297      */
298     public static function count_competencies($filters) {
299         // First we do a permissions check.
300         $context = context_system::instance();
301         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
302              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
303         }
305         // OK - all set.
306         $competency = new competency();
307         return $competency->count_records($filters);
308     }
310     /**
311      * Create a competency framework from a record containing all the data for the class.
312      *
313      * Requires tool/lp:competencymanage capability at the system context.
314      *
315      * @param stdClass $record Record containing all the data for an instance of the class.
316      * @return competency_framework
317      */
318     public static function create_framework(stdClass $record) {
319         // First we do a permissions check.
320         require_capability('tool/lp:competencymanage', context_system::instance());
322         // OK - all set.
323         $framework = new competency_framework(0, $record);
324         $id = $framework->create();
325         return $framework;
326     }
328     /**
329      * Delete a competency framework by id.
330      *
331      * Requires tool/lp:competencymanage capability at the system context.
332      *
333      * @param int $id The record to delete. This will delete alot of related data - you better be sure.
334      * @return boolean
335      */
336     public static function delete_framework($id) {
337         // First we do a permissions check.
338         require_capability('tool/lp:competencymanage', context_system::instance());
340         // OK - all set.
341         $framework = new competency_framework();
342         $framework->set_id($id);
343         return $framework->delete();
344     }
346     /**
347      * Update the details for a competency framework.
348      *
349      * Requires tool/lp:competencymanage capability at the system context.
350      *
351      * @param stdClass $record The new details for the framework. Note - must contain an id that points to the framework to update.
352      * @return boolean
353      */
354     public static function update_framework($record) {
355         // First we do a permissions check.
356         require_capability('tool/lp:competencymanage', context_system::instance());
358         // OK - all set.
359         $framework = new competency_framework(0, $record);
360         return $framework->update();
361     }
363     /**
364      * Read a the details for a single competency framework and return a record.
365      *
366      * Requires tool/lp:competencyread capability at the system context.
367      *
368      * @param int $id The id of the framework to read.
369      * @return stdClass
370      */
371     public static function read_framework($id) {
372         // First we do a permissions check.
373         $context = context_system::instance();
374         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
375              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
376         }
378         // OK - all set.
379         return new competency_framework($id);
380     }
382     /**
383      * Move the competency framework up or down in the display list.
384      *
385      * Requires tool/lp:competencymanage capability at the system context.
386      *
387      * @param int $frameworkidfrom The framework we are moving.
388      * @param int $frameworkidto Where we are moving to. If moving down, it will go after this framework,
389      *                           If moving up, it will go before this framework.
390      * @return boolean
391      */
392     public static function reorder_framework($frameworkidfrom, $frameworkidto) {
393         require_capability('tool/lp:competencymanage', context_system::instance());
394         $down = true;
395         $frameworkfrom = new competency_framework($frameworkidfrom);
396         $frameworkto = new competency_framework($frameworkidto);
398         $all = self::list_frameworks(array(), 'sortorder', 'ASC', 0, 0);
400         if ($frameworkfrom->get_sortorder() > $frameworkto->get_sortorder()) {
401             // We are moving down, so put it after the "to" item.
402             $down = false;
403         }
405         foreach ($all as $id => $framework) {
406             $sort = $framework->get_sortorder();
407             if ($down && $sort >  $frameworkfrom->get_sortorder() && $sort <= $frameworkto->get_sortorder()) {
408                 $framework->set_sortorder($framework->get_sortorder() - 1);
409                 $framework->update();
410             } else if (!$down && $sort >=  $frameworkto->get_sortorder() && $sort < $frameworkfrom->get_sortorder()) {
411                 $framework->set_sortorder($framework->get_sortorder() + 1);
412                 $framework->update();
413             }
414         }
415         $frameworkfrom->set_sortorder($frameworkto->get_sortorder());
416         return $frameworkfrom->update();
417     }
419     /**
420      * Perform a search based on the provided filters and return a paginated list of records.
421      *
422      * Requires tool/lp:competencyread capability at the system context.
423      *
424      * @param array $filters A list of filters to apply to the list.
425      * @param string $sort The column to sort on
426      * @param string $order ('ASC' or 'DESC')
427      * @param int $skip Number of records to skip (pagination)
428      * @param int $limit Max of records to return (pagination)
429      * @return array of competency_framework
430      */
431     public static function list_frameworks($filters, $sort, $order, $skip, $limit) {
432         // First we do a permissions check.
433         $context = context_system::instance();
434         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
435              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
436         }
438         // OK - all set.
439         $framework = new competency_framework();
440         return $framework->get_records($filters, $sort, $order, $skip, $limit);
441     }
443     /**
444      * Perform a search based on the provided filters and return a paginated list of records.
445      *
446      * Requires tool/lp:competencyread capability at the system context.
447      *
448      * @param array $filters A list of filters to apply to the list.
449      * @return int
450      */
451     public static function count_frameworks($filters) {
452         // First we do a permissions check.
453         $context = context_system::instance();
454         if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
455              throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
456         }
458         // OK - all set.
459         $framework = new competency_framework();
460         return $framework->count_records($filters);
461     }
463     /**
464      * Count all the courses using a competency.
465      *
466      * @param int $competencyid The id of the competency to check.
467      * @return int
468      */
469     public static function count_courses_using_competency($competencyid) {
471         // OK - all set.
472         $coursecompetency = new course_competency();
473         $courses = $coursecompetency->list_courses_min($competencyid);
474         $count = 0;
475         // Now check permissions on each course.
476         foreach ($courses as $course) {
477             $context = context_course::instance($course->id);
478             $capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
479             if (!has_any_capability($capabilities, $context)) {
480                 continue;
481             }
483             if (!$course->visible && !has_capability('course:viewhidden', $context)) {
484                 continue;
485             }
487             $count++;
488         }
490         return $count;
491     }
493     /**
494      * List all the courses using a competency.
495      *
496      * @param int $competencyid The id of the competency to check.
497      * @return array[stdClass] Array of stdClass containing id and shortname.
498      */
499     public static function list_courses_using_competency($competencyid) {
501         // OK - all set.
502         $coursecompetency = new course_competency();
503         $courses = $coursecompetency->list_courses($competencyid);
504         $count = 0;
505         $result = array();
506         // Now check permissions on each course.
507         foreach ($courses as $id => $course) {
508             $context = context_course::instance($course->id);
509             $capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
510             if (!has_any_capability($capabilities, $context)) {
511                 unset($courses[$id]);
512                 continue;
513             }
515             if (!$course->visible && !has_capability('course:viewhidden', $context)) {
516                 unset($courses[$id]);
517                 continue;
518             }
519             $course->fullnameformatted = format_text($course->fullname, array('context' => $context));
520             $course->shortnameformatted = format_text($course->shortname, array('context' => $context));
521             array_push($result, $course);
522         }
524         return $result;
525     }
527     /**
528      * Count all the competencies in a course.
529      *
530      * @param int $courseid The id of the course to check.
531      * @return int
532      */
533     public static function count_competencies_in_course($courseid) {
534         // First we do a permissions check.
535         $context = context_course::instance($courseid);
536         $onlyvisible = 1;
538         $capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
539         if (!has_any_capability($capabilities, $context)) {
540              throw new required_capability_exception($context, 'tool/lp:coursecompetencyread', 'nopermissions', '');
541         }
543         if (has_capability('tool/lp:coursecompetencymanage', $context)) {
544             $onlyvisible = 0;
545         }
547         // OK - all set.
548         $coursecompetency = new course_competency();
549         return $coursecompetency->count_competencies($courseid, $onlyvisible);
550     }
552     /**
553      * List all the competencies in a course.
554      *
555      * @param int $courseid The id of the course to check.
556      * @return array of competencies
557      */
558     public static function list_competencies_in_course($courseid) {
559         // First we do a permissions check.
560         $context = context_course::instance($courseid);
561         $onlyvisible = 1;
563         $capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
564         if (!has_any_capability($capabilities, $context)) {
565              throw new required_capability_exception($context, 'tool/lp:coursecompetencyread', 'nopermissions', '');
566         }
568         if (has_capability('tool/lp:coursecompetencymanage', $context)) {
569             $onlyvisible = 0;
570         }
572         // OK - all set.
573         $coursecompetency = new course_competency();
574         return $coursecompetency->list_competencies($courseid, $onlyvisible);
575     }
577     /**
578      * Add a competency to this course.
579      *
580      * @param int $courseid The id of the course
581      * @param int $competencyid The id of the competency
582      * @return bool
583      */
584     public static function add_competency_to_course($courseid, $competencyid) {
585         // First we do a permissions check.
586         $context = context_course::instance($courseid);
588         require_capability('tool/lp:coursecompetencymanage', $context);
590         $record = new stdClass();
591         $record->courseid = $courseid;
592         $record->competencyid = $competencyid;
594         $competency = new competency();
595         $competency->set_id($competencyid);
596         if (!$competency->read()) {
597              throw new coding_exception('The competency does not exist');
598         }
600         $coursecompetency = new course_competency();
601         $exists = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyid));
602         if (!$exists) {
603             $coursecompetency->from_record($record);
604             if ($coursecompetency->create()) {
605                 return true;
606             }
607         }
608         return false;
609     }
611     /**
612      * Remove a competency from this course.
613      *
614      * @param int $courseid The id of the course
615      * @param int $competencyid The id of the competency
616      * @return bool
617      */
618     public static function remove_competency_from_course($courseid, $competencyid) {
619         // First we do a permissions check.
620         $context = context_course::instance($courseid);
622         require_capability('tool/lp:coursecompetencymanage', $context);
624         $record = new stdClass();
625         $record->courseid = $courseid;
626         $record->competencyid = $competencyid;
628         $competency = new competency();
629         $competency->set_id($competencyid);
630         if (!$competency->read()) {
631              throw new coding_exception('The competency does not exist');
632         }
634         $coursecompetency = new course_competency();
635         $exists = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyid));
636         if ($exists) {
637             $competency = array_pop($exists);
638             return $competency->delete();
639         }
640         return false;
641     }
643     /**
644      * Move the course competency up or down in the display list.
645      *
646      * Requires tool/lp:coursecompetencymanage capability at the course context.
647      *
648      * @param int $courseid The course
649      * @param int $competencyidfrom The id of the competency we are moving.
650      * @param int $competencyidto The id of the competency we are moving to.
651      * @return boolean
652      */
653     public static function reorder_course_competency($courseid, $competencyidfrom, $competencyidto) {
654         // First we do a permissions check.
655         $context = context_course::instance($courseid);
657         require_capability('tool/lp:coursecompetencymanage', $context);
659         $down = true;
660         $coursecompetency = new course_competency();
661         $matches = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyidfrom));
662         if (count($matches) == 0) {
663              throw new coding_exception('The link does not exist');
664         }
666         $competencyfrom = array_pop($matches);
667         $matches = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyidto));
668         if (count($matches) == 0) {
669              throw new coding_exception('The link does not exist');
670         }
672         $competencyto = array_pop($matches);
674         $all = $coursecompetency->get_records(array('courseid' => $courseid), 'sortorder', 'ASC', 0, 0);
676         if ($competencyfrom->get_sortorder() > $competencyto->get_sortorder()) {
677             // We are moving up, so put it before the "to" item.
678             $down = false;
679         }
681         foreach ($all as $id => $coursecompetency) {
682             $sort = $coursecompetency->get_sortorder();
683             if ($down && $sort > $competencyfrom->get_sortorder() && $sort <= $competencyto->get_sortorder()) {
684                 $coursecompetency->set_sortorder($coursecompetency->get_sortorder() - 1);
685                 $coursecompetency->update();
686             } else if (!$down && $sort >= $competencyto->get_sortorder() && $sort < $competencyfrom->get_sortorder()) {
687                 $coursecompetency->set_sortorder($coursecompetency->get_sortorder() + 1);
688                 $coursecompetency->update();
689             }
690         }
691         $competencyfrom->set_sortorder($competencyto->get_sortorder());
692         return $competencyfrom->update();
693     }
695     /**
696      * Create a learning plan template from a record containing all the data for the class.
697      *
698      * Requires tool/lp:templatemanage capability at the system context.
699      *
700      * @param stdClass $record Record containing all the data for an instance of the class.
701      * @return template
702      */
703     public static function create_template(stdClass $record) {
704         // First we do a permissions check.
705         require_capability('tool/lp:templatemanage', context_system::instance());
707         // OK - all set.
708         $template = new template(0, $record);
709         $id = $template->create();
710         return $template;
711     }
713     /**
714      * Delete a learning plan template by id.
715      *
716      * Requires tool/lp:templatemanage capability at the system context.
717      *
718      * @param int $id The record to delete.
719      * @return boolean
720      */
721     public static function delete_template($id) {
722         // First we do a permissions check.
723         require_capability('tool/lp:templatemanage', context_system::instance());
725         // OK - all set.
726         $template = new template();
727         $template->set_id($id);
728         return $template->delete();
729     }
731     /**
732      * Update the details for a learning plan template.
733      *
734      * Requires tool/lp:templatemanage capability at the system context.
735      *
736      * @param stdClass $record The new details for the template. Note - must contain an id that points to the template to update.
737      * @return boolean
738      */
739     public static function update_template($record) {
740         // First we do a permissions check.
741         require_capability('tool/lp:templatemanage', context_system::instance());
743         // OK - all set.
744         $template = new template(0, $record);
745         return $template->update();
746     }
748     /**
749      * Read a the details for a single learning plan template and return a record.
750      *
751      * Requires tool/lp:templateread capability at the system context.
752      *
753      * @param int $id The id of the template to read.
754      * @return stdClass
755      */
756     public static function read_template($id) {
757         // First we do a permissions check.
758         $context = context_system::instance();
759         $caps = array('tool/lp:templateread', 'tool/lp:templatemanage');
760         if (!has_any_capability($caps, $context)) {
761              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
762         }
764         // OK - all set.
765         return new template($id);
766     }
768     /**
769      * Move the learning plan template up or down in the display list.
770      *
771      * Requires tool/lp:templatemanage capability at the system context.
772      *
773      * @param int $templateidfrom The template we are moving.
774      * @param int $templateidto Where we are moving to. If moving down, it will go after this template,
775      *                           If moving up, it will go before this template.
776      * @return boolean
777      */
778     public static function reorder_template($templateidfrom, $templateidto) {
779         require_capability('tool/lp:templatemanage', context_system::instance());
780         $down = true;
781         $templatefrom = new template($templateidfrom);
782         $templateto = new template($templateidto);
784         $all = self::list_templates(array(), 'sortorder', 'ASC', 0, 0);
786         if ($templatefrom->get_sortorder() > $templateto->get_sortorder()) {
787             // We are moving down, so put it after the "to" item.
788             $down = false;
789         }
791         foreach ($all as $id => $template) {
792             $sort = $template->get_sortorder();
793             if ($down && $sort >  $templatefrom->get_sortorder() && $sort <= $templateto->get_sortorder()) {
794                 $template->set_sortorder($template->get_sortorder() - 1);
795                 $template->update();
796             } else if (!$down && $sort >=  $templateto->get_sortorder() && $sort < $templatefrom->get_sortorder()) {
797                 $template->set_sortorder($template->get_sortorder() + 1);
798                 $template->update();
799             }
800         }
801         $templatefrom->set_sortorder($templateto->get_sortorder());
802         return $templatefrom->update();
803     }
805     /**
806      * Perform a search based on the provided filters and return a paginated list of records.
807      *
808      * Requires tool/lp:templateread capability at the system context.
809      *
810      * @param array $filters A list of filters to apply to the list.
811      * @param string $sort The column to sort on
812      * @param string $order ('ASC' or 'DESC')
813      * @param int $skip Number of records to skip (pagination)
814      * @param int $limit Max of records to return (pagination)
815      * @return array of competency_framework
816      */
817     public static function list_templates($filters = array(), $sort = '', $order = 'ASC', $skip = 0, $limit = 0) {
818         // First we do a permissions check.
819         $context = context_system::instance();
820         $caps = array('tool/lp:templateread', 'tool/lp:templatemanage');
821         if (!has_any_capability($caps, $context)) {
822              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
823         }
825         // OK - all set.
826         $template = new template();
827         return $template->get_records($filters, $sort, $order, $skip, $limit);
828     }
830     /**
831      * Perform a search based on the provided filters and return how many results there are.
832      *
833      * Requires tool/lp:templateread capability at the system context.
834      *
835      * @param array $filters A list of filters to apply to the list.
836      * @return int
837      */
838     public static function count_templates($filters) {
839         // First we do a permissions check.
840         $context = context_system::instance();
841         $caps = array('tool/lp:templateread', 'tool/lp:templatemanage');
842         if (!has_any_capability($caps, $context)) {
843              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
844         }
846         // OK - all set.
847         $template = new template();
848         return $template->count_records($filters);
849     }
851     /**
852      * Count all the templates using a competency.
853      *
854      * @param int $competencyid The id of the competency to check.
855      * @return int
856      */
857     public static function count_templates_using_competency($competencyid) {
858         // First we do a permissions check.
859         $context = context_system::instance();
860         $onlyvisible = 1;
862         $capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
863         if (!has_any_capability($capabilities, $context)) {
864              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
865         }
867         if (has_capability('tool/lp:templatemanage', $context)) {
868             $onlyvisible = 0;
869         }
871         // OK - all set.
872         $templatecompetency = new template_competency();
873         return $templatecompetency->count_templates($competencyid, $onlyvisible);
874     }
876     /**
877      * List all the learning plan templatesd using a competency.
878      *
879      * @param int $competencyid The id of the competency to check.
880      * @return array[stdClass] Array of stdClass containing id and shortname.
881      */
882     public static function list_templates_using_competency($competencyid) {
883         // First we do a permissions check.
884         $context = context_system::instance();
885         $onlyvisible = 1;
887         $capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
888         if (!has_any_capability($capabilities, $context)) {
889              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
890         }
892         if (has_capability('tool/lp:templatemanage', $context)) {
893             $onlyvisible = 0;
894         }
896         // OK - all set.
897         $templatecompetency = new template_competency();
898         return $templatecompetency->list_templates($competencyid, $onlyvisible);
900     }
902     /**
903      * Count all the competencies in a learning plan template.
904      *
905      * @param int $templateid The id of the template to check.
906      * @return int
907      */
908     public static function count_competencies_in_template($templateid) {
909         // First we do a permissions check.
910         $context = context_system::instance();
911         $onlyvisible = 1;
913         $capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
914         if (!has_any_capability($capabilities, $context)) {
915              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
916         }
918         if (has_capability('tool/lp:templatemanage', $context)) {
919             $onlyvisible = 0;
920         }
922         // OK - all set.
923         $templatecompetency = new template_competency();
924         return $templatecompetency->count_competencies($templateid, $onlyvisible);
925     }
927     /**
928      * List all the competencies in a template.
929      *
930      * @param int $templateid The id of the template to check.
931      * @return array of competencies
932      */
933     public static function list_competencies_in_template($templateid) {
934         // First we do a permissions check.
935         $context = context_system::instance();
936         $onlyvisible = 1;
938         $capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
939         if (!has_any_capability($capabilities, $context)) {
940              throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
941         }
943         if (has_capability('tool/lp:templatemanage', $context)) {
944             $onlyvisible = 0;
945         }
947         // OK - all set.
948         $templatecompetency = new template_competency();
949         return $templatecompetency->list_competencies($templateid, $onlyvisible);
950     }
952     /**
953      * Add a competency to this template.
954      *
955      * @param int $templateid The id of the template
956      * @param int $competencyid The id of the competency
957      * @return bool
958      */
959     public static function add_competency_to_template($templateid, $competencyid) {
960         // First we do a permissions check.
961         $context = context_system::instance();
963         require_capability('tool/lp:templatecompetencymanage', $context);
965         $record = new stdClass();
966         $record->templateid = $templateid;
967         $record->competencyid = $competencyid;
969         $competency = new competency();
970         $competency->set_id($competencyid);
971         if (!$competency->read()) {
972             throw new coding_exception('The competency does not exist');
973         }
975         $templatecompetency = new template_competency();
976         $exists = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyid));
977         if (!$exists) {
978             $templatecompetency->from_record($record);
979             if ($templatecompetency->create()) {
980                 return true;
981             }
982         }
983         return false;
984     }
986     /**
987      * Remove a competency from this template.
988      *
989      * @param int $templateid The id of the template
990      * @param int $competencyid The id of the competency
991      * @return bool
992      */
993     public static function remove_competency_from_template($templateid, $competencyid) {
994         // First we do a permissions check.
995         $context = context_system::instance();
997         require_capability('tool/lp:templatecompetencymanage', $context);
999         $record = new stdClass();
1000         $record->templateid = $templateid;
1001         $record->competencyid = $competencyid;
1003         $competency = new competency();
1004         $competency->set_id($competencyid);
1005         if (!$competency->read()) {
1006              throw new coding_exception('The competency does not exist');
1007         }
1009         $templatecompetency = new template_competency();
1010         $exists = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyid));
1011         if ($exists) {
1012             $link = array_pop($exists);
1013             return $link->delete();
1014         }
1015         return false;
1016     }
1018     /**
1019      * Lists user plans.
1020      *
1021      * @param int userid
1022      * @return \tool_lp\plan[]
1023      */
1024     public static function list_user_plans($userid) {
1025         global $USER;
1027         $select = 'userid = :userid';
1028         $params = array('userid' => $userid);
1030         $context = context_user::instance($userid);
1032         // We can allow guest user to pass they will not have LP.
1033         if ($USER->id != $userid) {
1034             require_capability('tool/lp:planviewall', $context);
1035         } else {
1036             require_capability('tool/lp:planviewown', $context);
1037         }
1039         // Users that can manage plans can only see active and completed plans.
1040         if (!has_any_capability(array('tool/lp:planmanage', 'tool/lp:planmanageown', 'tool/lp:plancreatedraft'), $context)) {
1041             $select = ' AND status != :statusdraft';
1042             $params['statusdraft'] = plan::STATUS_DRAFT;
1043         }
1045         $plans = new plan();
1046         return $plans->get_records_select($select, $params, 'timemodified DESC');
1047     }
1049     /**
1050      * Creates a learning plan based on the provided data.
1051      *
1052      * @param stdClass $record
1053      * @return \tool_lp\plan
1054      */
1055     public static function create_plan(stdClass $record) {
1056         global $USER;
1058         $context = context_user::instance($record->userid);
1060         $manageplans = has_capability('tool/lp:planmanage', $context);
1061         $createdraft = has_capability('tool/lp:plancreatedraft', $context);
1062         $manageownplan = has_capability('tool/lp:planmanageown', $context);
1064         // Any of them is enough.
1065         if ($USER->id == $record->userid && !$manageplans && !$createdraft && !$manageownplan) {
1066             // Exception about plancreatedraft as it is the one that is closer to basic users.
1067             throw new required_capability_exception($context, 'tool/lp:plancreatedraft', 'nopermissions', '');
1068         } else if ($USER->id != $record->userid && !$manageplans) {
1069             throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
1070         }
1072         if (!isset($record->status)) {
1073             // Default to status draft.
1074             $record->status = plan::STATUS_DRAFT;
1075         } else if ($record->status !== plan::STATUS_DRAFT && !$manageplans && !$manageownplan) {
1076             // If the user can only create drafts we don't allow them to set other status.
1077             throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', '');
1078         }
1080         $plan = new plan(0, $record);
1081         $id = $plan->create();
1082         return $plan;
1083     }
1085     /**
1086      * Updates a plan.
1087      *
1088      * @param stdClass $record
1089      * @return \tool_lp\plan
1090      */
1091     public static function update_plan(stdClass $record) {
1092         global $USER;
1094         $context = context_user::instance($record->userid);
1096         $manageplans = has_capability('tool/lp:planmanage', $context);
1097         $createdraft = has_capability('tool/lp:plancreatedraft', $context);
1098         $manageownplan = has_capability('tool/lp:planmanageown', $context);
1100         // Any of them is enough.
1101         if ($USER->id == $record->userid && !$manageplans && !$createdraft && !$manageownplan) {
1102             throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', '');
1103         } else if (!$manageplans) {
1104             throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
1105         }
1107         $current = new plan($record->id);
1109         // We don't allow users without planmanage and without
1110         // planmanageown to edit plans that other users modified.
1111         if (!$manageplans && !$manageownplan && $USER->id != $current->get_usermodified()) {
1112             throw new moodle_exception('erroreditingmodifiedplan', 'tool_lp');
1113         } else if (!$manageplans && $USER->id != $current->get_userid()) {
1114             throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
1115         }
1117         // If the user can only create drafts we don't allow them to set other status.
1118         if ($record->status !== plan::STATUS_DRAFT && !$manageplans && !$manageownplan) {
1119             throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', '');
1120         }
1122         $plan = new plan($record->id, $record);
1123         return $plan->update();
1124     }
1126     /**
1127      * Returns a plan data.
1128      *
1129      * @param int $id
1130      * @return \tool_lp\plan
1131      */
1132     public static function read_plan($id) {
1133         global $USER;
1135         $plan = new plan($id);
1136         $context = context_user::instance($plan->get_userid());
1138         if ($USER->id == $plan->get_userid()) {
1139             require_capability('tool/lp:planviewown', $context);
1140         } else {
1141             require_capability('tool/lp:planviewall', $context);
1142         }
1144         // We require any of these capabilities to retrieve draft plans.
1145         if ($plan->get_status() === plan::STATUS_DRAFT &&
1146                 !has_any_capability(array('tool/lp:planmanageown', 'tool/lp:planmanage', 'tool/lp:plancreatedraft'), $context)) {
1147             // Exception about plancreatedraft as it is the one that is closer to basic users.
1148             throw new required_capability_exception($context, 'tool/lp:plancreatedraft', 'nopermissions', '');
1149         }
1150         return $plan;
1151     }
1153     /**
1154      * Deletes a plan.
1155      *
1156      * @param int $id
1157      * @return bool Success?
1158      */
1159     public static function delete_plan($id) {
1160         global $USER;
1162         $plan = new plan($id);
1164         $context = context_user::instance($plan->get_userid());
1166         $manageplans = has_capability('tool/lp:planmanage', $context);
1167         $manageownplan = has_capability('tool/lp:planmanageown', $context);
1169         if ($USER->id == $plan->get_userid() && $USER->id != $plan->get_usermodified() &&
1170                 !$manageplans && !$manageownplan) {
1171             // A normal user can only edit its plan if they created it.
1172             throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', '');
1173         } else if ($USER->id != $plan->get_userid() && !$manageplans) {
1174             // Other users needs to have tool/lp:planmanage.
1175             throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
1176         }
1178         return $plan->delete();
1179     }
1181     /**
1182      * Move the template competency up or down in the display list.
1183      *
1184      * Requires tool/lp:templatecompetencymanage capability at the system context.
1185      *
1186      * @param int $templateid The template id
1187      * @param int $competencyidfrom The id of the competency we are moving.
1188      * @param int $competencyidto The id of the competency we are moving to.
1189      * @return boolean
1190      */
1191     public static function reorder_template_competency($templateid, $competencyidfrom, $competencyidto) {
1192         // First we do a permissions check.
1193         $context = context_system::instance();
1195         require_capability('tool/lp:templatecompetencymanage', $context);
1197         $down = true;
1198         $templatecompetency = new template_competency();
1199         $matches = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyidfrom));
1200         if (count($matches) == 0) {
1201             throw new coding_exception('The link does not exist');
1202         }
1204         $competencyfrom = array_pop($matches);
1205         $matches = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyidto));
1206         if (count($matches) == 0) {
1207             throw new coding_exception('The link does not exist');
1208         }
1210         $competencyto = array_pop($matches);
1212         $all = $templatecompetency->get_records(array('templateid' => $templateid), 'sortorder', 'ASC', 0, 0);
1214         if ($competencyfrom->get_sortorder() > $competencyto->get_sortorder()) {
1215             // We are moving up, so put it before the "to" item.
1216             $down = false;
1217         }
1219         foreach ($all as $id => $templatecompetency) {
1220             $sort = $templatecompetency->get_sortorder();
1221             if ($down && $sort > $competencyfrom->get_sortorder() && $sort <= $competencyto->get_sortorder()) {
1222                 $templatecompetency->set_sortorder($templatecompetency->get_sortorder() - 1);
1223                 $templatecompetency->update();
1224             } else if (!$down && $sort >= $competencyto->get_sortorder() && $sort < $competencyfrom->get_sortorder()) {
1225                 $templatecompetency->set_sortorder($templatecompetency->get_sortorder() + 1);
1226                 $templatecompetency->update();
1227             }
1228         }
1229         $competencyfrom->set_sortorder($competencyto->get_sortorder());
1230         return $competencyfrom->update();
1231     }