Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
display
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 5
380
0.00% covered (danger)
0.00%
0 / 1
 status_label
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 badge
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 grade
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 submission
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
56
 compare
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
72
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_doublemark\local;
18
19/**
20 * Labels, badges and number formats shared by the pages.
21 *
22 * @package    local_doublemark
23 * @copyright  2026 DevLMS <contact@devlms.com>
24 * @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26final class display {
27    /** @var string[] Badge classes per status. Text colours pass WCAG AA on Moodle 4.5 and 5.x. */
28    private const BADGES = [
29        double_marking::UNALLOCATED => 'bg-light text-dark border',
30        reconciler::MARKING => 'bg-secondary text-dark',
31        reconciler::RECONCILE => 'bg-warning text-dark',
32        reconciler::AGREED => 'bg-success text-white',
33        double_marking::RESOLVED => 'bg-primary text-white',
34        double_marking::RELEASED => 'bg-dark text-white',
35    ];
36
37    /**
38     * Label of a status.
39     *
40     * @param string $status
41     * @return string
42     */
43    public static function status_label(string $status): string {
44        return get_string('status:' . $status, 'local_doublemark');
45    }
46
47    /**
48     * Badge classes of a status.
49     *
50     * @param string $status
51     * @return string
52     */
53    public static function badge(string $status): string {
54        return 'badge ' . (self::BADGES[$status] ?? 'bg-light text-dark border');
55    }
56
57    /**
58     * A grade without trailing zeros, or an empty string.
59     *
60     * @param float|null $grade
61     * @return string
62     */
63    public static function grade(?float $grade): string {
64        return $grade === null ? '' : format_float($grade, 2, true, true);
65    }
66
67    /**
68     * The student's submission as the assignment's own submission plugins show it, read only.
69     *
70     * Rendered here instead of linking to the assignment's grader, so markers never see
71     * the grade box there and the two marks stay apart.
72     *
73     * @param double_marking $dm
74     * @param int $userid
75     * @return string HTML
76     */
77    public static function submission(double_marking $dm, int $userid): string {
78        global $OUTPUT;
79        $assign = $dm->assign();
80        $submission = $assign->get_user_submission($userid, false);
81        if (!$submission || $submission->status === ASSIGN_SUBMISSION_STATUS_NEW) {
82            return $OUTPUT->notification(get_string('nosubmission', 'local_doublemark'), 'info', false);
83        }
84        $html = '';
85        foreach ($assign->get_submission_plugins() as $plugin) {
86            if ($plugin->is_enabled() && $plugin->is_visible() && !$plugin->is_empty($submission)) {
87                $html .= \html_writer::tag('h4', $plugin->get_name(), ['class' => 'local-doublemark-subhead']);
88                $html .= \html_writer::div($plugin->view($submission), 'local-doublemark-submission-body');
89            }
90        }
91        $when = get_string('submittedon', 'local_doublemark', userdate($submission->timemodified));
92        return \html_writer::tag('p', $when, ['class' => 'local-doublemark-pending']) . $html;
93    }
94
95    /**
96     * Both marks side by side, for the agree page and for a marker once both are in.
97     *
98     * @param \stdClass $row A row of double_marking::rows().
99     * @param \stdClass[] $markers double_marking::markers().
100     * @return array Context for local_doublemark/compare.
101     */
102    public static function compare(\stdClass $row, array $markers): array {
103        $cards = [];
104        foreach ([1, 2] as $position) {
105            $mark = $position === 1 ? $row->mark1 : $row->mark2;
106            $markerid = $position === 1 ? $row->marker1 : $row->marker2;
107            $cards[] = [
108                'title' => get_string($position === 1 ? 'firstmarker' : 'secondmarker', 'local_doublemark'),
109                'marker' => isset($markers[$markerid]) ? fullname($markers[$markerid]) : '',
110                'mark' => self::grade($mark?->grade),
111                'comment' => $mark ? $mark->comment : '',
112                'when' => $mark ? userdate($mark->timemodified, get_string('strftimedatetimeshort', 'langconfig')) : '',
113            ];
114        }
115        return ['cards' => $cards, 'gap' => self::grade($row->gap), 'hasgap' => $row->gap !== null];
116    }
117}