diff --git a/admin/tool/lp/classes/api.php b/admin/tool/lp/classes/api.php
index 1f2f77be4e2..1f817df628e 100644
--- a/admin/tool/lp/classes/api.php
+++ b/admin/tool/lp/classes/api.php
@@ -1306,6 +1306,52 @@ class api {
return $plan->delete();
}
+ /**
+ * List the competencies in a user plan.
+ *
+ * @param int $planorid The plan, or its ID.
+ * @return array((object) array('competency' => competency, 'usercompetency' => user_competency))
+ */
+ public static function list_plan_competencies($planorid) {
+ $plan = $planorid;
+ if (!is_object($planorid)) {
+ $plan = new plan($planorid);
+ }
+
+ if (!$plan->can_read()) {
+ $context = context_user::instance($plan->get_userid());
+ throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', '');
+ }
+
+ $result = array();
+ $competencies = $plan->get_competencies();
+ $usercompetencies = user_competency::get_multiple($plan->get_userid(), $competencies);
+
+ // Build the return values.
+ foreach ($competencies as $key => $competency) {
+ $found = false;
+
+ foreach ($usercompetencies as $uckey => $uc) {
+ if ($uc->get_competencyid() == $competency->get_id()) {
+ $found = true;
+ unset($usercompetencies[$uckey]);
+ break;
+ }
+ }
+
+ if (!$found) {
+ $uc = user_competency::create_relation($plan->get_userid(), $competency->get_id());
+ }
+
+ $result[] = (object) array(
+ 'competency' => $competency,
+ 'usercompetency' => $uc,
+ );
+ }
+
+ return $result;
+ }
+
/**
* List all the related competencies.
*
diff --git a/admin/tool/lp/classes/competency_framework.php b/admin/tool/lp/classes/competency_framework.php
index 79ab66972e9..844390b567b 100644
--- a/admin/tool/lp/classes/competency_framework.php
+++ b/admin/tool/lp/classes/competency_framework.php
@@ -27,6 +27,8 @@ use context;
use lang_string;
use stdClass;
+require_once($CFG->libdir . '/grade/grade_scale.php');
+
/**
* Class for loading/storing competency frameworks from the DB.
*
@@ -111,6 +113,17 @@ class competency_framework extends persistent {
);
}
+ /**
+ * Return the scale.
+ *
+ * @return \grade_scale
+ */
+ public function get_scale() {
+ $scale = \grade_scale::fetch(array('id' => $this->get_scaleid()));
+ $scale->load_items();
+ return $scale;
+ }
+
/**
* Get the constant name for a level.
*
diff --git a/admin/tool/lp/classes/external.php b/admin/tool/lp/classes/external.php
index 69651c48fd1..4ec68a91972 100644
--- a/admin/tool/lp/classes/external.php
+++ b/admin/tool/lp/classes/external.php
@@ -865,6 +865,69 @@ class external extends external_api {
return new external_single_structure($returns);
}
+ /**
+ * Returns the external structure of a full user_competency record.
+ *
+ * @return \external_single_structure
+ */
+ protected static function get_user_competency_external_structure() {
+ $id = new external_value(
+ PARAM_INT,
+ 'Database record id'
+ );
+ $userid = new external_value(
+ PARAM_INT,
+ 'User to whom this record belongs to'
+ );
+ $competencyid = new external_value(
+ PARAM_INT,
+ 'The competency associated with this record'
+ );
+ $status = new external_value(
+ PARAM_INT,
+ 'The status of the user competency'
+ );
+ $reviewerid = new external_value(
+ PARAM_INT,
+ 'The reviewer ID'
+ );
+ $proficiency = new external_value(
+ PARAM_BOOL,
+ 'Whether or not the user is proficient'
+ );
+ $grade = new external_value(
+ PARAM_INT,
+ 'The scale grade'
+ );
+ $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,
+ 'userid' => $userid,
+ 'competencyid' => $competencyid,
+ 'status' => $status,
+ 'reviewerid' => $reviewerid,
+ 'proficiency' => $proficiency,
+ 'grade' => $grade,
+ 'timecreated' => $timecreated,
+ 'timemodified' => $timemodified,
+ 'usermodified' => $usermodified,
+ );
+
+ return new external_single_structure($returns);
+ }
+
/**
* Returns description of create_competency() parameters.
*
@@ -3356,6 +3419,50 @@ class external extends external_api {
));
}
+ /**
+ * External function parameters structure.
+ *
+ * @return \external_description
+ */
+ public static function list_plan_competencies_parameters() {
+ return new external_single_structure(array(
+ 'id' => new external_value(PARAM_INT, 'The plan ID.')
+ ));
+ }
+
+ /**
+ * List plan competencies.
+ * @param int $id The plan ID.
+ * @return array
+ */
+ public static function list_plan_competencies($id) {
+ $params = self::validate_parameters(self::list_plan_competencies_parameters(), array('id' => $id));
+ $id = $params['id'];
+ $plan = api::read_plan($id);
+ $result = api::list_plan_competencies($plan);
+ foreach ($result as $key => $r) {
+ $r->competency = $r->competency->to_record();
+ $r->competency->descriptionformatted = format_text($r->competency->description,
+ $r->competency->descriptionformat, array('context' => $plan->get_context()));
+ $r->usercompetency = $r->usercompetency->to_record();
+ }
+ return $result;
+ }
+
+ /**
+ * External function return structure.
+ *
+ * @return \external_description
+ */
+ public static function list_plan_competencies_returns() {
+ return new external_multiple_structure(
+ new external_single_structure(array(
+ 'competency' => self::get_competency_external_structure(),
+ 'usercompetency' => self::get_user_competency_external_structure(),
+ )
+ ));
+ }
+
/**
* Returns the description of the get_scale_values() parameters.
*
diff --git a/admin/tool/lp/classes/output/plan_page.php b/admin/tool/lp/classes/output/plan_page.php
new file mode 100644
index 00000000000..cf1f3154b0c
--- /dev/null
+++ b/admin/tool/lp/classes/output/plan_page.php
@@ -0,0 +1,114 @@
+.
+
+/**
+ * Plan page output.
+ *
+ * @package tool_lp
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace tool_lp\output;
+
+use renderable;
+use templatable;
+use stdClass;
+use tool_lp\api;
+use tool_lp\user_competency;
+use context_user;
+
+/**
+ * Plan page class.
+ *
+ * @package tool_lp
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class plan_page implements renderable, templatable {
+
+ /** @var plan */
+ protected $plan;
+
+ /**
+ * Construct.
+ *
+ * @param plan $plan
+ */
+ public function __construct($plan) {
+ $this->plan = $plan;
+ }
+
+ /**
+ * Export the data.
+ *
+ * @param renderer_base $output
+ * @return stdClass
+ */
+ public function export_for_template(\renderer_base $output) {
+ $options = array('context' => $this->plan->get_context());
+ $frameworks = array();
+ $scales = array();
+
+ $data = new stdClass();
+ $data->competencies = array();
+
+ $pclist = api::list_plan_competencies($this->plan);
+ foreach ($pclist as $pc) {
+ $comp = $pc->competency;
+ $usercomp = $pc->usercompetency;
+
+ if (!isset($frameworks[$comp->get_competencyframeworkid()])) {
+ $frameworks[$comp->get_competencyframeworkid()] = $comp->get_framework();
+ }
+ $framework = $frameworks[$comp->get_competencyframeworkid()];
+ if (!isset($scales[$framework->get_scaleid()])) {
+ $scales[$framework->get_scaleid()] = $framework->get_scale();
+ }
+ $scale = $scales[$framework->get_scaleid()];
+
+ // Prepare the data.
+ $competency = $comp->to_record();
+ $competency->descriptionformatted = format_text($competency->description, $competency->descriptionformat, $options);
+ $usercompetency = $usercomp->to_record();
+ $competency->usercompetency = $usercompetency;
+
+ if ($usercompetency->grade === null) {
+ $gradename = '-';
+ } else {
+ $gradename = format_string($scale->scale_items[$usercompetency->grade - 1], null, $options);
+ }
+
+ if ($usercompetency->proficiency === null) {
+ $proficiencyname = '-';
+ } else {
+ $proficiencyname = get_string($usercompetency->proficiency ? 'yes' : 'no');
+ }
+
+ $statusname = '-';
+ if ($usercompetency->status != user_competency::STATUS_IDLE) {
+ $statusname = (string) user_competency::get_status_name($usercompetency->status);
+ }
+
+ $usercompetency->gradename = $gradename;
+ $usercompetency->proficiencyname = $proficiencyname;
+ $usercompetency->statusname = $statusname;
+
+ $data->competencies[] = $competency;
+ }
+
+ return $data;
+ }
+}
diff --git a/admin/tool/lp/classes/output/renderer.php b/admin/tool/lp/classes/output/renderer.php
index 6b6d1944e9a..a06514c632b 100644
--- a/admin/tool/lp/classes/output/renderer.php
+++ b/admin/tool/lp/classes/output/renderer.php
@@ -98,6 +98,17 @@ class renderer extends plugin_renderer_base {
return parent::render_from_template('tool_lp/manage_templates_page', $data);
}
+ /**
+ * Defer to template.
+ *
+ * @param plan_page $page
+ * @return bool|string
+ */
+ public function render_plan_page(plan_page $page) {
+ $data = $page->export_for_template($this);
+ return parent::render_from_template('tool_lp/plan_page', $data);
+ }
+
/**
* Defer to template.
*
diff --git a/admin/tool/lp/classes/persistent.php b/admin/tool/lp/classes/persistent.php
index fbd27618827..1c5ad2207c8 100644
--- a/admin/tool/lp/classes/persistent.php
+++ b/admin/tool/lp/classes/persistent.php
@@ -629,7 +629,7 @@ abstract class persistent {
* @param int $skip Limitstart.
* @param int $limit Number of rows to return.
*
- * @return persistent[]
+ * @return \tool_lp\persistent[]
*/
public static function get_records($filters = array(), $sort = '', $order = 'ASC', $skip = 0, $limit = 0) {
global $DB;
@@ -658,7 +658,7 @@ abstract class persistent {
* @param string $fields
* @param int $limitfrom
* @param int $limitnum
- * @return \tool_lp\plan[]
+ * @return \tool_lp\persistent[]
*/
public static function get_records_select($select, $params = null, $sort = '', $fields = '*', $limitfrom = 0, $limitnum = 0) {
global $DB;
diff --git a/admin/tool/lp/classes/plan.php b/admin/tool/lp/classes/plan.php
index d130608cb76..767b10aa0c2 100644
--- a/admin/tool/lp/classes/plan.php
+++ b/admin/tool/lp/classes/plan.php
@@ -109,6 +109,33 @@ class plan extends persistent {
return self::can_read_user($this->get_userid());
}
+ /**
+ * Get the competencies in this plan.
+ *
+ * @return competency[]
+ */
+ public function get_competencies() {
+ $competencies = array();
+ if ($this->get_templateid()) {
+ // Get the competencies from the template.
+ $competencies = template_competency::list_competencies($this->get_templateid(), true);
+ } else {
+ // TODO MDL-50328.
+ // Get the competencies in this plan.
+ // $competencies = plan_competency::list_competencies($this->get_id());
+ }
+ return $competencies;
+ }
+
+ /**
+ * Get the context in which the plan is attached.
+ *
+ * @return context_user
+ */
+ public function get_context() {
+ return context_user::instance($this->get_userid());
+ }
+
/**
* Human readable status name.
*
diff --git a/admin/tool/lp/classes/template_competency.php b/admin/tool/lp/classes/template_competency.php
index 2b9a53a7726..7aeeb10c04d 100644
--- a/admin/tool/lp/classes/template_competency.php
+++ b/admin/tool/lp/classes/template_competency.php
@@ -157,8 +157,7 @@ class template_competency extends persistent {
FROM {' . competency::TABLE . '} comp
JOIN {' . self::TABLE . '} tplcomp
ON tplcomp.competencyid = comp.id
- WHERE tplcomp.templateid = ?
- ORDER BY tplcomp.sortorder ASC';
+ WHERE tplcomp.templateid = ?';
$params = array($templateid);
if ($onlyvisible) {
@@ -166,6 +165,8 @@ class template_competency extends persistent {
$params[] = 1;
}
+ $sql .= 'ORDER BY tplcomp.sortorder ASC';
+
$results = $DB->get_records_sql($sql, $params);
$instances = array();
diff --git a/admin/tool/lp/classes/user_competency.php b/admin/tool/lp/classes/user_competency.php
index 574f79db697..0f260047345 100644
--- a/admin/tool/lp/classes/user_competency.php
+++ b/admin/tool/lp/classes/user_competency.php
@@ -190,4 +190,52 @@ class user_competency extends persistent {
return true;
}
+ /**
+ * Create a new user_competency object.
+ *
+ * Note, this is intended to be used to create a blank relation, for instance when
+ * the record was not found in the database. This does not save the model.
+ *
+ * @param int $userid The user ID.
+ * @param int $competencyid The competency ID.
+ * @return \tool_lp\user_competency
+ */
+ public static function create_relation($userid, $competencyid) {
+ $relation = new user_competency(0, (object) array('userid' => $userid, 'competencyid' => $competencyid));
+ return $relation;
+ }
+
+ /**
+ * Get multiple user_competency for a user.
+ *
+ * @param int $userid
+ * @param array $competenciesorids Limit search to those competencies, or competency IDs.
+ * @return \tool_lp\user_competency[]
+ */
+ public static function get_multiple($userid, array $competenciesorids = null) {
+ global $DB;
+
+ $params = array();
+ $params['userid'] = $userid;
+ $sql = '1 = 1';
+
+ if (!empty($competenciesorids)) {
+ $test = reset($competenciesorids);
+ if (is_int($test)) {
+ $ids = $competenciesorids;
+ } else {
+ $ids = array();
+ foreach ($competenciesorids as $comp) {
+ $ids[] = $comp->get_id();
+ }
+ }
+
+ list($insql, $inparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED);
+ $params += $inparams;
+ $sql = "competencyid $insql";
+ }
+
+ return parent::get_records_select("userid = :userid AND $sql", $params);
+ }
+
}
diff --git a/admin/tool/lp/db/services.php b/admin/tool/lp/db/services.php
index 814c04ce30f..16482961555 100644
--- a/admin/tool/lp/db/services.php
+++ b/admin/tool/lp/db/services.php
@@ -424,6 +424,15 @@ $functions = array(
'capabilities' => 'tool/lp:planviewown',
'ajax' => true,
),
+ 'tool_lp_list_plan_competencies' => array(
+ 'classname' => 'tool_lp\external',
+ 'methodname' => 'list_plan_competencies',
+ 'classpath' => '',
+ 'description' => 'List the competencies in a plan',
+ 'type' => 'read',
+ 'capabilities' => 'tool/lp:planviewown',
+ 'ajax' => true,
+ ),
'tool_lp_get_scale_values' => array(
'classname' => 'tool_lp\external',
'methodname' => 'get_scale_values',
diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php
index 45b7524c6b5..08af2fea377 100644
--- a/admin/tool/lp/lang/en/tool_lp.php
+++ b/admin/tool/lp/lang/en/tool_lp.php
@@ -39,9 +39,6 @@ $string['competencyframeworks'] = 'Competency Frameworks';
$string['competencyframeworkupdated'] = 'Competency framework updated.';
$string['competencypicker'] = 'Competency picker';
$string['competencyrelatedcompetencies'] = '{$a} related competencies';
-$string['usercompetencystatus_idle'] = 'Idle';
-$string['usercompetencystatus_inreview'] = 'In review';
-$string['usercompetencystatus_waitingforreview'] = 'Waiting for review';
$string['competencyupdated'] = 'Competency updated';
$string['configurescale'] = 'Configure scales';
$string['coursecompetencies'] = 'Course competencies';
@@ -134,6 +131,7 @@ $string['search'] = 'Search...';
$string['selectcompetencymovetarget'] = 'Select a location to move this competency to:';
$string['selectedcompetency'] = 'Selected competency';
$string['shortname'] = 'Name';
+$string['state'] = 'State';
$string['status'] = 'Status';
$string['taxonomies'] = 'Taxonomies';
$string['taxonomy_add_behaviour'] = 'Add behaviour';
@@ -196,5 +194,8 @@ $string['templatecreated'] = 'Learning plan template created';
$string['templatename'] = 'Name';
$string['templates'] = 'Learning plan templates';
$string['templateupdated'] = 'Learning plan template updated';
+$string['usercompetencystatus_idle'] = 'Idle';
+$string['usercompetencystatus_inreview'] = 'In review';
+$string['usercompetencystatus_waitingforreview'] = 'Waiting for review';
$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.';
diff --git a/admin/tool/lp/plan.php b/admin/tool/lp/plan.php
new file mode 100644
index 00000000000..365d2967e95
--- /dev/null
+++ b/admin/tool/lp/plan.php
@@ -0,0 +1,52 @@
+.
+
+/**
+ * Plan page.
+ *
+ * @package tool_lp
+ * @copyright 2015 Frédéric Massart - FMCorz.net
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require(__DIR__ . '/../../../config.php');
+
+$id = required_param('id', PARAM_INT);
+
+require_login(null, false);
+if (isguestuser()) {
+ throw new require_login_exception('Guests are not allowed here.');
+}
+
+$plan = \tool_lp\api::read_plan($id);
+$context = $plan->get_context();
+
+$url = new moodle_url('/admin/tool/lp/plan.php', array('id' => $id));
+$title = format_string($plan->get_name(), true, array('context' => $context));
+$PAGE->set_context($context);
+$PAGE->set_pagelayout('admin');
+$PAGE->set_url($url);
+$PAGE->set_title($title);
+$PAGE->set_heading($title);
+
+$output = $PAGE->get_renderer('tool_lp');
+echo $output->header();
+echo $output->heading($title);
+
+$page = new \tool_lp\output\plan_page($plan);
+echo $output->render($page);
+
+echo $output->footer();
diff --git a/admin/tool/lp/templates/plan_page.mustache b/admin/tool/lp/templates/plan_page.mustache
new file mode 100644
index 00000000000..e552e47fdd4
--- /dev/null
+++ b/admin/tool/lp/templates/plan_page.mustache
@@ -0,0 +1,53 @@
+{{!
+ 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
| {{#str}}shortname, tool_lp{{/str}} | +{{#str}}status, tool_lp{{/str}} | +{{#str}}proficient, tool_lp{{/str}} | +{{#str}}state, tool_lp{{/str}} | +{{#str}}actions, tool_lp{{/str}} | +
|---|---|---|---|---|
| {{shortname}} | +{{usercompetency.gradename}} | +{{usercompetency.proficiencyname}} | +{{usercompetency.statusname}} | ++ |