a214d35ec2
- Use to_record instead of custom getters - Remove custom formatting for taxonomies - Fix bugs in exporter (PARAM_FORMAT was wrong) - use $comp->get_context() instead of $comp->get_framework()->get_context()
1683 lines
62 KiB
PHP
1683 lines
62 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* Class for loading/storing competency frameworks from the DB.
|
|
*
|
|
* @package tool_lp
|
|
* @copyright 2015 Damyon Wiese
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
namespace tool_lp;
|
|
|
|
use stdClass;
|
|
use context;
|
|
use context_helper;
|
|
use context_system;
|
|
use context_course;
|
|
use context_user;
|
|
use coding_exception;
|
|
use required_capability_exception;
|
|
|
|
/**
|
|
* Class for doing things with competency frameworks.
|
|
*
|
|
* @copyright 2015 Damyon Wiese
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class api {
|
|
|
|
/**
|
|
* Create a competency from a record containing all the data for the class.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param stdClass $record Record containing all the data for an instance of the class.
|
|
* @return competency
|
|
*/
|
|
public static function create_competency(stdClass $record) {
|
|
$competency = new competency(0, $record);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
// OK - all set.
|
|
$id = $competency->create();
|
|
return $competency;
|
|
}
|
|
|
|
/**
|
|
* Delete a competency by id.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The record to delete. This will delete alot of related data - you better be sure.
|
|
* @return boolean
|
|
*/
|
|
public static function delete_competency($id) {
|
|
$competency = new competency($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
// OK - all set.
|
|
return $competency->delete();
|
|
}
|
|
|
|
/**
|
|
* Reorder this competency.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The id of the competency to move.
|
|
* @return boolean
|
|
*/
|
|
public static function move_down_competency($id) {
|
|
$current = new competency($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $current->get_context());
|
|
|
|
$max = self::count_competencies(array('parentid' => $current->get_parentid(),
|
|
'competencyframeworkid' => $current->get_competencyframeworkid()));
|
|
if ($max > 0) {
|
|
$max--;
|
|
}
|
|
|
|
$sortorder = $current->get_sortorder();
|
|
if ($sortorder >= $max) {
|
|
return false;
|
|
}
|
|
$sortorder = $sortorder + 1;
|
|
$current->set_sortorder($sortorder);
|
|
|
|
$filters = array('parentid' => $current->get_parentid(),
|
|
'competencyframeworkid' => $current->get_competencyframeworkid(),
|
|
'sortorder' => $sortorder);
|
|
$children = self::list_competencies($filters, 'id');
|
|
foreach ($children as $needtoswap) {
|
|
$needtoswap->set_sortorder($sortorder - 1);
|
|
$needtoswap->update();
|
|
}
|
|
|
|
// OK - all set.
|
|
$current->update();
|
|
|
|
}
|
|
|
|
/**
|
|
* Reorder this competency.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The id of the competency to move.
|
|
* @return boolean
|
|
*/
|
|
public static function move_up_competency($id) {
|
|
$current = new competency($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $current->get_context());
|
|
|
|
$sortorder = $current->get_sortorder();
|
|
if ($sortorder == 0) {
|
|
return false;
|
|
}
|
|
|
|
$sortorder = $sortorder - 1;
|
|
$current->set_sortorder($sortorder);
|
|
|
|
$filters = array('parentid' => $current->get_parentid(),
|
|
'competencyframeworkid' => $current->get_competencyframeworkid(),
|
|
'sortorder' => $sortorder);
|
|
$children = self::list_competencies($filters, 'id');
|
|
foreach ($children as $needtoswap) {
|
|
$needtoswap->set_sortorder($sortorder + 1);
|
|
$needtoswap->update();
|
|
}
|
|
|
|
// OK - all set.
|
|
return $current->update();
|
|
}
|
|
|
|
/**
|
|
* Move this competency so it sits in a new parent.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The id of the competency to move.
|
|
* @param int $newparentid The new parent id for the competency.
|
|
* @return boolean
|
|
*/
|
|
public static function set_parent_competency($id, $newparentid) {
|
|
$current = new competency($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $current->get_context());
|
|
|
|
// This will throw an exception if the parent does not exist.
|
|
|
|
// Check the current one too.
|
|
$parentframeworkid = $current->get_competencyframeworkid();
|
|
$parentpath = '/0/';
|
|
if ($newparentid) {
|
|
$parent = new competency($newparentid);
|
|
$parentframeworkid = $parent->get_competencyframeworkid();
|
|
$parentpath = $parent->get_path();
|
|
}
|
|
|
|
// If we are moving a node to a child of itself, promote all the child nodes by one level.
|
|
|
|
$newparents = explode('/', $parentpath);
|
|
if (in_array($current->get_id(), $newparents)) {
|
|
$filters = array('parentid' => $current->get_id(), 'competencyframeworkid' => $current->get_competencyframeworkid());
|
|
$children = self::list_competencies($filters, 'id');
|
|
|
|
foreach ($children as $child) {
|
|
$child->set_parentid($current->get_parentid());
|
|
$child->update();
|
|
}
|
|
}
|
|
|
|
$current->set_parentid($newparentid);
|
|
|
|
// OK - all set.
|
|
return $current->update();
|
|
}
|
|
|
|
/**
|
|
* Update the details for a competency.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param stdClass $record The new details for the competency.
|
|
* Note - must contain an id that points to the competency to update.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public static function update_competency($record) {
|
|
$competency = new competency($record->id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
// Some things should not be changed in an update - they should use a more specific method.
|
|
$record->sortorder = $competency->get_sortorder();
|
|
$record->parentid = $competency->get_parentid();
|
|
$record->competencyframeworkid = $competency->get_competencyframeworkid();
|
|
|
|
$competency->from_record($record);
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
// OK - all set.
|
|
return $competency->update();
|
|
}
|
|
|
|
/**
|
|
* Read a the details for a single competency and return a record.
|
|
*
|
|
* Requires tool/lp:competencyread capability at the system context.
|
|
*
|
|
* @param int $id The id of the competency to read.
|
|
* @param bool $includerelated Include related tags or not.
|
|
* @return stdClass
|
|
*/
|
|
public static function read_competency($id, $includerelated = false) {
|
|
$competency = new competency($id);
|
|
|
|
// First we do a permissions check.
|
|
$context = $competency->get_context();
|
|
if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
if ($includerelated) {
|
|
$relatedcompetency = new related_competency();
|
|
if ($related = $relatedcompetency->list_relations($id)) {
|
|
$competency->relatedcompetencies = $related;
|
|
}
|
|
}
|
|
|
|
return $competency;
|
|
}
|
|
|
|
/**
|
|
* Perform a text search based and return all results and their parents.
|
|
*
|
|
* Requires tool/lp:competencyread capability at the framework context.
|
|
*
|
|
* @param string $textsearch A string to search for.
|
|
* @param int $competencyframeworkid The id of the framework to limit the search.
|
|
* @return array of competencies
|
|
*/
|
|
public static function search_competencies($textsearch, $competencyframeworkid) {
|
|
$framework = new competency_framework($competencyframeworkid);
|
|
|
|
// First we do a permissions check.
|
|
$context = $framework->get_context();
|
|
if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
$competencies = competency::search($textsearch, $competencyframeworkid);
|
|
return $competencies;
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return a paginated list of records.
|
|
*
|
|
* Requires tool/lp:competencyread capability at some context.
|
|
*
|
|
* @param array $filters A list of filters to apply to the list.
|
|
* @param string $sort The column to sort on
|
|
* @param string $order ('ASC' or 'DESC')
|
|
* @param int $skip Number of records to skip (pagination)
|
|
* @param int $limit Max of records to return (pagination)
|
|
* @return array of competencies
|
|
*/
|
|
public static function list_competencies($filters, $sort = '', $order = 'ASC', $skip = 0, $limit = 0) {
|
|
if (!isset($filters['competencyframeworkid'])) {
|
|
$context = context_system::instance();
|
|
} else {
|
|
$framework = new competency_framework($filters['competencyframeworkid']);
|
|
$context = $framework->get_context();
|
|
}
|
|
|
|
// First we do a permissions check.
|
|
if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
return competency::get_records($filters, $sort, $order, $skip, $limit);
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return a paginated list of records.
|
|
*
|
|
* Requires tool/lp:competencyread capability at some context.
|
|
*
|
|
* @param array $filters A list of filters to apply to the list.
|
|
* @return int
|
|
*/
|
|
public static function count_competencies($filters) {
|
|
if (!isset($filters['competencyframeworkid'])) {
|
|
$context = context_system::instance();
|
|
} else {
|
|
$framework = new competency_framework($filters['competencyframeworkid']);
|
|
$context = $framework->get_context();
|
|
}
|
|
|
|
// First we do a permissions check.
|
|
if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
return competency::count_records($filters);
|
|
}
|
|
|
|
/**
|
|
* Create a competency framework from a record containing all the data for the class.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param stdClass $record Record containing all the data for an instance of the class.
|
|
* @return competency_framework
|
|
*/
|
|
public static function create_framework(stdClass $record) {
|
|
$framework = new competency_framework(0, $record);
|
|
require_capability('tool/lp:competencymanage', $framework->get_context());
|
|
|
|
// Account for different formats of taxonomies.
|
|
if (isset($record->taxonomies)) {
|
|
$framework->set_taxonomies($record->taxonomies);
|
|
}
|
|
|
|
$id = $framework->create();
|
|
return $framework;
|
|
}
|
|
|
|
/**
|
|
* Duplicate a competency framework by id.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The record to duplicate. All competencies associated and related will be duplicated.
|
|
* @return competency_framework the framework duplicated
|
|
*/
|
|
public static function duplicate_framework($id) {
|
|
$framework = new competency_framework($id);
|
|
require_capability('tool/lp:competencymanage', $framework->get_context());
|
|
|
|
// Get a uniq idnumber based on the origin framework.
|
|
$idnumber = competency_framework::get_unused_idnumber($framework->get_idnumber());
|
|
$framework->set_idnumber($idnumber);
|
|
// Adding the suffix copy to the shortname.
|
|
$framework->set_shortname(get_string('duplicateditemname', 'tool_lp', $framework->get_shortname()));
|
|
$framework->set_id(0);
|
|
$framework->create();
|
|
|
|
// Array that match the old competencies ids with the new one to use when copying related competencies.
|
|
$matchids = self::duplicate_competency_tree($framework->get_id(), competency::get_framework_tree($id), 0, 0);
|
|
|
|
// Copy the related competencies.
|
|
$relcomps = related_competency::get_multiple_relations(array_keys($matchids));
|
|
|
|
foreach ($relcomps as $relcomp) {
|
|
$compid = $relcomp->get_competencyid();
|
|
$relcompid = $relcomp->get_relatedcompetencyid();
|
|
if (isset($matchids[$compid]) && isset($matchids[$relcompid])) {
|
|
$newcompid = $matchids[$compid];
|
|
$newrelcompid = $matchids[$relcompid];
|
|
if ($newcompid < $newrelcompid) {
|
|
$relcomp->set_competencyid($newcompid);
|
|
$relcomp->set_relatedcompetencyid($newrelcompid);
|
|
} else {
|
|
$relcomp->set_competencyid($newrelcompid);
|
|
$relcomp->set_relatedcompetencyid($newcompid);
|
|
}
|
|
$relcomp->set_id(0);
|
|
$relcomp->create();
|
|
} else {
|
|
// Debugging message when there is no match found.
|
|
debugging('related competency id not found');
|
|
}
|
|
}
|
|
return $framework;
|
|
}
|
|
|
|
/**
|
|
* Delete a competency framework by id.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param int $id The record to delete. This will delete alot of related data - you better be sure.
|
|
* @return boolean
|
|
*/
|
|
public static function delete_framework($id) {
|
|
$framework = new competency_framework($id);
|
|
require_capability('tool/lp:competencymanage', $framework->get_context());
|
|
return $framework->delete();
|
|
}
|
|
|
|
/**
|
|
* Update the details for a competency framework.
|
|
*
|
|
* Requires tool/lp:competencymanage capability at the system context.
|
|
*
|
|
* @param stdClass $record The new details for the framework. Note - must contain an id that points to the framework to update.
|
|
* @return boolean
|
|
*/
|
|
public static function update_framework($record) {
|
|
$framework = new competency_framework($record->id);
|
|
|
|
// Check the permissions before update.
|
|
require_capability('tool/lp:competencymanage', $framework->get_context());
|
|
|
|
// Account for different formats of taxonomies.
|
|
$framework->from_record($record);
|
|
if (isset($record->taxonomies)) {
|
|
$framework->set_taxonomies($record->taxonomies);
|
|
}
|
|
|
|
return $framework->update();
|
|
}
|
|
|
|
/**
|
|
* Read a the details for a single competency framework and return a record.
|
|
*
|
|
* Requires tool/lp:competencyread capability at the system context.
|
|
*
|
|
* @param int $id The id of the framework to read.
|
|
* @return competency_framework
|
|
*/
|
|
public static function read_framework($id) {
|
|
$framework = new competency_framework($id);
|
|
if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $framework->get_context())) {
|
|
throw new required_capability_exception($framework->get_context(), 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
return $framework;
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return a paginated list of records.
|
|
*
|
|
* Requires tool/lp:competencyread capability at the system context.
|
|
*
|
|
* @param string $sort The column to sort on
|
|
* @param string $order ('ASC' or 'DESC')
|
|
* @param int $skip Number of records to skip (pagination)
|
|
* @param int $limit Max of records to return (pagination)
|
|
* @param context $context The parent context of the frameworks.
|
|
* @param string $includes Defines what other contexts to fetch frameworks from.
|
|
* Accepted values are:
|
|
* - children: All descendants
|
|
* - parents: All parents, grand parents, etc...
|
|
* - self: Context passed only.
|
|
* @return array of competency_framework
|
|
*/
|
|
public static function list_frameworks($sort, $order, $skip, $limit, $context, $includes = 'children') {
|
|
global $DB;
|
|
|
|
// Get all the relevant contexts.
|
|
$contexts = self::get_related_contexts($context, $includes,
|
|
array('tool/lp:competencyread', 'tool/lp:competencymanage'));
|
|
|
|
if (empty($contexts)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
|
|
return competency_framework::get_records_select("contextid $insql", $inparams, $sort . ' ' . $order, '*', $skip, $limit);
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return a paginated list of records.
|
|
*
|
|
* Requires tool/lp:competencyread capability at the system context.
|
|
*
|
|
* @param context $context The parent context of the frameworks.
|
|
* @param string $includes Defines what other contexts to fetch frameworks from.
|
|
* Accepted values are:
|
|
* - children: All descendants
|
|
* - parents: All parents, grand parents, etc...
|
|
* - self: Context passed only.
|
|
* @return int
|
|
*/
|
|
public static function count_frameworks($context, $includes) {
|
|
global $DB;
|
|
|
|
// Get all the relevant contexts.
|
|
$contexts = self::get_related_contexts($context, $includes,
|
|
array('tool/lp:competencyread', 'tool/lp:competencymanage'));
|
|
|
|
if (empty($contexts)) {
|
|
throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
|
|
return competency_framework::count_records_select("contextid $insql", $inparams);
|
|
}
|
|
|
|
/**
|
|
* Fetches all the relevant contexts.
|
|
*
|
|
* Note: This currently only supports system, category and user contexts. However user contexts
|
|
* behave a bit differently and will fallback on the system context. This is what makes the most
|
|
* sense because a user context does not have descendants, and only has system as a parent.
|
|
*
|
|
* @param context $context The context to start from.
|
|
* @param string $includes Defines what other contexts to find.
|
|
* Accepted values are:
|
|
* - children: All descendants
|
|
* - parents: All parents, grand parents, etc...
|
|
* - self: Context passed only.
|
|
* @param array $hasanycapability Array of capabilities passed to {@link has_any_capability()} in each context.
|
|
* @return context[] An array of contexts where keys are context IDs.
|
|
*/
|
|
public static function get_related_contexts($context, $includes, array $hasanycapability = null) {
|
|
global $DB;
|
|
|
|
if (!in_array($includes, array('children', 'parents', 'self'))) {
|
|
throw new coding_exception('Invalid parameter value for \'includes\'.');
|
|
}
|
|
|
|
// If context user swap it for the context_system.
|
|
if ($context->contextlevel == CONTEXT_USER) {
|
|
$context = context_system::instance();
|
|
}
|
|
|
|
$contexts = array($context->id => $context);
|
|
|
|
if ($includes == 'children') {
|
|
$params = array('coursecatlevel' => CONTEXT_COURSECAT, 'path' => $context->path . '/%');
|
|
$pathlike = $DB->sql_like('path', ':path');
|
|
$sql = "contextlevel = :coursecatlevel AND $pathlike";
|
|
$rs = $DB->get_recordset_select('context', $sql, $params);
|
|
foreach ($rs as $record) {
|
|
$ctxid = $record->id;
|
|
context_helper::preload_from_record($record);
|
|
$contexts[$ctxid] = context::instance_by_id($ctxid);
|
|
}
|
|
$rs->close();
|
|
|
|
} else if ($includes == 'parents') {
|
|
$children = $context->get_parent_contexts();
|
|
foreach ($children as $ctx) {
|
|
$contexts[$ctx->id] = $ctx;
|
|
}
|
|
}
|
|
|
|
// Filter according to the capabilities required.
|
|
if (!empty($hasanycapability)) {
|
|
foreach ($contexts as $key => $ctx) {
|
|
if (!has_any_capability($hasanycapability, $ctx)) {
|
|
unset($contexts[$key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $contexts;
|
|
}
|
|
|
|
/**
|
|
* Count all the courses using a competency.
|
|
*
|
|
* @param int $competencyid The id of the competency to check.
|
|
* @return int
|
|
*/
|
|
public static function count_courses_using_competency($competencyid) {
|
|
|
|
// OK - all set.
|
|
$courses = course_competency::list_courses_min($competencyid);
|
|
$count = 0;
|
|
|
|
// Now check permissions on each course.
|
|
foreach ($courses as $course) {
|
|
$context = context_course::instance($course->id);
|
|
$capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
continue;
|
|
}
|
|
|
|
if (!$course->visible && !has_capability('course:viewhidden', $context)) {
|
|
continue;
|
|
}
|
|
|
|
$count++;
|
|
}
|
|
|
|
return $count;
|
|
}
|
|
|
|
/**
|
|
* List all the courses using a competency.
|
|
*
|
|
* @param int $competencyid The id of the competency to check.
|
|
* @return array[stdClass] Array of stdClass containing id and shortname.
|
|
*/
|
|
public static function list_courses_using_competency($competencyid) {
|
|
|
|
// OK - all set.
|
|
$courses = course_competency::list_courses($competencyid);
|
|
$result = array();
|
|
|
|
// Now check permissions on each course.
|
|
foreach ($courses as $id => $course) {
|
|
$context = context_course::instance($course->id);
|
|
$capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
unset($courses[$id]);
|
|
continue;
|
|
}
|
|
if (!$course->visible && !has_capability('course:viewhidden', $context)) {
|
|
unset($courses[$id]);
|
|
continue;
|
|
}
|
|
$course->fullnameformatted = format_text($course->fullname, array('context' => $context));
|
|
$course->shortnameformatted = format_text($course->shortname, array('context' => $context));
|
|
array_push($result, $course);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Count all the competencies in a course.
|
|
*
|
|
* @param int $courseid The id of the course to check.
|
|
* @return int
|
|
*/
|
|
public static function count_competencies_in_course($courseid) {
|
|
// First we do a permissions check.
|
|
$context = context_course::instance($courseid);
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:coursecompetencyread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:coursecompetencymanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return course_competency::count_competencies($courseid, $onlyvisible);
|
|
}
|
|
|
|
/**
|
|
* List all the competencies in a course.
|
|
*
|
|
* @param int $courseid The id of the course to check.
|
|
* @return array of competencies
|
|
*/
|
|
public static function list_competencies_in_course($courseid) {
|
|
// First we do a permissions check.
|
|
$context = context_course::instance($courseid);
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:coursecompetencyread', 'tool/lp:coursecompetencymanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:coursecompetencyread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:coursecompetencymanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return course_competency::list_competencies($courseid, $onlyvisible);
|
|
}
|
|
|
|
/**
|
|
* Add a competency to this course.
|
|
*
|
|
* @param int $courseid The id of the course
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function add_competency_to_course($courseid, $competencyid) {
|
|
// First we do a permissions check.
|
|
$context = context_course::instance($courseid);
|
|
|
|
require_capability('tool/lp:coursecompetencymanage', $context);
|
|
|
|
$record = new stdClass();
|
|
$record->courseid = $courseid;
|
|
$record->competencyid = $competencyid;
|
|
|
|
$competency = new competency();
|
|
$competency->set_id($competencyid);
|
|
if (!$competency->read()) {
|
|
throw new coding_exception('The competency does not exist');
|
|
}
|
|
|
|
$coursecompetency = new course_competency();
|
|
$exists = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyid));
|
|
if (!$exists) {
|
|
$coursecompetency->from_record($record);
|
|
if ($coursecompetency->create()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Remove a competency from this course.
|
|
*
|
|
* @param int $courseid The id of the course
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function remove_competency_from_course($courseid, $competencyid) {
|
|
// First we do a permissions check.
|
|
$context = context_course::instance($courseid);
|
|
|
|
require_capability('tool/lp:coursecompetencymanage', $context);
|
|
|
|
$record = new stdClass();
|
|
$record->courseid = $courseid;
|
|
$record->competencyid = $competencyid;
|
|
|
|
$competency = new competency();
|
|
$competency->set_id($competencyid);
|
|
if (!$competency->read()) {
|
|
throw new coding_exception('The competency does not exist');
|
|
}
|
|
|
|
$coursecompetency = new course_competency();
|
|
$exists = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyid));
|
|
if ($exists) {
|
|
$competency = array_pop($exists);
|
|
return $competency->delete();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Move the course competency up or down in the display list.
|
|
*
|
|
* Requires tool/lp:coursecompetencymanage capability at the course context.
|
|
*
|
|
* @param int $courseid The course
|
|
* @param int $competencyidfrom The id of the competency we are moving.
|
|
* @param int $competencyidto The id of the competency we are moving to.
|
|
* @return boolean
|
|
*/
|
|
public static function reorder_course_competency($courseid, $competencyidfrom, $competencyidto) {
|
|
// First we do a permissions check.
|
|
$context = context_course::instance($courseid);
|
|
|
|
require_capability('tool/lp:coursecompetencymanage', $context);
|
|
|
|
$down = true;
|
|
$coursecompetency = new course_competency();
|
|
$matches = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyidfrom));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyfrom = array_pop($matches);
|
|
$matches = $coursecompetency->get_records(array('courseid' => $courseid, 'competencyid' => $competencyidto));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyto = array_pop($matches);
|
|
|
|
$all = $coursecompetency->get_records(array('courseid' => $courseid), 'sortorder', 'ASC', 0, 0);
|
|
|
|
if ($competencyfrom->get_sortorder() > $competencyto->get_sortorder()) {
|
|
// We are moving up, so put it before the "to" item.
|
|
$down = false;
|
|
}
|
|
|
|
foreach ($all as $id => $coursecompetency) {
|
|
$sort = $coursecompetency->get_sortorder();
|
|
if ($down && $sort > $competencyfrom->get_sortorder() && $sort <= $competencyto->get_sortorder()) {
|
|
$coursecompetency->set_sortorder($coursecompetency->get_sortorder() - 1);
|
|
$coursecompetency->update();
|
|
} else if (!$down && $sort >= $competencyto->get_sortorder() && $sort < $competencyfrom->get_sortorder()) {
|
|
$coursecompetency->set_sortorder($coursecompetency->get_sortorder() + 1);
|
|
$coursecompetency->update();
|
|
}
|
|
}
|
|
$competencyfrom->set_sortorder($competencyto->get_sortorder());
|
|
return $competencyfrom->update();
|
|
}
|
|
|
|
/**
|
|
* Create a learning plan template from a record containing all the data for the class.
|
|
*
|
|
* Requires tool/lp:templatemanage capability.
|
|
*
|
|
* @param stdClass $record Record containing all the data for an instance of the class.
|
|
* @return template
|
|
*/
|
|
public static function create_template(stdClass $record) {
|
|
$template = new template(0, $record);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
|
|
// OK - all set.
|
|
$id = $template->create();
|
|
return $template;
|
|
}
|
|
|
|
/**
|
|
* Duplicate a learning plan template.
|
|
*
|
|
* Requires tool/lp:templatemanage capability at the template context.
|
|
*
|
|
* @param int $id the template id.
|
|
* @return template
|
|
*/
|
|
public static function duplicate_template($id) {
|
|
$template = new template($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
|
|
// OK - all set.
|
|
$competencies = template_competency::list_competencies($id, false);
|
|
|
|
// Adding the suffix copy.
|
|
$template->set_shortname(get_string('duplicateditemname', 'tool_lp', $template->get_shortname()));
|
|
$template->set_id(0);
|
|
|
|
$duplicatedtemplate = $template->create();
|
|
|
|
// Associate each competency for the duplicated template.
|
|
foreach ($competencies as $competency) {
|
|
self::add_competency_to_template($duplicatedtemplate->get_id(), $competency->get_id());
|
|
}
|
|
return $duplicatedtemplate;
|
|
}
|
|
|
|
/**
|
|
* Delete a learning plan template by id.
|
|
*
|
|
* Requires tool/lp:templatemanage capability.
|
|
*
|
|
* @param int $id The record to delete.
|
|
* @return boolean
|
|
*/
|
|
public static function delete_template($id) {
|
|
$template = new template($id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
|
|
// OK - all set.
|
|
return $template->delete();
|
|
}
|
|
|
|
/**
|
|
* Update the details for a learning plan template.
|
|
*
|
|
* Requires tool/lp:templatemanage capability.
|
|
*
|
|
* @param stdClass $record The new details for the template. Note - must contain an id that points to the template to update.
|
|
* @return boolean
|
|
*/
|
|
public static function update_template($record) {
|
|
$template = new template($record->id);
|
|
|
|
// First we do a permissions check.
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
if (isset($record->contextid) && $record->contextid != $template->get_contextid()) {
|
|
throw new coding_exception('Changing the context of an existing tempalte is forbidden.');
|
|
}
|
|
|
|
$template->from_record($record);
|
|
return $template->update();
|
|
}
|
|
|
|
/**
|
|
* Read a the details for a single learning plan template and return a record.
|
|
*
|
|
* Requires tool/lp:templateread capability at the system context.
|
|
*
|
|
* @param int $id The id of the template to read.
|
|
* @return template
|
|
*/
|
|
public static function read_template($id) {
|
|
$template = new template($id);
|
|
$context = $template->get_context();
|
|
|
|
// First we do a permissions check.
|
|
$caps = array('tool/lp:templateread', 'tool/lp:templatemanage');
|
|
if (!has_any_capability($caps, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
return $template;
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return a paginated list of records.
|
|
*
|
|
* Requires tool/lp:templateread capability at the system context.
|
|
*
|
|
* @param string $sort The column to sort on
|
|
* @param string $order ('ASC' or 'DESC')
|
|
* @param int $skip Number of records to skip (pagination)
|
|
* @param int $limit Max of records to return (pagination)
|
|
* @param context $context The parent context of the frameworks.
|
|
* @param string $includes Defines what other contexts to fetch frameworks from.
|
|
* Accepted values are:
|
|
* - children: All descendants
|
|
* - parents: All parents, grand parents, etc...
|
|
* - self: Context passed only.
|
|
* @return array of competency_framework
|
|
*/
|
|
public static function list_templates($sort, $order, $skip, $limit, $context, $includes = 'children') {
|
|
global $DB;
|
|
|
|
// Get all the relevant contexts.
|
|
$contexts = self::get_related_contexts($context, $includes,
|
|
array('tool/lp:templateread', 'tool/lp:templatemanage'));
|
|
|
|
// First we do a permissions check.
|
|
if (empty($contexts)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
// Make the order by.
|
|
$orderby = '';
|
|
if (!empty($sort)) {
|
|
$orderby = $sort . ' ' . $order;
|
|
}
|
|
|
|
// OK - all set.
|
|
$template = new template();
|
|
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
|
|
return $template->get_records_select("contextid $insql", $inparams, $orderby, '*', $skip, $limit);
|
|
}
|
|
|
|
/**
|
|
* Perform a search based on the provided filters and return how many results there are.
|
|
*
|
|
* Requires tool/lp:templateread capability at the system context.
|
|
*
|
|
* @param context $context The parent context of the frameworks.
|
|
* @param string $includes Defines what other contexts to fetch frameworks from.
|
|
* Accepted values are:
|
|
* - children: All descendants
|
|
* - parents: All parents, grand parents, etc...
|
|
* - self: Context passed only.
|
|
* @return int
|
|
*/
|
|
public static function count_templates($context, $includes) {
|
|
global $DB;
|
|
|
|
// First we do a permissions check.
|
|
$contexts = self::get_related_contexts($context, $includes,
|
|
array('tool/lp:templateread', 'tool/lp:templatemanage'));
|
|
|
|
if (empty($contexts)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
// OK - all set.
|
|
$template = new template();
|
|
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contexts), SQL_PARAMS_NAMED);
|
|
return $template->count_records_select("contextid $insql", $inparams);
|
|
}
|
|
|
|
/**
|
|
* Count all the templates using a competency.
|
|
*
|
|
* @param int $competencyid The id of the competency to check.
|
|
* @return int
|
|
*/
|
|
public static function count_templates_using_competency($competencyid) {
|
|
// First we do a permissions check.
|
|
$context = context_system::instance();
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:templatemanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return template_competency::count_templates($competencyid, $onlyvisible);
|
|
}
|
|
|
|
/**
|
|
* List all the learning plan templatesd using a competency.
|
|
*
|
|
* @param int $competencyid The id of the competency to check.
|
|
* @return array[stdClass] Array of stdClass containing id and shortname.
|
|
*/
|
|
public static function list_templates_using_competency($competencyid) {
|
|
// First we do a permissions check.
|
|
$context = context_system::instance();
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:templatemanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return template_competency::list_templates($competencyid, $onlyvisible);
|
|
|
|
}
|
|
|
|
/**
|
|
* Count all the competencies in a learning plan template.
|
|
*
|
|
* @param int $templateid The id of the template to check.
|
|
* @return int
|
|
*/
|
|
public static function count_competencies_in_template($templateid) {
|
|
// First we do a permissions check.
|
|
$template = new template($templateid);
|
|
$context = $template->get_context();
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:templatemanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return template_competency::count_competencies($templateid, $onlyvisible);
|
|
}
|
|
|
|
/**
|
|
* List all the competencies in a template.
|
|
*
|
|
* @param int $templateid The id of the template to check.
|
|
* @return array of competencies
|
|
*/
|
|
public static function list_competencies_in_template($templateid) {
|
|
// First we do a permissions check.
|
|
$template = new template($templateid);
|
|
$context = $template->get_context();
|
|
$onlyvisible = 1;
|
|
|
|
$capabilities = array('tool/lp:templateread', 'tool/lp:templatemanage');
|
|
if (!has_any_capability($capabilities, $context)) {
|
|
throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermissions', '');
|
|
}
|
|
|
|
if (has_capability('tool/lp:templatemanage', $context)) {
|
|
$onlyvisible = 0;
|
|
}
|
|
|
|
// OK - all set.
|
|
return template_competency::list_competencies($templateid, $onlyvisible);
|
|
}
|
|
|
|
/**
|
|
* Add a competency to this template.
|
|
*
|
|
* @param int $templateid The id of the template
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function add_competency_to_template($templateid, $competencyid) {
|
|
// First we do a permissions check.
|
|
$template = new template($templateid);
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
|
|
$record = new stdClass();
|
|
$record->templateid = $templateid;
|
|
$record->competencyid = $competencyid;
|
|
|
|
$competency = new competency();
|
|
$competency->set_id($competencyid);
|
|
if (!$competency->read()) {
|
|
throw new coding_exception('The competency does not exist');
|
|
}
|
|
|
|
$exists = template_competency::get_records(array('templateid' => $templateid, 'competencyid' => $competencyid));
|
|
if (!$exists) {
|
|
$templatecompetency = new template_competency(0, $record);
|
|
$templatecompetency->create();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Remove a competency from this template.
|
|
*
|
|
* @param int $templateid The id of the template
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function remove_competency_from_template($templateid, $competencyid) {
|
|
// First we do a permissions check.
|
|
$template = new template($templateid);
|
|
require_capability('tool/lp:templatemanage', $template->get_context());
|
|
|
|
$record = new stdClass();
|
|
$record->templateid = $templateid;
|
|
$record->competencyid = $competencyid;
|
|
|
|
$competency = new competency($competencyid);
|
|
$competency->set_id($competencyid);
|
|
if (!$competency->read()) {
|
|
throw new coding_exception('The competency does not exist');
|
|
}
|
|
|
|
$exists = template_competency::get_records(array('templateid' => $templateid, 'competencyid' => $competencyid));
|
|
if ($exists) {
|
|
$link = array_pop($exists);
|
|
return $link->delete();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Move the template competency up or down in the display list.
|
|
*
|
|
* Requires tool/lp:templatemanage capability at the system context.
|
|
*
|
|
* @param int $templateid The template id
|
|
* @param int $competencyidfrom The id of the competency we are moving.
|
|
* @param int $competencyidto The id of the competency we are moving to.
|
|
* @return boolean
|
|
*/
|
|
public static function reorder_template_competency($templateid, $competencyidfrom, $competencyidto) {
|
|
// First we do a permissions check.
|
|
$context = context_system::instance();
|
|
|
|
require_capability('tool/lp:templatemanage', $context);
|
|
|
|
$down = true;
|
|
$matches = template_competency::get_records(array('templateid' => $templateid, 'competencyid' => $competencyidfrom));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyfrom = array_pop($matches);
|
|
$matches = template_competency::get_records(array('templateid' => $templateid, 'competencyid' => $competencyidto));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyto = array_pop($matches);
|
|
|
|
$all = template_competency::get_records(array('templateid' => $templateid), 'sortorder', 'ASC', 0, 0);
|
|
|
|
if ($competencyfrom->get_sortorder() > $competencyto->get_sortorder()) {
|
|
// We are moving up, so put it before the "to" item.
|
|
$down = false;
|
|
}
|
|
|
|
foreach ($all as $id => $templatecompetency) {
|
|
$sort = $templatecompetency->get_sortorder();
|
|
if ($down && $sort > $competencyfrom->get_sortorder() && $sort <= $competencyto->get_sortorder()) {
|
|
$templatecompetency->set_sortorder($templatecompetency->get_sortorder() - 1);
|
|
$templatecompetency->update();
|
|
} else if (!$down && $sort >= $competencyto->get_sortorder() && $sort < $competencyfrom->get_sortorder()) {
|
|
$templatecompetency->set_sortorder($templatecompetency->get_sortorder() + 1);
|
|
$templatecompetency->update();
|
|
}
|
|
}
|
|
$competencyfrom->set_sortorder($competencyto->get_sortorder());
|
|
return $competencyfrom->update();
|
|
}
|
|
|
|
/**
|
|
* Lists user plans.
|
|
*
|
|
* @param int $userid
|
|
* @return \tool_lp\plan[]
|
|
*/
|
|
public static function list_user_plans($userid) {
|
|
global $USER;
|
|
$select = 'userid = :userid';
|
|
$params = array('userid' => $userid);
|
|
$context = context_user::instance($userid);
|
|
|
|
// Check that we can read something here.
|
|
if (!plan::can_read_user($userid) && !plan::can_read_user_draft($userid)) {
|
|
throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', '');
|
|
}
|
|
|
|
// The user cannot view the drafts.
|
|
if (!plan::can_read_user_draft($userid)) {
|
|
$select .= ' AND status != :statusdraft';
|
|
$params['statusdraft'] = plan::STATUS_DRAFT;
|
|
}
|
|
// The user cannot view the non-drafts.
|
|
if (!plan::can_read_user($userid)) {
|
|
$select .= ' AND status = :statusdraft';
|
|
$params['statusdraft'] = plan::STATUS_DRAFT;
|
|
}
|
|
|
|
return plan::get_records_select($select, $params, 'timemodified DESC');
|
|
}
|
|
|
|
/**
|
|
* Creates a learning plan based on the provided data.
|
|
*
|
|
* @param stdClass $record
|
|
* @return \tool_lp\plan
|
|
*/
|
|
public static function create_plan(stdClass $record) {
|
|
global $USER;
|
|
$plan = new plan(0, $record);
|
|
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
}
|
|
|
|
$plan->create();
|
|
return $plan;
|
|
}
|
|
|
|
/**
|
|
* Updates a plan.
|
|
*
|
|
* @param stdClass $record
|
|
* @return \tool_lp\plan
|
|
*/
|
|
public static function update_plan(stdClass $record) {
|
|
global $DB;
|
|
|
|
$plan = new plan($record->id);
|
|
|
|
// Validate that the plan as it is can be managed.
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
}
|
|
|
|
// Prevent change of ownership as the capabilities are checked against that.
|
|
if (isset($record->userid) && $plan->get_userid() != $record->userid) {
|
|
throw new coding_exception('A plan cannot be transfered to another user');
|
|
}
|
|
|
|
$beforestatus = $plan->get_status();
|
|
$plan->from_record($record);
|
|
|
|
// Revalidate after the data has be injected. This handles status change, etc...
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
}
|
|
|
|
// Wrap the updates in a DB transaction.
|
|
$transaction = $DB->start_delegated_transaction();
|
|
|
|
// Archive user competencies if the status of the plan is changed to complete.
|
|
$mustarchivecompetencies = ($plan->get_status() == plan::STATUS_COMPLETE && $beforestatus != plan::STATUS_COMPLETE);
|
|
if ($mustarchivecompetencies) {
|
|
self::archive_user_competencies_in_plan($plan);
|
|
}
|
|
|
|
// Delete archived user competencies if the status of the plan is changed from complete to another status.
|
|
$mustremovearchivedcompetencies = ($beforestatus == plan::STATUS_COMPLETE && $plan->get_status() != plan::STATUS_COMPLETE);
|
|
if ($mustremovearchivedcompetencies) {
|
|
self::remove_archived_user_competencies_in_plan($plan);
|
|
}
|
|
|
|
$plan->update();
|
|
|
|
$transaction->allow_commit();
|
|
|
|
return $plan;
|
|
}
|
|
|
|
/**
|
|
* Returns a plan data.
|
|
*
|
|
* @param int $id
|
|
* @return \tool_lp\plan
|
|
*/
|
|
public static function read_plan($id) {
|
|
$plan = new plan($id);
|
|
|
|
if (!$plan->can_read()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', '');
|
|
}
|
|
|
|
return $plan;
|
|
}
|
|
|
|
/**
|
|
* Deletes a plan.
|
|
*
|
|
* @param int $id
|
|
* @return bool Success?
|
|
*/
|
|
public static function delete_plan($id) {
|
|
global $DB;
|
|
|
|
$plan = new plan($id);
|
|
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
}
|
|
|
|
// Wrap the suppression in a DB transaction.
|
|
$transaction = $DB->start_delegated_transaction();
|
|
|
|
// Delete archive user competencies if the status of the plan is complete.
|
|
if ($plan->get_status() == plan::STATUS_COMPLETE) {
|
|
self::remove_archived_user_competencies_in_plan($plan);
|
|
}
|
|
|
|
$success = $plan->delete();
|
|
|
|
$transaction->allow_commit();
|
|
|
|
return $success;
|
|
}
|
|
|
|
/**
|
|
* List the competencies in a user plan.
|
|
*
|
|
* @param int $planorid The plan, or its ID.
|
|
* @return array((object) array(
|
|
* 'competency' => \tool_lp\competency,
|
|
* 'usercompetency' => \tool_lp\user_competency
|
|
* 'usercompetencyplan' => \tool_lp\user_competency_plan
|
|
* ))
|
|
* The values of of keys usercompetency and usercompetencyplan cannot be defined at the same time.
|
|
*/
|
|
public static function list_plan_competencies($planorid) {
|
|
$plan = $planorid;
|
|
if (!is_object($planorid)) {
|
|
$plan = new plan($planorid);
|
|
}
|
|
|
|
if (!$plan->can_read()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', '');
|
|
}
|
|
|
|
$result = array();
|
|
$competencies = $plan->get_competencies();
|
|
|
|
// Get user competencies from user_competency_plan if the plan status is set to complete.
|
|
$iscompletedplan = $plan->get_status() == plan::STATUS_COMPLETE;
|
|
if ($iscompletedplan) {
|
|
$usercompetencies = user_competency_plan::get_multiple($plan->get_userid(), $plan->get_id(), $competencies);
|
|
$ucresultkey = 'usercompetencyplan';
|
|
} else {
|
|
$usercompetencies = user_competency::get_multiple($plan->get_userid(), $competencies);
|
|
$ucresultkey = 'usercompetency';
|
|
}
|
|
|
|
// Build the return values.
|
|
foreach ($competencies as $key => $competency) {
|
|
$found = false;
|
|
|
|
foreach ($usercompetencies as $uckey => $uc) {
|
|
if ($uc->get_competencyid() == $competency->get_id()) {
|
|
$found = true;
|
|
unset($usercompetencies[$uckey]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$found) {
|
|
if ($iscompletedplan) {
|
|
throw new coding_exception('A user competency plan is missing');
|
|
} else {
|
|
$uc = user_competency::create_relation($plan->get_userid(), $competency->get_id());
|
|
}
|
|
}
|
|
|
|
$plancompetency = (object) array(
|
|
'competency' => $competency,
|
|
'usercompetency' => null,
|
|
'usercompetencyplan' => null
|
|
);
|
|
$plancompetency->$ucresultkey = $uc;
|
|
$result[] = $plancompetency;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Add a competency to a plan.
|
|
*
|
|
* @param int $planid The id of the plan
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function add_competency_to_plan($planid, $competencyid) {
|
|
$plan = new plan($planid);
|
|
|
|
// First we do a permissions check.
|
|
if (!$plan->can_manage()) {
|
|
throw new required_capability_exception($plan->get_context(), 'tool/lp:planmanage', 'nopermissions', '');
|
|
|
|
} else if ($plan->is_based_on_template()) {
|
|
throw new coding_exception('A competency can not be added to a learning plan based on a template');
|
|
}
|
|
|
|
$exists = plan_competency::get_record(array('planid' => $planid, 'competencyid' => $competencyid));
|
|
if (!$exists) {
|
|
$record = new stdClass();
|
|
$record->planid = $planid;
|
|
$record->competencyid = $competencyid;
|
|
$plancompetency = new plan_competency(0, $record);
|
|
$plancompetency->create();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove a competency from a plan.
|
|
*
|
|
* @param int $planid The plan id
|
|
* @param int $competencyid The id of the competency
|
|
* @return bool
|
|
*/
|
|
public static function remove_competency_from_plan($planid, $competencyid) {
|
|
$plan = new plan($planid);
|
|
|
|
// First we do a permissions check.
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
|
|
} else if ($plan->is_based_on_template()) {
|
|
throw new coding_exception('A competency can not be removed from a learning plan based on a template');
|
|
}
|
|
|
|
$link = plan_competency::get_record(array('planid' => $planid, 'competencyid' => $competencyid));
|
|
if ($link) {
|
|
return $link->delete();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Move the plan competency up or down in the display list.
|
|
*
|
|
* Requires tool/lp:planmanage capability at the system context.
|
|
*
|
|
* @param int $planid The plan id
|
|
* @param int $competencyidfrom The id of the competency we are moving.
|
|
* @param int $competencyidto The id of the competency we are moving to.
|
|
* @return boolean
|
|
*/
|
|
public static function reorder_plan_competency($planid, $competencyidfrom, $competencyidto) {
|
|
$plan = new plan($planid);
|
|
|
|
// First we do a permissions check.
|
|
if (!$plan->can_manage()) {
|
|
$context = context_user::instance($plan->get_userid());
|
|
throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', '');
|
|
|
|
} else if ($plan->is_based_on_template()) {
|
|
throw new coding_exception('A competency can not be reordered in a learning plan based on a template');
|
|
}
|
|
|
|
$down = true;
|
|
$matches = plan_competency::get_records(array('planid' => $planid, 'competencyid' => $competencyidfrom));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyfrom = array_pop($matches);
|
|
$matches = plan_competency::get_records(array('planid' => $planid, 'competencyid' => $competencyidto));
|
|
if (count($matches) == 0) {
|
|
throw new coding_exception('The link does not exist');
|
|
}
|
|
|
|
$competencyto = array_pop($matches);
|
|
|
|
$all = plan_competency::get_records(array('planid' => $planid), 'sortorder', 'ASC', 0, 0);
|
|
|
|
if ($competencyfrom->get_sortorder() > $competencyto->get_sortorder()) {
|
|
// We are moving up, so put it before the "to" item.
|
|
$down = false;
|
|
}
|
|
|
|
foreach ($all as $id => $plancompetency) {
|
|
$sort = $plancompetency->get_sortorder();
|
|
if ($down && $sort > $competencyfrom->get_sortorder() && $sort <= $competencyto->get_sortorder()) {
|
|
$plancompetency->set_sortorder($plancompetency->get_sortorder() - 1);
|
|
$plancompetency->update();
|
|
} else if (!$down && $sort >= $competencyto->get_sortorder() && $sort < $competencyfrom->get_sortorder()) {
|
|
$plancompetency->set_sortorder($plancompetency->get_sortorder() + 1);
|
|
$plancompetency->update();
|
|
}
|
|
}
|
|
$competencyfrom->set_sortorder($competencyto->get_sortorder());
|
|
return $competencyfrom->update();
|
|
}
|
|
|
|
/**
|
|
* List all the related competencies.
|
|
*
|
|
* @param int $competencyid The id of the competency to check.
|
|
* @return competency[]
|
|
*/
|
|
public static function list_related_competencies($competencyid) {
|
|
$competency = new competency($competencyid);
|
|
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
return $competency->get_related_competencies();
|
|
}
|
|
|
|
/**
|
|
* Add a related competency.
|
|
*
|
|
* @param int $competencyid The id of the competency
|
|
* @param int $relatedcompetencyid The id of the related competency.
|
|
* @return bool False when create failed, true on success, or if the relation already existed.
|
|
*/
|
|
public static function add_related_competency($competencyid, $relatedcompetencyid) {
|
|
$competency1 = new competency($competencyid);
|
|
$competency2 = new competency($relatedcompetencyid);
|
|
|
|
require_capability('tool/lp:competencymanage', $competency1->get_context());
|
|
|
|
$relatedcompetency = related_competency::get_relation($competency1->get_id(), $competency2->get_id());
|
|
if (!$relatedcompetency->get_id()) {
|
|
$relatedcompetency->create();
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Remove a related competency.
|
|
*
|
|
* @param int $competencyid The id of the competency.
|
|
* @param int $relatedcompetencyid The id of the related competency.
|
|
* @return bool True when it was deleted, false when it wasn't or the relation doesn't exist.
|
|
*/
|
|
public static function remove_related_competency($competencyid, $relatedcompetencyid) {
|
|
$competency = new competency($competencyid);
|
|
|
|
// This only check if we have the permission in either competency because both competencies
|
|
// should belong to the same framework.
|
|
require_capability('tool/lp:competencymanage', $competency->get_context());
|
|
|
|
$relatedcompetency = related_competency::get_relation($competencyid, $relatedcompetencyid);
|
|
if ($relatedcompetency->get_id()) {
|
|
return $relatedcompetency->delete();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Recursively duplicate competencies from a tree, we start duplicating from parents to children to have a correct path.
|
|
* This method does not copy the related competencies.
|
|
*
|
|
* @param int $frameworkid - framework id
|
|
* @param competency[] $tree - array of competencies object
|
|
* @param int $oldparent - old parent id
|
|
* @param int $newparent - new parent id
|
|
* @return array $matchids - List of old competencies ids matched with new ids.
|
|
*/
|
|
protected static function duplicate_competency_tree($frameworkid, $tree, $oldparent = 0, $newparent = 0) {
|
|
$matchids = array();
|
|
foreach ($tree as $node) {
|
|
if ($node->competency->get_parentid() == $oldparent) {
|
|
$parentid = $node->competency->get_id();
|
|
|
|
// Create the competency.
|
|
$competency = $node->competency;
|
|
$competency->set_competencyframeworkid($frameworkid);
|
|
$competency->set_parentid($newparent);
|
|
$competency->set_path('');
|
|
$competency->set_id(0);
|
|
$competency->create();
|
|
|
|
// Match the old id with the new one.
|
|
$matchids[$parentid] = $competency->get_id();
|
|
|
|
if (!empty($node->children)) {
|
|
// Duplicate children competency.
|
|
$childrenids = self::duplicate_competency_tree($frameworkid, $node->children, $parentid, $competency->get_id());
|
|
// Array_merge does not keep keys when merging so we use the + operator.
|
|
$matchids = $matchids + $childrenids;
|
|
}
|
|
}
|
|
}
|
|
return $matchids;
|
|
}
|
|
|
|
/**
|
|
* Archive user competencies in a plan.
|
|
*
|
|
* @param int $plan The plan object.
|
|
* @return void
|
|
*/
|
|
protected static function archive_user_competencies_in_plan($plan) {
|
|
$competencies = $plan->get_competencies();
|
|
$usercompetencies = user_competency::get_multiple($plan->get_userid(), $competencies);
|
|
|
|
foreach ($competencies as $competency) {
|
|
$found = false;
|
|
|
|
foreach ($usercompetencies as $uckey => $uc) {
|
|
if ($uc->get_competencyid() == $competency->get_id()) {
|
|
$found = true;
|
|
|
|
$ucprecord = $uc->to_record();
|
|
$ucprecord->planid = $plan->get_id();
|
|
unset($ucprecord->id);
|
|
unset($ucprecord->status);
|
|
unset($ucprecord->reviewerid);
|
|
|
|
$usercompetencyplan = new user_competency_plan(0, $ucprecord);
|
|
$usercompetencyplan->create();
|
|
|
|
unset($usercompetencies[$uckey]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If the user competency doesn't exist, we create a new relation in user_competency_plan.
|
|
if (!$found) {
|
|
$usercompetencyplan = user_competency_plan::create_relation($plan->get_userid(), $competency->get_id(),
|
|
$plan->get_id());
|
|
$usercompetencyplan->create();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete archived user competencies in a plan.
|
|
*
|
|
* @param int $plan The plan object.
|
|
* @return void
|
|
*/
|
|
protected static function remove_archived_user_competencies_in_plan($plan) {
|
|
$competencies = $plan->get_competencies();
|
|
$usercompetenciesplan = user_competency_plan::get_multiple($plan->get_userid(), $plan->get_id(), $competencies);
|
|
|
|
foreach ($usercompetenciesplan as $ucpkey => $ucp) {
|
|
$ucp->delete();
|
|
}
|
|
}
|
|
}
|