Skip to content

Commit

Permalink
MDL-53654 competency: Provide a way to delete evidence
Browse files Browse the repository at this point in the history
  • Loading branch information
Frederic Massart committed Apr 18, 2016
1 parent 5aa9ded commit 1e99f31
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 9 deletions.
1 change: 1 addition & 0 deletions admin/tool/lp/amd/build/evidence_delete.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 101 additions & 0 deletions admin/tool/lp/amd/src/evidence_delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// 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/>.

/**
* Evidence delete.
*
* @package tool_lp
* @copyright 2016 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

define(['jquery',
'core/notification',
'core/ajax',
'core/str',
'core/log'],
function($, Notification, Ajax, Str, Log) {

var selectors = {};

/**
* Register an event listener.
*
* @param {String} triggerSelector The node on which the click will happen.
* @param {String} containerSelector The parent node that will be removed and contains the evidence ID.
* @return {Void}
*/
var register = function(triggerSelector, containerSelector) {
if (typeof selectors[triggerSelector] !== 'undefined') {
return;
}

selectors[triggerSelector] = $('body').delegate(triggerSelector, 'click', function(e) {
var parent = $(e.currentTarget).parents(containerSelector);
if (!parent.length || parent.length > 1) {
Log.error('None or too many evidence container were found.');
return;
}
var evidenceId = parent.data('id');
if (!evidenceId) {
Log.error('Evidence ID was not found.');
return;
}

e.preventDefault();
e.stopPropagation();

Str.get_strings([
{ key: 'confirm', component: 'moodle' },
{ key: 'areyousure', component: 'moodle' },
{ key: 'delete', component: 'moodle' },
{ key: 'cancel', component: 'moodle' }
]).done(function (strings) {
Notification.confirm(
strings[0], // Confirm.
strings[1], // Are you sure?
strings[2], // Delete.
strings[3], // Cancel.
function() {
var promise = Ajax.call([{
methodname: 'core_competency_delete_evidence',
args: {
id: evidenceId
}
}]);
promise[0].then(function() {
parent.remove();
}).fail(Notification.exception);
}
);
}).fail(Notification.exception);


});
};

return /** @alias module:tool_lp/evidence_delete */ {

/**
* Register an event listener.
*
* @param {String} triggerSelector The node on which the click will happen.
* @param {String} containerSelector The parent node that will be removed and contains the evidence ID.
* @return {Void}
*/
register: register
};

});
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ protected function get_other_values(renderer_base $output) {

foreach ($this->related['evidence'] as $evidence) {
$actionuserid = $evidence->get_actionuserid();
$related = array('scale' => $scale);
$related = array(
'scale' => $scale,
'usercompetency' => ($this->related['usercompetency'] ? $this->related['usercompetency'] : null),
'usercompetencyplan' => ($this->related['usercompetencyplan'] ? $this->related['usercompetencyplan'] : null),
);
$related['actionuser'] = !empty($actionuserid) ? $usercache[$actionuserid] : null;
$exporter = new evidence_exporter($evidence, $related);
$allevidence[] = $exporter->export($output);
Expand Down
17 changes: 15 additions & 2 deletions admin/tool/lp/templates/evidence_summary.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,17 @@
"grade": 2,
"gradename": "Met",
"description": "The user competency was manually rated in the plan Personal plan A",
"url": "http://moodle.org/"
"url": "http://moodle.org/",
"candelete": true,
"id": 1
}
}}
<div class="well well-small evidence">
<div class="well well-small evidence" data-region="evidence" data-id="{{id}}">
{{#candelete}}
<div class="pull-right">
<a href="#" data-action="delete-evidence">{{#pix}}t/delete{{/pix}}</a>
</div>
{{/candelete}}
{{#actionuser}}
<div>
{{> tool_lp/user_summary }}
Expand All @@ -60,3 +67,9 @@
<p><a href="{{url}}" target="_blank" rel="noreferrer">{{url}}</a></p>
{{/url}}
</div>

{{#js}}
require(['tool_lp/evidence_delete'], function(EvidenceDelete) {
EvidenceDelete.register('[data-action="delete-evidence"]', '[data-region="evidence"]');
});
{{/js}}
38 changes: 38 additions & 0 deletions competency/classes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -4437,6 +4437,44 @@ public static function add_evidence($userid,
return $evidence;
}

/**
* Read an evidence.
* @param int $evidenceid The evidence ID.
* @return evidence
*/
public static function read_evidence($evidenceid) {
static::require_enabled();

$evidence = new evidence($evidenceid);
$uc = new user_competency($evidence->get_usercompetencyid());
if (!$uc->can_read()) {
throw new required_capability_exception($uc->get_context(), 'moodle/competency:usercompetencyview',
'nopermissions', '');
}

return $evidence;
}

/**
* Delete an evidence.
*
* @param evidence|int $evidenceorid The evidence, or its ID.
* @return bool
*/
public static function delete_evidence($evidenceorid) {
$evidence = $evidenceorid;
if (!is_object($evidence)) {
$evidence = new evidence($evidenceorid);
}

$uc = new user_competency($evidence->get_usercompetencyid());
if (!evidence::can_delete_user($uc->get_userid())) {
throw new required_capability_exception($uc->get_context(), 'moodle/competency:evidencedelete', 'nopermissions', '');
}

return $evidence->delete();
}

/**
* Apply the competency rules from a user competency.
*
Expand Down
11 changes: 11 additions & 0 deletions competency/classes/evidence.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

use coding_exception;
use context;
use context_user;
use lang_string;
use moodle_exception;
use stdClass;
Expand Down Expand Up @@ -273,4 +274,14 @@ protected function validate_usercompetencyid($value) {
return true;
}

/**
* Whether the current user can delete an evidence in the context of a user.
*
* @param int $userid The user ID the evidence belongs to.
* @return bool
*/
public static function can_delete_user($userid) {
return has_capability('moodle/competency:evidencedelete', context_user::instance($userid));
}

}
59 changes: 56 additions & 3 deletions competency/classes/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -3719,7 +3719,12 @@ public static function grade_competency($userid, $competencyid, $grade, $note =
);

$scale = $uc->get_competency()->get_scale();
$exporter = new evidence_exporter($evidence, array('actionuser' => $USER, 'scale' => $scale));
$exporter = new evidence_exporter($evidence, [
'actionuser' => $USER,
'scale' => $scale,
'usercompetency' => $uc,
'usercompetencyplan' => null,
]);
return $exporter->export($output);
}

Expand Down Expand Up @@ -3800,7 +3805,12 @@ public static function grade_competency_in_plan($planid, $competencyid, $grade,
);
$competency = api::read_competency($params['competencyid']);
$scale = $competency->get_scale();
$exporter = new evidence_exporter($evidence, array('actionuser' => $USER, 'scale' => $scale));
$exporter = new evidence_exporter($evidence, [
'actionuser' => $USER,
'scale' => $scale,
'usercompetency' => null,
'usercompetencyplan' => null,
]);
return $exporter->export($output);
}

Expand Down Expand Up @@ -4107,7 +4117,12 @@ public static function grade_competency_in_course($courseid, $userid, $competenc
);
$competency = api::read_competency($params['competencyid']);
$scale = $competency->get_scale();
$exporter = new evidence_exporter($evidence, array('actionuser' => $USER, 'scale' => $scale));
$exporter = new evidence_exporter($evidence, array(
'actionuser' => $USER,
'scale' => $scale,
'usercompetency' => null,
'usercompetencyplan' => null,
));
return $exporter->export($output);
}

Expand Down Expand Up @@ -4264,4 +4279,42 @@ public static function update_course_competency_settings_returns() {
return new external_value(PARAM_BOOL, 'True if the update was successful.');
}

/**
* Returns description of external function parameters.
*
* @return \external_function_parameters
*/
public static function delete_evidence_parameters() {
return new external_function_parameters(array(
'id' => new external_value(PARAM_INT, 'The evidence ID'),
));
}

/**
* External function delete_evidence.
*
* @param int $id The evidence ID.
* @return boolean
*/
public static function delete_evidence($id) {
$params = self::validate_parameters(self::delete_evidence_parameters(), array(
'id' => $id
));

$evidence = api::read_evidence($params['id']);
$uc = api::get_user_competency_by_id($evidence->get_usercompetencyid());
self::validate_context($uc->get_context());

return api::delete_evidence($evidence);
}

/**
* Returns description of external function result value.
*
* @return \external_function_parameters
*/
public static function delete_evidence_returns() {
return new external_value(PARAM_BOOL, 'The success');
}

}
25 changes: 23 additions & 2 deletions competency/classes/external/evidence_exporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
namespace core_competency\external;

use renderer_base;
use core_competency\evidence;
use core_competency\user_competency;

/**
* Class for exporting evidence data.
Expand All @@ -34,8 +36,12 @@
class evidence_exporter extends persistent_exporter {

protected static function define_related() {
return array('actionuser' => 'stdClass?',
'scale' => 'grade_scale');
return array(
'actionuser' => 'stdClass?',
'scale' => 'grade_scale',
'usercompetency' => 'core_competency\\user_competency?',
'usercompetencyplan' => 'core_competency\\user_competency_plan?',
);
}

protected static function define_class() {
Expand All @@ -62,6 +68,18 @@ protected function get_other_values(renderer_base $output) {
}
$other['gradename'] = $gradename;

// Try to guess the user from the user competency.
$userid = null;
if ($this->related['usercompetency']) {
$userid = $this->related['usercompetency']->get_userid();
} else if ($this->related['usercompetencyplan']) {
$userid = $this->related['usercompetencyplan']->get_userid();
} else {
$uc = user_competency::get_record(['id' => $this->persistent->get_usercompetencyid()]);
$userid = $uc->get_userid();
}
$other['candelete'] = evidence::can_delete_user($userid);

return $other;
}

Expand All @@ -79,6 +97,9 @@ public static function define_other_properties() {
),
'userdate' => array(
'type' => PARAM_TEXT
),
'candelete' => array(
'type' => PARAM_BOOL
)
);
}
Expand Down
39 changes: 39 additions & 0 deletions competency/tests/api_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -4375,4 +4375,43 @@ public function test_is_scale_used_anywhere() {
$this->assertTrue(api::is_scale_used_anywhere($scale3->id));
$this->assertTrue(api::is_scale_used_anywhere($scale4->id));
}

public function test_delete_evidence() {
$this->resetAfterTest();
$dg = $this->getDataGenerator();
$ccg = $dg->get_plugin_generator('core_competency');

$u1 = $dg->create_user();
$f1 = $ccg->create_framework();
$comp1 = $ccg->create_competency(['competencyframeworkid' => $f1->get_id()]);
$uc1 = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $comp1->get_id()]);

$ev1 = $ccg->create_evidence(['usercompetencyid' => $uc1->get_id()]);
$ev2 = $ccg->create_evidence(['usercompetencyid' => $uc1->get_id()]);

$this->setAdminUser($u1);

$this->assertEquals(2, evidence::count_records());
api::delete_evidence($ev1);
$this->assertEquals(1, evidence::count_records());
$this->assertFalse(evidence::record_exists($ev1->get_id()));
$this->assertTrue(evidence::record_exists($ev2->get_id()));
}

public function test_delete_evidence_without_permissions() {
$this->resetAfterTest();
$dg = $this->getDataGenerator();
$ccg = $dg->get_plugin_generator('core_competency');

$u1 = $dg->create_user();
$f1 = $ccg->create_framework();
$comp1 = $ccg->create_competency(['competencyframeworkid' => $f1->get_id()]);
$uc1 = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $comp1->get_id()]);
$ev1 = $ccg->create_evidence(['usercompetencyid' => $uc1->get_id()]);

$this->setUser($u1);
$this->setExpectedException('required_capability_exception');

api::delete_evidence($ev1);
}
}
Loading

0 comments on commit 1e99f31

Please sign in to comment.