Skip to content

Commit dd5cfd6

Browse files
committed
Fetched upstream changes
2 parents 92ca409 + 44e1ef4 commit dd5cfd6

File tree

10 files changed

+115
-14
lines changed

10 files changed

+115
-14
lines changed

backup/moodle2/backup_customcert_stepslib.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ protected function define_structure() {
4040

4141
// The instance.
4242
$customcert = new backup_nested_element('customcert', ['id'], [
43-
'templateid', 'name', 'intro', 'introformat', 'requiredtime', 'verifyany', 'emailstudents',
44-
'emailteachers', 'emailothers', 'protection', 'timecreated', 'timemodified']);
43+
'templateid', 'name', 'intro', 'introformat', 'requiredtime', 'verifyany',
44+
'deliveryoption', 'usecustomfilename', 'customfilenamepattern', 'emailstudents',
45+
'emailteachers', 'emailothers', 'protection', 'language', 'timecreated',
46+
'timemodified']);
4547

4648
// The template.
4749
$template = new backup_nested_element('template', ['id'], [

classes/task/issue_certificates_task.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,8 @@ public function execute() {
5656
if ($CFG->dbtype === 'oci') {
5757
// For Oracle, convert the CLOB to a VARCHAR2 (limiting to 4000 characters) since we are using DISTINCT.
5858
$emailothersselect = "DBMS_LOB.SUBSTR(c.emailothers, 4000, 1) AS emailothers";
59-
$emailotherslengthsql = "DBMS_LOB.GETLENGTH(c.emailothers)";
6059
} else {
6160
$emailothersselect = "c.emailothers";
62-
$emailotherslengthsql = $DB->sql_length('c.emailothers');
6361
}
6462

6563
$emailotherslengthsql = $DB->sql_length('c.emailothers');

classes/template.php

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,24 +314,75 @@ public function generate_pdf(bool $preview = false, ?int $userid = null, bool $r
314314
$deliveryoption = $customcert->deliveryoption;
315315
}
316316

317-
// Remove full-stop at the end, if it exists, to avoid "..pdf" being created and being filtered by clean_filename.
318-
$filename = rtrim(format_string($this->name, true, ['context' => $this->get_context()]), '.');
319-
317+
// Set up PDF document properties — no header/footer, auto page break.
320318
$pdf->setPrintHeader(false);
321319
$pdf->setPrintFooter(false);
322-
$pdf->SetTitle($filename);
323320
$pdf->SetAutoPageBreak(true, 0);
324321

322+
// Get filename pattern from global settings.
323+
if (empty($customcert->usecustomfilename) || empty($customcert->customfilenamepattern)) {
324+
// Use the custom cert name as the base filename (strip any trailing dot).
325+
$filename = rtrim(format_string($this->name, true, ['context' => $this->get_context()]), '.');
326+
} else {
327+
// Get issue record for date (if issued); fallback to current date if not found.
328+
$issue = $DB->get_record('customcert_issues', [
329+
'userid' => $user->id,
330+
'customcertid' => $customcert->id,
331+
]);
332+
333+
if ($issue && !empty($issue->timecreated)) {
334+
$issuedate = date('Y-m-d', $issue->timecreated);
335+
} else {
336+
$issuedate = date('Y-m-d');
337+
}
338+
339+
$course = $DB->get_record('course', ['id' => $customcert->course]);
340+
341+
$values = [
342+
'{FIRST_NAME}' => $user->firstname ?? '',
343+
'{LAST_NAME}' => $user->lastname ?? '',
344+
'{COURSE_SHORT_NAME}' => $course ? $course->shortname : '',
345+
'{COURSE_FULL_NAME}' => $course ? $course->fullname : '',
346+
'{ISSUE_DATE}' => $issuedate,
347+
];
348+
349+
// Handle group if needed.
350+
$groups = groups_get_all_groups($course->id, $user->id);
351+
if (!empty($groups)) {
352+
$groupnames = array_map(function($g) {
353+
return $g->name;
354+
}, $groups);
355+
$values['{GROUP_NAME}'] = implode(', ', $groupnames);
356+
} else {
357+
$values['{GROUP_NAME}'] = '';
358+
}
359+
360+
// Replace placeholders with actual values.
361+
$filename = strtr($customcert->customfilenamepattern, $values);
362+
363+
// Remove trailing dot to avoid "..pdf" issues.
364+
$filename = rtrim($filename, '.');
365+
}
366+
325367
// This is the logic the TCPDF library uses when processing the name. This makes names
326368
// such as 'الشهادة' become empty, so set a default name in these cases.
327369
$filename = preg_replace('/[\s]+/', '_', $filename);
328370
$filename = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $filename);
329371

372+
// If filename ends up empty (e.g. after removing unsupported characters), use default string.
330373
if (empty($filename)) {
331374
$filename = get_string('certificate', 'customcert');
332375
}
333376

377+
// Remove existing ".pdf" extension if present to avoid duplication.
378+
$filename = preg_replace('/\.pdf$/i', '', $filename);
379+
380+
// Clean the final filename and append ".pdf".
334381
$filename = clean_filename($filename . '.pdf');
382+
383+
// Set the PDF document title (for metadata, not the filename itself).
384+
$pdf->SetTitle($filename);
385+
335386
// Loop through the pages and display their content.
336387
foreach ($pages as $page) {
337388
// Add the page to the PDF.

db/install.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<FIELD NAME="requiredtime" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
1616
<FIELD NAME="verifyany" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
1717
<FIELD NAME="deliveryoption" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
18+
<FIELD NAME="usecustomfilename" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
19+
<FIELD NAME="customfilenamepattern" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
1820
<FIELD NAME="emailstudents" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
1921
<FIELD NAME="emailteachers" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
2022
<FIELD NAME="emailothers" TYPE="text" NOTNULL="false" SEQUENCE="false"/>

db/upgrade.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,5 +318,24 @@ function xmldb_customcert_upgrade($oldversion) {
318318
upgrade_plugin_savepoint(true, 2024042210, 'mod', 'customcert');
319319
}
320320

321+
if ($oldversion < 2024042213) {
322+
$table = new xmldb_table('customcert');
323+
324+
// Add 'usecustomfilename' field.
325+
$field = new xmldb_field('usecustomfilename', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'deliveryoption');
326+
if (!$dbman->field_exists($table, $field)) {
327+
$dbman->add_field($table, $field);
328+
}
329+
330+
// Add 'customfilenamepattern' field.
331+
$field = new xmldb_field('customfilenamepattern', XMLDB_TYPE_TEXT, null, null, null, null, null, 'usecustomfilename');
332+
if (!$dbman->field_exists($table, $field)) {
333+
$dbman->add_field($table, $field);
334+
}
335+
336+
// Savepoint reached.
337+
upgrade_mod_savepoint(true, 2024042213, 'customcert');
338+
}
339+
321340
return true;
322341
}

lang/en/customcert.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
$string['customcert:viewallcertificates'] = 'View all certificates';
6464
$string['customcert:viewreport'] = 'View course report';
6565
$string['customcertsettings'] = 'Custom certificate settings';
66+
$string['customfilenamepattern'] = 'Custom file name pattern';
67+
$string['customfilenamepattern_help'] = 'Enter the pattern for naming certificate files. You can use placeholders such as {firstname}, {lastname}, {group}, {coursename}, {date}.';
6668
$string['deletecertpage'] = 'Delete page';
6769
$string['deleteconfirm'] = 'Delete confirmation';
6870
$string['deleteelement'] = 'Delete element';
@@ -201,6 +203,9 @@
201203
$string['refpoint_help'] = 'The reference point is the location of an element from which its x and y coordinates are determined. It is indicated by the \'+\' that appears in the centre or corners of the element.';
202204
$string['replacetemplate'] = 'Replace';
203205
$string['requiredtimenotmet'] = 'You must spend at least a minimum of {$a->requiredtime} minutes in the course before you can access this certificate.';
206+
$string['returncourse'] = 'Return to course button';
207+
$string['returncourse_desc'] = 'Display a "Return to course" button on the view certificate page.';
208+
$string['returncourselabel'] = 'Return to course page';
204209
$string['rightmargin'] = 'Right margin';
205210
$string['rightmargin_help'] = 'This is the right margin of the certificate PDF in mm.';
206211
$string['save'] = 'Save';
@@ -231,10 +236,12 @@
231236
$string['uploadimage'] = 'Upload image';
232237
$string['uploadimagedesc'] = 'This link will take you to a new screen where you will be able to upload images. Images uploaded using
233238
this method will be available throughout your site to all users who are able to create a certificate.';
234-
$string['useadhoc'] = 'Use Email Certificate Ad-hoc Task';
239+
$string['useadhoc'] = 'Use email certificate ad-hoc task';
235240
$string['useadhoc_desc'] = 'When enabled, emails related to certificates will be handled immediately through an ad-hoc task created for each issue. When disabled, emails will be managed by the regular scheduled task.
236241
237242
Enabling this option may improve the performance of the scheduled task by offloading email processing to ad-hoc tasks.';
243+
$string['usecustomfilename'] = 'Use custom file name pattern';
244+
$string['usecustomfilename_help'] = 'If enabled, you can define a custom file name pattern for certificates using placeholders. The placeholders are {FIRST_NAME}, {LAST_NAME}, {GROUP_NAME}, {COURSE_SHORT_NAME}, {COURSE_FULL_NAME} and {ISSUE_DATE}.';
238245
$string['userlanguage'] = 'Use user preferences';
239246
$string['userlanguage_help'] = 'You can force the language of the certificate to override the user\'s language preferences.';
240247
$string['verified'] = 'Verified';
@@ -249,7 +256,3 @@
249256
$string['verifycertificatedesc'] = 'This link will take you to a new screen where you will be able to verify certificates on the site';
250257
$string['width'] = 'Width';
251258
$string['width_help'] = 'This is the width of the certificate PDF in mm. For reference an A4 piece of paper is 210mm wide and a letter is 216mm wide.';
252-
$string['codegenerationmethod'] = 'Code generation method';
253-
$string['codegenerationmethod_desc'] = 'Choose between the two methods for generating certificate codes.';
254-
$string['Upper/lower/digits'] = '6aOdbLEuoC (Upper/lower/digits random string)';
255-
$string['digits-with-hyphens'] = '0123-4567-8901 (Digits with hyphens)';

mod_form.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ public function definition() {
6666
$mform->addElement('select', 'deliveryoption', get_string('deliveryoptions', 'customcert'), $deliveryoptions);
6767
$mform->setDefault('deliveryoption', certificate::DELIVERY_OPTION_INLINE);
6868

69+
// Checkbox to enable custom file name pattern.
70+
$mform->addElement('advcheckbox', 'usecustomfilename', get_string('usecustomfilename', 'customcert'));
71+
$mform->addHelpButton('usecustomfilename', 'usecustomfilename', 'customcert');
72+
$mform->setDefault('usecustomfilename', 0);
73+
74+
// Text field for custom file name pattern.
75+
$mform->addElement('text', 'customfilenamepattern', get_string('customfilenamepattern', 'customcert'), ['size' => '50']);
76+
$mform->setType('customfilenamepattern', PARAM_TEXT);
77+
$mform->addHelpButton('customfilenamepattern', 'customfilenamepattern', 'customcert');
78+
$mform->disabledIf('customfilenamepattern', 'usecustomfilename', 'notchecked');
79+
6980
if (has_capability('mod/customcert:manageemailstudents', $this->get_context())) {
7081
$mform->addElement('selectyesno', 'emailstudents', get_string('emailstudents', 'customcert'));
7182
$mform->setDefault('emailstudents', get_config('customcert', 'emailstudents'));

settings.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@
7878
get_string('certificateexecutionperiod', 'customcert'),
7979
get_string('certificateexecutionperiod_desc', 'customcert'), 365 * DAYSECS));
8080

81+
$settings->add(new admin_setting_configcheckbox('customcert/returncourse',
82+
get_string('returncourse', 'customcert'),
83+
get_string('returncourse_desc', 'customcert'),
84+
0));
85+
8186
$settings->add(new admin_setting_heading('defaults',
8287
get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin')));
8388

version.php

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

2525
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
2626

27-
$plugin->version = 2024042212; // The current module version (Date: YYYYMMDDXX).
27+
$plugin->version = 2024042213; // The current module version (Date: YYYYMMDDXX).
2828
$plugin->requires = 2024042200; // Requires this Moodle version (4.4).
2929
$plugin->cron = 0; // Period for cron to check this module (secs).
3030
$plugin->component = 'mod_customcert';

view.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,19 @@
157157

158158
// Create the button to download the customcert.
159159
$downloadbutton = '';
160+
$renderbuttoncourse = '';
161+
$displayreturnbutton = get_config('customcert', 'returncourse');
160162
if ($canreceive) {
161163
$linkname = get_string('getcustomcert', 'customcert');
162164
$link = new moodle_url('/mod/customcert/view.php', ['id' => $cm->id, 'downloadown' => true]);
163165
$downloadbutton = new single_button($link, $linkname, 'get', single_button::BUTTON_PRIMARY);
164166
$downloadbutton->class .= ' m-b-1'; // Seems a bit hackish, ahem.
165167
$downloadbutton = $OUTPUT->render($downloadbutton);
168+
if ($displayreturnbutton) {
169+
$url = new moodle_url('/course/view.php', ['id' => $course->id]);
170+
$buttonreturntocourse = new single_button($url, get_string('returncourselabel', 'customcert'), 'get');
171+
$renderbuttoncourse = $OUTPUT->render($buttonreturntocourse);
172+
}
166173
}
167174

168175
$numissues = \mod_customcert\certificate::get_number_of_issues($customcert->id, $cm, $groupmode);
@@ -187,6 +194,9 @@
187194
echo $issuehtml;
188195
echo $downloadbutton;
189196
echo $downloadallbutton;
197+
if ($displayreturnbutton) {
198+
echo $renderbuttoncourse;
199+
}
190200
if (isset($reporttable)) {
191201
echo $OUTPUT->heading(get_string('listofissues', 'customcert', $numissues), 3);
192202
groups_print_activity_menu($cm, $pageurl);

0 commit comments

Comments
 (0)