diff --git a/admin/tool/lp/amd/build/frameworkdelete.min.js b/admin/tool/lp/amd/build/frameworkdelete.min.js new file mode 100644 index 00000000000..00fc1559d64 --- /dev/null +++ b/admin/tool/lp/amd/build/frameworkdelete.min.js @@ -0,0 +1 @@ +define(["jquery","core/templates","core/ajax","core/notification"],function(a,b,c,d){var e=0,f=function(c,d){a('[data-region="managecompetencies"]').replaceWith(c),b.runTemplateJS(d)},g=function(a){b.render("tool_lp/manage_competency_frameworks_page",a).done(f).fail(d.exception)},h=function(){var a=c.call([{methodname:"tool_lp_delete_competency_framework",args:{id:e}},{methodname:"tool_lp_data_for_competency_frameworks_manage_page",args:[]}]);a[1].done(g).fail(d.exception)},i=function(b){b.preventDefault();var c=a(this).attr("data-frameworkid");e=c,d.confirm("Confirm",'Delete competency framework "blah"?',"Delete","Cancel",h)};return{init:function(){a('[data-region="managecompetencies"]').on("click",'[data-action="deletecompetencyframework"]',i)}}}); diff --git a/admin/tool/lp/amd/build/frameworkmove.min.js b/admin/tool/lp/amd/build/frameworkmove.min.js new file mode 100644 index 00000000000..9a2a7dbd1e6 --- /dev/null +++ b/admin/tool/lp/amd/build/frameworkmove.min.js @@ -0,0 +1 @@ +define(["core/dragdrop-reorder","core/str","core/notification","jquery","core/ajax"],function(a,b,c,d,e){var f=function(a,b){var f=d(a).data("frameworkid"),g=d(b).data("frameworkid"),h=e.call([{methodname:"tool_lp_reorder_competency_framework",args:{from:f,to:g}}]);h[0].fail(c.exception)};return{init:function(){b.get_string("movecompetencyframework","tool_lp").done(function(b){a.dragdrop("movecompetencyframework",b,{identifier:"movecompetencyframework",component:"tool_lp"},{identifier:"movecompetencyframeworkafter",component:"tool_lp"},"drag-samenode","drag-parentnode","drag-handlecontainer",f)}).fail(c.exception)}}}); diff --git a/admin/tool/lp/amd/src/competencyactions.js b/admin/tool/lp/amd/src/competencyactions.js new file mode 100644 index 00000000000..71f6ad7f591 --- /dev/null +++ b/admin/tool/lp/amd/src/competencyactions.js @@ -0,0 +1,370 @@ +// 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 . + +/** + * Handle selection changes and actions on the competency tree. + * + * @module tool_lp/competencyselect + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery', 'core/url', 'core/templates', 'core/notification', 'core/str', 'core/ajax', 'core/dragdrop-reorder', 'core/tree', 'core/dialogue', 'core/menu'], + function($, url, templates, notification, str, ajax, dragdrop, ariatree, dialogue, menu) { + + // Private variables and functions. + var treeModel = null; + + var moveSource = null; + var moveTarget = null; + + var addHandler = function(e) { + e.preventDefault(); + var parent = $('[data-region="competencyactions"]').data('competency'); + + var params = { + competencyframeworkid : treeModel.getCompetencyFrameworkId() + }; + + if (parent == null) { + // We are adding at the root node. + } else { + // We are adding at a sub node. + params['parentid'] = parent.id; + } + var queryparams = $.param(params); + var actionurl = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams); + window.location = actionurl; + }; + + var doMove = function() { + if (typeof (moveTarget) === "undefined") { + // This is a top level node. + moveTarget = 0; + } + + if (moveTarget == moveSource) { + return; + } + var frameworkid = $('[data-region="filtercompetencies"]').data('frameworkid'); + var requests = ajax.call([{ + methodname: 'tool_lp_set_parent_competency', + args: { competencyid: moveSource, parentid: moveTarget } + }, { + methodname: 'tool_lp_data_for_competencies_manage_page', + args: { competencyframeworkid: frameworkid, + search: $('[data-region="filtercompetencies"] input').val() } + }]); + requests[1].done(reloadPage).fail(notification.exception); + }; + + var initMovePopup = function(popup) { + var movetree = new ariatree('[data-enhance=movetree]', function(target) { + moveTarget = $(target).data('id'); + }); + + var body = $(popup.getContent()); + body.on('click', '[data-action="move"]', function(e) { popup.close(); doMove() }); + body.on('click', '[data-action="cancel"]', function(e) { popup.close(); }); + }; + + var addCompetencyChildren = function(parent, competencies) { + var i; + + for (i = 0; i < competencies.length; i++) { + if (competencies[i].parentid == parent.id) { + parent.haschildren = true; + competencies[i].children = []; + competencies[i].haschildren = false; + parent.children[parent.children.length] = competencies[i]; + addCompetencyChildren(competencies[i], competencies); + } + } + }; + + var moveHandler = function(e) { + e.preventDefault(); + var competency = $('[data-region="competencyactions"]').data('competency'); + + // Remember what we are moving. + moveSource = competency.id; + + // Load data for the template. + var requests = ajax.call([ + { + methodname: 'tool_lp_search_competencies', + args: { + competencyframeworkid: competency.competencyframeworkid, + searchtext: '' + } + },{ + methodname: 'tool_lp_read_competency_framework', + args: { + id: competency.competencyframeworkid + } + } + ]); + + // When all data has arrived, continue. + $.when.apply(null, requests).done(function(competencies, framework) { + + // Expand the list of competencies into a tree. + var i, competenciestree = []; + for (i = 0; i < competencies.length; i++) { + var onecompetency = competencies[i]; + if (onecompetency.parentid == 0) { + onecompetency.children = []; + onecompetency.haschildren = 0; + competenciestree[competenciestree.length] = onecompetency; + addCompetencyChildren(onecompetency, competencies); + } + } + + var strings = str.get_strings([ + { key: 'movecompetency', component: 'tool_lp', param: competency.shortname }, + { key: 'move', component: 'tool_lp' }, + { key: 'cancel', component: 'tool_lp' } + ]).done(function (strings) { + + var context = { + framework: framework, + competencies: competenciestree + }; + + templates.render('tool_lp/competencies_move_tree', context) + .done(function(tree) { + var popup = new dialogue( + strings[0], // Move competency x. + tree, // The move tree. + initMovePopup + ); + + }).fail(notification.exception); + + }).fail(notification.exception); + + }).fail(notification.exception); + + }; + + var editHandler = function(e) { + e.preventDefault(); + var competency = $('[data-region="competencyactions"]').data('competency'); + + var params = { + competencyframeworkid : treeModel.getCompetencyFrameworkId(), + id : competency.id, + parentid: competency.parentid + }; + + var queryparams = $.param(params); + var actionurl = url.relativeUrl('/admin/tool/lp/editcompetency.php?' + queryparams); + window.location = actionurl; + }; + + var reloadPage = function(context) { + templates.render('tool_lp/manage_competencies_page', context) + .done(function(newhtml, newjs) { + $('[data-region="managecompetencies"]').replaceWith(newhtml); + templates.runTemplateJS(newjs); + }) + .fail(notification.exception); + }; + + var updateSearchHandler = function(e) { + e.preventDefault(); + + var frameworkid = $('[data-region="filtercompetencies"]').data('frameworkid'); + + var requests = ajax.call([{ + methodname: 'tool_lp_data_for_competencies_manage_page', + args: { competencyframeworkid: frameworkid, + search: $('[data-region="filtercompetencies"] input').val() } + }]); + requests[0].done(reloadPage).fail(notification.exception); + }; + + var moveUpHandler = function() { + // We are chaining ajax requests here. + var competency = $('[data-region="competencyactions"]').data('competency'); + var requests = ajax.call([{ + methodname: 'tool_lp_move_up_competency', + args: { id: competency.id } + }, { + methodname: 'tool_lp_data_for_competencies_manage_page', + args: { competencyframeworkid: competency.competencyframeworkid, + search: $('[data-region="filtercompetencies"] input').val() } + }]); + requests[1].done(reloadPage).fail(notification.exception); + }; + + var moveDownHandler = function() { + // We are chaining ajax requests here. + var competency = $('[data-region="competencyactions"]').data('competency'); + var requests = ajax.call([{ + methodname: 'tool_lp_move_down_competency', + args: { id: competency.id } + }, { + methodname: 'tool_lp_data_for_competencies_manage_page', + args: { competencyframeworkid: competency.competencyframeworkid, + search: $('[data-region="filtercompetencies"] input').val() } + }]); + requests[1].done(reloadPage).fail(notification.exception); + }; + + var seeCoursesHandler = function(e) { + e.preventDefault(); + var competency = $('[data-region="competencyactions"]').data('competency'); + var localthis = this; + + var requests = ajax.call([{ + methodname: 'tool_lp_list_courses_using_competency', + args: { id: competency.id } + }]); + + requests[0].done(function(courses) { + var context = { + courseviewurl: url.relativeUrl('/course/view.php'), + courses: courses + }; + templates.render('tool_lp/linked_courses_summary', context).done(function(html) { + str.get_string('linkedcourses', 'tool_lp').done(function (linkedcourses) { + var popup = new dialogue( + linkedcourses, // Title. + html, // The linked courses. + initMovePopup + ); + }).fail(notification.exception); + }).fail(notification.exception); + }).fail(notification.exception); + } + + var doDelete = function() { + // We are chaining ajax requests here. + var competency = $('[data-region="competencyactions"]').data('competency'); + var requests = ajax.call([{ + methodname: 'tool_lp_delete_competency', + args: { id: competency.id } + }, { + methodname: 'tool_lp_data_for_competencies_manage_page', + args: { competencyframeworkid: competency.competencyframeworkid, + search: $('[data-region="filtercompetencies"] input').val() } + }]); + requests[1].done(reloadPage).fail(notification.exception); + }; + + var deleteHandler = function(e) { + e.preventDefault(); + var competency = $('[data-region="competencyactions"]').data('competency'); + + templates.render('tool_lp/competency_summary', competency) + .done(function(html) { + + var strings = str.get_strings([ + { key: 'confirm', component: 'tool_lp' }, + { key: 'deletecompetency', component: 'tool_lp', param: html }, + { key: 'delete', component: 'tool_lp' }, + { key: 'cancel', component: 'tool_lp' } + ]).done(function (strings) { + notification.confirm( + strings[0], // Confirm. + strings[1], // Delete competency X? + strings[2], // Delete. + strings[3], // Cancel. + doDelete + ); + }).fail(notification.exception); + }).fail(notification.exception); + + }; + + var dragStart = function(e) { + e.originalEvent.dataTransfer.setData('text', $(e.target).data('id')); + }; + + var allowDrop = function(e) { + e.originalEvent.dataTransfer.dropEffect = 'move'; + e.preventDefault(); + }; + + var dragEnter = function(e) { + e.preventDefault(); + $(this).addClass('currentdragtarget'); + } + + var dragLeave = function(e) { + e.preventDefault(); + $(this).removeClass('currentdragtarget'); + } + + var dropOver = function(e) { + e.preventDefault(); + moveSource = e.originalEvent.dataTransfer.getData('text'); + moveTarget = $(e.target).data('id'); + $(this).removeClass('currentdragtarget'); + + doMove(); + }; + + return { + init: function(model) { + treeModel = model; + str.get_string('edit', 'core').done(function (edit) { + menu.menu(edit, '.competencyactionsmenu'); + + $('[data-region="competencyactions"]').on('click', '[data-action="add"]', addHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="edit"]', editHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="delete"]', deleteHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="move"]', moveHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="moveup"]', moveUpHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="movedown"]', moveDownHandler); + $('[data-region="competencyactions"]').on('click', '[data-action="linkedcourses"]', seeCoursesHandler); + + }).fail(notification.exception); + $('[data-region="filtercompetencies"]').on('submit', updateSearchHandler); + // Simple html5 drag drop because we already added an accessible alternative. + $('[data-region="managecompetencies"] li').on('dragstart', dragStart); + $('[data-region="managecompetencies"] li').on('dragover', allowDrop); + $('[data-region="managecompetencies"] li').on('dragenter', dragEnter); + $('[data-region="managecompetencies"] li').on('dragleave', dragLeave); + $('[data-region="managecompetencies"] li').on('drop', dropOver); + }, + // Public variables and functions. + selectionChanged: function(node) { + var id = $(node).data('id'); + if (typeof id === "undefined") { + // Assume this is the root of the tree. + // Here we are only getting the text from the top of the tree, to do it we clone the tree, + // remove all children and then call text on the result. + $('[data-region="competencyinfo"]').html(node.clone().children().remove().end().text()); + $('[data-region="competencyactions"]').data('competency', null); + $('[data-region="competencyactionsmenu"]').hide(); + $('[data-region="competencyactions"] [data-action="add"]').removeAttr("disabled"); + } else { + var competency = treeModel.getCompetency(id); + + templates.render('tool_lp/competency_summary', competency) + .done(function(html) { + $('[data-region="competencyinfo"]').html(html); + }).fail(notification.exception); + + $('[data-region="competencyactions"]').data('competency', competency); + $('[data-region="competencyactions"] [data-action="add"]').removeAttr("disabled"); + $('[data-region="competencyactionsmenu"]').css('display', 'inline-block'); + + } + } + }; +}); diff --git a/admin/tool/lp/amd/src/competencytree.js b/admin/tool/lp/amd/src/competencytree.js new file mode 100644 index 00000000000..7118c40f600 --- /dev/null +++ b/admin/tool/lp/amd/src/competencytree.js @@ -0,0 +1,78 @@ +// 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 . + +/** + * Handle selection changes on the competency tree. + * + * @module tool_lp/competencyselect + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + define(['core/ajax', 'core/notification', 'jquery'], function(ajax, notification, $) { + // Private variables and functions. + var competencies = []; + + var competencyFrameworkId = 0; + + var loadCompetencies = function(searchtext) { + var deferred = $.Deferred(); + searchtext = ''; + var promises = ajax.call([{ + methodname: 'tool_lp_search_competencies', + args: { + searchtext: searchtext, + competencyframeworkid: competencyFrameworkId + } + }]); + promises[0].done(function(result) { + competencies = []; + var i = 0; + for (i = 0; i < result.length; i++) { + competencies[result[i].id] = result[i]; + } + deferred.resolve(competencies); + }).fail(function(exception) { + deferred.reject(exception); + }); + + return deferred.promise(); + }; + + + return { + // Public variables and functions. + init: function(id) { + competencyFrameworkId = id; + loadCompetencies('').fail(notification.exception); + }, + + getCompetencyFrameworkId: function() { + return competencyFrameworkId; + }, + // Public variables and functions. + getCompetency: function(id) { + return competencies[id]; + }, + + listCompetencies: function() { + return competencies; + }, + + applySearch: function(searchtext) { + return loadCompetencies(searchtext); + } + }; + }); diff --git a/admin/tool/lp/amd/src/coursecompetencies.js b/admin/tool/lp/amd/src/coursecompetencies.js new file mode 100644 index 00000000000..8f6b153096d --- /dev/null +++ b/admin/tool/lp/amd/src/coursecompetencies.js @@ -0,0 +1,262 @@ +// 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 . + +/** + * Handle add/remove course competency links. + * + * @module tool_lp/coursecompetencies + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery', 'core/notification', 'core/ajax', 'core/templates', 'core/dialogue', 'core/str', 'core/tree', 'core/dragdrop-reorder'], + function($, notification, ajax, templates, dialogue, str, ariatree, dragdrop) { + + /** + * Constructor + * + * @param {int} courseid + */ + var coursecompetencies = function(courseid) { + this.courseid = courseid; + this.selectedCompetency = 0; + var localthis = this; + var loadframeworks = ajax.call([ + { methodname: 'tool_lp_list_competency_frameworks', args: { filters: {}, sort: 'sortorder' } } + ]); + + loadframeworks[0].done(function(frameworks) { + localthis.frameworks = frameworks; + if (frameworks.length == 0) { + templates.render('tool_lp/no_frameworks_warning', {}) + .done(function(html) { + $('[data-region="actions"]').append(html); + $('[data-region="actions"] button').hide(); + }).fail(notification.exception); + return; + } + $('[data-region="actions"] button').show(); + localthis.registerEvents(); + localthis.registerDragDrop(); + }).fail(notification.exception); + }; + + coursecompetencies.prototype.registerDragDrop = function() { + var localthis = this; + // Init this module. + str.get_string('movecoursecompetency', 'tool_lp').done( + function(movestring) { + dragdrop.dragdrop('movecoursecompetency', + movestring, + { identifier: 'movecoursecompetency', component: 'tool_lp'}, + { identifier: 'movecoursecompetencyafter', component: 'tool_lp'}, + 'drag-samenode', + 'drag-parentnode', + 'drag-handlecontainer', + function(drag, drop) { + localthis.handleDrop.call(localthis, drag, drop); + }); + } + ).fail(notification.exception); + + }; + + coursecompetencies.prototype.handleDrop = function(drag, drop) { + var fromid = $(drag).data('id'); + var toid = $(drop).data('id'); + var localthis = this; + + var requests = ajax.call([ + { methodname: 'tool_lp_reorder_course_competency', + args: { courseid: localthis.courseid, competencyidfrom: fromid, competencyidto: toid } } + ]); + requests[0].fail(notification.exception); + + }; + + coursecompetencies.prototype.applyFilter = function(e) { + e.preventDefault(); + var localthis = this; + var searchInput = $('[data-region="filtercompetencies"] input'); + var searchText = searchInput.val(); + var framework = $('[data-action="chooseframework"]'); + var frameworkid = framework.val(); + + this.searchCompetencies().done(function (competencies) { + var i = 0; + + var framework = localthis.frameworks[0]; + for (i = 0; i < localthis.frameworks.length; i++) { + if (localthis.frameworks[i].id == frameworkid) { + framework = localthis.frameworks[i]; + framework.selected = true; + } else { + localthis.frameworks[i].selected = false; + } + } + framework.selected = true; + var context = { framework: framework, frameworks: localthis.frameworks, competencies: competencies, search: searchText }; + templates.render('tool_lp/link_course_competencies', context).done(function(html) { + $('[data-region="competencylinktree"]').replaceWith(html); + localthis.initLinkCourseCompetencies(); + }).fail(notification.exception);; + }).fail(notification.exception); + }; + + coursecompetencies.prototype.initLinkCourseCompetencies = function() { + var localthis = this; + + var competencytree = new ariatree('[data-enhance=linktree]', function(target) { + localthis.selectedCompetency = target.data('id'); + }); + + $('[data-action="chooseframework"]').change(function(e) { + return localthis.applyFilter.call(localthis, e); + }); + + $('[data-region="filtercompetencies"] button').click(function(e) { + $(e.target).attr('disabled', 'disabled'); + return localthis.applyFilter.call(localthis, e); + }); + + $('[data-region="competencylinktree"] [data-action="cancel"]').click(function(e) { + $(e.target).attr('disabled', 'disabled'); + e.preventDefault(); + localthis.popup.close(); + }); + $('[data-region="competencylinktree"] [data-action="add"]').click(function(e) { + e.preventDefault(); + if (!localthis.selectedCompetency) { + return; + } + + $(e.target).attr('disabled', 'disabled'); + // Add the link and reload the page template. + var requests = ajax.call([ + { methodname: 'tool_lp_add_competency_to_course', + args: { courseid: localthis.courseid, competencyid: localthis.selectedCompetency } }, + { methodname: 'tool_lp_data_for_course_competencies_page', + args: { courseid: localthis.courseid } } + ]); + + requests[1].done(function(context) { + templates.render('tool_lp/course_competencies_page', context).done(function(html, js) { + localthis.popup.close(); + $('[data-region="coursecompetenciespage"]').replaceWith(html); + templates.runTemplateJS(js); + }).fail(notification.exception); + }).fail(notification.exception); + }); + }; + + coursecompetencies.prototype.registerEvents = function() { + var localthis = this; + $('[data-region="actions"] button').click(function(e) { + return localthis.openCompetencySelector.call(localthis, e); + }); + $('[data-action="delete-competency-link"]').click(function(e) { + e.preventDefault(); + + var deleteid = $(e.target).closest('[data-id]').data('id'); + + // Delete the link and reload the page template. + var requests = ajax.call([ + { methodname: 'tool_lp_remove_competency_from_course', + args: { courseid: localthis.courseid, competencyid: deleteid } }, + { methodname: 'tool_lp_data_for_course_competencies_page', + args: { courseid: localthis.courseid } } + ]); + + requests[1].done(function(context) { + templates.render('tool_lp/course_competencies_page', context).done(function(html, js) { + $('[data-region="coursecompetenciespage"]').replaceWith(html); + templates.runTemplateJS(js); + }).fail(notification.exception); + }).fail(notification.exception); + }); + }; + + coursecompetencies.prototype.addCompetencyChildren = function(parent, competencies) { + var i; + + for (i = 0; i < competencies.length; i++) { + if (competencies[i].parentid == parent.id) { + parent.haschildren = true; + competencies[i].children = []; + competencies[i].haschildren = false; + parent.children[parent.children.length] = competencies[i]; + this.addCompetencyChildren(competencies[i], competencies); + } + } + }; + + coursecompetencies.prototype.searchCompetencies = function() { + var localthis = this; + var deferred = $.Deferred(); + var searchInput = $('[data-region="filtercompetencies"] input'); + var searchText = ''; + if (searchInput.length) { + searchText = searchInput.val(); + } + var framework = $('[data-action="chooseframework"]'); + var frameworkid = localthis.frameworks[0].id; + if (framework.length) { + var frameworkid = framework.val(); + } + + var loadcompetencies = ajax.call([ + { methodname: 'tool_lp_search_competencies', args: { searchtext: searchText, competencyframeworkid: frameworkid } } + ]); + + loadcompetencies[0].done(function (competencies) { + // Expand the list of competencies into a tree. + var i, competenciestree = []; + for (i = 0; i < competencies.length; i++) { + var onecompetency = competencies[i]; + if (onecompetency.parentid == 0) { + onecompetency.children = []; + onecompetency.haschildren = 0; + competenciestree[competenciestree.length] = onecompetency; + localthis.addCompetencyChildren(onecompetency, competencies); + } + } + deferred.resolve(competenciestree); + }).fail(function (ex) { deferred.reject(ex); }); + + return deferred.promise(); + }; + + coursecompetencies.prototype.openCompetencySelector = function(e) { + e.preventDefault(); + var localthis = this; + + this.searchCompetencies().done(function (competencies) { + var framework = localthis.frameworks[0]; + framework.selected = true; + var context = { framework: framework, frameworks: localthis.frameworks, competencies: competencies, search: '' }; + templates.render('tool_lp/link_course_competencies', context).done(function(html) { + str.get_string('linkcoursecompetencies', 'tool_lp').done(function(title) {; + localthis.popup = new dialogue( + title, + html, // The link UI. + (function() {localthis.initLinkCourseCompetencies.call(localthis)}) + ); + }).fail(notification.exception); + }).fail(notification.exception);; + }).fail(notification.exception); + }; + + return /** @alias module:core/tree */ coursecompetencies; +}); diff --git a/admin/tool/lp/amd/src/frameworkdelete.js b/admin/tool/lp/amd/src/frameworkdelete.js new file mode 100644 index 00000000000..a3da25d9988 --- /dev/null +++ b/admin/tool/lp/amd/src/frameworkdelete.js @@ -0,0 +1,118 @@ +// 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 . + +/** + * Delete competency frameworks via ajax. + * + * @module tool_lp/frameworkdelete + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'], function($, templates, ajax, notification, str) { + // Private variables and functions. + + /** @var {Number} frameworkid The id of the framework */ + var frameworkid = 0; + + /** + * Callback to replace the dom element with the rendered template. + * + * @param {string} newhtml The new html to insert. + * @param {string} newjs The new js to run. + */ + var updatePage = function(newhtml, newjs) { + $('[data-region="managecompetencies"]').replaceWith(newhtml); + templates.runTemplateJS(newjs); + }; + + /** + * Callback to render the page template again and update the page. + * + * @param {Object} context The context for the template. + */ + var reloadList = function(context) { + templates.render('tool_lp/manage_competency_frameworks_page', context) + .done(updatePage) + .fail(notification.exception); + }; + + /** + * Delete a framework and reload the page. + */ + var doDelete = function() { + + // We are chaining ajax requests here. + var requests = ajax.call([{ + methodname: 'tool_lp_delete_competency_framework', + args: { id: frameworkid } + }, { + methodname: 'tool_lp_data_for_competency_frameworks_manage_page', + args: [] + }]); + requests[1].done(reloadList).fail(notification.exception); + }; + + /** + * Handler for "Delete competency framework" actions. + * @param {Event} e + */ + var confirmDelete = function(e) { + e.preventDefault(); + + var id = $(this).attr('data-frameworkid'); + frameworkid = id; + + var requests = ajax.call([{ + methodname: 'tool_lp_read_competency_framework', + args: { id: frameworkid } + }]); + + requests[0].done(function(framework) { + var strings = str.get_strings([ + { key: 'confirm', component: 'tool_lp' }, + { key: 'deletecompetencyframework', component: 'tool_lp', param: framework.shortname }, + { key: 'delete', component: 'tool_lp' }, + { key: 'cancel', component: 'tool_lp' } + ]).done(function (strings) { + notification.confirm( + strings[0], // Confirm. + strings[1], // Delete competency framework X? + strings[2], // Delete. + strings[3], // Cancel. + doDelete + ); + }).fail(notification.exception); + }).fail(notification.exception); + + }; + + + return { + // Public variables and functions. + /** + * Initialise this plugin. Just attaches some event handlers to the delete entries in the menu. + */ + init: function() { + // Init this module. + $('[data-region="managecompetencies"]').on( + "click", + '[data-action="deletecompetencyframework"]', + confirmDelete + ); + } + + }; +}); diff --git a/admin/tool/lp/amd/src/frameworkmove.js b/admin/tool/lp/amd/src/frameworkmove.js new file mode 100644 index 00000000000..a62570c5e11 --- /dev/null +++ b/admin/tool/lp/amd/src/frameworkmove.js @@ -0,0 +1,72 @@ +// 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 . + +/** + * Move competency frameworks via ajax. + * + * @module tool_lp/frameworkdelete + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['core/dragdrop-reorder', + 'core/str', + 'core/notification', + 'jquery', + 'core/ajax'], + function(dragdrop, str, notification, $, ajax) { + // Private variables and functions. + + /** + * Handle a drop on a node. + * + * @param {DOMNode} drag + * @param {DOMNode} drop + */ + var handleDrop = function(drag, drop) { + var from = $(drag).data('frameworkid'); + var to = $(drop).data('frameworkid'); + + var requests = ajax.call([{ + methodname: 'tool_lp_reorder_competency_framework', + args: { from: from, to: to } + }]); + requests[0].fail(notification.exception); + + }; + + return { + // Public variables and functions. + /** + * Initialise this plugin. It loads some strings, then adds the drag/drop functions. + */ + init: function() { + // Init this module. + str.get_string('movecompetencyframework', 'tool_lp').done( + function(movestring) { + dragdrop.dragdrop('movecompetencyframework', + movestring, + { identifier: 'movecompetencyframework', component: 'tool_lp'}, + { identifier: 'movecompetencyframeworkafter', component: 'tool_lp'}, + 'drag-samenode', + 'drag-parentnode', + 'drag-handlecontainer', + handleDrop); + } + ).fail(notification.exception); + } + + }; +}); diff --git a/admin/tool/lp/amd/src/templatedelete.js b/admin/tool/lp/amd/src/templatedelete.js new file mode 100644 index 00000000000..0a680bd40da --- /dev/null +++ b/admin/tool/lp/amd/src/templatedelete.js @@ -0,0 +1,118 @@ +// 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 . + +/** + * Delete learning plan templates via ajax. + * + * @module tool_lp/templatedelete + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str'], function($, templates, ajax, notification, str) { + // Private variables and functions. + + /** @var {Number} templateid The id of the template */ + var templateid = 0; + + /** + * Callback to replace the dom element with the rendered template. + * + * @param {string} newhtml The new html to insert. + * @param {string} newjs The new js to run. + */ + var updatePage = function(newhtml, newjs) { + $('[data-region="managetemplates"]').replaceWith(newhtml); + templates.runTemplateJS(newjs); + }; + + /** + * Callback to render the page template again and update the page. + * + * @param {Object} context The context for the template. + */ + var reloadList = function(context) { + templates.render('tool_lp/manage_templates_page', context) + .done(updatePage) + .fail(notification.exception); + }; + + /** + * Delete a template and reload the page. + */ + var doDelete = function() { + + // We are chaining ajax requests here. + var requests = ajax.call([{ + methodname: 'tool_lp_delete_template', + args: { id: templateid } + }, { + methodname: 'tool_lp_data_for_templates_manage_page', + args: [] + }]); + requests[1].done(reloadList).fail(notification.exception); + }; + + /** + * Handler for "Delete learning plan template" actions. + * @param {Event} e + */ + var confirmDelete = function(e) { + e.preventDefault(); + + var id = $(this).attr('data-templateid'); + templateid = id; + + var requests = ajax.call([{ + methodname: 'tool_lp_read_template', + args: { id: templateid } + }]); + + requests[0].done(function(template) { + var strings = str.get_strings([ + { key: 'confirm', component: 'tool_lp' }, + { key: 'deletetemplate', component: 'tool_lp', param: template.shortname }, + { key: 'delete', component: 'tool_lp' }, + { key: 'cancel', component: 'tool_lp' } + ]).done(function (strings) { + notification.confirm( + strings[0], // Confirm. + strings[1], // Delete learning plan template X? + strings[2], // Delete. + strings[3], // Cancel. + doDelete + ); + }).fail(notification.exception); + }).fail(notification.exception); + + }; + + + return { + // Public variables and functions. + /** + * Initialise this plugin. Just attaches some event handlers to the delete entries in the menu. + */ + init: function() { + // Init this module. + $('[data-region="managetemplates"]').on( + "click", + '[data-action="deletetemplate"]', + confirmDelete + ); + } + + }; +}); diff --git a/admin/tool/lp/amd/src/templatemove.js b/admin/tool/lp/amd/src/templatemove.js new file mode 100644 index 00000000000..7be9940f29d --- /dev/null +++ b/admin/tool/lp/amd/src/templatemove.js @@ -0,0 +1,72 @@ +// 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 . + +/** + * Move learning plan templates via ajax. + * + * @module tool_lp/templatedelete + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['core/dragdrop-reorder', + 'core/str', + 'core/notification', + 'jquery', + 'core/ajax'], + function(dragdrop, str, notification, $, ajax) { + // Private variables and functions. + + /** + * Handle a drop on a node. + * + * @param {DOMNode} drag + * @param {DOMNode} drop + */ + var handleDrop = function(drag, drop) { + var from = $(drag).data('templateid'); + var to = $(drop).data('templateid'); + + var requests = ajax.call([{ + methodname: 'tool_lp_reorder_template', + args: { from: from, to: to } + }]); + requests[0].fail(notification.exception); + + }; + + return { + // Public variables and functions. + /** + * Initialise this plugin. It loads some strings, then adds the drag/drop functions. + */ + init: function() { + // Init this module. + str.get_string('movetemplate', 'tool_lp').done( + function(movestring) { + dragdrop.dragdrop('movetemplate', + movestring, + { identifier: 'movetemplate', component: 'tool_lp'}, + { identifier: 'movetemplateafter', component: 'tool_lp'}, + 'drag-samenode', + 'drag-parentnode', + 'drag-handlecontainer', + handleDrop); + } + ).fail(notification.exception); + } + + }; +}); diff --git a/admin/tool/lp/classes/api.php b/admin/tool/lp/classes/api.php new file mode 100644 index 00000000000..c6372002b00 --- /dev/null +++ b/admin/tool/lp/classes/api.php @@ -0,0 +1,1026 @@ +. + +/** + * 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_system; +use context_course; +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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // OK - all set. + $competency = new competency(0, $record); + $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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // OK - all set. + $competency = new competency(); + $competency->set_id($id); + 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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // Check the current one too. + $current = new competency($id); + + $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. + return $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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // Check the current one too. + $current = new competency($id); + + $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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // This will throw an exception if the parent does not exist. + + // Check the current one too. + $current = new competency($id); + $parentframeworkid = $current->get_competencyframeworkid(); + $parentpath = '/0/'; + if ($newparentid) { + $parent = new competency($newparentid); + $parentframeworkid = $parent->get_competencyframeworkid(); + $parentpath = $parent->get_path(); + } + + if ($parentframeworkid != $current->get_competencyframeworkid()) { + // Only allow moving within the same framework. + throw new coding_exception('Moving competencies is only supported within the same framework.'); + } + + // 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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // Some things should not be changed in an update - they should use a more specific method. + $current = new competency($record->id); + $record->sortorder = $current->get_sortorder(); + $record->parentid = $current->get_parentid(); + $record->competencyframeworkid = $current->get_competencyframeworkid(); + + // OK - all set. + $competency = new competency(0, $record); + 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. + * @return stdClass + */ + public static function read_competency($id) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + return new competency($id); + } + + /** + * Perform a text search based and return all results and their parents. + * + * Requires tool/lp:competencyread capability at the system 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) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + $competency = new competency(); + return $competency->search($textsearch, $competencyframeworkid); + } + + /** + * 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 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, $skip, $limit) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + $competency = new competency(); + 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 the system context. + * + * @param array $filters A list of filters to apply to the list. + * @return int + */ + public static function count_competencies($filters) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + $competency = new competency(); + 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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // OK - all set. + $framework = new competency_framework(0, $record); + $id = $framework->create(); + 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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // OK - all set. + $framework = new competency_framework(); + $framework->set_id($id); + 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) { + // First we do a permissions check. + require_capability('tool/lp:competencymanage', context_system::instance()); + + // OK - all set. + $framework = new competency_framework(0, $record); + 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 stdClass + */ + public static function read_framework($id) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + return new competency_framework($id); + } + + /** + * Move the competency framework up or down in the display list. + * + * Requires tool/lp:competencymanage capability at the system context. + * + * @param int $frameworkidfrom The framework we are moving. + * @param int $frameworkidto Where we are moving to. If moving down, it will go after this framework, + * If moving up, it will go before this framework. + * @return boolean + */ + public static function reorder_framework($frameworkidfrom, $frameworkidto) { + require_capability('tool/lp:competencymanage', context_system::instance()); + $down = true; + $frameworkfrom = new competency_framework($frameworkidfrom); + $frameworkto = new competency_framework($frameworkidto); + + $all = self::list_frameworks(array(), 'sortorder', 'ASC', 0, 0); + + if ($frameworkfrom->get_sortorder() > $frameworkto->get_sortorder()) { + // We are moving down, so put it after the "to" item. + $down = false; + } + + foreach ($all as $id => $framework) { + $sort = $framework->get_sortorder(); + if ($down && $sort > $frameworkfrom->get_sortorder() && $sort <= $frameworkto->get_sortorder()) { + $framework->set_sortorder($framework->get_sortorder() - 1); + $framework->update(); + } else if (!$down && $sort >= $frameworkto->get_sortorder() && $sort < $frameworkfrom->get_sortorder()) { + $framework->set_sortorder($framework->get_sortorder() + 1); + $framework->update(); + } + } + $frameworkfrom->set_sortorder($frameworkto->get_sortorder()); + return $frameworkfrom->update(); + } + + /** + * 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 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 competency_framework + */ + public static function list_frameworks($filters, $sort, $order, $skip, $limit) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + $framework = new competency_framework(); + return $framework->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 the system context. + * + * @param array $filters A list of filters to apply to the list. + * @return int + */ + public static function count_frameworks($filters) { + // First we do a permissions check. + $context = context_system::instance(); + if (!has_any_capability(array('tool/lp:competencyread', 'tool/lp:competencymanage'), $context)) { + throw new required_capability_exception($context, 'tool/lp:competencyread', 'nopermission', ''); + } + + // OK - all set. + $framework = new competency_framework(); + return $framework->count_records($filters); + } + + /** + * 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. + $coursecompetency = new course_competency(); + $courses = $coursecompetency->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. + $coursecompetency = new course_competency(); + $courses = $coursecompetency->list_courses($competencyid); + $count = 0; + $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', 'nopermission', ''); + } + + if (has_capability('tool/lp:coursecompetencymanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $coursecompetency = new course_competency(); + return $coursecompetency->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', 'nopermission', ''); + } + + if (has_capability('tool/lp:coursecompetencymanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $coursecompetency = new course_competency(); + return $coursecompetency->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); + + if (!has_capability('tool/lp:coursecompetencymanage', $context)) { + throw new required_capability_exception($context, 'tool/lp:coursecompetencymanage', 'nopermission', ''); + } + $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); + + if (!has_capability('tool/lp:coursecompetencymanage', $context)) { + throw new required_capability_exception($context, 'tool/lp:coursecompetencymanage', 'nopermission', ''); + } + $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); + + if (!has_capability('tool/lp:coursecompetencymanage', $context)) { + throw new required_capability_exception($context, 'tool/lp:coursecompetencymanage', 'nopermission', ''); + } + + $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 at the system context. + * + * @param stdClass $record Record containing all the data for an instance of the class. + * @return template + */ + public static function create_template(stdClass $record) { + // First we do a permissions check. + require_capability('tool/lp:templatemanage', context_system::instance()); + + // OK - all set. + $template = new template(0, $record); + $id = $template->create(); + return $template; + } + + /** + * Delete a learning plan template by id. + * + * Requires tool/lp:templatemanage capability at the system context. + * + * @param int $id The record to delete. + * @return boolean + */ + public static function delete_template($id) { + // First we do a permissions check. + require_capability('tool/lp:templatemanage', context_system::instance()); + + // OK - all set. + $template = new template(); + $template->set_id($id); + return $template->delete(); + } + + /** + * Update the details for a learning plan template. + * + * Requires tool/lp:templatemanage capability at the system context. + * + * @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) { + // First we do a permissions check. + require_capability('tool/lp:templatemanage', context_system::instance()); + + // OK - all set. + $template = new template(0, $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 stdClass + */ + public static function read_template($id) { + // First we do a permissions check. + $context = context_system::instance(); + $caps = array('tool/lp:templateread', 'tool/lp:templatemanage'); + if (!has_any_capability($caps, $context)) { + throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermission', ''); + } + + // OK - all set. + return new template($id); + } + + /** + * Move the learning plan template up or down in the display list. + * + * Requires tool/lp:templatemanage capability at the system context. + * + * @param int $templateidfrom The template we are moving. + * @param int $templateidto Where we are moving to. If moving down, it will go after this template, + * If moving up, it will go before this template. + * @return boolean + */ + public static function reorder_template($templateidfrom, $templateidto) { + require_capability('tool/lp:templatemanage', context_system::instance()); + $down = true; + $templatefrom = new template($templateidfrom); + $templateto = new template($templateidto); + + $all = self::list_templates(array(), 'sortorder', 'ASC', 0, 0); + + if ($templatefrom->get_sortorder() > $templateto->get_sortorder()) { + // We are moving down, so put it after the "to" item. + $down = false; + } + + foreach ($all as $id => $template) { + $sort = $template->get_sortorder(); + if ($down && $sort > $templatefrom->get_sortorder() && $sort <= $templateto->get_sortorder()) { + $template->set_sortorder($template->get_sortorder() - 1); + $template->update(); + } else if (!$down && $sort >= $templateto->get_sortorder() && $sort < $templatefrom->get_sortorder()) { + $template->set_sortorder($template->get_sortorder() + 1); + $template->update(); + } + } + $templatefrom->set_sortorder($templateto->get_sortorder()); + return $templatefrom->update(); + } + + /** + * 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 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 competency_framework + */ + public static function list_templates($filters, $sort, $order, $skip, $limit) { + // First we do a permissions check. + $context = context_system::instance(); + $caps = array('tool/lp:templateread', 'tool/lp:templatemanage'); + if (!has_any_capability($caps, $context)) { + throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermission', ''); + } + + // OK - all set. + $template = new template(); + return $template->get_records($filters, $sort, $order, $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 array $filters A list of filters to apply to the list. + * @return int + */ + public static function count_templates($filters) { + // First we do a permissions check. + $context = context_system::instance(); + $caps = array('tool/lp:templateread', 'tool/lp:templatemanage'); + if (!has_any_capability($caps, $context)) { + throw new required_capability_exception($context, 'tool/lp:templateread', 'nopermission', ''); + } + + // OK - all set. + $template = new template(); + return $template->count_records($filters); + } + + /** + * 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', 'nopermission', ''); + } + + if (has_capability('tool/lp:templatemanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $templatecompetency = new template_competency(); + return $templatecompetency->count_competencies($templateid, $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', 'nopermission', ''); + } + + if (has_capability('tool/lp:templatemanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $templatecompetency = new template_competency(); + return $templatecompetency->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. + $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', 'nopermission', ''); + } + + if (has_capability('tool/lp:templatemanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $templatecompetency = new template_competency(); + return $templatecompetency->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. + $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', 'nopermission', ''); + } + + if (has_capability('tool/lp:templatemanage', $context)) { + $onlyvisible = 0; + } + + // OK - all set. + $templatecompetency = new template_competency(); + return $templatecompetency->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. + $context = context_course::instance($courseid); + + require_capability('tool/lp:templatemanage', $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'); + } + + $templatecompetency = new template_competency(); + $exists = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyid)); + if (!$exists) { + $templatecompetency->from_record($record); + if ($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. + $context = context_system::instance(); + + require_capability('tool/lp:templatemanage', $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'); + } + + $template = new template(); + $template->set_id($template); + if (!$template->read()) { + throw new coding_exception('The learning plan template does not exist'); + } + + $templatecompetency = new template_competency(); + $exists = $templatecompetency->get_records(array('templateid' => $templateid, 'competencyid' => $competencyid)); + if ($exists) { + $link = array_pop($exists); + return $link->delete(); + } + return false; + } +} diff --git a/admin/tool/lp/classes/competency.php b/admin/tool/lp/classes/competency.php new file mode 100644 index 00000000000..77449c1a74e --- /dev/null +++ b/admin/tool/lp/classes/competency.php @@ -0,0 +1,439 @@ +. + +/** + * Class for loading/storing competencies 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_system; + +/** + * Class for loading/storing competencies from the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class competency extends persistent { + + /** @var string $shortname Short name for this competency */ + private $shortname = ''; + + /** @var string $idnumber Unique idnumber for this competency - must be unique within the framework if it is non-empty */ + private $idnumber = ''; + + /** @var string $description Description for this competency */ + private $description = ''; + + /** @var int $descriptionformat Format for the description */ + private $descriptionformat = 0; + + /** @var int $sortorder A number used to influence sorting */ + private $sortorder = 0; + + /** @var bool $visible Used to show/hide this competency */ + private $visible = true; + + /** @var int $parentid id of the parent of this competency (0 means root competency) */ + private $parentid = 0; + + /** @var string $path ids of all the parents up the tree separated with slashes */ + private $path = '/0/'; + + /** @var int $id of the competency framework this competency belongs to */ + private $competencyframeworkid = 0; + + /** + * Method that provides the table name matching this class. + * + * @return string + */ + public function get_table_name() { + return 'tool_lp_competency'; + } + + /** + * Get the short name. + * + * @return string The short name + */ + public function get_shortname() { + return $this->shortname; + } + + /** + * Set the short name. + * + * @param string $shortname The short name + */ + public function set_shortname($shortname) { + $this->shortname = $shortname; + } + + /** + * Get the description format. + * + * @return int The description format + */ + public function get_descriptionformat() { + return $this->descriptionformat; + } + + /** + * Set the description format + * + * @param int $descriptionformat The description format + */ + public function set_descriptionformat($descriptionformat) { + $this->descriptionformat = $descriptionformat; + } + + /** + * Get the id number. + * + * @return string The id number + */ + public function get_idnumber() { + return $this->idnumber; + } + + /** + * Set the id number. + * + * @param string $idnumber The id number + */ + public function set_idnumber($idnumber) { + $this->idnumber = $idnumber; + } + + /** + * Get the description. + * + * @return string The description + */ + public function get_description() { + return $this->description; + } + + /** + * Set the description. + * + * @param string $description The description + */ + public function set_description($description) { + $this->description = $description; + } + + /** + * Get the sort order index. + * + * @return string The sort order index + */ + public function get_sortorder() { + return $this->sortorder; + } + + /** + * Set the sort order index. + * + * @param string $sortorder The sort order index + */ + public function set_sortorder($sortorder) { + $this->sortorder = $sortorder; + } + + /** + * Get the visible flag. + * + * @return string The visible flag + */ + public function get_visible() { + return $this->visible; + } + + /** + * Set the visible flag. + * + * @param string $visible The visible flag + */ + public function set_visible($visible) { + $this->visible = $visible; + } + + /** + * Get the parentid + * + * @return int The id of the parent + */ + public function get_parentid() { + return $this->parentid; + } + + /** + * Set the parent id + * + * @param int $parentid The parent id number (can be null) + */ + public function set_parentid($id) { + $this->parentid = $id; + } + + /** + * Get the path + * + * @return string The ids of all the parents joined with a slash. + */ + public function get_path() { + return $this->path; + } + + /** + * Set the path. + * + * @param string $path The ids of all the parents joined with a slash. + */ + public function set_path($path) { + $this->path = $path; + } + + /** + * Get the competencyframeworkid + * + * @return int The competency framework id. + */ + public function get_competencyframeworkid() { + return $this->competencyframeworkid; + } + + /** + * Set the competencyframeworkid. + * + * @param int $competencyframeworkid The competency framework id. + */ + public function set_competencyframeworkid($competencyframeworkid) { + $this->competencyframeworkid = $competencyframeworkid; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return framework + */ + public function from_record($record) { + if (isset($record->id)) { + $this->set_id($record->id); + } + if (isset($record->shortname)) { + $this->set_shortname($record->shortname); + } + if (isset($record->idnumber)) { + $this->set_idnumber($record->idnumber); + } + if (isset($record->description)) { + $this->set_description($record->description); + } + if (isset($record->descriptionformat)) { + $this->set_descriptionformat($record->descriptionformat); + } + if (isset($record->sortorder)) { + $this->set_sortorder($record->sortorder); + } + if (isset($record->visible)) { + $this->set_visible($record->visible); + } + if (isset($record->timecreated)) { + $this->set_timecreated($record->timecreated); + } + if (isset($record->timemodified)) { + $this->set_timemodified($record->timemodified); + } + if (isset($record->usermodified)) { + $this->set_usermodified($record->usermodified); + } + if (isset($record->competencyframeworkid)) { + $this->set_competencyframeworkid($record->competencyframeworkid); + } + if (isset($record->parentid)) { + $this->set_parentid($record->parentid); + } + if (isset($record->path)) { + $this->set_path($record->path); + } + return $this; + } + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + public function to_record() { + $record = new stdClass(); + $record->id = $this->get_id(); + $record->shortname = $this->get_shortname(); + $record->idnumber = $this->get_idnumber(); + $record->description = $this->get_description(); + $record->descriptionformat = $this->get_descriptionformat(); + $options = array('context' => context_system::instance()); + $record->descriptionformatted = format_text($this->get_description(), $this->get_descriptionformat(), $options); + $record->sortorder = $this->get_sortorder(); + $record->visible = $this->get_visible(); + $record->timecreated = $this->get_timecreated(); + $record->timemodified = $this->get_timemodified(); + $record->usermodified = $this->get_usermodified(); + $record->competencyframeworkid = $this->get_competencyframeworkid(); + $record->parentid = $this->get_parentid(); + $record->path = $this->get_path(); + + return $record; + } + + /** + * Add a default for the sortorder field to the default create logic. + * + * @return persistent + */ + public function create() { + if ($this->parentid) { + // Load the parent so we can set the path. + $parent = new competency($this->parentid); + $this->path = $parent->path . $this->parentid . '/'; + } else { + $this->path = '/0/'; + } + $this->sortorder = $this->count_records(array('parentid' => $this->parentid, 'competencyframeworkid' => $this->competencyframeworkid)); + return parent::create(); + } + + /** + * Fix all paths when moving to a new parent. + * + * @return persistent + */ + public function update() { + global $DB; + + // See if the parentid changed, if so we have work to do. + $before = new competency($this->get_id()); + if ($before->parentid != $this->parentid) { + if ($this->parentid) { + $parent = new competency($this->parentid); + $this->path = $parent->path . $this->parentid . '/'; + } else { + $this->path = '/0/'; + } + + $search = array('parentid' => $this->parentid, + 'competencyframeworkid' => $this->competencyframeworkid); + $this->sortorder = $this->count_records($search); + + // We need to fix all the paths of the children. + $like = $DB->sql_like('path', '?'); + $likesearch = $DB->sql_like_escape($before->path . $before->id . '/') . '%'; + $sql = 'UPDATE {tool_lp_competency} SET path = REPLACE(path, ?, ?) WHERE ' . $like; + $DB->execute($sql, array($before->path . $this->id . '/', $this->path . $this->id . '/', $likesearch)); + } + // Do the default update. + return parent::update(); + } + + /** + * This does a specialised search that finds all nodes in the tree with matching text on any text like field, + * and returns this node and all its parents in a displayable sort order. + * + * @param string $searchText The text to search for. + * @param int $competencyframeworkid The competency framework to limit the search. + * @return persistent + */ + public function search($searchText, $competencyframeworkid) { + global $DB; + + $like1 = $DB->sql_like('shortname', ':like1', false); + $like2 = $DB->sql_like('idnumber', ':like2', false); + $like3 = $DB->sql_like('description', ':like3', false); + + $params = array( + 'like1' => '%' . $DB->sql_like_escape($searchText) . '%', + 'like2' => '%' . $DB->sql_like_escape($searchText) . '%', + 'like3' => '%' . $DB->sql_like_escape($searchText) . '%', + 'frameworkid' => $competencyframeworkid + ); + + $sql = 'competencyframeworkid = :frameworkid AND ((' . $like1 . ') OR (' . $like2 . ') OR (' . $like3 . '))'; + $records = $DB->get_records_select($this->get_table_name(), $sql, $params, 'path, sortorder ASC', '*'); + + // Now get all the parents. + $parents = array(); + foreach ($records as $record) { + $parents = explode('/', $record->path); + foreach ($parents as $parent) { + $parents[intval($parent)] = true; + } + } + $parents = array_keys($parents); + + // Skip ones we already fetched. + foreach ($parents as $idx => $parent) { + if ($parent == 0 || isset($records[$parent])) { + unset($parents[$idx]); + } + } + + if (count($parents)) { + list($parentsql, $parentparams) = $DB->get_in_or_equal($parents, SQL_PARAMS_NAMED); + + $parentrecords = $DB->get_records_select($this->get_table_name(), 'id ' . $parentsql, $parentparams, 'path, sortorder ASC', '*'); + + foreach ($parentrecords as $id => $record) { + $records[$id] = $record; + } + } + + $instances = array(); + // Convert to instances of this class. + foreach ($records as $record) { + $newrecord = new static(0, $record); + array_push($instances, $newrecord); + } + return $instances; + } + + /** + * Delete a competency (drastic). Will delete all child nodes in the tree. + * + * @return persistent + */ + public function delete() { + global $DB; + + $deletepath = $DB->sql_like_escape($this->path . $this->get_id() . '/') . '%'; + + // We need to delete all the children. + $like = $DB->sql_like('path', ':deletepath'); + $DB->delete_records_select('tool_lp_competency', $like, array('deletepath' => $deletepath)); + + // And all the links to courses. + $DB->delete_records('tool_lp_course_competency', array('competencyid' => $this->get_id())); + // Do the default delete. + return parent::delete(); + } +} diff --git a/admin/tool/lp/classes/competency_framework.php b/admin/tool/lp/classes/competency_framework.php new file mode 100644 index 00000000000..a4f3eb85504 --- /dev/null +++ b/admin/tool/lp/classes/competency_framework.php @@ -0,0 +1,243 @@ +. + +/** + * 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; + +/** + * Class for loading/storing competency frameworks from the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class competency_framework extends persistent { + + /** @var string $shortname Short name for this framework */ + private $shortname = ''; + + /** @var string $idnumber Unique idnumber for this framework - must be unique if it is non-empty */ + private $idnumber = ''; + + /** @var string $description Description for this framework */ + private $description = ''; + + /** @var int $descriptionformat Format for the description */ + private $descriptionformat = 0; + + /** @var int $sortorder A number used to influence sorting */ + private $sortorder = 0; + + /** @var bool $visible Used to show/hide this framework */ + private $visible = true; + + /** + * Method that provides the table name matching this class. + * + * @return string + */ + public function get_table_name() { + return 'tool_lp_competency_framework'; + } + + /** + * Get the short name. + * + * @return string The short name + */ + public function get_shortname() { + return $this->shortname; + } + + /** + * Set the short name. + * + * @param string $shortname The short name + */ + public function set_shortname($shortname) { + $this->shortname = $shortname; + } + + /** + * Get the description format. + * + * @return int The description format + */ + public function get_descriptionformat() { + return $this->descriptionformat; + } + + /** + * Set the description format + * + * @param int $descriptionformat The description format + */ + public function set_descriptionformat($descriptionformat) { + $this->descriptionformat = $descriptionformat; + } + /** + * Get the id number. + * + * @return string The id number + */ + public function get_idnumber() { + return $this->idnumber; + } + + /** + * Set the id number. + * + * @param string $idnumber The id number + */ + public function set_idnumber($idnumber) { + $this->idnumber = $idnumber; + } + + /** + * Get the description. + * + * @return string The description + */ + public function get_description() { + return $this->description; + } + + /** + * Set the description. + * + * @param string $description The description + */ + public function set_description($description) { + $this->description = $description; + } + + /** + * Get the sort order index. + * + * @return string The sort order index + */ + public function get_sortorder() { + return $this->sortorder; + } + + /** + * Set the sort order index. + * + * @param string $sortorder The sort order index + */ + public function set_sortorder($sortorder) { + $this->sortorder = $sortorder; + } + + /** + * Get the visible flag. + * + * @return string The visible flag + */ + public function get_visible() { + return $this->visible; + } + + /** + * Set the visible flag. + * + * @param string $visible The visible flag + */ + public function set_visible($visible) { + $this->visible = $visible; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return framework + */ + public function from_record($record) { + if (isset($record->id)) { + $this->set_id($record->id); + } + if (isset($record->shortname)) { + $this->set_shortname($record->shortname); + } + if (isset($record->idnumber)) { + $this->set_idnumber($record->idnumber); + } + if (isset($record->description)) { + $this->set_description($record->description); + } + if (isset($record->descriptionformat)) { + $this->set_descriptionformat($record->descriptionformat); + } + if (isset($record->sortorder)) { + $this->set_sortorder($record->sortorder); + } + if (isset($record->visible)) { + $this->set_visible($record->visible); + } + if (isset($record->timecreated)) { + $this->set_timecreated($record->timecreated); + } + if (isset($record->timemodified)) { + $this->set_timemodified($record->timemodified); + } + if (isset($record->usermodified)) { + $this->set_usermodified($record->usermodified); + } + return $this; + } + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + public function to_record() { + $record = new stdClass(); + $record->id = $this->get_id(); + $record->shortname = $this->get_shortname(); + $record->idnumber = $this->get_idnumber(); + $record->description = $this->get_description(); + $record->descriptionformat = $this->get_descriptionformat(); + $record->descriptionformatted = format_text($this->get_description(), $this->get_descriptionformat()); + $record->sortorder = $this->get_sortorder(); + $record->visible = $this->get_visible(); + $record->timecreated = $this->get_timecreated(); + $record->timemodified = $this->get_timemodified(); + $record->usermodified = $this->get_usermodified(); + + return $record; + } + + /** + * Add a default for the sortorder field to the default create logic. + * + * @return persistent + */ + public function create() { + $this->sortorder = $this->count_records(); + return parent::create(); + } + + +} diff --git a/admin/tool/lp/classes/course_competency.php b/admin/tool/lp/classes/course_competency.php new file mode 100644 index 00000000000..045e0e389a8 --- /dev/null +++ b/admin/tool/lp/classes/course_competency.php @@ -0,0 +1,267 @@ +. + +/** + * Class for loading/storing competencies 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_system; + +/** + * Class for loading/storing course_competencies from the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_competency extends persistent { + + /** @var int $courseid The course id */ + private $courseid = 0; + + /** @var int $competencyid The competency id */ + private $competencyid = 0; + + /** @var int $sortorder A number used to influence sorting */ + private $sortorder = 0; + + /** + * Method that provides the table name matching this class. + * + * @return string + */ + public function get_table_name() { + return 'tool_lp_course_competency'; + } + + /** + * Get the competency id + * + * @return int The competency id + */ + public function get_competencyid() { + return $this->competencyid; + } + + /** + * Set the competency id + * + * @param int $competencyid The competency id + */ + public function set_competencyid($competencyid) { + $this->competencyid = $competencyid; + } + + /** + * Get the sort order index. + * + * @return string The sort order index + */ + public function get_sortorder() { + return $this->sortorder; + } + + /** + * Set the sort order index. + * + * @param string $sortorder The sort order index + */ + public function set_sortorder($sortorder) { + $this->sortorder = $sortorder; + } + + /** + * Get the course id + * + * @return int The course id + */ + public function get_courseid() { + return $this->courseid; + } + + /** + * Set the course id + * + * @param int $courseid The course id + */ + public function set_courseid($courseid) { + $this->courseid = $courseid; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return framework + */ + public function from_record($record) { + if (isset($record->id)) { + $this->set_id($record->id); + } + if (isset($record->courseid)) { + $this->set_courseid($record->courseid); + } + if (isset($record->competencyid)) { + $this->set_competencyid($record->competencyid); + } + if (isset($record->sortorder)) { + $this->set_sortorder($record->sortorder); + } + if (isset($record->timecreated)) { + $this->set_timecreated($record->timecreated); + } + if (isset($record->timemodified)) { + $this->set_timemodified($record->timemodified); + } + if (isset($record->usermodified)) { + $this->set_usermodified($record->usermodified); + } + return $this; + } + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + public function to_record() { + $record = new stdClass(); + $record->id = $this->get_id(); + $record->courseid = $this->get_courseid(); + $record->competencyid = $this->get_competencyid(); + $record->sortorder = $this->get_sortorder(); + $record->timecreated = $this->get_timecreated(); + $record->timemodified = $this->get_timemodified(); + $record->usermodified = $this->get_usermodified(); + + return $record; + } + + /** + * Return the course ids and visible flags that include this competency. Only the ids and visible flag are returned, + * for the full records use list_courses. + * + * @param int $competencyid The competency id + * @return int + */ + public function list_courses_min($competencyid) { + global $DB; + + $results = $DB->get_records_sql('SELECT course.id as id, course.visible as visible + FROM {' . self::get_table_name() . '} coursecomp + JOIN {course} course + ON coursecomp.courseid = course.id + WHERE coursecomp.competencyid = ? ', array($competencyid)); + + return $results; + } + + /** + * Return partial course records foreach course that contains this competency. + * + * @param int $competencyid The competency id + * @return array[stdClass] Array of course records containg id, visible, shortname, idnumber, fullname + */ + public function list_courses($competencyid) { + global $DB; + + $results = $DB->get_records_sql('SELECT course.id, course.visible, course.shortname, course.idnumber, course.fullname + FROM {course} course + JOIN {' . self::get_table_name() . '} coursecomp + ON coursecomp.courseid = course.id + WHERE coursecomp.competencyid = ? ', array($competencyid)); + + return $results; + } + + /** + * Count the competencies in this course. + * + * @param int $courseid The course id + * @param bool $onlyvisible If true, only count visible competencies in this course. + * @return int + */ + public function count_competencies($courseid, $onlyvisible) { + global $DB; + + + $sql = 'SELECT COUNT(comp.id) + FROM {' . self::get_table_name() . '} coursecomp + JOIN {' . competency::get_table_name() . '} comp + ON coursecomp.competencyid = comp.id + WHERE coursecomp.courseid = ? '; + $params = array($courseid); + + if ($onlyvisible) { + $sql .= ' AND comp.visible = ?'; + $params[] = 1; + } + + $results = $DB->count_records_sql($sql, $params); + + return $results; + } + + /** + * List the competencies in this course. + * + * @param int $courseid The course id + * @param bool $onlyvisible If true, only count visible competencies in this course. + * @return array[competency] + */ + public function list_competencies($courseid, $onlyvisible) { + global $DB; + + $competency = new competency(); + + $sql = 'SELECT comp.* + FROM {' . $competency->get_table_name() . '} comp + JOIN {' . self::get_table_name() . '} coursecomp + ON coursecomp.competencyid = comp.id + WHERE coursecomp.courseid = ? ORDER BY coursecomp.sortorder ASC'; + $params = array($courseid); + + if ($onlyvisible) { + $sql .= ' AND comp.visible = ?'; + $params[] = 1; + } + + $results = $DB->get_records_sql($sql, $params); + + $instances = array(); + foreach ($results as $result) { + array_push($instances, new competency(0, $result)); + } + + return $instances; + } + + /** + * Add a default for the sortorder field to the default create logic. + * + * @return persistent + */ + public function create() { + $this->sortorder = $this->count_records(array('courseid' => $this->get_courseid())); + return parent::create(); + } + +} diff --git a/admin/tool/lp/classes/external.php b/admin/tool/lp/classes/external.php new file mode 100644 index 00000000000..f63ab611de4 --- /dev/null +++ b/admin/tool/lp/classes/external.php @@ -0,0 +1,2956 @@ +. + +/** + * This is the external API for this tool. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp; + +require_once("$CFG->libdir/externallib.php"); + +use external_api; +use external_function_parameters; +use external_value; +use external_format_value; +use external_single_structure; +use external_multiple_structure; +use invalid_parameter_exception; + +/** + * This is the external API for this tool. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class external extends external_api { + + /** + * Returns description of a generic list() parameters. + * + * @return external_function_parameters + */ + protected static function list_parameters_structure() { + $filters = new external_multiple_structure(new external_single_structure( + array( + 'column' => new external_value(PARAM_ALPHANUMEXT, 'Column name to filter by'), + 'value' => new external_value(PARAM_TEXT, 'Value to filter by. Must be exact match') + ) + )); + $sort = new external_value( + PARAM_ALPHANUMEXT, + 'Column to sort by.', + VALUE_DEFAULT, + '' + ); + $order = new external_value( + PARAM_ALPHA, + 'Sort direction. Should be either ASC or DESC', + VALUE_DEFAULT, + '' + ); + $skip = new external_value( + PARAM_INT, + 'Skip this number of records before returning results', + VALUE_DEFAULT, + 0 + ); + $limit = new external_value( + PARAM_INT, + 'Return this number of records at most.', + VALUE_DEFAULT, + 0 + ); + + $params = array( + 'filters' => $filters, + 'sort' => $sort, + 'order' => $order, + 'skip' => $skip, + 'limit' => $limit + ); + return new external_function_parameters($params); + } + + /** + * Returns description of a generic count_x() parameters. + * + * @return external_function_parameters + */ + public static function count_parameters_structure() { + $filters = new external_multiple_structure(new external_single_structure( + array( + 'column' => new external_value(PARAM_ALPHANUMEXT, 'Column name to filter by'), + 'value' => new external_value(PARAM_TEXT, 'Value to filter by. Must be exact match') + ) + )); + + $params = array( + 'filters' => $filters, + ); + return new external_function_parameters($params); + } + + /** + * Returns the external structure of a full competency_framework record. + * + * @return external_single_structure + */ + protected static function get_competency_framework_external_structure() { + $id = new external_value( + PARAM_INT, + 'Database record id' + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency framework' + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency framework' + ); + $description = new external_value( + PARAM_RAW, + 'Description for the framework' + ); + $descriptionformat = new external_format_value( + 'Description format for the framework' + ); + $descriptionformatted = new external_value( + PARAM_RAW, + 'Description that has been formatted for display' + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this framework visible?' + ); + $sortorder = new external_value( + PARAM_INT, + 'Relative sort order of this framework' + ); + $timecreated = new external_value( + PARAM_INT, + 'Timestamp this record was created' + ); + $timemodified = new external_value( + PARAM_INT, + 'Timestamp this record was modified' + ); + $usermodified = new external_value( + PARAM_INT, + 'User who modified this record last' + ); + + $returns = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'descriptionformatted' => $descriptionformatted, + 'visible' => $visible, + 'sortorder' => $sortorder, + 'timecreated' => $timecreated, + 'timemodified' => $timemodified, + 'usermodified' => $usermodified, + ); + return new external_single_structure($returns); + } + + /** + * Returns description of create_competency_framework() parameters. + * + * @return external_function_parameters + */ + public static function create_competency_framework_parameters() { + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency framework.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency framework.', + VALUE_DEFAULT, + '' + ); + $description = new external_value( + PARAM_RAW, + 'Optional description for the framework', + VALUE_DEFAULT, + '' + ); + $descriptionformat = new external_format_value( + 'Optional description format for the framework', + VALUE_DEFAULT, + FORMAT_HTML + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this framework visible?', + VALUE_DEFAULT, + true + ); + + $params = array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function create_competency_framework_is_allowed_from_ajax() { + return true; + } + + /** + * Create a new competency framework + * + * @param string $shortname The short name + * @param string $idnumber The idnumber + * @param string $description The description + * @param int $descriptionformat The description format + * @param bool $visible Is this framework visible. + * @return stdClass The new record + */ + public static function create_competency_framework($shortname, $idnumber, $description, $descriptionformat, $visible) { + $params = self::validate_parameters(self::create_competency_framework_parameters(), + array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + )); + + $params = (object) $params; + + $result = api::create_framework($params); + return $result->to_record(); + } + + /** + * Returns description of create_competency_framework() result value. + * + * @return external_description + */ + public static function create_competency_framework_returns() { + return self::get_competency_framework_external_structure(); + } + + /** + * Returns description of read_competency_framework() parameters. + * + * @return external_function_parameters + */ + public static function read_competency_framework_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the framework', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function read_competency_framework_is_allowed_from_ajax() { + return true; + } + + /** + * Read a competency framework by id. + * + * @param int $id The id of the framework. + * @return stdClass + */ + public static function read_competency_framework($id) { + $params = self::validate_parameters(self::read_competency_framework_parameters(), + array( + 'id' => $id, + )); + + $result = api::read_framework($params['id']); + return $result->to_record(); + } + + /** + * Returns description of read_competency_framework() result value. + * + * @return external_description + */ + public static function read_competency_framework_returns() { + return self::get_competency_framework_external_structure(); + } + + /** + * Returns description of delete_competency_framework() parameters. + * + * @return external_function_parameters + */ + public static function delete_competency_framework_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the framework', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function delete_competency_framework_is_allowed_from_ajax() { + return true; + } + + /** + * Delete a competency framework + * + * @param int $id The competency framework id + * @return boolean + */ + public static function delete_competency_framework($id) { + $params = self::validate_parameters(self::delete_competency_framework_parameters(), + array( + 'id' => $id, + )); + + return api::delete_framework($params['id']); + } + + /** + * Returns description of delete_competency_framework() result value. + * + * @return external_description + */ + public static function delete_competency_framework_returns() { + return new external_value(PARAM_BOOL, 'True if the delete was successful'); + } + + /** + * Returns description of update_competency_framework() parameters. + * + * @return external_function_parameters + */ + public static function update_competency_framework_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the framework', + VALUE_REQUIRED + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency framework.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency framework.', + VALUE_REQUIRED + ); + $description = new external_value( + PARAM_RAW, + 'Description for the framework', + VALUE_REQUIRED + ); + $descriptionformat = new external_format_value( + 'Description format for the framework', + VALUE_REQUIRED + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this framework visible?', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function update_competency_framework_is_allowed_from_ajax() { + return true; + } + + /** + * Update an existing competency framework + * + * @param int $id The competency framework id + * @param string $shortname + * @param string $idnumber + * @param string $description + * @param int $descriptionformat + * @param boolean $visible + * @return boolean + */ + public static function update_competency_framework($id, + $shortname, + $idnumber, + $description, + $descriptionformat, + $visible) { + + $params = self::validate_parameters(self::update_competency_framework_parameters(), + array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible + )); + $params = (object) $params; + + return api::update_framework($params); + } + + /** + * Returns description of update_competency_framework() result value. + * + * @return external_description + */ + public static function update_competency_framework_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of list_competency_frameworks() parameters. + * + * @return external_function_parameters + */ + public static function list_competency_frameworks_parameters() { + return self::list_parameters_structure(); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_competency_frameworks_is_allowed_from_ajax() { + return true; + } + + /** + * List the existing competency frameworks + * + * @return boolean + */ + public static function list_competency_frameworks($filters, $sort, $order, $skip, $limit) { + $params = self::validate_parameters(self::list_competency_frameworks_parameters(), + array( + 'filters' => $filters, + 'sort' => $sort, + 'order' => $order, + 'skip' => $skip, + 'limit' => $limit + )); + + if ($params['order'] !== '' && $params['order'] !== 'ASC' && $params['order'] !== 'DESC') { + throw new invalid_parameter_exception('Invalid order param. Must be ASC, DESC or empty.'); + } + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + $results = api::list_frameworks($safefilters, + $params['sort'], + $params['order'], + $params['skip'], + $params['limit']); + $records = array(); + foreach ($results as $result) { + $record = $result->to_record(); + array_push($records, $record); + } + return $records; + } + + /** + * Returns description of list_competency_frameworks() result value. + * + * @return external_description + */ + public static function list_competency_frameworks_returns() { + return new external_multiple_structure(self::get_competency_framework_external_structure()); + } + + /** + * Returns description of count_competency_frameworks() parameters. + * + * @return external_function_parameters + */ + public static function count_competency_frameworks_parameters() { + $filters = new external_multiple_structure(new external_single_structure( + array( + 'column' => new external_value(PARAM_ALPHANUMEXT, 'Column name to filter by'), + 'value' => new external_value(PARAM_TEXT, 'Value to filter by. Must be exact match') + ) + )); + + $params = array( + 'filters' => $filters, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_competency_frameworks_is_allowed_from_ajax() { + return true; + } + + /** + * Count the existing competency frameworks + * + * @return boolean + */ + public static function count_competency_frameworks($filters) { + $params = self::validate_parameters(self::count_competency_frameworks_parameters(), + array( + 'filters' => $filters + )); + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + return api::count_frameworks($safefilters); + } + + /** + * Returns description of count_competency_frameworks() result value. + * + * @return external_description + */ + public static function count_competency_frameworks_returns() { + return new external_value(PARAM_INT, 'The number of competency frameworks found.'); + } + + /** + * Returns description of data_for_competency_frameworks_manage_page() parameters. + * + * @return external_function_parameters + */ + public static function data_for_competency_frameworks_manage_page_parameters() { + // No params required. + $params = array(); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function data_for_competency_frameworks_manage_page_is_allowed_from_ajax() { + return true; + } + + /** + * Loads the data required to render the competency_frameworks_manage_page template. + * + * @return boolean + */ + public static function data_for_competency_frameworks_manage_page() { + global $PAGE; + + $renderable = new \tool_lp\output\manage_competency_frameworks_page(); + $renderer = $PAGE->get_renderer('tool_lp'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_competency_frameworks_manage_page() result value. + * + * @return external_description + */ + public static function data_for_competency_frameworks_manage_page_returns() { + return new external_single_structure(array ( + 'canmanage' => new external_value(PARAM_BOOL, 'True if this user has permission to manage competency frameworks'), + 'competencyframeworks' => new external_multiple_structure( + self::get_competency_framework_external_structure() + ), + 'pluginbaseurl' => new external_value(PARAM_LOCALURL, 'Url to the tool_lp plugin folder on this Moodle site'), + 'navigation' => new external_multiple_structure( + new external_value(PARAM_RAW, 'HTML for a navigation item that should be on this page') + ) + )); + + } + + /** + * Move a competency framework and adjust sort order of all affected. + * + * @return external_function_parameters + */ + public static function reorder_competency_framework_parameters() { + $from = new external_value( + PARAM_INT, + 'Framework id to reorder.', + VALUE_REQUIRED + ); + $to = new external_value( + PARAM_INT, + 'Framework id to move to.', + VALUE_REQUIRED + ); + $params = array( + 'from' => $from, + 'to' => $to + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function reorder_competency_framework_is_allowed_from_ajax() { + return true; + } + + /** + * Move this competency_framework to a new relative sort order. + * + * @param int $from + * @param int $to + * @return boolean + */ + public static function reorder_competency_framework($from, $to) { + $params = self::validate_parameters(self::reorder_competency_framework_parameters(), + array( + 'from' => $from, + 'to' => $to + )); + return api::reorder_framework($params['from'], $params['to']); + } + + /** + * Returns description of reorder_competency_framework return value. + * + * @return external_description + */ + public static function reorder_competency_framework_returns() { + return new external_value(PARAM_BOOL, 'True if this framework was moved.'); + } + + /** + * Returns the external structure of a full competency record. + * + * @return external_single_structure + */ + protected static function get_competency_external_structure() { + $id = new external_value( + PARAM_INT, + 'Database record id' + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency' + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency' + ); + $description = new external_value( + PARAM_RAW, + 'Description for the competency' + ); + $descriptionformat = new external_format_value( + 'Description format for the competency' + ); + $descriptionformatted = new external_value( + PARAM_RAW, + 'Description formatted for display' + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this competency visible?' + ); + $sortorder = new external_value( + PARAM_INT, + 'Relative sort order of this competency' + ); + $competencyframeworkid = new external_value( + PARAM_INT, + 'Competency framework id that this competency belongs to' + ); + $parentid = new external_value( + PARAM_INT, + 'Parent competency id. 0 means top level node.' + ); + $timecreated = new external_value( + PARAM_INT, + 'Timestamp this record was created' + ); + $timemodified = new external_value( + PARAM_INT, + 'Timestamp this record was modified' + ); + $usermodified = new external_value( + PARAM_INT, + 'User who modified this record last' + ); + $parentid = new external_value( + PARAM_INT, + 'The id of the parent competency.' + ); + $path = new external_value( + PARAM_RAW, + 'The path of parents all the way to the root of the tree.' + ); + + $returns = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'descriptionformatted' => $descriptionformatted, + 'visible' => $visible, + 'sortorder' => $sortorder, + 'timecreated' => $timecreated, + 'timemodified' => $timemodified, + 'usermodified' => $usermodified, + 'parentid' => $parentid, + 'competencyframeworkid' => $competencyframeworkid, + 'path' => $path, + ); + return new external_single_structure($returns); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function create_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Returns description of create_competency() parameters. + * + * @return external_function_parameters + */ + public static function create_competency_parameters() { + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency framework.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency framework.', + VALUE_DEFAULT, + '' + ); + $description = new external_value( + PARAM_RAW, + 'Optional description for the framework', + VALUE_DEFAULT, + '' + ); + $descriptionformat = new external_format_value( + 'Optional description format for the framework', + VALUE_DEFAULT, + FORMAT_HTML + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this competency visible?', + VALUE_DEFAULT, + true + ); + $competencyframeworkid = new external_value( + PARAM_INT, + 'Which competency framework does this competency belong to?' + ); + $parentid = new external_value( + PARAM_INT, + 'The parent competency. 0 means this is a top level competency.' + ); + + $params = array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + 'competencyframeworkid' => $competencyframeworkid, + 'parentid' => $parentid, + ); + return new external_function_parameters($params); + } + + /** + * Create a new competency framework + * + * @param string $shortname + * @param string $idnumber + * @param string $description + * @param int $descriptionformat + * @param bool $visible + * @param int $competencyframeworkid + * @param int $parentid + * @return string the template + */ + public static function create_competency($shortname, + $idnumber, + $description, + $descriptionformat, + $visible, + $competencyframeworkid, + $parentid) { + $params = self::validate_parameters(self::create_competency_parameters(), + array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + 'competencyframeworkid' => $competencyframeworkid, + 'parentid' => $parentid, + )); + + $params = (object) $params; + + $result = api::create_competency($params); + return $result->to_record(); + } + + /** + * Returns description of create_competency() result value. + * + * @return external_description + */ + public static function create_competency_returns() { + return self::get_competency_external_structure(); + } + + /** + * Returns description of read_competency() parameters. + * + * @return external_function_parameters + */ + public static function read_competency_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the competency', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function read_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Read a competency by id. + * + * @param int $id The id of the competency + * @return stdClass + */ + public static function read_competency($id) { + $params = self::validate_parameters(self::read_competency_parameters(), + array( + 'id' => $id, + )); + + $result = api::read_competency($params['id']); + return $result->to_record(); + } + + /** + * Returns description of read_competency() result value. + * + * @return external_description + */ + public static function read_competency_returns() { + return self::get_competency_external_structure(); + } + + /** + * Returns description of delete_competency() parameters. + * + * @return external_function_parameters + */ + public static function delete_competency_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the competency', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function delete_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Delete a competency + * + * @param int $id The competency id + * @return boolean + */ + public static function delete_competency($id) { + $params = self::validate_parameters(self::delete_competency_parameters(), + array( + 'id' => $id, + )); + + return api::delete_competency($params['id']); + } + + /** + * Returns description of delete_competency() result value. + * + * @return external_description + */ + public static function delete_competency_returns() { + return new external_value(PARAM_BOOL, 'True if the delete was successful'); + } + + /** + * Returns description of update_competency() parameters. + * + * @return external_function_parameters + */ + public static function update_competency_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the competency', + VALUE_REQUIRED + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the competency.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this competency.', + VALUE_REQUIRED + ); + $description = new external_value( + PARAM_RAW, + 'Description for the framework', + VALUE_REQUIRED + ); + $descriptionformat = new external_format_value( + 'Description format for the framework', + VALUE_REQUIRED + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this framework visible?', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function update_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Update an existing competency + * + * @param int $id The competency id + * @param string $shortname + * @param string $idnumber + * @param string $description + * @param int $descriptionformat + * @param boolean $visible + * @return boolean + */ + public static function update_competency($id, + $shortname, + $idnumber, + $description, + $descriptionformat, + $visible) { + + $params = self::validate_parameters(self::update_competency_parameters(), + array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible + )); + $params = (object) $params; + + return api::update_competency($params); + } + + /** + * Returns description of update_competency_framework() result value. + * + * @return external_description + */ + public static function update_competency_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of list_competencies() parameters. + * + * @return external_function_parameters + */ + public static function list_competencies_parameters() { + return self::list_parameters_structure(); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_competencies_is_allowed_from_ajax() { + return true; + } + + /** + * List the existing competency frameworks + * + * @return boolean + */ + public static function list_competencies($filters, $sort, $order, $skip, $limit) { + $params = self::validate_parameters(self::list_competencies_parameters(), + array( + 'filters' => $filters, + 'sort' => $sort, + 'order' => $order, + 'skip' => $skip, + 'limit' => $limit + )); + + if ($params['order'] !== '' && $params['order'] !== 'ASC' && $params['order'] !== 'DESC') { + throw new invalid_parameter_exception('Invalid order param. Must be ASC, DESC or empty.'); + } + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible', 'parentid', 'competencyframeworkid'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + $results = api::list_competencies($safefilters, + $params['sort'], + $params['order'], + $params['skip'], + $params['limit']); + $records = array(); + foreach ($results as $result) { + $record = $result->to_record(); + array_push($records, $record); + } + return $records; + } + + /** + * Returns description of list_competencies() result value. + * + * @return external_description + */ + public static function list_competencies_returns() { + return new external_multiple_structure(self::get_competency_external_structure()); + } + + /** + * Returns description of search_competencies() parameters. + * + * @return external_function_parameters + */ + public static function search_competencies_parameters() { + $searchtext = new external_value( + PARAM_RAW, + 'Text to search for', + VALUE_REQUIRED + ); + $frameworkid = new external_value( + PARAM_INT, + 'Competency framework id', + VALUE_REQUIRED + ); + + $params = array( + 'searchtext' => $searchtext, + 'competencyframeworkid' => $frameworkid + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function search_competencies_is_allowed_from_ajax() { + return true; + } + + /** + * List the existing competency frameworks + * + * @return boolean + */ + public static function search_competencies($searchtext, $competencyframeworkid) { + $params = self::validate_parameters(self::search_competencies_parameters(), + array( + 'searchtext' => $searchtext, + 'competencyframeworkid' => $competencyframeworkid + )); + + $results = api::search_competencies($searchtext, $competencyframeworkid); + $records = array(); + foreach ($results as $result) { + $record = $result->to_record(); + array_push($records, $record); + } + return $records; + } + + /** + * Returns description of search_competencies() result value. + * + * @return external_description + */ + public static function search_competencies_returns() { + return new external_multiple_structure(self::get_competency_external_structure()); + } + + + /** + * Returns description of count_competencies() parameters. + * + * @return external_function_parameters + */ + public static function count_competencies_parameters() { + return self::count_parameters_structure(); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_competencies_is_allowed_from_ajax() { + return true; + } + + /** + * Count the existing competency frameworks + * + * @return boolean + */ + public static function count_competencies($filters) { + $params = self::validate_parameters(self::count_competencies_parameters(), + array( + 'filters' => $filters + )); + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible', 'parentid', 'competencyframeworkid'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + return api::count_competencies($safefilters); + } + + /** + * Returns description of count_competencies() result value. + * + * @return external_description + */ + public static function count_competencies_returns() { + return new external_value(PARAM_INT, 'The number of competencies found.'); + } + + /** + * Returns description of data_for_competencies_manage_page() parameters. + * + * @return external_function_parameters + */ + public static function data_for_competencies_manage_page_parameters() { + $competencyframeworkid = new external_value( + PARAM_INT, + 'The competency framework id', + VALUE_REQUIRED + ); + $search = new external_value( + PARAM_RAW, + 'A search string', + VALUE_DEFAULT, + '' + ); + $params = array( + 'competencyframeworkid' => $competencyframeworkid, + 'search' => $search + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function data_for_competencies_manage_page_is_allowed_from_ajax() { + return true; + } + + /** + * Loads the data required to render the competencies_manage_page template. + * + * @return boolean + */ + public static function data_for_competencies_manage_page($competencyframeworkid, $search) { + global $PAGE; + $params = self::validate_parameters(self::data_for_competencies_manage_page_parameters(), + array( + 'competencyframeworkid' => $competencyframeworkid, + 'search' => $search + )); + + $framework = new \tool_lp\competency_framework($params['competencyframeworkid']); + + $renderable = new \tool_lp\output\manage_competencies_page($framework, $params['search']); + $renderer = $PAGE->get_renderer('tool_lp'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_competencies_manage_page() result value. + * + * @return external_description + */ + public static function data_for_competencies_manage_page_returns() { + return new external_single_structure(array ( + 'framework' => self::get_competency_framework_external_structure(), + 'canmanage' => new external_value(PARAM_BOOL, 'True if this user has permission to manage competency frameworks'), + 'competencies' => new external_multiple_structure( + self::get_competency_external_structure() + ) + )); + + } + + /** + * Returns description of set_parent_competency() parameters. + * + * @return external_function_parameters + */ + public static function set_parent_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $parentid = new external_value( + PARAM_INT, + 'The new competency parent id', + VALUE_REQUIRED + ); + $params = array( + 'competencyid' => $competencyid, + 'parentid' => $parentid + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function set_parent_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Move the competency to a new parent. + * + * @return boolean + */ + public static function set_parent_competency($competencyid, $parentid) { + global $PAGE; + $params = self::validate_parameters(self::set_parent_competency_parameters(), + array( + 'competencyid' => $competencyid, + 'parentid' => $parentid + )); + + return api::set_parent_competency($competencyid, $parentid); + } + + /** + * Returns description of set_parent_competency() result value. + * + * @return external_description + */ + public static function set_parent_competency_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of move_up_competency() parameters. + * + * @return external_function_parameters + */ + public static function move_up_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function move_up_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Change the sort order of a competency. + * + * @return boolean + */ + public static function move_up_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::move_up_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::move_up_competency($params['id']); + } + + /** + * Returns description of move_up_competency() result value. + * + * @return external_description + */ + public static function move_up_competency_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of move_down_competency() parameters. + * + * @return external_function_parameters + */ + public static function move_down_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function move_down_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Change the sort order of a competency. + * + * @return boolean + */ + public static function move_down_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::move_down_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::move_down_competency($params['id']); + } + + /** + * Returns description of move_down_competency() result value. + * + * @return external_description + */ + public static function move_down_competency_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of count_courses_using_competency() parameters. + * + * @return external_function_parameters + */ + public static function count_courses_using_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_courses_using_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Count the courses (visible to this user) that use this competency. + * + * @return int + */ + public static function count_courses_using_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::count_courses_using_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::count_courses_using_competency($params['id']); + } + + /** + * Returns description of count_courses_using_competency() result value. + * + * @return external_description + */ + public static function count_courses_using_competency_returns() { + return new external_value(PARAM_INT, 'The number of courses using this competency'); + } + + /** + * Returns description of list_courses_using_competency() parameters. + * + * @return external_function_parameters + */ + public static function list_courses_using_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_courses_using_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Count the courses (visible to this user) that use this competency. + * + * @return array + */ + public static function list_courses_using_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::list_courses_using_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::list_courses_using_competency($params['id']); + } + + /** + * Returns description of list_courses_using_competency() result value. + * + * @return external_description + */ + public static function list_courses_using_competency_returns() { + $id = new external_value( + PARAM_INT, + 'Course id' + ); + $visible = new external_value( + PARAM_BOOL, + 'Is the course visible.' + ); + $idnumber = new external_value( + PARAM_TEXT, + 'Course id number' + ); + $shortname = new external_value( + PARAM_TEXT, + 'Course short name' + ); + $shortnameformatted = new external_value( + PARAM_RAW, + 'Shortname that has been formatted for display' + ); + $fullname = new external_value( + PARAM_TEXT, + 'Course fullname' + ); + $fullnameformatted = new external_value( + PARAM_RAW, + 'Fullname that has been formatted for display' + ); + + $returns = array( + 'id' => $id, + 'shortname' => $shortname, + 'shortnameformatted' => $shortnameformatted, + 'idnumber' => $idnumber, + 'fullname' => $fullname, + 'fullnameformatted' => $fullnameformatted, + 'visible' => $visible + ); + return new external_multiple_structure(new external_single_structure($returns)); + } + + /** + * Returns description of count_competencies_in_course() parameters. + * + * @return external_function_parameters + */ + public static function count_competencies_in_course_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $courseid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_competencies_in_course_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this course. + * + * @param int $couseid The course id to check. + * @return int + */ + public static function count_competencies_in_course($courseid) { + global $PAGE; + $params = self::validate_parameters(self::count_competencies_in_course_parameters(), + array( + 'id' => $courseid, + )); + + return api::count_competencies_in_course($params['id']); + } + + /** + * Returns description of count_competencies_in_course() result value. + * + * @return external_description + */ + public static function count_competencies_in_course_returns() { + return new external_value(PARAM_INT, 'The number of competencies in this course.'); + } + + /** + * Returns description of list_competencies_in_course() parameters. + * + * @return external_function_parameters + */ + public static function list_competencies_in_course_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $courseid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_competencies_in_course_is_allowed_from_ajax() { + return true; + } + + /** + * List the competencies (visible to this user) in this course. + * + * @return array + */ + public static function list_competencies_in_course($courseid) { + global $PAGE; + $params = self::validate_parameters(self::list_competencies_in_course_parameters(), + array( + 'id' => $courseid, + )); + + $competencies = api::list_competencies_in_course($params['id']); + $results = array(); + foreach ($competencies as $competency) { + $record = $competency->to_record(); + array_push($results, $record); + } + return $results; + } + + /** + * Returns description of list_competencies_in_course() result value. + * + * @return external_description + */ + public static function list_competencies_in_course_returns() { + return new external_multiple_structure(self::get_competency_external_structure()); + } + + /** + * Returns description of add_competency_to_course() parameters. + * + * @return external_function_parameters + */ + public static function add_competency_to_course_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'courseid' => $courseid, + 'competencyid' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function add_competency_to_course_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this course. + * + * @return int + */ + public static function add_competency_to_course($courseid, $competencyid) { + global $PAGE; + $params = self::validate_parameters(self::add_competency_to_course_parameters(), + array( + 'courseid' => $courseid, + 'competencyid' => $competencyid, + )); + + return api::add_competency_to_course($params['courseid'], $params['competencyid']); + } + + /** + * Returns description of add_competency_to_course() result value. + * + * @return external_description + */ + public static function add_competency_to_course_returns() { + return new external_value(PARAM_BOOL, 'True if successful.'); + } + + /** + * Returns description of remove_competency_from_course() parameters. + * + * @return external_function_parameters + */ + public static function remove_competency_from_course_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'courseid' => $courseid, + 'competencyid' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function remove_competency_from_course_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this course. + * + * @return int + */ + public static function remove_competency_from_course($courseid, $competencyid) { + $params = self::validate_parameters(self::remove_competency_from_course_parameters(), + array( + 'courseid' => $courseid, + 'competencyid' => $competencyid, + )); + + return api::remove_competency_from_course($params['courseid'], $params['competencyid']); + } + + /** + * Returns description of remove_competency_from_course() result value. + * + * @return external_description + */ + public static function remove_competency_from_course_returns() { + return new external_value(PARAM_BOOL, 'True if successful.'); + } + + /** + * Returns description of data_for_course_competenies_page() parameters. + * + * @return external_function_parameters + */ + public static function data_for_course_competencies_page_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $params = array('courseid' => $courseid); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function data_for_course_competencies_page_is_allowed_from_ajax() { + return true; + } + + /** + * Loads the data required to render the course_competencies_page template. + * + * @return boolean + */ + public static function data_for_course_competencies_page($courseid) { + global $PAGE; + $params = self::validate_parameters(self::data_for_course_competencies_page_parameters(), + array( + 'courseid' => $courseid, + )); + + $renderable = new \tool_lp\output\course_competencies_page($params['courseid']); + $renderer = $PAGE->get_renderer('tool_lp'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_course_competencies_page() result value. + * + * @return external_description + */ + public static function data_for_course_competencies_page_returns() { + return new external_single_structure(array ( + 'courseid' => new external_value(PARAM_INT, 'The current course id'), + 'canmanagecompetencyframeworks' => new external_value(PARAM_BOOL, 'User can manage competency frameworks'), + 'canmanagecoursecompetencies' => new external_value(PARAM_BOOL, 'User can manage linked course competencies'), + 'competencies' => new external_multiple_structure( + self::get_competency_external_structure() + ), + 'manageurl' => new external_value(PARAM_LOCALURL, 'Url to the manage competencies page.'), + )); + + } + + /** + * Returns description of reorder_course_competency() parameters. + * + * @return external_function_parameters + */ + public static function reorder_course_competency_parameters() { + $courseid = new external_value( + PARAM_INT, + 'The course id', + VALUE_REQUIRED + ); + $competencyidfrom = new external_value( + PARAM_INT, + 'The competency id we are moving', + VALUE_REQUIRED + ); + $competencyidto = new external_value( + PARAM_INT, + 'The competency id we are moving to', + VALUE_REQUIRED + ); + $params = array( + 'courseid' => $courseid, + 'competencyidfrom' => $competencyidfrom, + 'competencyidto' => $competencyidto, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function reorder_course_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Change the order of course competencies. + * + * @param int $courseid The course id + * @param int $competencyidfrom The competency to move. + * @param int $competencyidto The competency to move to. + * @return bool + */ + public static function reorder_course_competency($courseid, $competencyidfrom, $competencyidto) { + $params = self::validate_parameters(self::reorder_course_competency_parameters(), + array( + 'courseid' => $courseid, + 'competencyidfrom' => $competencyidfrom, + 'competencyidto' => $competencyidto, + )); + + return api::reorder_course_competency($params['courseid'], $params['competencyidfrom'], $params['competencyidto']); + } + + /** + * Returns description of reorder_course_competency() result value. + * + * @return external_description + */ + public static function reorder_course_competency_returns() { + return new external_value(PARAM_BOOL, 'True if successful.'); + } + + /** + * Returns the external structure of a full template record. + * + * @return external_single_structure + */ + protected static function get_template_external_structure() { + $id = new external_value( + PARAM_INT, + 'Database record id' + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the learning plan template' + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this learning plan template' + ); + $duedate = new external_value( + PARAM_INT, + 'The default due date for instances of this plan.' + ); + $duedateformatted = new external_value( + PARAM_RAW, + 'Due date that has been formatted for display' + ); + $description = new external_value( + PARAM_RAW, + 'Description for the template' + ); + $descriptionformat = new external_format_value( + 'Description format for the template' + ); + $descriptionformatted = new external_value( + PARAM_RAW, + 'Description that has been formatted for display' + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this template visible?' + ); + $sortorder = new external_value( + PARAM_INT, + 'Relative sort order of this template' + ); + $timecreated = new external_value( + PARAM_INT, + 'Timestamp this record was created' + ); + $timemodified = new external_value( + PARAM_INT, + 'Timestamp this record was modified' + ); + $usermodified = new external_value( + PARAM_INT, + 'User who modified this record last' + ); + + $returns = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'descriptionformatted' => $descriptionformatted, + 'visible' => $visible, + 'sortorder' => $sortorder, + 'timecreated' => $timecreated, + 'timemodified' => $timemodified, + 'usermodified' => $usermodified, + ); + return new external_single_structure($returns); + } + + /** + * Returns description of create_template() parameters. + * + * @return external_function_parameters + */ + public static function create_template_parameters() { + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the learning plan template.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this learning plan template.', + VALUE_DEFAULT, + '' + ); + $duedate = new external_value( + PARAM_INT, + 'The default due date for instances of this plan', + VALUE_DEFAULT, + 0 + ); + $description = new external_value( + PARAM_RAW, + 'Optional description for the learning plan template', + VALUE_DEFAULT, + '' + ); + $descriptionformat = new external_format_value( + 'Optional description format for the learning plan template', + VALUE_DEFAULT, + FORMAT_HTML + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this learning plan template visible?', + VALUE_DEFAULT, + true + ); + + $params = array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'duedate' => $duedate, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function create_template_is_allowed_from_ajax() { + return true; + } + + /** + * Create a new learning plan template + * + * @param string $shortname The short name of the template. + * @param string $idnumber The idnumber of the template. + * @param int $duedate The due date for instances of this plan. + * @param string $description The description of the template. + * @param int $descriptionformat The format of the description + * @param bool $visible Is this template visible. + * @return stdClass Record of new template. + */ + public static function create_template($shortname, $idnumber, $description, $descriptionformat, $visible) { + $params = self::validate_parameters(self::create_template_parameters(), + array( + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'duedate' => $duedate, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + )); + + $params = (object) $params; + + $result = api::create_template($params); + return $result->to_record(); + } + + /** + * Returns description of create_template() result value. + * + * @return external_description + */ + public static function create_template_returns() { + return self::get_template_external_structure(); + } + + /** + * Returns description of read_template() parameters. + * + * @return external_function_parameters + */ + public static function read_template_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the template', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function read_template_is_allowed_from_ajax() { + return true; + } + + /** + * Read a learning plan template by id. + * + * @param int $id The id of the template. + * @return stdClass + */ + public static function read_template($id) { + $params = self::validate_parameters(self::read_template_parameters(), + array( + 'id' => $id, + )); + + $result = api::read_template($params['id']); + return $result->to_record(); + } + + /** + * Returns description of read_template() result value. + * + * @return external_description + */ + public static function read_template_returns() { + return self::get_template_external_structure(); + } + + /** + * Returns description of delete_template() parameters. + * + * @return external_function_parameters + */ + public static function delete_template_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the template', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function delete_template_is_allowed_from_ajax() { + return true; + } + + /** + * Delete a learning plan template + * + * @param int $id The learning plan template id + * @return boolean + */ + public static function delete_template($id) { + $params = self::validate_parameters(self::delete_template_parameters(), + array( + 'id' => $id, + )); + + return api::delete_template($params['id']); + } + + /** + * Returns description of delete_template() result value. + * + * @return external_description + */ + public static function delete_template_returns() { + return new external_value(PARAM_BOOL, 'True if the delete was successful'); + } + + /** + * Returns description of update_template() parameters. + * + * @return external_function_parameters + */ + public static function update_template_parameters() { + $id = new external_value( + PARAM_INT, + 'Data base record id for the template', + VALUE_REQUIRED + ); + $shortname = new external_value( + PARAM_TEXT, + 'Short name for the learning plan template.', + VALUE_REQUIRED + ); + $idnumber = new external_value( + PARAM_TEXT, + 'If provided, must be a unique string to identify this learning plan template.', + VALUE_REQUIRED + ); + $duedate = new external_value( + PARAM_INT, + 'Default due date for instances of this plan', + VALUE_REQUIRED + ); + $description = new external_value( + PARAM_RAW, + 'Description for the template', + VALUE_REQUIRED + ); + $descriptionformat = new external_format_value( + 'Description format for the template', + VALUE_REQUIRED + ); + $visible = new external_value( + PARAM_BOOL, + 'Is this template visible?', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'duedate' => $duedate, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function update_template_is_allowed_from_ajax() { + return true; + } + + /** + * Update an existing learning plan template + * + * @param int $id The learning plan template id + * @param string $shortname + * @param string $idnumber + * @param int $duedate + * @param string $description + * @param int $descriptionformat + * @param boolean $visible + * @return boolean + */ + public static function update_template($id, + $shortname, + $idnumber, + $duedate, + $description, + $descriptionformat, + $visible) { + + $params = self::validate_parameters(self::update_template_parameters(), + array( + 'id' => $id, + 'shortname' => $shortname, + 'idnumber' => $idnumber, + 'duedate' => $duedate, + 'description' => $description, + 'descriptionformat' => $descriptionformat, + 'visible' => $visible + )); + $params = (object) $params; + + return api::update_template($params); + } + + /** + * Returns description of update_template() result value. + * + * @return external_description + */ + public static function update_template_returns() { + return new external_value(PARAM_BOOL, 'True if the update was successful'); + } + + /** + * Returns description of list_templates() parameters. + * + * @return external_function_parameters + */ + public static function list_templates_parameters() { + return self::list_parameters_structure(); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_templates_is_allowed_from_ajax() { + return true; + } + + /** + * List the existing learning plan templates + * + * @return boolean + */ + public static function list_templates($filters, $sort, $order, $skip, $limit) { + $params = self::validate_parameters(self::list_templates_parameters(), + array( + 'filters' => $filters, + 'sort' => $sort, + 'order' => $order, + 'skip' => $skip, + 'limit' => $limit + )); + + if ($params['order'] !== '' && $params['order'] !== 'ASC' && $params['order'] !== 'DESC') { + throw new invalid_parameter_exception('Invalid order param. Must be ASC, DESC or empty.'); + } + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + $results = api::list_templates($safefilters, + $params['sort'], + $params['order'], + $params['skip'], + $params['limit']); + $records = array(); + foreach ($results as $result) { + $record = $result->to_record(); + array_push($records, $record); + } + return $records; + } + + /** + * Returns description of list_templates() result value. + * + * @return external_description + */ + public static function list_templates_returns() { + return new external_multiple_structure(self::get_template_external_structure()); + } + + /** + * Returns description of count_templates() parameters. + * + * @return external_function_parameters + */ + public static function count_templates_parameters() { + $filters = new external_multiple_structure(new external_single_structure( + array( + 'column' => new external_value(PARAM_ALPHANUMEXT, 'Column name to filter by'), + 'value' => new external_value(PARAM_TEXT, 'Value to filter by. Must be exact match') + ) + )); + + $params = array( + 'filters' => $filters, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_templates_is_allowed_from_ajax() { + return true; + } + + /** + * Count the existing learning plan templates + * + * @return boolean + */ + public static function count_templates($filters) { + $params = self::validate_parameters(self::count_templates_parameters(), + array( + 'filters' => $filters + )); + + $safefilters = array(); + $validcolumns = array('id', 'shortname', 'description', 'sortorder', 'idnumber', 'visible'); + foreach ($params['filters'] as $filter) { + if (!in_array($filter->column, $validcolumns)) { + throw new invalid_parameter_exception('Filter column was invalid'); + } + $safefilters[$filter->column] = $filter->value; + } + + return api::count_templates($safefilters); + } + + /** + * Returns description of count_templates() result value. + * + * @return external_description + */ + public static function count_templates_returns() { + return new external_value(PARAM_INT, 'The number of learning plan templates found.'); + } + + /** + * Move a learning plan template and adjust sort order of all affected. + * + * @return external_function_parameters + */ + public static function reorder_template_parameters() { + $from = new external_value( + PARAM_INT, + 'Template id to reorder.', + VALUE_REQUIRED + ); + $to = new external_value( + PARAM_INT, + 'Template id to move to.', + VALUE_REQUIRED + ); + $params = array( + 'from' => $from, + 'to' => $to + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function reorder_template_is_allowed_from_ajax() { + return true; + } + + /** + * Move this template to a new relative sort order. + * + * @param int $from + * @param int $to + * @return boolean + */ + public static function reorder_template($from, $to) { + $params = self::validate_parameters(self::reorder_template_parameters(), + array( + 'from' => $from, + 'to' => $to + )); + return api::reorder_template($params['from'], $params['to']); + } + + /** + * Returns description of reorder_template return value. + * + * @return external_description + */ + public static function reorder_template_returns() { + return new external_value(PARAM_BOOL, 'True if this template was moved.'); + } + + /** + * Returns description of data_for_templates_manage_page() parameters. + * + * @return external_function_parameters + */ + public static function data_for_templates_manage_page_parameters() { + // No params required. + $params = array(); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function data_for_templates_manage_page_is_allowed_from_ajax() { + return true; + } + + /** + * Loads the data required to render the templates_manage_page template. + * + * @return boolean + */ + public static function data_for_templates_manage_page() { + global $PAGE; + + $renderable = new \tool_lp\output\manage_templates_page(); + $renderer = $PAGE->get_renderer('tool_lp'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_templates_manage_page() result value. + * + * @return external_description + */ + public static function data_for_templates_manage_page_returns() { + return new external_single_structure(array ( + 'canmanage' => new external_value(PARAM_BOOL, 'True if this user has permission to manage learning plan templates'), + 'templates' => new external_multiple_structure( + self::get_template_external_structure() + ), + 'pluginbaseurl' => new external_value(PARAM_LOCALURL, 'Url to the tool_lp plugin folder on this Moodle site'), + 'navigation' => new external_multiple_structure( + new external_value(PARAM_RAW, 'HTML for a navigation item that should be on this page') + ) + )); + + } + + /** + * Returns description of count_templates_using_competency() parameters. + * + * @return external_function_parameters + */ + public static function count_templates_using_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_templates_using_competency_is_allowed_from_ajax() { + return true; + } + + /** + * Count the learning plan templates (visible to this user) that use this competency. + * + * @return int + */ + public static function count_templates_using_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::count_templates_using_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::count_templates_using_competency($params['id']); + } + + /** + * Returns description of count_templates_using_competency() result value. + * + * @return external_description + */ + public static function count_templates_using_competency_returns() { + return new external_value(PARAM_INT, 'The number of learning plan templates using this competency'); + } + + /** + * Returns description of list_templates_using_competency() parameters. + * + * @return external_function_parameters + */ + public static function list_templates_using_competency_parameters() { + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_templates_using_competency_is_allowed_from_ajax() { + return true; + } + + /** + * List the learning plan templates (visible to this user) that use this competency. + * + * @return array + */ + public static function list_templates_using_competency($competencyid) { + global $PAGE; + $params = self::validate_parameters(self::list_templates_using_competency_parameters(), + array( + 'id' => $competencyid, + )); + + return api::list_templates_using_competency($params['id']); + } + + /** + * Returns description of list_templates_using_competency() result value. + * + * @return external_description + */ + public static function list_templates_using_competency_returns() { + return new external_multiple_structure(self::get_template_external_structure()); + } + + /** + * Returns description of count_competencies_in_template() parameters. + * + * @return external_function_parameters + */ + public static function count_competencies_in_template_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $templateid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function count_competencies_in_template_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this learning plan template. + * + * @param int $templateid The template id to check + * @return int + */ + public static function count_competencies_in_template($templateid) { + global $PAGE; + $params = self::validate_parameters(self::count_competencies_in_template_parameters(), + array( + 'id' => $templateid, + )); + + return api::count_competencies_in_template($params['id']); + } + + /** + * Returns description of count_competencies_in_template() result value. + * + * @return external_description + */ + public static function count_competencies_in_template_returns() { + return new external_value(PARAM_INT, 'The number of competencies in this learning plan template.'); + } + + /** + * Returns description of list_competencies_in_template() parameters. + * + * @return external_function_parameters + */ + public static function list_competencies_in_template_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + $params = array( + 'id' => $courseid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function list_competencies_in_template_is_allowed_from_ajax() { + return true; + } + + /** + * List the competencies (visible to this user) in this learning plan template. + * + * @return array + */ + public static function list_competencies_in_template($templateid) { + global $PAGE; + $params = self::validate_parameters(self::list_competencies_in_template_parameters(), + array( + 'id' => $templateid, + )); + + $competencies = api::list_competencies_in_template($params['id']); + $results = array(); + foreach ($competencies as $competency) { + $record = $competency->to_record(); + array_push($results, $record); + } + return $results; + } + + /** + * Returns description of list_competencies_in_template() result value. + * + * @return external_description + */ + public static function list_competencies_in_template_returns() { + return new external_multiple_structure(self::get_competency_external_structure()); + } + + /** + * Returns description of add_competency_to_template() parameters. + * + * @return external_function_parameters + */ + public static function add_competency_to_template_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'templateid' => $templateid, + 'competencyid' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function add_competency_to_template_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this template. + * + * @return int + */ + public static function add_competency_to_template($templateid, $competencyid) { + global $PAGE; + $params = self::validate_parameters(self::add_competency_to_template_parameters(), + array( + 'templateid' => $templateid, + 'competencyid' => $competencyid, + )); + + return api::add_competency_to_template($params['templateid'], $params['competencyid']); + } + + /** + * Returns description of add_competency_to_template() result value. + * + * @return external_description + */ + public static function add_competency_to_template_returns() { + return new external_value(PARAM_BOOL, 'True if successful.'); + } + + /** + * Returns description of remove_competency_from_template() parameters. + * + * @return external_function_parameters + */ + public static function remove_competency_from_template_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + $competencyid = new external_value( + PARAM_INT, + 'The competency id', + VALUE_REQUIRED + ); + $params = array( + 'templateid' => $templateid, + 'competencyid' => $competencyid, + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function remove_competency_from_template_is_allowed_from_ajax() { + return true; + } + + /** + * Count the competencies (visible to this user) in this learning plan template. + * + * @return int + */ + public static function remove_competency_from_template($templateid, $competencyid) { + $params = self::validate_parameters(self::remove_competency_from_template_parameters(), + array( + 'templateid' => $templateid, + 'competencyid' => $competencyid, + )); + + return api::remove_competency_from_template($params['templateid'], $params['competencyid']); + } + + /** + * Returns description of remove_competency_from_template() result value. + * + * @return external_description + */ + public static function remove_competency_from_template_returns() { + return new external_value(PARAM_BOOL, 'True if successful.'); + } + + /** + * Returns description of data_for_template_competenies_page() parameters. + * + * @return external_function_parameters + */ + public static function data_for_template_competencies_page_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + $params = array('templateid' => $templateid); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX + * @return boolean + */ + public static function data_for_template_competencies_page_is_allowed_from_ajax() { + return true; + } + + /** + * Loads the data required to render the template_competencies_page template. + * + * @return boolean + */ + public static function data_for_template_competencies_page($templateid) { + global $PAGE; + $params = self::validate_parameters(self::data_for_template_competencies_page_parameters(), + array( + 'templateid' => $templateid, + )); + + $renderable = new \tool_lp\output\template_competencies_page($params['templateid']); + $renderer = $PAGE->get_renderer('tool_lp'); + + $data = $renderable->export_for_template($renderer); + + return $data; + } + + /** + * Returns description of data_for_template_competencies_page() result value. + * + * @return external_description + */ + public static function data_for_template_competencies_page_returns() { + return new external_single_structure(array ( + 'templateid' => new external_value(PARAM_INT, 'The current template id'), + 'canmanagecompetencyframeworks' => new external_value(PARAM_BOOL, 'User can manage competency frameworks'), + 'canmanagetemplates' => new external_value(PARAM_BOOL, 'User can manage learning plan templates'), + 'competencies' => new external_multiple_structure( + self::get_competency_external_structure() + ), + 'manageurl' => new external_value(PARAM_LOCALURL, 'Url to the manage competencies page.'), + )); + + } +} diff --git a/admin/tool/lp/classes/form/competency.php b/admin/tool/lp/classes/form/competency.php new file mode 100644 index 00000000000..3f7224b8da0 --- /dev/null +++ b/admin/tool/lp/classes/form/competency.php @@ -0,0 +1,107 @@ +. + +/** + * This file contains the form add/update a competency framework. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_lp\form; + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + +use moodleform; +use tool_lp\api; + +require_once($CFG->libdir.'/formslib.php'); + +/** + * Competency framework form. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class competency extends moodleform { + + /** + * Define the form - called by parent constructor + */ + public function definition() { + $mform = $this->_form; + $id = $this->_customdata['id']; + $framework = $this->_customdata['competencyframework']; + $parent = $this->_customdata['parent']; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + $mform->setDefault('id', 0); + + $mform->addElement('hidden', 'parentid'); + $mform->setType('parentid', PARAM_INT); + if ($parent) { + $mform->setDefault('parentid', $parent->get_id()); + } else { + $mform->setDefault('parentid', 0); + } + + $mform->addElement('hidden', 'competencyframeworkid'); + $mform->setType('competencyframeworkid', PARAM_INT); + $mform->setDefault('competencyframeworkid', $framework->get_id()); + + $mform->addElement('static', + 'frameworkdesc', + get_string('competencyframework', 'tool_lp'), + s($framework->get_shortname())); + if ($parent) { + $mform->addElement('static', + 'parentdesc', + get_string('parentcompetency', 'tool_lp'), + s($parent->get_shortname())); + } + + $mform->addElement('text', 'shortname', + get_string('shortname', 'tool_lp')); + $mform->setType('shortname', PARAM_TEXT); + $mform->addRule('shortname', null, 'required', null, 'client'); + $mform->addElement('editor', 'description', + get_string('description', 'tool_lp'), array('rows'=>4)); + $mform->setType('description', PARAM_TEXT); + $mform->addElement('text', 'idnumber', + get_string('idnumber', 'tool_lp')); + $mform->setType('idnumber', PARAM_TEXT); + $mform->addElement('selectyesno', 'visible', + get_string('visible', 'tool_lp')); + $mform->setDefault('visible', true); + $mform->addHelpButton('visible', 'visible', 'tool_lp'); + + $this->add_action_buttons(true, get_string('savechanges', 'tool_lp')); + + if (!empty($id)) { + if (!$this->is_submitted()) { + $competency = api::read_competency($id); + $record = $competency->to_record(); + // Massage for editor API. + $record->description = array('text'=>$record->description, 'format'=>$record->descriptionformat); + $this->set_data($record); + } + } + + } +} diff --git a/admin/tool/lp/classes/form/competency_framework.php b/admin/tool/lp/classes/form/competency_framework.php new file mode 100644 index 00000000000..203ae2708c2 --- /dev/null +++ b/admin/tool/lp/classes/form/competency_framework.php @@ -0,0 +1,82 @@ +. + +/** + * This file contains the form add/update a competency framework. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_lp\form; + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + +use moodleform; +use tool_lp\api; + +require_once($CFG->libdir.'/formslib.php'); + +/** + * Competency framework form. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class competency_framework extends moodleform { + + /** + * Define the form - called by parent constructor + */ + public function definition() { + $mform = $this->_form; + $id = $this->_customdata; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + $mform->setDefault('id', 0); + + $mform->addElement('text', 'shortname', + get_string('shortname', 'tool_lp')); + $mform->setType('shortname', PARAM_TEXT); + $mform->addRule('shortname', null, 'required', null, 'client'); + $mform->addElement('editor', 'description', + get_string('description', 'tool_lp'), array('rows'=>4)); + $mform->setType('description', PARAM_TEXT); + $mform->addElement('text', 'idnumber', + get_string('idnumber', 'tool_lp')); + $mform->setType('idnumber', PARAM_TEXT); + $mform->addElement('selectyesno', 'visible', + get_string('visible', 'tool_lp')); + $mform->setDefault('visible', true); + $mform->addHelpButton('visible', 'visible', 'tool_lp'); + + $this->add_action_buttons(true, get_string('savechanges', 'tool_lp')); + + if (!empty($id)) { + if (!$this->is_submitted()) { + $framework = api::read_framework($id); + $record = $framework->to_record(); + // Massage for editor API. + $record->description = array('text'=>$record->description, 'format'=>$record->descriptionformat); + $this->set_data($record); + } + } + + } +} diff --git a/admin/tool/lp/classes/form/template.php b/admin/tool/lp/classes/form/template.php new file mode 100644 index 00000000000..dd951523868 --- /dev/null +++ b/admin/tool/lp/classes/form/template.php @@ -0,0 +1,88 @@ +. + +/** + * This file contains the form add/update a competency framework. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_lp\form; + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + +use moodleform; +use tool_lp\api; + +require_once($CFG->libdir.'/formslib.php'); + +/** + * Learning plan template form. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template extends moodleform { + + /** + * Define the form - called by parent constructor + */ + public function definition() { + $mform = $this->_form; + $id = $this->_customdata; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + $mform->setDefault('id', 0); + + $mform->addElement('text', 'shortname', + get_string('shortname', 'tool_lp')); + $mform->setType('shortname', PARAM_TEXT); + $mform->addRule('shortname', null, 'required', null, 'client'); + $mform->addElement('editor', 'description', + get_string('description', 'tool_lp'), array('rows'=>4)); + $mform->setType('description', PARAM_TEXT); + $mform->addElement('text', 'idnumber', + get_string('idnumber', 'tool_lp')); + $mform->setType('idnumber', PARAM_TEXT); + $mform->addElement('selectyesno', 'visible', + get_string('visible', 'tool_lp')); + $mform->addElement('date_time_selector', + 'duedate', + get_string('duedate', 'tool_lp'), + array('optional'=>true)); + $mform->addHelpButton('duedate', 'duedate', 'tool_lp'); + + $mform->setDefault('visible', true); + $mform->addHelpButton('visible', 'visible', 'tool_lp'); + + $this->add_action_buttons(true, get_string('savechanges', 'tool_lp')); + + if (!empty($id)) { + if (!$this->is_submitted()) { + $template = api::read_template($id); + $record = $template->to_record(); + // Massage for editor API. + $record->description = array('text'=>$record->description, 'format'=>$record->descriptionformat); + $this->set_data($record); + } + } + + } +} diff --git a/admin/tool/lp/classes/output/course_competencies_page.php b/admin/tool/lp/classes/output/course_competencies_page.php new file mode 100644 index 00000000000..0532eac62e4 --- /dev/null +++ b/admin/tool/lp/classes/output/course_competencies_page.php @@ -0,0 +1,78 @@ +. + +/** + * Class containing data for course competencies page + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\output; + +use renderable; +use templatable; +use renderer_base; +use stdClass; +use moodle_url; +use context_system; +use context_course; +use tool_lp\api; + +/** + * Class containing data for course competencies page + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_competencies_page implements renderable, templatable { + + /** @var stdClass $course Course record for this page. */ + var $course = null; + + /** + * Construct this renderable. + * @param stdClass $course The course record for this page. + */ + public function __construct($courseid) { + $context = context_course::instance($courseid); + $this->courseid = $courseid; + $this->competencies = api::list_competencies_in_course($courseid); + $this->canmanagecompetencyframeworks = has_capability('tool/lp:competencymanage', context_system::instance()); + $this->canmanagecoursecompetencies = has_capability('tool/lp:coursecompetencymanage', $context); + $this->manageurl = new moodle_url('/admin/tool/lp/competencyframeworks.php'); + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @return stdClass + */ + public function export_for_template(renderer_base $output) { + $data = new stdClass(); + $data->courseid = $this->courseid; + $data->competencies = array(); + foreach ($this->competencies as $competency) { + $record = $competency->to_record(); + array_push($data->competencies, $record); + } + $data->canmanagecompetencyframeworks = $this->canmanagecompetencyframeworks; + $data->canmanagecoursecompetencies = $this->canmanagecoursecompetencies; + $data->manageurl = $this->manageurl->out(true); + + return $data; + } +} diff --git a/admin/tool/lp/classes/output/manage_competencies_page.php b/admin/tool/lp/classes/output/manage_competencies_page.php new file mode 100644 index 00000000000..7408d09a3c5 --- /dev/null +++ b/admin/tool/lp/classes/output/manage_competencies_page.php @@ -0,0 +1,120 @@ +. + +/** + * Class containing data for managecompetencyframeworks page + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\output; + +use renderable; +use templatable; +use renderer_base; +use single_button; +use stdClass; +use moodle_url; +use context_system; +use tool_lp\api; + +/** + * Class containing data for managecompetencies page + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class manage_competencies_page implements renderable, templatable { + + /** @var \tool_lp\competency_framework $framework This competency framework. */ + var $framework = null; + + /** @var array $competencies List of competencies. */ + var $competencies = array(); + + /** @var string $search Text to search for. */ + var $search = ''; + + /** @var bool $canmanage Result of permissions checks. */ + var $canmanage = false; + + /** @var moodle_url $pluginurlbase Base url to use constructing links. */ + var $pluginbaseurl = null; + + /** + * Construct this renderable. + * @param \tool_lp\competency_framework $framework + */ + public function __construct($framework, $search) { + $this->framework = $framework; + $this->search = $search; + $addpage = new single_button( + new moodle_url('/admin/tool/lp/editcompetencyframework.php'), + get_string('addnewcompetency', 'tool_lp') + ); + $this->navigation[] = $addpage; + + $this->competencies = api::search_competencies($search, $framework->get_id()); + + $context = context_system::instance(); + $this->canmanage = has_capability('tool/lp:competencymanage', $context); + } + + /** + * Recursively build up the tree of nodes. + * + * @param stdClass $parent - the exported parent node + * @param array $all - List of all competency classes. + */ + private function add_competency_children($parent, $all) { + foreach ($all as $one) { + if ($one->get_parentid() == $parent->id) { + $parent->haschildren = true; + $record = $one->to_record(); + $record->children = array(); + $record->haschildren = false; + $parent->children[] = $record; + $this->add_competency_children($record, $all); + } + } + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @return stdClass + */ + public function export_for_template(renderer_base $output) { + $data = new stdClass(); + $data->framework = $this->framework->to_record(); + $data->canmanage = $this->canmanage; + $data->competencies = array(); + $data->search = $this->search; + + foreach ($this->competencies as $competency) { + if ($competency->get_parentid() == 0) { + $record = $competency->to_record(); + $record->children = array(); + $record->haschildren = false; + $data->competencies[] = $record; + $this->add_competency_children($record, $this->competencies); + } + } + + return $data; + } +} diff --git a/admin/tool/lp/classes/output/manage_competency_frameworks_page.php b/admin/tool/lp/classes/output/manage_competency_frameworks_page.php new file mode 100644 index 00000000000..f74eb7b1061 --- /dev/null +++ b/admin/tool/lp/classes/output/manage_competency_frameworks_page.php @@ -0,0 +1,94 @@ +. + +/** + * Class containing data for managecompetencyframeworks page + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\output; + +use renderable; +use templatable; +use renderer_base; +use single_button; +use stdClass; +use moodle_url; +use context_system; +use tool_lp\api; + +/** + * Class containing data for managecompetencyframeworks page + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class manage_competency_frameworks_page implements renderable, templatable { + + /** @var array $navigation List of links to display on the page. Each link contains a url and a title. */ + var $navigation = array(); + + /** @var array $competencyframeworks List of competency frameworks. */ + var $competencyframeworks = array(); + + /** @var bool $canmanage Result of permissions checks. */ + var $canmanage = false; + + /** @var moodle_url $pluginurlbase Base url to use constructing links. */ + var $pluginbaseurl = null; + + /** + * Construct this renderable. + */ + public function __construct() { + $addpage = new single_button( + new moodle_url('/admin/tool/lp/editcompetencyframework.php'), + get_string('addnewcompetencyframework', 'tool_lp') + ); + $this->navigation[] = $addpage; + + $this->competencyframeworks = api::list_frameworks(array(), 'sortorder', 'ASC', 0, 0); + + $context = context_system::instance(); + $this->canmanage = has_capability('tool/lp:competencymanage', $context); + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @return stdClass + */ + public function export_for_template(renderer_base $output) { + $data = new stdClass(); + $data->canmanage = $this->canmanage; + $data->competencyframeworks = array(); + foreach ($this->competencyframeworks as $framework) { + $record = $framework->to_record(); + $filters = array('competencyframeworkid' => $framework->get_id()); + $record->competencies_count = api::count_competencies($filters); + $data->competencyframeworks[] = $record; + } + $data->pluginbaseurl = (new moodle_url('/admin/tool/lp'))->out(true); + $data->navigation = array(); + foreach ($this->navigation as $button) { + $data->navigation[] = $output->render($button); + } + + return $data; + } +} diff --git a/admin/tool/lp/classes/output/manage_templates_page.php b/admin/tool/lp/classes/output/manage_templates_page.php new file mode 100644 index 00000000000..43708c06980 --- /dev/null +++ b/admin/tool/lp/classes/output/manage_templates_page.php @@ -0,0 +1,89 @@ +. + +/** + * Class containing data for managelearningplans page + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\output; + +use renderable; +use templatable; +use renderer_base; +use single_button; +use stdClass; +use moodle_url; +use context_system; +use tool_lp\api; + +/** + * Class containing data for managecompetencyframeworks page + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class manage_templates_page implements renderable, templatable { + + /** @var array $navigation List of links to display on the page. Each link contains a url and a title. */ + var $navigation = array(); + + /** @var array $templates List of learning plan templates. */ + var $templates = array(); + + /** @var bool $canmanage Result of permissions checks. */ + var $canmanage = false; + + /** + * Construct this renderable. + */ + public function __construct() { + $addpage = new single_button( + new moodle_url('/admin/tool/lp/edittemplate.php'), + get_string('addnewtemplate', 'tool_lp') + ); + $this->navigation[] = $addpage; + + $this->templates = api::list_templates(array(), 'sortorder', 'ASC', 0, 0); + + $context = context_system::instance(); + $this->canmanage = has_capability('tool/lp:learningplanmanage', $context); + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @return stdClass + */ + public function export_for_template(renderer_base $output) { + $data = new stdClass(); + $data->canmanage = $this->canmanage; + $data->templates = array(); + foreach ($this->templates as $template) { + $record = $template->to_record(); + $data->templates[] = $record; + } + $data->pluginbaseurl = (new moodle_url('/admin/tool/lp'))->out(true); + $data->navigation = array(); + foreach ($this->navigation as $button) { + $data->navigation[] = $output->render($button); + } + + return $data; + } +} diff --git a/admin/tool/lp/classes/output/renderer.php b/admin/tool/lp/classes/output/renderer.php new file mode 100644 index 00000000000..71cd64844e5 --- /dev/null +++ b/admin/tool/lp/classes/output/renderer.php @@ -0,0 +1,88 @@ +. + +/** + * Renderer class for learning plans + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_lp\output; + +defined('MOODLE_INTERNAL') || die; + +use plugin_renderer_base; + +/** + * Renderer class for learning plans + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class renderer extends plugin_renderer_base { + + /** + * Defer to template. + * + * @param manage_competency_frameworks_page $page + * + * @return string html for the page + */ + public function render_manage_competency_frameworks_page($page) { + $data = $page->export_for_template($this); + return parent::render_from_template('tool_lp/manage_competency_frameworks_page', $data); + } + + /** + * Defer to template. + * + * @param manage_competencies_page $page + * + * @return string html for the page + */ + public function render_manage_competencies_page($page) { + $data = $page->export_for_template($this); + return parent::render_from_template('tool_lp/manage_competencies_page', $data); + } + + /** + * Defer to template. + * + * @param course_competencies_page $page + * + * @return string html for the page + */ + public function render_course_competencies_page($page) { + $data = $page->export_for_template($this); + return parent::render_from_template('tool_lp/course_competencies_page', $data); + } + + /** + * Defer to template. + * + * @param manage_templates_page $page + * + * @return string html for the page + */ + public function render_manage_templates_page($page) { + $data = $page->export_for_template($this); + return parent::render_from_template('tool_lp/manage_templates_page', $data); + } + +} diff --git a/admin/tool/lp/classes/output/template_competencies_page.php b/admin/tool/lp/classes/output/template_competencies_page.php new file mode 100644 index 00000000000..705d036284c --- /dev/null +++ b/admin/tool/lp/classes/output/template_competencies_page.php @@ -0,0 +1,73 @@ +. + +/** + * Class containing data for learning plan template competencies page + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\output; + +use renderable; +use templatable; +use renderer_base; +use stdClass; +use moodle_url; +use context_system; +use tool_lp\api; + +/** + * Class containing data for learning plan template competencies page + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template_competencies_page implements renderable, templatable { + + /** + * Construct this renderable. + * @param int $templateid The learning plan template id for this page. + */ + public function __construct($templateid) { + $this->courseid = $templateid; + $this->competencies = api::list_competencies_in_template($templateid); + $this->canmanagecompetencyframeworks = has_capability('tool/lp:competencymanage', context_system::instance()); + $this->canmanagetemplates = has_capability('tool/lp:templatesmanage', $context); + $this->manageurl = new moodle_url('/admin/tool/lp/competencyframeworks.php'); + } + + /** + * Export this data so it can be used as the context for a mustache template. + * + * @return stdClass + */ + public function export_for_template(renderer_base $output) { + $data = new stdClass(); + $data->templateid = $this->templateid; + $data->competencies = array(); + foreach ($this->competencies as $competency) { + $record = $competency->to_record(); + array_push($data->competencies, $record); + } + $data->canmanagecompetencyframeworks = $this->canmanagecompetencyframeworks; + $data->canmanagecoursecompetencies = $this->canmanagecoursecompetencies; + $data->manageurl = $this->manageurl->out(true); + + return $data; + } +} diff --git a/admin/tool/lp/classes/persistent.php b/admin/tool/lp/classes/persistent.php new file mode 100644 index 00000000000..2a98c2fec09 --- /dev/null +++ b/admin/tool/lp/classes/persistent.php @@ -0,0 +1,260 @@ +. + +/** + * Abstract class for tool_lp objects saved to 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 external_function_parameters; +use external_value; + +/** + * Abstract class for tool_lp objects saved to the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class persistent { + + /** @var int|null $id Database id for this framework */ + private $id = null; + + /** @var int $timecreated Creation timestamp */ + private $timecreated = 0; + + /** @var int $timemodified Modification timestamp */ + private $timemodified = 0; + + /** @var int $usermodified The user who last modified this framework */ + private $usermodified = 0; + + /** + * Abstract method that provides the table name matching this class. + * + * @return string + */ + abstract public function get_table_name(); + + /** + * Create an instance of this class. + * @param int $id If set, this is the id of an existing record, used to load the data. + * @param stdClass $record If set, the data for this class will be taken from the record. + */ + public function __construct($id = 0, $record = null) { + if ($id > 0) { + $this->id = $id; + $this->read(); + } + if (!empty($record)) { + $this->from_record($record); + } + } + + /** + * Get the record id + * + * @return int + */ + public function get_id() { + return $this->id; + } + + /** + * Set the record id + * + * @param int $id The record id + */ + public function set_id($id) { + $this->id = $id; + } + + /** + * Get the time the record was created. + * + * @return string The time the record was created. + */ + public function get_timecreated() { + return $this->timecreated; + } + + /** + * Set the time created timestamp + * + * @param int $timecreated The timestamp + */ + public function set_timecreated($timecreated) { + $this->timecreated = $timecreated; + } + + /** + * Get the last time the record was modified. + * + * @return string The last time the record was modified + */ + public function get_timemodified() { + return $this->timemodified; + } + + /** + * Set the last modified timestamp + * + * @param int $timemodified The timestamp + */ + public function set_timemodified($timemodified) { + $this->timemodified = $timemodified; + } + + /** + * Get the user who last modified the record. + * + * @return string The user who last modified the record + */ + public function get_usermodified() { + return $this->usermodified; + } + + /** + * Set the user id that last modified the record. + * + * @param int $usermodified The user id + */ + public function set_usermodified($usermodified) { + $this->usermodified = $usermodified; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return persistent + */ + abstract public function from_record($record); + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + abstract public function to_record(); + + /** + * Reload the data for this class from the DB. + * + * @return framework + */ + public function read() { + global $DB; + + if ($this->id <= 0) { + throw new coding_exception('id is required to load'); + } + $record = $DB->get_record($this->get_table_name(), array('id' => $this->id), '*', MUST_EXIST); + return $this->from_record($record); + } + + /** + * Insert a record in the DB + * + * @return persistent + */ + public function create() { + global $DB, $USER; + + $this->id = 0; + $this->timecreated = $this->timemodified = time(); + $this->usermodified = $USER->id; + $record = $this->to_record(); + + $id = $DB->insert_record($this->get_table_name(), $record); + $this->set_id($id); + return $this; + } + + + + /** + * Update the existing record in the DB. + * + * @return bool Success + */ + public function update() { + global $DB, $USER; + + if ($this->id <= 0) { + throw new coding_exception('id is required to update'); + } + $record = $this->to_record(); + unset($record->timecreated); + $record->timemodified = time(); + $record->usermodified = $USER->id; + $record = (array) $record; + return $DB->update_record($this->get_table_name(), $record); + } + + /** + * Delete the existing record in the DB. + * + * @return bool Success + */ + public function delete() { + global $DB; + + if ($this->id <= 0) { + throw new coding_exception('id is required to delete'); + } + return $DB->delete_records($this->get_table_name(), array('id' => $this->id)); + } + + /** + * Load a list of records. + * + * @return array of persistent instances. + */ + public function get_records($filters = array(), $sort = '', $order = 'ASC', $skip = 0, $limit = 0) { + global $DB; + + $orderby = ''; + if (!empty($sort)) { + $orderby = $sort . ' ' . $order; + } + + $records = $DB->get_records($this->get_table_name(), $filters, $orderby, '*', $skip, $limit); + $instances = array(); + + foreach ($records as $record) { + $newrecord = new static(0, $record); + array_push($instances, $newrecord); + } + return $instances; + } + + /** + * Count a list of records. + * + * @return int + */ + public function count_records($filters = array()) { + global $DB; + + $count = $DB->count_records($this->get_table_name(), $filters); + return $count; + } +} diff --git a/admin/tool/lp/classes/template.php b/admin/tool/lp/classes/template.php new file mode 100644 index 00000000000..8f5988faf5b --- /dev/null +++ b/admin/tool/lp/classes/template.php @@ -0,0 +1,274 @@ +. + +/** + * Class for loading/storing learning plan templates 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; + +/** + * Class for loading/storing learning plan templates from the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template extends persistent { + + /** @var string $shortname Short name for this template */ + private $shortname = ''; + + /** @var string $description Description for this framework */ + private $description = ''; + + /** @var int $descriptionformat Format for the description */ + private $descriptionformat = 0; + + /** @var int $sortorder A number used to influence sorting */ + private $sortorder = 0; + + /** @var string $idnumber Unique idnumber for this template - must be unique if it is non-empty */ + private $idnumber = ''; + + /** @var int $duedate A default due date for instances of this plan */ + private $duedate = 0; + + /** @var bool $visible Used to show/hide this template */ + private $visible = true; + + /** + * Method that provides the table name matching this class. + * + * @return string + */ + public function get_table_name() { + return 'tool_lp_plan_template'; + } + + /** + * Get the short name. + * + * @return string The short name + */ + public function get_shortname() { + return $this->shortname; + } + + /** + * Set the short name. + * + * @param string $shortname The short name + */ + public function set_shortname($shortname) { + $this->shortname = $shortname; + } + + /** + * Get the description format. + * + * @return int The description format + */ + public function get_descriptionformat() { + return $this->descriptionformat; + } + + /** + * Set the description format + * + * @param int $descriptionformat The description format + */ + public function set_descriptionformat($descriptionformat) { + $this->descriptionformat = $descriptionformat; + } + + /** + * Get the id number. + * + * @return string The id number + */ + public function get_idnumber() { + return $this->idnumber; + } + + /** + * Set the id number. + * + * @param string $idnumber The id number + */ + public function set_idnumber($idnumber) { + $this->idnumber = $idnumber; + } + + /** + * Get the description. + * + * @return string The description + */ + public function get_description() { + return $this->description; + } + + /** + * Set the description. + * + * @param string $description The description + */ + public function set_description($description) { + $this->description = $description; + } + + /** + * Get the sort order index. + * + * @return string The sort order index + */ + public function get_sortorder() { + return $this->sortorder; + } + + /** + * Set the sort order index. + * + * @param string $sortorder The sort order index + */ + public function set_sortorder($sortorder) { + $this->sortorder = $sortorder; + } + + /** + * Get the due date + * + * @return string The due date + */ + public function get_duedate() { + return $this->duedate; + } + + /** + * Set the due date + * + * @param string $duedate The due date + */ + public function set_duedate($duedate) { + $this->duedate = $duedate; + } + + + /** + * Get the visible flag. + * + * @return string The visible flag + */ + public function get_visible() { + return $this->visible; + } + + /** + * Set the visible flag. + * + * @param string $visible The visible flag + */ + public function set_visible($visible) { + $this->visible = $visible; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return template + */ + public function from_record($record) { + if (isset($record->id)) { + $this->set_id($record->id); + } + if (isset($record->shortname)) { + $this->set_shortname($record->shortname); + } + if (isset($record->idnumber)) { + $this->set_idnumber($record->idnumber); + } + if (isset($record->description)) { + $this->set_description($record->description); + } + if (isset($record->descriptionformat)) { + $this->set_descriptionformat($record->descriptionformat); + } + if (isset($record->sortorder)) { + $this->set_sortorder($record->sortorder); + } + if (isset($record->visible)) { + $this->set_visible($record->visible); + } + if (isset($record->duedate)) { + $this->set_duedate($record->duedate); + } + if (isset($record->timecreated)) { + $this->set_timecreated($record->timecreated); + } + if (isset($record->timemodified)) { + $this->set_timemodified($record->timemodified); + } + if (isset($record->usermodified)) { + $this->set_usermodified($record->usermodified); + } + return $this; + } + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + public function to_record() { + $record = new stdClass(); + $record->id = $this->get_id(); + $record->shortname = $this->get_shortname(); + $record->idnumber = $this->get_idnumber(); + $record->duedate = $this->get_duedate(); + $record->duedateformatted = ''; + if ($record->duedate) { + $record->duedateformatted = userdate($this->get_duedate()); + } + $record->description = $this->get_description(); + $record->descriptionformat = $this->get_descriptionformat(); + $record->descriptionformatted = format_text($this->get_description(), $this->get_descriptionformat()); + $record->sortorder = $this->get_sortorder(); + $record->visible = $this->get_visible(); + $record->timecreated = $this->get_timecreated(); + $record->timemodified = $this->get_timemodified(); + $record->usermodified = $this->get_usermodified(); + + return $record; + } + + /** + * Add a default for the sortorder field to the default create logic. + * + * @return persistent + */ + public function create() { + $this->sortorder = $this->count_records(); + return parent::create(); + } + + +} diff --git a/admin/tool/lp/classes/template_competency.php b/admin/tool/lp/classes/template_competency.php new file mode 100644 index 00000000000..79bc4ae33d5 --- /dev/null +++ b/admin/tool/lp/classes/template_competency.php @@ -0,0 +1,254 @@ +. + +/** + * Class for loading/storing competencies 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_system; + +/** + * Class for loading/storing template_competencies from the DB. + * + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class template_competency extends persistent { + + /** @var int $templateid The template id */ + private $templateid = 0; + + /** @var int $competencyid The competency id */ + private $competencyid = 0; + + /** + * Method that provides the table name matching this class. + * + * @return string + */ + public function get_table_name() { + return 'tool_lp_template_competency'; + } + + /** + * Get the competency id + * + * @return int The competency id + */ + public function get_competencyid() { + return $this->competencyid; + } + + /** + * Set the competency id + * + * @param int $competencyid The competency id + */ + public function set_competencyid($competencyid) { + $this->competencyid = $competencyid; + } + + /** + * Get the template id + * + * @return int The template id + */ + public function get_templateid() { + return $this->templateid; + } + + /** + * Set the template id + * + * @param int $templateid The template id + */ + public function set_templateid($templateid) { + $this->templateid = $templateid; + } + + /** + * Populate this class with data from a DB record. + * + * @param stdClass $record A DB record. + * @return framework + */ + public function from_record($record) { + if (isset($record->id)) { + $this->set_id($record->id); + } + if (isset($record->templateid)) { + $this->set_templateid($record->templateid); + } + if (isset($record->competencyid)) { + $this->set_competencyid($record->competencyid); + } + if (isset($record->timecreated)) { + $this->set_timecreated($record->timecreated); + } + if (isset($record->timemodified)) { + $this->set_timemodified($record->timemodified); + } + if (isset($record->usermodified)) { + $this->set_usermodified($record->usermodified); + } + return $this; + } + + /** + * Create a DB record from this class. + * + * @return stdClass + */ + public function to_record() { + $record = new stdClass(); + $record->id = $this->get_id(); + $record->templateid = $this->get_templateid(); + $record->competencyid = $this->get_competencyid(); + $record->timecreated = $this->get_timecreated(); + $record->timemodified = $this->get_timemodified(); + $record->usermodified = $this->get_usermodified(); + + return $record; + } + + /** + * Count the templates using this competency + * + * @param int $competencyid The competency id + * @param bool $onlyvisible If true, only count visible templates using this competency. + * @return int + */ + public function count_templates($competencyid, $onlyvisible) { + global $DB; + + $sql = 'SELECT COUNT(template.id) + FROM {' . self::get_table_name() . '} tplcomp + JOIN {' . template::get_table_name() . '} tpl + ON tplcomp.templateid = tpl.id + WHERE tplcomp.competencyid = ? '; + $params = array($templateid); + + if ($onlyvisible) { + $sql .= ' AND tpl.visible = ?'; + $params[] = 1; + } + + $results = $DB->count_records_sql($sql, $params); + + return $results; + } + + /** + * List the templates using this competency. + * + * @param int $competencyid The competency id + * @param bool $onlyvisible If true, only count visible templates using this competency. + * @return array[competency] + */ + public function list_templates($competencyid, $onlyvisible) { + global $DB; + + $template = new template(); + + $sql = 'SELECT tpl.* + FROM {' . $template->get_table_name() . '} tpl + JOIN {' . self::get_table_name() . '} tplcomp + ON tplcomp.templateid = tpl.id + WHERE tplcomp.competencyid = ? '; + $params = array($competencyid); + + if ($onlyvisible) { + $sql .= ' AND tpl.visible = ?'; + $params[] = 1; + } + + $results = $DB->get_records_sql($sql, $params); + + $instances = array(); + foreach ($results as $result) { + array_push($instances, new template(0, $result)); + } + + return $instances; + } + + /** + * Count the competencies in this template. + * + * @param int $templateid The template id + * @param bool $onlyvisible If true, only count visible competencies in this template. + * @return int + */ + public function count_competencies($templateid, $onlyvisible) { + global $DB; + + $sql = 'SELECT COUNT(comp.id) + FROM {' . self::get_table_name() . '} tplcomp + JOIN {' . competency::get_table_name() . '} comp + ON tplcomp.competencyid = comp.id + WHERE tplcomp.templateid = ? '; + $params = array($templateid); + + if ($onlyvisible) { + $sql .= ' AND comp.visible = ?'; + $params[] = 1; + } + + $results = $DB->count_records_sql($sql, $params); + + return $results; + } + + /** + * List the competencies in this template. + * + * @param int $templateid The template id + * @param bool $onlyvisible If true, only count visible competencies in this template. + * @return array[competency] + */ + public function list_competencies($templateid, $onlyvisible) { + global $DB; + + $competency = new competency(); + + $sql = 'SELECT comp.* + FROM {' . $competency->get_table_name() . '} comp + JOIN {' . self::get_table_name() . '} tplcomp + ON tplcomp.competencyid = comp.id + WHERE tplcomp.templateid = ? '; + $params = array($templateid); + + if ($onlyvisible) { + $sql .= ' AND comp.visible = ?'; + $params[] = 1; + } + + $results = $DB->get_records_sql($sql, $params); + + $instances = array(); + foreach ($results as $result) { + array_push($instances, new competency(0, $result)); + } + + return $instances; + } +} diff --git a/admin/tool/lp/competencies.php b/admin/tool/lp/competencies.php new file mode 100644 index 00000000000..82b7f352e78 --- /dev/null +++ b/admin/tool/lp/competencies.php @@ -0,0 +1,50 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollpcompetencies'); + +$id = required_param('competencyframeworkid', PARAM_INT); +$search = optional_param('search', '', PARAM_RAW); + +$framework = \tool_lp\api::read_framework($id); + +$title = get_string('competencies', 'tool_lp'); +$pagetitle = get_string('competenciesforframework', 'tool_lp', $framework->get_shortname()); +// Set up the page. +$url = new moodle_url("/admin/tool/lp/competencies.php", array('competencyframeworkid' => $framework->get_id())); +$PAGE->set_url($url); +$PAGE->navbar->add($framework->get_shortname(), $url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); +echo $output->header(); +echo $output->heading($pagetitle); + +$page = new \tool_lp\output\manage_competencies_page($framework, $search); +echo $output->render($page); + +echo $output->footer(); diff --git a/admin/tool/lp/competencyframeworks.php b/admin/tool/lp/competencyframeworks.php new file mode 100644 index 00000000000..280020879af --- /dev/null +++ b/admin/tool/lp/competencyframeworks.php @@ -0,0 +1,44 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollpcompetencies'); + +$title = get_string('competencies', 'tool_lp'); +$pagetitle = get_string('competencyframeworks', 'tool_lp'); +// Set up the page. +$url = new moodle_url("/admin/tool/lp/competencyframeworks.php"); +$PAGE->set_url($url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); +echo $output->header(); +echo $output->heading($pagetitle); + +$page = new \tool_lp\output\manage_competency_frameworks_page(); +echo $output->render($page); + +echo $output->footer(); diff --git a/admin/tool/lp/coursecompetencies.php b/admin/tool/lp/coursecompetencies.php new file mode 100644 index 00000000000..5cf5050c1e3 --- /dev/null +++ b/admin/tool/lp/coursecompetencies.php @@ -0,0 +1,50 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); + +$id = required_param('courseid', PARAM_INT); + +$params = array('id' => $id); +$course = $DB->get_record('course', $params, '*', MUST_EXIST); +require_login($course); +$context = context_course::instance($course->id); +$urlparams = array('courseid' => $id); + +$url = new moodle_url('/admin/tool/lp/coursecompetencies.php', $urlparams); +$title = get_string('coursecompetencies', 'tool_lp'); +$PAGE->set_url($url); +$PAGE->set_title($title); +$coursename = format_text($course->fullname, false, array('context' => $context)); +$PAGE->set_heading($coursename); +$PAGE->set_pagelayout('incourse'); + +$output = $PAGE->get_renderer('tool_lp'); +echo $output->header(); +echo $output->heading($title); + +$page = new \tool_lp\output\course_competencies_page($course->id); +echo $output->render($page); + +echo $output->footer(); diff --git a/admin/tool/lp/db/access.php b/admin/tool/lp/db/access.php new file mode 100644 index 00000000000..bc2bf2b1162 --- /dev/null +++ b/admin/tool/lp/db/access.php @@ -0,0 +1,94 @@ +. + +/** + * Capabilities. + * + * This files lists capabilities related to tool_lp. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$capabilities = array( + + 'tool/lp:competencyread' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + 'user' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/block:view' + ), + 'tool/lp:competencymanage' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), + 'tool/lp:templateread' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + 'user' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/block:view' + ), + 'tool/lp:templatemanage' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), + 'tool/lp:learningplanread' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + 'user' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/block:view' + ), + 'tool/lp:learningplanmanage' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), + 'tool/lp:coursecompetencyread' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_COURSE, + 'archetypes' => array( + 'user' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/block:view' + ), + 'tool/lp:coursecompetencymanage' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_COURSE, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/site:backup' + ) + +); diff --git a/admin/tool/lp/db/install.xml b/admin/tool/lp/db/install.xml new file mode 100755 index 00000000000..257fae750c1 --- /dev/null +++ b/admin/tool/lp/db/install.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+
+
diff --git a/admin/tool/lp/db/services.php b/admin/tool/lp/db/services.php new file mode 100644 index 00000000000..ffab45e86a7 --- /dev/null +++ b/admin/tool/lp/db/services.php @@ -0,0 +1,313 @@ +. + + +/** + * Learning plan webservice functions. + * + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$functions = array( + + // Learning plan related functions. + + 'tool_lp_create_competency_framework' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'create_competency_framework', + 'classpath' => '', + 'description' => 'Creates new competency frameworks.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_read_competency_framework' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'read_competency_framework', + 'classpath' => '', + 'description' => 'Load a summary of a competency framework.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_delete_competency_framework' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'delete_competency_framework', + 'classpath' => '', + 'description' => 'Delete a competency framework.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_update_competency_framework' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'update_competency_framework', + 'classpath' => '', + 'description' => 'Update a competency framework.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_list_competency_frameworks' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'list_competency_frameworks', + 'classpath' => '', + 'description' => 'Load a list of a competency frameworks.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_count_competency_frameworks' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'count_competency_frameworks', + 'classpath' => '', + 'description' => 'Count a list of a competency frameworks.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_data_for_competency_frameworks_manage_page' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'data_for_competency_frameworks_manage_page', + 'classpath' => '', + 'description' => 'Load the data for the competency frameworks manage page template', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_reorder_competency_framework' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'reorder_competency_framework', + 'classpath' => '', + 'description' => 'Move a competency framework to a new relative sort order.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_create_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'create_competency', + 'classpath' => '', + 'description' => 'Creates new competencies.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_read_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'read_competency', + 'classpath' => '', + 'description' => 'Load a summary of a competency.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_delete_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'delete_competency', + 'classpath' => '', + 'description' => 'Delete a competency.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_update_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'update_competency', + 'classpath' => '', + 'description' => 'Update a competency.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_list_competencies' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'list_competencies', + 'classpath' => '', + 'description' => 'Load a list of a competencies.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_count_competencies' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'count_competencies', + 'classpath' => '', + 'description' => 'Count a list of a competencies.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_search_competencies' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'search_competencies', + 'classpath' => '', + 'description' => 'Search a list of a competencies.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_data_for_competencies_manage_page' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'data_for_competencies_manage_page', + 'classpath' => '', + 'description' => 'Load the data for the competencies manage page template', + 'type' => 'read', + 'capabilities'=> 'tool/lp:competencyview', + ), + 'tool_lp_set_parent_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'set_parent_competency', + 'classpath' => '', + 'description' => 'Set a new parent for a competency.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_move_up_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'move_up_competency', + 'classpath' => '', + 'description' => 'Re-order a competency.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_move_down_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'move_down_competency', + 'classpath' => '', + 'description' => 'Re-order a competency.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:competencymanage', + ), + 'tool_lp_list_competencies_in_course' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'list_competencies_in_course', + 'classpath' => '', + 'description' => 'List the competencies in a course', + 'type' => 'read', + 'capabilities'=> 'tool/lp:coursecompetencyread', + ), + 'tool_lp_list_courses_using_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'list_courses_using_competency', + 'classpath' => '', + 'description' => 'List the courses using a competency', + 'type' => 'read', + 'capabilities'=> 'tool/lp:coursecompetencyread', + ), + 'tool_lp_count_competencies_in_course' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'count_competencies_in_course', + 'classpath' => '', + 'description' => 'List the competencies in a course', + 'type' => 'read', + 'capabilities'=> 'tool/lp:coursecompetencyread', + ), + 'tool_lp_count_courses_using_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'count_courses_using_competency', + 'classpath' => '', + 'description' => 'List the courses using a competency', + 'type' => 'read', + 'capabilities'=> 'tool/lp:coursecompetencyread', + ), + 'tool_lp_add_competency_to_course' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'add_competency_to_course', + 'classpath' => '', + 'description' => 'Add the competency to a course', + 'type' => 'write', + 'capabilities'=> 'tool/lp:coursecompetencymanage', + ), + 'tool_lp_remove_competency_from_course' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'remove_competency_from_course', + 'classpath' => '', + 'description' => 'Remove a competency from a course', + 'type' => 'write', + 'capabilities'=> 'tool/lp:coursecompetencymanage', + ), + 'tool_lp_data_for_course_competencies_page' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'data_for_course_competencies_page', + 'classpath' => '', + 'description' => 'Load the data for the course competencies page template.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:coursecompetencyread', + ), + 'tool_lp_reorder_course_competency' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'reorder_course_competency', + 'classpath' => '', + 'description' => 'Move a course competency to a new relative sort order.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:coursecompetencymanage', + ), + 'tool_lp_create_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'create_template', + 'classpath' => '', + 'description' => 'Creates new learning plan templates.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:templatemanage', + ), + 'tool_lp_read_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'read_template', + 'classpath' => '', + 'description' => 'Load a summary of a learning plan template.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:templateview', + ), + 'tool_lp_delete_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'delete_template', + 'classpath' => '', + 'description' => 'Delete a learning plan template.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:templatemanage', + ), + 'tool_lp_update_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'update_template', + 'classpath' => '', + 'description' => 'Update a learning plan template.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:templatemanage', + ), + 'tool_lp_list_templates' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'list_templates', + 'classpath' => '', + 'description' => 'Load a list of a learning plan templates.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:templateview', + ), + 'tool_lp_count_templates' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'count_templates', + 'classpath' => '', + 'description' => 'Count a list of a learning plan templates.', + 'type' => 'read', + 'capabilities'=> 'tool/lp:templateview', + ), + 'tool_lp_data_for_templates_manage_page' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'data_for_templates_manage_page', + 'classpath' => '', + 'description' => 'Load the data for the learning plan templates manage page template', + 'type' => 'read', + 'capabilities'=> 'tool/lp:templateview', + ), + 'tool_lp_reorder_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'reorder_template', + 'classpath' => '', + 'description' => 'Move a learning plan template to a new relative sort order.', + 'type' => 'write', + 'capabilities'=> 'tool/lp:templatemanage', + ), + +); + diff --git a/admin/tool/lp/editcompetency.php b/admin/tool/lp/editcompetency.php new file mode 100644 index 00000000000..7608c7b7876 --- /dev/null +++ b/admin/tool/lp/editcompetency.php @@ -0,0 +1,86 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollpcompetencies'); + +$title = get_string('competencies', 'tool_lp'); +$id = optional_param('id', 0, PARAM_INT); +$competencyframeworkid = required_param('competencyframeworkid', PARAM_INT); +$parentid = optional_param('parentid', 0, PARAM_INT); + +if (empty($id)) { + $pagetitle = get_string('addnewcompetency', 'tool_lp'); +} else { + $pagetitle = get_string('editcompetency', 'tool_lp'); +} +// Set up the page. +$params = array('id'=>$id, 'competencyframeworkid'=>$competencyframeworkid, 'parentid'=>$parentid); +$url = new moodle_url("/admin/tool/lp/editcompetency.php", $params); +$PAGE->set_url($url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); + +$competencyframework = \tool_lp\api::read_framework($competencyframeworkid); +$parent = null; +if ($parentid) { + $parent = \tool_lp\api::read_competency($parentid); +} + +$form = new \tool_lp\form\competency(null, array('id' => $id, 'competencyframework' => $competencyframework, 'parent' => $parent)); + +if ($form->is_cancelled()) { + redirect(new moodle_url('/admin/tool/lp/competencies.php', array('competencyframeworkid'=>$competencyframeworkid))); +} + +echo $output->header(); +echo $output->heading($pagetitle); + +$data = $form->get_data(); +if ($data) { + // Save the changes and continue back to the manage page. + // Massage the editor data. + $data->descriptionformat = $data->description['format']; + $data->description = $data->description['text']; + if (empty($data->id)) { + // Create new framework. + require_sesskey(); + \tool_lp\api::create_competency($data); + echo $output->notification(get_string('competencycreated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button(new moodle_url('/admin/tool/lp/competencies.php', array('competencyframeworkid'=>$competencyframeworkid))); + } else { + require_sesskey(); + \tool_lp\api::update_competency($data); + echo $output->notification(get_string('competencyupdated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button(new moodle_url('/admin/tool/lp/competencies.php', array('competencyframeworkid'=>$competencyframeworkid))); + } +} else { + $form->display(); +} + + +echo $output->footer(); diff --git a/admin/tool/lp/editcompetencyframework.php b/admin/tool/lp/editcompetencyframework.php new file mode 100644 index 00000000000..46735b96474 --- /dev/null +++ b/admin/tool/lp/editcompetencyframework.php @@ -0,0 +1,76 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollpcompetencies'); + +$title = get_string('competencies', 'tool_lp'); +$id = optional_param('id', 0, PARAM_INT); +if (empty($id)) { + $pagetitle = get_string('addnewcompetencyframework', 'tool_lp'); +} else { + $pagetitle = get_string('editcompetencyframework', 'tool_lp'); +} +// Set up the page. +$url = new moodle_url("/admin/tool/lp/editcompetencyframework.php", array('id'=>$id)); +$PAGE->set_url($url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); + +$form = new \tool_lp\form\competency_framework(null, $id); + +if ($form->is_cancelled()) { + redirect(new moodle_url('/admin/tool/lp/competencyframeworks.php')); +} + +echo $output->header(); +echo $output->heading($pagetitle); + +$data = $form->get_data(); +if ($data) { + // Save the changes and continue back to the manage page. + // Massage the editor data. + $data->descriptionformat = $data->description['format']; + $data->description = $data->description['text']; + if (empty($data->id)) { + // Create new framework. + require_sesskey(); + \tool_lp\api::create_framework($data); + echo $output->notification(get_string('competencyframeworkcreated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button('/admin/tool/lp/competencyframeworks.php'); + } else { + require_sesskey(); + \tool_lp\api::update_framework($data); + echo $output->notification(get_string('competencyframeworkupdated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button('/admin/tool/lp/competencyframeworks.php'); + } +} else { + $form->display(); +} + + +echo $output->footer(); diff --git a/admin/tool/lp/edittemplate.php b/admin/tool/lp/edittemplate.php new file mode 100644 index 00000000000..b2c2db53be6 --- /dev/null +++ b/admin/tool/lp/edittemplate.php @@ -0,0 +1,76 @@ +. + +/** + * This page lets users to manage site wide learning plan templates. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollplearningplans'); + +$title = get_string('templates', 'tool_lp'); +$id = optional_param('id', 0, PARAM_INT); +if (empty($id)) { + $pagetitle = get_string('addnewtemplate', 'tool_lp'); +} else { + $pagetitle = get_string('edittemplate', 'tool_lp'); +} +// Set up the page. +$url = new moodle_url("/admin/tool/lp/edittemplate.php", array('id'=>$id)); +$PAGE->set_url($url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); + +$form = new \tool_lp\form\template(null, $id); + +if ($form->is_cancelled()) { + redirect(new moodle_url('/admin/tool/lp/learningplans.php')); +} + +echo $output->header(); +echo $output->heading($pagetitle); + +$data = $form->get_data(); +if ($data) { + // Save the changes and continue back to the manage page. + // Massage the editor data. + $data->descriptionformat = $data->description['format']; + $data->description = $data->description['text']; + if (empty($data->id)) { + // Create new template. + require_sesskey(); + \tool_lp\api::create_template($data); + echo $output->notification(get_string('templatecreated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button('/admin/tool/lp/learningplans.php'); + } else { + require_sesskey(); + \tool_lp\api::update_template($data); + echo $output->notification(get_string('templateupdated', 'tool_lp'), 'notifysuccess'); + echo $output->continue_button('/admin/tool/lp/learningplans.php'); + } +} else { + $form->display(); +} + + +echo $output->footer(); diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php new file mode 100644 index 00000000000..813c8685461 --- /dev/null +++ b/admin/tool/lp/lang/en/tool_lp.php @@ -0,0 +1,102 @@ +. + +/** + * Strings for component 'tool_lp', language 'en' + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$string['pluginname'] = 'Learning Plans'; +$string['lp:learningplanmanage'] = 'Manage learning plans'; +$string['lp:learningplanread'] = 'View learning plans'; +$string['lp:competencymanage'] = 'Manage competency frameworks'; +$string['lp:competencyread'] = 'View competency frameworks'; +$string['lp:coursecompetencymanage'] = 'Manage course competencies'; +$string['lp:coursecompetencyread'] = 'View course competencies'; +$string['competencies'] = 'Competencies'; +$string['competenciesforframework'] = 'Competencies for {$a}'; +$string['competencyframeworks'] = 'Competency Frameworks'; +$string['addnewcompetencyframework'] = 'Add new competency framework'; +$string['addnewtemplate'] = 'Add new learning plan template'; +$string['addnewcompetency'] = 'Add new competency'; +$string['addcompetency'] = 'Add competency'; +$string['editcompetencyframework'] = 'Edit competency framework'; +$string['listcompetencyframeworkscaption'] = 'List of competency frameworks'; +$string['listtemplatescaption'] = 'List of learning plan templates'; +$string['competencyframeworkname'] = 'Name'; +$string['actions'] = 'Actions'; +$string['notemplates'] = 'No learning plan templates have been created yet.'; +$string['nocompetencyframeworks'] = 'No competency frameworks have been created yet.'; +$string['nocompetencies'] = 'No competencies have been created in this framework.'; +$string['nocompetenciesincourse'] = 'No competencies have been linked to this course.'; + +$string['shortname'] = 'Name'; +$string['savechanges'] = 'Save changes'; +$string['description'] = 'Description'; +$string['visible'] = 'Visible'; +$string['visible_help'] = 'A competency framework can be hidden from teachers. This could be useful if a framework is still in the process of being developed.'; +$string['idnumber'] = 'Id number'; +$string['competencyframework'] = 'Competency framework'; +$string['parentcompetency'] = 'Parent competency'; +$string['competencyframeworkcreated'] = 'Competency framework created.'; +$string['competencyframeworkupdated'] = 'Competency framework updated.'; +$string['editcompetencyframework'] = 'Edit competency framework'; +$string['editthiscompetencyframework'] = 'Edit'; +$string['deletethiscompetencyframework'] = 'Delete'; +$string['deletethistemplate'] = 'Delete'; +$string['hiddenhint'] = '(hidden)'; +$string['movecompetencyframework'] = 'Move competency framework'; +$string['movetonewparent'] = 'Relocate'; +$string['moveframeworkafter'] = 'Move competency framework after {$a}'; +$string['selectedcompetency'] = 'Selected competency'; +$string['nocompetencyselected'] = 'No competency selected'; +$string['search'] = 'Search...'; +$string['competencycreated'] = 'Competency created'; +$string['competencyupdated'] = 'Competency updated'; +$string['hidden'] = 'Hidden'; +$string['editcompetency'] = 'Edit competency'; +$string['confirm'] = 'Confirm'; +$string['delete'] = 'Delete'; +$string['deletecompetency'] = 'Delete competency? {$a}'; +$string['deletecompetencyframework'] = 'Delete competency framework? {$a}'; +$string['cancel'] = 'Cancel'; +$string['move'] = 'Move'; +$string['movecompetency'] = 'Move competency: {$a}'; +$string['selectcompetencymovetarget'] = 'Select a location to move this competency to:'; +$string['coursecompetencies'] = 'Course competencies'; +$string['linkcoursecompetencies'] = 'Link course competencies'; +$string['managecompetenciesandframeworks'] = 'Manage competencies and frameworks'; +$string['locatecompetency'] = 'Locate competency'; +$string['itemstoadd'] = 'Items to add'; +$string['linkedcourses'] = 'Linked courses'; +$string['nolinkedcourses'] = 'No courses are using this competency'; +$string['coursesusingthiscompetency'] = 'Courses using this competency'; +$string['learningplans'] = 'Learning plans'; +$string['movecoursecompetency'] = 'Move course competency'; +$string['movecoursecompetencyafter'] = 'Move course competency after {$a}'; + +$string['templates'] = 'Learning plan templates'; +$string['templatename'] = 'Name'; +$string['editthistemplate'] = 'Edit'; +$string['templatecreated'] = 'Learning plan template created'; +$string['templateupdated'] = 'Learning plan template updated'; +$string['edittemplate'] = 'Edit learning plan template'; +$string['deletetemplate'] = 'Delete learning plan template? {$a}'; +$string['duedate'] = 'Due date'; +$string['duedate_help'] = 'The date that a learning plan should be completed by.'; diff --git a/admin/tool/lp/learningplans.php b/admin/tool/lp/learningplans.php new file mode 100644 index 00000000000..bdb782cccfb --- /dev/null +++ b/admin/tool/lp/learningplans.php @@ -0,0 +1,44 @@ +. + +/** + * This page lets users to manage site wide competencies. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(__DIR__ . '/../../../config.php'); +require_once($CFG->libdir.'/adminlib.php'); + +admin_externalpage_setup('toollplearningplans'); + +$title = get_string('learningplans', 'tool_lp'); +$pagetitle = get_string('templates', 'tool_lp'); +// Set up the page. +$url = new moodle_url("/admin/tool/lp/learningplans.php"); +$PAGE->set_url($url); +$PAGE->set_title($title); +$PAGE->set_heading($title); +$output = $PAGE->get_renderer('tool_lp'); +echo $output->header(); +echo $output->heading($pagetitle); + +$page = new \tool_lp\output\manage_templates_page(); +echo $output->render($page); + +echo $output->footer(); diff --git a/admin/tool/lp/lib.php b/admin/tool/lp/lib.php new file mode 100644 index 00000000000..6b72ba71d4c --- /dev/null +++ b/admin/tool/lp/lib.php @@ -0,0 +1,47 @@ +. + +/** + * This page contains navigation hooks for learning plans. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +/** + * This function extends the course navigation + * + * @param navigation_node $navigation The navigation node to extend + * @param stdClass $course The course to object for the tool + * @param context $coursecontext The context of the course + */ +function tool_lp_extend_navigation_course($navigation, $course, $coursecontext) { + // Just a link to course report. + $title = get_string('coursecompetencies', 'tool_lp'); + $path = new moodle_url("/admin/tool/lp/coursecompetencies.php", array('courseid' => $course->id)); + $settingsnode = navigation_node::create($title, + $path, + navigation_node::TYPE_SETTING, + null, + null, + new pix_icon('competency', '', 'tool_lp')); + if (isset($settingsnode)) { + $navigation->add_node($settingsnode); + } +} diff --git a/admin/tool/lp/pix/competency.png b/admin/tool/lp/pix/competency.png new file mode 100644 index 00000000000..52fe956c0ef Binary files /dev/null and b/admin/tool/lp/pix/competency.png differ diff --git a/admin/tool/lp/pix/competency.svg b/admin/tool/lp/pix/competency.svg new file mode 100644 index 00000000000..2f845cee491 --- /dev/null +++ b/admin/tool/lp/pix/competency.svg @@ -0,0 +1,76 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/admin/tool/lp/settings.php b/admin/tool/lp/settings.php new file mode 100644 index 00000000000..3e46a8cabe8 --- /dev/null +++ b/admin/tool/lp/settings.php @@ -0,0 +1,46 @@ +. + +/** + * Links and settings + * + * This file contains links and settings used by tool_lp + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +defined('MOODLE_INTERNAL') || die; + +// Manage competency frameworks page. +$temp = new admin_externalpage( + 'toollpcompetencies', + get_string('competencyframeworks', 'tool_lp'), + new moodle_url('/admin/tool/lp/competencyframeworks.php'), + 'tool/lp:competencymanage' +); +$ADMIN->add('root', $temp, 'badges'); +// Manage learning plans page. +$temp = new admin_externalpage( + 'toollplearningplans', + get_string('learningplans', 'tool_lp'), + new moodle_url('/admin/tool/lp/learningplans.php'), + 'tool/lp:learningplanmanage' +); +$ADMIN->add('root', $temp, 'toollpcompetencies'); + +// No report settings. +$settings = null; diff --git a/admin/tool/lp/styles.css b/admin/tool/lp/styles.css new file mode 100644 index 00000000000..9765b198b1f --- /dev/null +++ b/admin/tool/lp/styles.css @@ -0,0 +1,59 @@ +.path-admin-tool-learningplan [data-region="managecompetencies"] ul li, +.path-admin-tool-learningplan [data-region="competencymovetree"] ul li, +.path-admin-tool-learningplan [data-region="competencylinktree"] ul li { + list-style-type: none; +} + +.path-admin-tool-learningplan [data-region="managecompetencies"] ul li img { + margin-left: -20px; + margin-right: 4px; +} +.dir-rtl.path-admin-tool-learningplan [data-region="managecompetencies"] ul li img { + margin-right: -20px; + margin-left: 4px; +} + +.path-admin-tool-learningplan [data-region="managecompetencies"] ul[data-enhance="tree"], +.path-admin-tool-learningplan [data-region="competencylinktree"] ul[data-enhance="linktree"], +.path-admin-tool-learningplan [data-region="competencymovetree"] ul[data-enhance="movetree"] { + border: 1px solid #ccc; + box-shadow: inset 0 1px 1px rgba(0,0,0,0.075); + transition: border linear .2s,box-shadow linear .2s; + border-radius: 4px; + padding-left: 20px; + padding-right: 20px; + margin-left: 10px; + margin-right: 10px; +} +.path-admin-tool-learningplan [data-region="managecompetencies"] ul, +.path-admin-tool-learningplan [data-region="competencylinktree"] ul, +.path-admin-tool-learningplan [data-region="competencymovetree"] ul { + cursor: pointer; +} +.path-admin-tool-learningplan [data-region="competencylinktree"] ul [aria-selected="true"], +.path-admin-tool-learningplan [data-region="competencymovetree"] ul [aria-selected="true"], +.path-admin-tool-learningplan [data-region="managecompetencies"] ul [aria-selected="true"] { + background-color: #dfdfdf; +} +.path-admin-tool-learningplan [data-region="filtercompetencies"] input { + margin-left: 10px; +} + +.path-admin-tool-learningplan [data-region="link-buttons"], +.path-admin-tool-learningplan [data-region="move-buttons"] { + text-align: center; +} + +.dir-rtl.path-admin-tool-learningplan [data-region="filtercompetencies"] input { + margin-right: 10px; +} + +.path-admin-tool-learningplan [data-region="competencyactionsmenu"] { + display: none; +} +.path-admin-tool-learningplan [data-region="competencyactionsmenu"] .moodle-actionmenu[data-enhanced].show .menu { + white-space: nowrap; +} +.path-admin-tool-learningplan .currentdragtarget { + border: 1px dashed; +} diff --git a/admin/tool/lp/templates/competencies_move_tree.mustache b/admin/tool/lp/templates/competencies_move_tree.mustache new file mode 100644 index 00000000000..06585110285 --- /dev/null +++ b/admin/tool/lp/templates/competencies_move_tree.mustache @@ -0,0 +1,46 @@ +{{! + 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 . +}} +{{! + Manage competencies template. + + Classes required for JS: + + Data attibutes required for JS: + * data-enhance=tree + + Context variables required for this template: + * framework - + * competencies - array of objects containing id, shortname, idnumber, sortorder, visible, parentid, competencyframeworkid, path +}} +
+ + +
    +
  • {{framework.shortname}} +
      + {{#competencies}} + {{> tool_lp/competencies_tree }} + {{/competencies}} +
    +
  • +
+
+ +
+ + +
diff --git a/admin/tool/lp/templates/competencies_tree.mustache b/admin/tool/lp/templates/competencies_tree.mustache new file mode 100644 index 00000000000..e28a967acc2 --- /dev/null +++ b/admin/tool/lp/templates/competencies_tree.mustache @@ -0,0 +1,12 @@ +
  • + {{^visible}}{{/visible}} + {{shortname}} {{idnumber}} + {{^visible}}{{/visible}} + {{#haschildren}} +
      + {{#children}} + {{> tool_lp/competencies_tree }} + {{/children}} +
    + {{/haschildren}} +
  • diff --git a/admin/tool/lp/templates/competency_summary.mustache b/admin/tool/lp/templates/competency_summary.mustache new file mode 100644 index 00000000000..d2cbe68a04d --- /dev/null +++ b/admin/tool/lp/templates/competency_summary.mustache @@ -0,0 +1,5 @@ +

    {{shortname}} {{idnumber}}

    +

    {{descriptionformatted}}

    +{{^visible}} +( {{#str}} hidden, tool_lp{{/str}}) +{{/visible}} diff --git a/admin/tool/lp/templates/course_competencies_page.mustache b/admin/tool/lp/templates/course_competencies_page.mustache new file mode 100644 index 00000000000..f57a4044368 --- /dev/null +++ b/admin/tool/lp/templates/course_competencies_page.mustache @@ -0,0 +1,56 @@ +{{! + 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 . +}} +{{! + Course competencies template. +}} +
    +
    + + +{{#competencies}} + + + +{{/competencies}} + +
    + + + {{> tool_lp/competency_summary }} +
    +{{^competencies}} +

    + {{#str}}nocompetenciesincourse, tool_lp{{/str}} +

    +{{/competencies}} +
    +
    +
    +{{#canmanagecoursecompetencies}} + +{{/canmanagecoursecompetencies}} +
    +{{#canmanagecompetencyframeworks}} +

    {{#str}}managecompetenciesandframeworks, tool_lp{{/str}}

    +{{/canmanagecompetencyframeworks}} +
    +
    +{{#js}} +require(['tool_lp/coursecompetencies'], function(mod) { + (new mod({{courseid}})); +}); +{{/js}} diff --git a/admin/tool/lp/templates/link_course_competencies.mustache b/admin/tool/lp/templates/link_course_competencies.mustache new file mode 100644 index 00000000000..d57e2e7c102 --- /dev/null +++ b/admin/tool/lp/templates/link_course_competencies.mustache @@ -0,0 +1,29 @@ +
    +

    {{#str}}competencyframeworks, tool_lp{{/str}}

    + +

    {{#str}}locatecompetency, tool_lp{{/str}}

    + + +
    + + + +
    +
      +
    • {{framework.shortname}} +
        + {{#competencies}} + {{> tool_lp/competencies_tree }} + {{/competencies}} +
      +
    • +
    +
    + + +
    +
    diff --git a/admin/tool/lp/templates/linked_courses_summary.mustache b/admin/tool/lp/templates/linked_courses_summary.mustache new file mode 100644 index 00000000000..9b6490579db --- /dev/null +++ b/admin/tool/lp/templates/linked_courses_summary.mustache @@ -0,0 +1,11 @@ +

    +{{#str}}coursesusingthiscompetency, tool_lp{{/str}} +

    +
      +{{#courses}} +
    1. {{{fullnameformatted}}} {{{shortnameformatted}}}
    2. +{{/courses}} +{{^courses}} + {{#str}}nolinkedcourses, tool_lp{{/str}} +{{/courses}} +
    diff --git a/admin/tool/lp/templates/manage_competencies_page.mustache b/admin/tool/lp/templates/manage_competencies_page.mustache new file mode 100644 index 00000000000..0108f278112 --- /dev/null +++ b/admin/tool/lp/templates/manage_competencies_page.mustache @@ -0,0 +1,114 @@ +{{! + 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 . +}} +{{! + Manage competencies template. + + Classes required for JS: + + Data attibutes required for JS: + * data-enhance=tree + + Context variables required for this template: + * framework - + * competencies - array of objects containing id, shortname, idnumber, sortorder, visible, parentid, competencyframeworkid, path + * canmanage - true if this user has permission to manage the competencies +}} +
    + +
    +
    +

    +

    + + + +
    +

    +
      +
    • {{framework.shortname}} +
        + {{#competencies}} + {{> tool_lp/competencies_tree }} + {{/competencies}} +
      +
    • +
    +
    + +
    +

    {{#str}}selectedcompetency, tool_lp{{/str}}

    +

    +{{#str}}nocompetencyselected, tool_lp{{/str}} +

    +{{#canmanage}} + +{{/canmanage}} +
    +
    + +{{#js}} +// Initialise the JS. +require(['core/tree', 'tool_lp/competencytree', 'tool_lp/competencyactions' ], function(ariatree, treeModel, actions) { + + treeModel.init({{framework.id}}); + + actions.init(treeModel); + + var competencytree = new ariatree('[data-enhance=tree]', actions.selectionChanged); + +}); +{{/js}} + +
    diff --git a/admin/tool/lp/templates/manage_competency_frameworks_page.mustache b/admin/tool/lp/templates/manage_competency_frameworks_page.mustache new file mode 100644 index 00000000000..fbe0df59c82 --- /dev/null +++ b/admin/tool/lp/templates/manage_competency_frameworks_page.mustache @@ -0,0 +1,100 @@ +{{! + 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 . +}} +{{! + Manage competency frameworks template. + + Classes required for JS: + * drag-parentnode + * drag-handlecontainer + * drag-samenode + * competencyframeworkactions + + Data attibutes required for JS: + * data-region = managecompetencies + * data-frameworkid = id + * data-action = deletecompetencyframework + + Context variables required for this template: + * competencyframeworks - array of objects containing id, shortname, idnumber, sortorder, visible + * canmanage - true if this user has permission to manage the frameworks + * navigation - array of strings containing buttons for navigation +}} +
    + + + + + + + + + + + {{#competencyframeworks}} + + + + + + {{/competencyframeworks}} + +
    {{#str}}listcompetencyframeworkscaption, tool_lp{{/str}}
    {{#str}}competencyframeworkname, tool_lp{{/str}}{{#str}}competencies, tool_lp{{/str}}{{#str}}actions, tool_lp{{/str}}
    {{shortname}} {{idnumber}} {{^visible}}{{#str}}hiddenhint, tool_lp{{/str}}{{/visible}}{{competencies_count}} + {{#canmanage}} + + {{/canmanage}} +
    +{{^competencyframeworks}} +

    + {{#str}}nocompetencyframeworks, tool_lp{{/str}} +

    +{{/competencyframeworks}} + +
    +{{#navigation}} +{{{.}}} +{{/navigation}} +
    + +{{#js}} +// Initialise the JS. +require(['tool_lp/frameworkdelete', + 'core/menu', + 'tool_lp/frameworkmove'], + function(deleteMod, menu, moveMod) { + + deleteMod.init(); + moveMod.init(); + + menu.menu('{{#str}}edit{{/str}}', '.competencyframeworkactions'); +}); + +{{/js}} + +
    diff --git a/admin/tool/lp/templates/manage_templates_page.mustache b/admin/tool/lp/templates/manage_templates_page.mustache new file mode 100644 index 00000000000..eb17c8cd775 --- /dev/null +++ b/admin/tool/lp/templates/manage_templates_page.mustache @@ -0,0 +1,98 @@ +{{! + 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 . +}} +{{! + Manage learning plan templates template. + + Classes required for JS: + * drag-parentnode + * drag-handlecontainer + * drag-samenode + * templateactions + + Data attibutes required for JS: + * data-region = managetemplates + * data-templateid = id + * data-action = deletetemplate + + Context variables required for this template: + * templates - array of objects containing id, shortname, idnumber, sortorder, visible + * canmanage - true if this user has permission to manage the templates + * navigation - array of strings containing buttons for navigation +}} +
    + + + + + + + + + + {{#templates}} + + + + + {{/templates}} + +
    {{#str}}listtemplatescaption, tool_lp{{/str}}
    {{#str}}templatename, tool_lp{{/str}}{{#str}}actions, tool_lp{{/str}}
    {{shortname}} {{idnumber}} {{^visible}}{{#str}}hiddenhint, tool_lp{{/str}}{{/visible}} + {{#canmanage}} + + {{/canmanage}} +
    +{{^templates}} +

    + {{#str}}notemplates, tool_lp{{/str}} +

    +{{/templates}} + +
    +{{#navigation}} +{{{.}}} +{{/navigation}} +
    + +{{#js}} +// Initialise the JS. +require(['tool_lp/templatedelete', + 'core/menu', + 'tool_lp/templatemove'], + function(deleteMod, menu, moveMod) { + + deleteMod.init(); + moveMod.init(); + + menu.menu('{{#str}}edit{{/str}}', '.templateactions'); +}); + +{{/js}} + +
    diff --git a/admin/tool/lp/templates/no_frameworks_warning.mustache b/admin/tool/lp/templates/no_frameworks_warning.mustache new file mode 100644 index 00000000000..d93b418a970 --- /dev/null +++ b/admin/tool/lp/templates/no_frameworks_warning.mustache @@ -0,0 +1,3 @@ +

    + {{#str}}nocompetencyframeworks, tool_lp{{/str}} +

    diff --git a/admin/tool/lp/tests/externallib_test.php b/admin/tool/lp/tests/externallib_test.php new file mode 100644 index 00000000000..6b2588ae04c --- /dev/null +++ b/admin/tool/lp/tests/externallib_test.php @@ -0,0 +1,578 @@ +. + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/webservice/tests/helpers.php'); + +use tool_lp\external; + +/** + * External learning plans webservice API tests. + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_lp_external_testcase extends externallib_advanced_testcase { + + /** @var stdClass $learningplancreator User with enough permissions to create */ + protected $creator = null; + + /** @var stdClass $learningplanuser User with enough permissions to view */ + protected $user = null; + + /** + * Setup function - we will create a course and add an assign instance to it. + */ + protected function setUp() { + global $DB; + + $this->resetAfterTest(true); + + // Create some users. + $creator = $this->getDataGenerator()->create_user(); + $user = $this->getDataGenerator()->create_user(); + $syscontext = context_system::instance(); + + $creatorrole = create_role('Creator role', 'creatorrole', 'learning plan creator role description'); + $userrole = create_role('User role', 'userrole', 'learning plan user role description'); + + assign_capability('tool/lp:competencymanage', CAP_ALLOW, $creatorrole, $syscontext->id); + assign_capability('tool/lp:competencyview', CAP_ALLOW, $userrole, $syscontext->id); + + role_assign($creatorrole, $creator->id, $syscontext->id); + role_assign($userrole, $user->id, $syscontext->id); + + $this->creator = $creator; + $this->user = $user; + accesslib_clear_all_caches_for_unit_testing(); + } + + /** + * Test we can't create a competency framework with only read permissions. + */ + public function test_create_competency_frameworks_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->user); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + } + + /** + * Test we can create a competency framework with manage permissions. + */ + public function test_create_competency_frameworks_with_manage_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we cannot create a competency framework with nasty data. + */ + public function test_create_competency_frameworks_with_nasty_data() { + $this->setUser($this->creator); + $this->setExpectedException('invalid_parameter_exception'); + $result = external::create_competency_framework('short', 'id;"number', 'de<>\\..scription', FORMAT_HTML, true); + } + + /** + * Test we can read a competency framework with manage permissions. + */ + public function test_read_competency_frameworks_with_manage_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $id = $result->id; + $result = external::read_competency_framework($id); + $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result); + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can read a competency framework with read permissions. + */ + public function test_read_competency_frameworks_with_read_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + // Switch users to someone with less permissions. + $this->setUser($this->user); + $id = $result->id; + $result = external::read_competency_framework($id); + $result = (object) external_api::clean_returnvalue(external::read_competency_framework_returns(), $result); + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can delete a competency framework with manage permissions. + */ + public function test_delete_competency_frameworks_with_manage_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $id = $result->id; + $result = external::delete_competency_framework($id); + $result = external_api::clean_returnvalue(external::delete_competency_framework_returns(), $result); + + $this->assertTrue($result); + } + + /** + * Test we can delete a competency framework with read permissions. + */ + public function test_delete_competency_frameworks_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $id = $result->id; + // Switch users to someone with less permissions. + $this->setUser($this->user); + $result = external::delete_competency_framework($id); + } + + /** + * Test we can update a competency framework with manage permissions. + */ + public function test_update_competency_frameworks_with_manage_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $result = external::update_competency_framework($result->id, 'shortname2', 'idnumber2', 'description2', FORMAT_PLAIN, false); + $result = external_api::clean_returnvalue(external::update_competency_framework_returns(), $result); + + $this->assertTrue($result); + } + + /** + * Test we can update a competency framework with read permissions. + */ + public function test_update_competency_frameworks_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $result); + + $this->setUser($this->user); + $result = external::update_competency_framework($result->id, 'shortname2', 'idnumber2', 'description2', FORMAT_PLAIN, false); + } + + /** + * Test we can list and count competency frameworks with manage permissions. + */ + public function test_list_and_count_competency_frameworks_with_manage_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = external::create_competency_framework('shortname2', 'idnumber2', 'description', FORMAT_HTML, true); + $result = external::create_competency_framework('shortname3', 'idnumber3', 'description', FORMAT_HTML, true); + + $result = external::count_competency_frameworks(array()); + $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result); + + $this->assertEquals($result, 3); + + $result = external::list_competency_frameworks(array(), 'shortname', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result); + + $this->assertEquals(count($result), 3); + $result = (object) $result[0]; + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can list and count competency frameworks with read permissions. + */ + public function test_list_and_count_competency_frameworks_with_read_permissions() { + $this->setUser($this->creator); + $result = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $result = external::create_competency_framework('shortname2', 'idnumber2', 'description', FORMAT_HTML, true); + $result = external::create_competency_framework('shortname3', 'idnumber3', 'description', FORMAT_HTML, true); + + $this->setUser($this->user); + $result = external::count_competency_frameworks(array()); + $result = external_api::clean_returnvalue(external::count_competency_frameworks_returns(), $result); + + $this->assertEquals($result, 3); + + $result = external::list_competency_frameworks(array(), 'shortname', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result); + + $this->assertEquals(count($result), 3); + $result = (object) $result[0]; + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can re-order competency frameworks. + */ + public function test_reorder_competency_framework() { + $this->setUser($this->creator); + $f1 = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $f2 = external::create_competency_framework('shortname2', 'idnumber2', 'description', FORMAT_HTML, true); + $f3 = external::create_competency_framework('shortname3', 'idnumber3', 'description', FORMAT_HTML, true); + $f4 = external::create_competency_framework('shortname4', 'idnumber4', 'description', FORMAT_HTML, true); + $f5 = external::create_competency_framework('shortname5', 'idnumber5', 'description', FORMAT_HTML, true); + $f6 = external::create_competency_framework('shortname6', 'idnumber6', 'description', FORMAT_HTML, true); + + // This is a move up. + $result = external::reorder_competency_framework($f5->id, $f2->id); + $result = external::list_competency_frameworks(array(), 'sortorder', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result); + + $r1 = (object) $result[0]; + $r2 = (object) $result[1]; + $r3 = (object) $result[2]; + $r4 = (object) $result[3]; + $r5 = (object) $result[4]; + $r6 = (object) $result[5]; + + $this->assertEquals($f1->id, $r1->id); + $this->assertEquals($f5->id, $r2->id); + $this->assertEquals($f2->id, $r3->id); + $this->assertEquals($f3->id, $r4->id); + $this->assertEquals($f4->id, $r5->id); + $this->assertEquals($f6->id, $r6->id); + + // This is a move down. + $result = external::reorder_competency_framework($f5->id, $f4->id); + $result = external::list_competency_frameworks(array(), 'sortorder', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competency_frameworks_returns(), $result); + + $r1 = (object) $result[0]; + $r2 = (object) $result[1]; + $r3 = (object) $result[2]; + $r4 = (object) $result[3]; + $r5 = (object) $result[4]; + $r6 = (object) $result[5]; + + $this->assertEquals($f1->id, $r1->id); + $this->assertEquals($f2->id, $r2->id); + $this->assertEquals($f3->id, $r3->id); + $this->assertEquals($f4->id, $r4->id); + $this->assertEquals($f5->id, $r5->id); + $this->assertEquals($f6->id, $r6->id); + + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->user); + $result = external::reorder_competency_framework($f5->id, $f4->id); + } + + /** + * Test we can't create a competency with only read permissions. + */ + public function test_create_competency_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $this->setUser($this->user); + $competency = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + } + + /** + * Test we can create a competency with manage permissions. + */ + public function test_create_competency_with_manage_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + + $competency = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $competency = (object) external_api::clean_returnvalue(external::create_competency_returns(), $competency); + + $this->assertGreaterThan(0, $competency->timecreated); + $this->assertGreaterThan(0, $competency->timemodified); + $this->assertEquals($this->creator->id, $competency->usermodified); + $this->assertEquals('shortname', $competency->shortname); + $this->assertEquals('idnumber', $competency->idnumber); + $this->assertEquals('description', $competency->description); + $this->assertEquals(FORMAT_HTML, $competency->descriptionformat); + $this->assertEquals(true, $competency->visible); + $this->assertEquals(0, $competency->parentid); + $this->assertEquals($framework->id, $competency->competencyframeworkid); + } + + /** + * Test we cannot create a competency with nasty data. + */ + public function test_create_competency_with_nasty_data() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $this->setExpectedException('invalid_parameter_exception'); + $competency = external::create_competency('shortname', 'id;"number', 'de<>\\..scription', FORMAT_HTML, true, $framework->id, 0); + } + + /** + * Test we can read a competency with manage permissions. + */ + public function test_read_competencies_with_manage_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + $id = $result->id; + $result = external::read_competency($id); + $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result); + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + $this->assertEquals(0, $result->parentid); + $this->assertEquals(0, $result->parentid); + } + + /** + * Test we can read a competency with read permissions. + */ + public function test_read_competencies_with_read_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + // Switch users to someone with less permissions. + $this->setUser($this->user); + $id = $result->id; + $result = external::read_competency($id); + $result = (object) external_api::clean_returnvalue(external::read_competency_returns(), $result); + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(FORMAT_HTML, $result->descriptionformat); + $this->assertEquals(true, $result->visible); + $this->assertEquals(0, $result->parentid); + $this->assertEquals(0, $result->parentid); + } + + /** + * Test we can delete a competency with manage permissions. + */ + public function test_delete_competency_with_manage_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + $id = $result->id; + $result = external::delete_competency($id); + $result = external_api::clean_returnvalue(external::delete_competency_returns(), $result); + + $this->assertTrue($result); + } + + /** + * Test we can delete a competency with read permissions. + */ + public function test_delete_competency_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + $id = $result->id; + // Switch users to someone with less permissions. + $this->setUser($this->user); + $result = external::delete_competency($id); + } + + /** + * Test we can update a competency with manage permissions. + */ + public function test_update_competency_with_manage_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + $result = external::update_competency($result->id, 'shortname2', 'idnumber2', 'description2', FORMAT_HTML, false); + $result = external_api::clean_returnvalue(external::update_competency_returns(), $result); + + $this->assertTrue($result); + } + + /** + * Test we can update a competency with read permissions. + */ + public function test_update_competency_with_read_permissions() { + $this->setExpectedException('required_capability_exception'); + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = (object) external_api::clean_returnvalue(external::create_competency_returns(), $result); + + $this->setUser($this->user); + $result = external::update_competency($result->id, 'shortname2', 'idnumber2', 'description2', FORMAT_HTML, false); + } + + /** + * Test we can list and count competencies with manage permissions. + */ + public function test_list_and_count_competencies_with_manage_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname2', 'idnumber2', 'description2', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname3', 'idnumber3', 'description3', FORMAT_HTML, true, $framework->id, 0); + + $result = external::count_competencies(array()); + $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result); + + $this->assertEquals($result, 3); + + $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result); + + $this->assertEquals(count($result), 3); + $result = (object) $result[0]; + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can list and count competencies with read permissions. + */ + public function test_list_and_count_competencies_with_read_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname2', 'idnumber2', 'description2', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname3', 'idnumber3', 'description3', FORMAT_HTML, true, $framework->id, 0); + + $this->setUser($this->user); + + $result = external::count_competencies(array()); + $result = external_api::clean_returnvalue(external::count_competencies_returns(), $result); + + $this->assertEquals($result, 3); + + $result = external::list_competencies(array(), 'shortname', 'ASC', 0, 10); + $result = external_api::clean_returnvalue(external::list_competencies_returns(), $result); + + $this->assertEquals(count($result), 3); + $result = (object) $result[0]; + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(true, $result->visible); + } + + /** + * Test we can search for competencies. + */ + public function test_search_competencies_with_read_permissions() { + $this->setUser($this->creator); + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, true); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + $result = external::create_competency('shortname', 'idnumber', 'description', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname2', 'idnumber2', 'description2', FORMAT_HTML, true, $framework->id, 0); + $result = external::create_competency('shortname3', 'idnumber3', 'description3', FORMAT_HTML, true, $framework->id, 0); + + $this->setUser($this->user); + + $result = external::search_competencies('short', $framework->id); + $result = external_api::clean_returnvalue(external::search_competencies_returns(), $result); + + $this->assertEquals(count($result), 3); + $result = (object) $result[0]; + + $this->assertGreaterThan(0, $result->timecreated); + $this->assertGreaterThan(0, $result->timemodified); + $this->assertEquals($this->creator->id, $result->usermodified); + $this->assertEquals('shortname', $result->shortname); + $this->assertEquals('idnumber', $result->idnumber); + $this->assertEquals('description', $result->description); + $this->assertEquals(true, $result->visible); + } + +} diff --git a/admin/tool/lp/version.php b/admin/tool/lp/version.php new file mode 100644 index 00000000000..118814e480b --- /dev/null +++ b/admin/tool/lp/version.php @@ -0,0 +1,30 @@ +. + +/** + * Plugin version info + * + * @package tool_lp + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2015021623; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2014110400; // Requires this Moodle version. +$plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics). + diff --git a/lib/amd/src/dialogue.js b/lib/amd/src/dialogue.js new file mode 100644 index 00000000000..034239e543c --- /dev/null +++ b/lib/amd/src/dialogue.js @@ -0,0 +1,76 @@ +// 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 . + +/** + * Wrapper for the YUI M.core.notification class. Allows us to + * use the YUI version in AMD code until it is replaced. + * + * @module core/dialogue + * @package core + * @copyright 2015 Damyon Wiese + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['core/yui'], function(Y) { + + // Private variables and functions. + /** + * Constructor + * + * @param {string} title Title for the window. + * @param {string} content The content for the window. + * @param {function} afterShow Callback executed after the window is opened. + */ + var dialogue = function(title, content, afterShow) { + this.yuiDialogue = null; + var parent = this; + + Y.use('moodle-core-notification', function () { + + parent.yuiDialogue = new M.core.dialogue({ + headerContent: title, + bodyContent: content, + draggable: true, + visible: false, + center: true, + modal: true + }); + + parent.yuiDialogue.after('visibleChange', function(e) { + if (e.newVal) { + afterShow(parent); + } + }); + + parent.yuiDialogue.show(); + }); + }; + + /** + * Close this window. + */ + dialogue.prototype.close = function() { + this.yuiDialogue.hide(); + this.yuiDialogue.destroy(); + }; + + /** + * Get content. + */ + dialogue.prototype.getContent = function() { + return this.yuiDialogue.bodyNode.getDOMNode(); + }; + + return /** @alias module:core/dialogue */ dialogue; +}); diff --git a/lib/amd/src/url.js b/lib/amd/src/url.js index b3263eec3d5..047e739e997 100644 --- a/lib/amd/src/url.js +++ b/lib/amd/src/url.js @@ -70,7 +70,7 @@ define(['core/config'], function(config) { } // Fix admin urls. - if (config.admin !== 'admin') { + if (typeof config.admin != "undefined" && config.admin !== 'admin') { relativePath = relativePath.replace(/^\/admin\//, '/' + config.admin + '/'); } return config.wwwroot + relativePath;