Skip to content

Commit dc1e5a2

Browse files
Allow overriding name on issued certificates
- Useful for when a common template is used across multiple certification paths - Overrides the certificate name when listing certificates to user - Is used for PDF document names
1 parent 20395db commit dc1e5a2

File tree

8 files changed

+59
-9
lines changed

8 files changed

+59
-9
lines changed

classes/certificate.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public static function get_issues_for_template($templateid, $limitfrom, $limitnu
110110
$userfields = self::get_extra_user_fields($context);
111111

112112
$sql = "SELECT ci.id as issueid, ci.code, ci.emailed, ci.timecreated, ci.userid, ci.templateid, ci.expires,
113-
t.name, ci.data, {$userfields}
113+
COALESCE(ci.name, t.name) AS name, ci.data, {$userfields}
114114
FROM {tool_certificate_templates} t
115115
JOIN {tool_certificate_issues} ci
116116
ON (ci.templateid = t.id)
@@ -245,7 +245,7 @@ public static function get_issues_for_course(int $templateid, int $courseid, str
245245
$userfields = self::get_extra_user_fields($context);
246246

247247
$sql = "SELECT ci.id as issueid, ci.code, ci.emailed, ci.timecreated, ci.userid, ci.templateid, ci.expires,
248-
t.name, ci.courseid, ci.archived, $userfields,
248+
COALESCE(ci.name, t.name) AS name, ci.courseid, ci.archived, $userfields,
249249
CASE WHEN ci.expires > 0 AND ci.expires < :now THEN 0
250250
ELSE 1
251251
END AS status
@@ -317,7 +317,7 @@ public static function get_issues_for_user($userid, $limitfrom, $limitnum, $sort
317317
}
318318

319319
$sql = "SELECT ci.id, ci.expires, ci.code, ci.timecreated, ci.userid, ci.courseid,
320-
t.id as templateid, t.contextid, t.name
320+
t.id as templateid, t.contextid, COALESCE(ci.name, t.name) AS name
321321
FROM {tool_certificate_templates} t
322322
INNER JOIN {tool_certificate_issues} ci
323323
ON t.id = ci.templateid
@@ -388,7 +388,8 @@ public static function verify($code) {
388388
$sql = "SELECT ci.id, ci.templateid, ci.code, ci.emailed, ci.timecreated,
389389
ci.expires, ci.data, ci.component, ci.courseid,
390390
ci.userid, ci.archived,
391-
t.name as certificatename,
391+
t.name AS certificatename,
392+
ci.name,
392393
t.contextid
393394
FROM {tool_certificate_templates} t
394395
JOIN {tool_certificate_issues} ci

classes/reportbuilder/local/entities/issue.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ protected function get_all_columns(): array {
118118
->add_field("{$certificateissuealias}.code")
119119
->add_callback([formatter::class, 'code_with_link']);
120120

121+
// Column certificate issue timecreated.
122+
$columns[] = (new column(
123+
'name',
124+
new lang_string('issuename', 'tool_certificate'),
125+
$this->get_entity_name()
126+
))
127+
->add_joins($this->get_joins())
128+
->set_type(column::TYPE_TEXT)
129+
->set_is_sortable(true)
130+
->add_field("{$certificateissuealias}.name");
131+
121132
// Column certificate issue timecreated.
122133
$columns[] = (new column(
123134
'timecreated',

classes/template.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,13 @@ public function generate_pdf($preview = false, $issue = null, $return = false) {
264264

265265
$pdf->setPrintHeader(false);
266266
$pdf->setPrintFooter(false);
267-
$pdf->SetTitle($this->get_formatted_name());
267+
$pdf->SetTitle($this->get_formatted_name($issue));
268268
$pdf->setViewerPreferences([
269269
'DisplayDocTitle' => true,
270270
]);
271271
$pdf->SetAutoPageBreak(true, 0);
272272
// Remove full-stop at the end, if it exists, to avoid "..pdf" being created and being filtered by clean_filename.
273-
$filename = rtrim($this->get_formatted_name(), '.');
273+
$filename = rtrim($this->get_formatted_name($issue), '.');
274274
$filename = clean_filename($filename . '.pdf');
275275
// Loop through the pages and display their content.
276276
foreach ($pages as $page) {
@@ -446,9 +446,13 @@ public function get_shared() {
446446
/**
447447
* Returns the formatted name of the template.
448448
*
449+
* @param \stdClass $issue The issued certificate we want to view
449450
* @return string the name of the template
450451
*/
451-
public function get_formatted_name() {
452+
public function get_formatted_name(\stdClass $issue = null) {
453+
if ($issue && $issue->name) {
454+
return format_string($issue->name, true, ['escape' => false, 'context' => $this->get_context()]);
455+
}
452456
return $this->persistent->get_formatted_name();
453457
}
454458

@@ -688,11 +692,12 @@ public static function find_by_name($name) {
688692
* @param array $data Additional data that will json_encode'd and stored with the issue.
689693
* @param string $component The component the certificate was issued by.
690694
* @param int|null $courseid
695+
* @param string $name Override the name for a certificate to display in the user's list
691696
* @param \core\lock\lock|null $lock optional lock to release after a record was inserted into the DB
692697
* @return int The ID of the issue
693698
*/
694699
public function issue_certificate($userid, $expires = null, array $data = [], $component = 'tool_certificate',
695-
$courseid = null, ?\core\lock\lock $lock = null) {
700+
$courseid = null, $name = null, ?\core\lock\lock $lock = null) {
696701
global $DB;
697702

698703
component_class_callback(\tool_tenant\config::class, 'push_for_user', [$userid]);
@@ -707,6 +712,7 @@ public function issue_certificate($userid, $expires = null, array $data = [], $c
707712
$issue->component = $component;
708713
$issue->courseid = $courseid;
709714
$issue->archived = 0;
715+
$issue->name = $name;
710716

711717
// Store user fullname.
712718
$data['userfullname'] = fullname($DB->get_record('user', ['id' => $userid]));

db/install.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
2424
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
2525
<FIELD NAME="templateid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
26+
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
2627
<FIELD NAME="code" TYPE="char" LENGTH="40" NOTNULL="false" SEQUENCE="false"/>
2728
<FIELD NAME="emailed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
2829
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>

db/upgrade.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,5 +247,18 @@ function xmldb_tool_certificate_upgrade($oldversion) {
247247
upgrade_plugin_savepoint(true, 2023071300, 'tool', 'certificate');
248248
}
249249

250+
if ($oldversion < 2024061000) {
251+
$table = new xmldb_table('tool_certificate_issues');
252+
$field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255');
253+
254+
// Conditionally add field name to tool_certificate_issues
255+
if (!$dbman->field_exists($table, $field)) {
256+
$dbman->add_field($table, $field);
257+
}
258+
259+
// Certificate savepoint reached.
260+
upgrade_plugin_savepoint(true, 2024061000, 'tool', 'certificate');
261+
}
262+
250263
return true;
251264
}

lang/en/tool_certificate.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
$string['issueddate'] = 'Date issued';
122122
$string['issuelang'] = 'Issue certificates in user language';
123123
$string['issuelangdesc'] = 'On multi-lingual sites when user language is different from the site language the certificates will be generated in the user\'s language, otherwise all certificates will be generated in the site default language.';
124+
$string['issuename'] = 'Name (issued)';
124125
$string['issuenotallowed'] = 'You are not allowed to issue certificates from this template.';
125126
$string['issueormangenotallowed'] = 'You are not allowed to issue certificates from or manage this template.';
126127
$string['leftmargin'] = 'Left margin';

tests/certificate_test.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,23 @@ public function test_verify(): void {
356356
$this->assertEquals($result->issue->id, $issueid1);
357357
}
358358

359+
/**
360+
* Verify a certificate issued with a custom name uses that custom name
361+
*/
362+
public function test_can_set_certificate_name(): void {
363+
$testname = 'Test Certificate 1';
364+
365+
$this->setAdminUser();
366+
$certificate1 = $this->get_generator()->create_template((object)['name' => 'Certificate 1']);
367+
$user1 = $this->getDataGenerator()->create_user();
368+
$certificate1->issue_certificate($user1->id, null, [], 'tool_certificate', null, $testname);
369+
370+
$issues = certificate::get_issues_for_template($certificate1->get_id(), 0, 100);
371+
$this->assertCount(1, $issues);
372+
$issue = reset($issues);
373+
$this->assertEquals($testname, $issue->name);
374+
}
375+
359376
/**
360377
* Test generate code.
361378
*/

version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
$plugin->component = 'tool_certificate';
2828
$plugin->release = '4.4';
29-
$plugin->version = 2024052100;
29+
$plugin->version = 2024061000;
3030
$plugin->requires = 2022041900.00;
3131
$plugin->maturity = MATURITY_STABLE;
3232
$plugin->supported = [400, 404];

0 commit comments

Comments
 (0)