Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
collector
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
2 / 2
15
100.00% covered (success)
100.00%
1 / 1
 collect
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
1 / 1
12
 grade
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2// This file is part of Moodle - https://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <https://www.gnu.org/licenses/>.
16
17namespace local_transcript\local;
18
19/**
20 * Collects what goes on a student's transcript: completed (or graded) visible courses with grade and date.
21 *
22 * @package    local_transcript
23 * @copyright  2026 DevLMS <contact@devlms.com>
24 * @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26class collector {
27    /**
28     * The transcript data for a student, as stored and signed.
29     *
30     * @param int $userid
31     * @return array{institution: string, student: array, courses: array}
32     */
33    public static function collect(int $userid): array {
34        global $CFG, $DB;
35        require_once($CFG->libdir . '/gradelib.php');
36        require_once($CFG->libdir . '/enrollib.php');
37
38        $user = \core_user::get_user($userid, '*', MUST_EXIST);
39        $include = get_config('local_transcript', 'include') ?: 'completed';
40        $showgrades = get_config('local_transcript', 'showgrades');
41        $showgrades = $showgrades === false || (bool) $showgrades;
42        $done = $DB->get_records_menu('course_completions', ['userid' => $userid], '', 'course, timecompleted');
43
44        $courses = [];
45        foreach (enrol_get_all_users_courses($userid, false, 'id, shortname, fullname, visible') as $course) {
46            if (!$course->visible) {
47                continue;
48            }
49            $completed = empty($done[$course->id]) ? null : (int) $done[$course->id];
50            $grade = self::grade($course->id, $userid);
51            if ($completed === null && !($include === 'graded' && $grade !== null)) {
52                continue;
53            }
54            $context = \context_course::instance($course->id);
55            $courses[] = [
56                'shortname' => format_string($course->shortname, true, ['context' => $context, 'escape' => false]),
57                'fullname' => format_string($course->fullname, true, ['context' => $context, 'escape' => false]),
58                'completed' => $completed,
59                'grade' => $showgrades && $grade !== null ? $grade : '',
60            ];
61        }
62        usort($courses, fn($a, $b) => [$a['completed'] ?? PHP_INT_MAX, $a['shortname']]
63            <=> [$b['completed'] ?? PHP_INT_MAX, $b['shortname']]);
64
65        $institution = trim((string) get_config('local_transcript', 'institution'));
66        return [
67            'institution' => $institution !== '' ? $institution : format_string(get_site()->fullname, true, ['escape' => false]),
68            'student' => ['fullname' => fullname($user), 'idnumber' => (string) $user->idnumber],
69            'courses' => $courses,
70        ];
71    }
72
73    /**
74     * The student's final course grade, formatted the way the course's gradebook shows it, or null.
75     *
76     * @param int $courseid
77     * @param int $userid
78     * @return string|null
79     */
80    private static function grade(int $courseid, int $userid): ?string {
81        grade_regrade_final_grades_if_required(get_course($courseid));
82        $item = \grade_item::fetch_course_item($courseid);
83        $grade = $item->get_grade($userid, false);
84        if (!$grade || $grade->finalgrade === null) {
85            return null;
86        }
87        return grade_format_gradevalue($grade->finalgrade, $item, true);
88    }
89}