Skip to content

Commit a487457

Browse files
committed
Limit the number of times a specific certificate can be issued to a user.
1 parent ac4def4 commit a487457

File tree

6 files changed

+84
-16
lines changed

6 files changed

+84
-16
lines changed

classes/form/details.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ public function definition() {
9494
$mform->addHelpButton('shared', 'availableincourses', 'tool_certificate');
9595
$mform->setDefault('shared', 1);
9696

97+
$mform->addElement('text', 'maxissuances', get_string('maxissuances', 'tool_certificate'), array('size' => '3'));
98+
$mform->setType('maxissuances', PARAM_INT);
99+
$mform->setDefault('maxissuances', 0);
100+
$mform->addHelpButton('maxissuances', 'maxissuances', 'tool_certificate');
101+
97102
if (!$this->get_template()->get_id()) {
98103
page::add_page_elements($mform);
99104
} else {
@@ -156,7 +161,7 @@ public function check_access_for_dynamic_submission(): void {
156161
*/
157162
public function process_dynamic_submission() {
158163
global $CFG;
159-
require_once($CFG->dirroot.'/course/lib.php');
164+
require_once($CFG->dirroot . '/course/lib.php');
160165
$data = $this->get_data();
161166

162167
if (isset($data->categoryid)) {
@@ -187,7 +192,9 @@ public function set_data_for_dynamic_submission(): void {
187192
'id' => $this->template->get_id(),
188193
'name' => $this->template->get_name(),
189194
'shared' => $this->template->get_shared(),
190-
'categoryid' => $this->template->get_category_id(), ]);
195+
'categoryid' => $this->template->get_category_id(),
196+
'maxissuances' => $this->template->get_maxissuances(),
197+
]);
191198
} else {
192199
$data = template::instance()->new_page()->to_record();
193200
unset($data->id, $data->templateid);

classes/persistent/template.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ protected static function define_properties() {
5555
'shared' => [
5656
'type' => PARAM_BOOL,
5757
],
58+
'maxissuances' => [
59+
'type' => PARAM_INT,
60+
]
5861
];
5962
}
6063

classes/template.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use core_user;
3131
use moodle_url;
3232
use tool_certificate\customfield\issue_handler;
33+
use moodle_exception;
3334

3435
/**
3536
* Class represents a certificate template.
@@ -84,6 +85,9 @@ public function save($data) {
8485
if (isset($data->shared)) {
8586
$this->persistent->set('shared', $data->shared);
8687
}
88+
if (isset($data->maxissuances)) {
89+
$this->persistent->set('maxissuances', $data->maxissuances);
90+
}
8791
$this->persistent->save();
8892
\tool_certificate\event\template_updated::create_from_template($this)->trigger();
8993
}
@@ -443,6 +447,15 @@ public function get_shared() {
443447
return $this->persistent->get('shared');
444448
}
445449

450+
/**
451+
* Returns the maxissuances setting of the template.
452+
*
453+
* @return string the shared setting of the template
454+
*/
455+
public function get_maxissuances() {
456+
return $this->persistent->get('maxissuances');
457+
}
458+
446459
/**
447460
* Returns the formatted name of the template.
448461
*
@@ -647,6 +660,7 @@ public static function create($formdata) {
647660
$template = new \stdClass();
648661
$template->name = $formdata->name;
649662
$template->shared = $formdata->shared ?? 0;
663+
$template->maxissuances = $formdata->maxissuances ?? 0;
650664
if (!isset($formdata->contextid)) {
651665
debugging('Context is missing', DEBUG_DEVELOPER);
652666
$template->contextid = \context_system::instance()->id;
@@ -697,6 +711,14 @@ public function issue_certificate($userid, $expires = null, array $data = [], $c
697711

698712
component_class_callback(\tool_tenant\config::class, 'push_for_user', [$userid]);
699713

714+
$maxissuances = $DB->get_field('tool_certificate_templates', 'maxissuances', array('id' => $this->get_id()));
715+
$usercertificates = $DB->count_records('tool_certificate_issues', array('userid' => $userid, 'templateid' => $this->get_id()));
716+
717+
if ($maxissuances > 0 && $usercertificates >= $maxissuances) {
718+
// Do not issue the certificate and possibly show an error message.
719+
throw new moodle_exception('maxissuancesreached', 'tool_certificate');
720+
}
721+
700722
$issue = new \stdClass();
701723
$issue->userid = $userid;
702724
$issue->templateid = $this->get_id();

db/install.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
2-
<XMLDB PATH="admin/tool/certificate/db" VERSION="20220518" COMMENT="XMLDB file for Moodle tool_certificate"
2+
<XMLDB PATH="admin/tool/certificate/db" VERSION="20240819" COMMENT="XMLDB file for Moodle tool_certificate"
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
55
>
@@ -12,6 +12,7 @@
1212
<FIELD NAME="shared" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
1313
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
1414
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
15+
<FIELD NAME="maxissuances" TYPE="int" LENGTH="3" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Maximum issuances per user. If 0 there is no limit."/>
1516
</FIELDS>
1617
<KEYS>
1718
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for certificate_template"/>

db/upgrade.php

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
*/
3131
function xmldb_tool_certificate_upgrade($oldversion) {
3232
global $DB, $CFG;
33-
require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/certificate/db/upgradelib.php');
33+
require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/certificate/db/upgradelib.php');
3434

3535
$dbman = $DB->get_manager();
3636

@@ -53,33 +53,41 @@ function xmldb_tool_certificate_upgrade($oldversion) {
5353
foreach ($elements as $element) {
5454
$data = @json_decode($element->data, true);
5555
$data['isbackground'] = 1;
56-
$DB->update_record('tool_certificate_elements',
57-
['id' => $element->id, 'element' => 'image', 'data' => json_encode($data)]);
56+
$DB->update_record(
57+
'tool_certificate_elements',
58+
['id' => $element->id, 'element' => 'image', 'data' => json_encode($data)]
59+
);
5860
}
5961

6062
upgrade_plugin_savepoint(true, 2019030707, 'tool', 'certificate');
6163
}
6264

6365
if ($oldversion < 2019030708) {
6466
// Change instances of studentname to userfield.
65-
$DB->execute("UPDATE {tool_certificate_elements} SET element = ?, data = ? WHERE element = ?",
66-
['userfield', 'fullname', 'studentname']);
67+
$DB->execute(
68+
"UPDATE {tool_certificate_elements} SET element = ?, data = ? WHERE element = ?",
69+
['userfield', 'fullname', 'studentname']
70+
);
6771

6872
upgrade_plugin_savepoint(true, 2019030708, 'tool', 'certificate');
6973
}
7074

7175
if ($oldversion < 2019030710) {
7276
// Change refpoint of all images.
73-
$DB->execute("UPDATE {tool_certificate_elements} SET refpoint = null WHERE element IN (?, ?, ?)",
74-
['image', 'userpicture', 'digitalsignature']);
77+
$DB->execute(
78+
"UPDATE {tool_certificate_elements} SET refpoint = null WHERE element IN (?, ?, ?)",
79+
['image', 'userpicture', 'digitalsignature']
80+
);
7581

7682
upgrade_plugin_savepoint(true, 2019030710, 'tool', 'certificate');
7783
}
7884

7985
if ($oldversion < 2019030711) {
8086
// Change refpoint of all images.
81-
$DB->execute("DELETE FROM {config_plugins} WHERE name = ? AND plugin IN (?, ?)",
82-
['version', 'certificateelement_bgimage', 'certificateelement_studentname']);
87+
$DB->execute(
88+
"DELETE FROM {config_plugins} WHERE name = ? AND plugin IN (?, ?)",
89+
['version', 'certificateelement_bgimage', 'certificateelement_studentname']
90+
);
8391

8492
upgrade_plugin_savepoint(true, 2019030711, 'tool', 'certificate');
8593
}
@@ -205,12 +213,21 @@ function xmldb_tool_certificate_upgrade($oldversion) {
205213
$duplicatecounter = 1;
206214

207215
// For each duplicate code, retrieve all subsequent duplicates after the initial one and append counter.
208-
$records = $DB->get_records_select('tool_certificate_issues', 'id <> :id AND code = :code',
209-
['id' => $duplicatecode->minid, 'code' => $duplicatecode->code], 'id', 'id');
216+
$records = $DB->get_records_select(
217+
'tool_certificate_issues',
218+
'id <> :id AND code = :code',
219+
['id' => $duplicatecode->minid, 'code' => $duplicatecode->code],
220+
'id',
221+
'id'
222+
);
210223

211224
foreach ($records as $record) {
212-
$DB->set_field('tool_certificate_issues', 'code', $duplicatecode->code . $duplicatecounter++,
213-
['id' => $record->id]);
225+
$DB->set_field(
226+
'tool_certificate_issues',
227+
'code',
228+
$duplicatecode->code . $duplicatecounter++,
229+
['id' => $record->id]
230+
);
214231
}
215232
}
216233

@@ -247,5 +264,20 @@ function xmldb_tool_certificate_upgrade($oldversion) {
247264
upgrade_plugin_savepoint(true, 2023071300, 'tool', 'certificate');
248265
}
249266

267+
if ($oldversion < 2024081902) {
268+
269+
// Define field maxissuances to be added to tool_certificate_templates.
270+
$table = new xmldb_table('tool_certificate_templates');
271+
$field = new xmldb_field('maxissuances', XMLDB_TYPE_INTEGER, '3', null, XMLDB_NOTNULL, null, '0', 'timemodified');
272+
273+
// Conditionally launch add field maxissuances.
274+
if (!$dbman->field_exists($table, $field)) {
275+
$dbman->add_field($table, $field);
276+
}
277+
278+
// Certificate savepoint reached.
279+
upgrade_plugin_savepoint(true, 2024081902, 'tool', 'certificate');
280+
}
281+
250282
return true;
251283
}

lang/en/tool_certificate.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@
199199
$string['verifycertificates'] = 'Verify certificates';
200200
$string['verifynotallowed'] = 'You are not allowed to verify certificates.';
201201
$string['viewcertificate'] = 'View certificate';
202+
$string['maxissuances'] = 'Maximum issuances per user';
203+
$string['maxissuances_help'] = 'The maximum number of times this certificate can be issued to a single user. If 0 there is no limit.';
204+
$string['maxissuancesreached'] = 'You have reached the maximum number of times this certificate can be issued to you.';
202205

203206
// Deprecated since 4.2.
204207
$string['editcertificate'] = 'Edit certificate template \'{$a}\'';

0 commit comments

Comments
 (0)