MDL-51034 tool_lp: List competencies in a user's plan

This commit is contained in:
Frederic Massart
2016-04-18 10:58:40 +08:00
parent 58405003f8
commit 1d8f0a6f50
13 changed files with 489 additions and 7 deletions
+46
View File
@@ -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.
*
@@ -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.
*
+107
View File
@@ -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.
*
+114
View File
@@ -0,0 +1,114 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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;
}
}
+11
View File
@@ -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.
*
+2 -2
View File
@@ -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;
+27
View File
@@ -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.
*
@@ -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();
+48
View File
@@ -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);
}
}
+9
View File
@@ -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',
+4 -3
View File
@@ -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.';
+52
View File
@@ -0,0 +1,52 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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();
@@ -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 <http://www.gnu.org/licenses/>.
}}
{{!
Plan page template.
}}
<div data-region="planpage">
<table class="generaltable fullwidth">
<thead>
<tr>
<th scope="col">{{#str}}shortname, tool_lp{{/str}}</th>
<th scope="col">{{#str}}status, tool_lp{{/str}}</th>
<th scope="col">{{#str}}proficient, tool_lp{{/str}}</th>
<th scope="col">{{#str}}state, tool_lp{{/str}}</th>
<th scope="col">{{#str}}actions, tool_lp{{/str}}</th>
</tr>
</thead>
<tbody>
{{#competencies}}
<tr data-id="{{id}}">
<td>{{shortname}}</td>
<td>{{usercompetency.gradename}}</td>
<td>{{usercompetency.proficiencyname}}</td>
<td>{{usercompetency.statusname}}</td>
<td><!-- Option to remove the competency from the plan, ... --></td>
</tr>
{{/competencies}}
</tbody>
</table>
<div data-region="actions">
<div class="pull-right">
<!-- Button to add competencies to the plan -->
</div>
</div>
</div>
{{#js}}
{{/js}}