Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
workflow
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
6 / 6
7
100.00% covered (success)
100.00%
1 / 1
 stages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 next_stages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 can_move
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 reveals
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 outcomes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 is_outcome
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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_integritycase\local;
18
19/**
20 * The stages a case moves through, and which moves staff may make.
21 *
22 * The student never sees a case while staff look into it. It becomes visible the first time it
23 * reaches a stage that asks something of the student or tells them a decision.
24 *
25 * @package    local_integritycase
26 * @copyright  2026 DevLMS <contact@devlms.com>
27 * @license    https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28 */
29final class workflow {
30    /** @var string Opened, nobody has looked yet. */
31    public const REPORTED = 'reported';
32    /** @var string Staff are looking into it. */
33    public const INVESTIGATING = 'investigating';
34    /** @var string The student has been asked for their side. */
35    public const AWAITING = 'awaitingresponse';
36    /** @var string An outcome has been recorded. */
37    public const DECIDED = 'decided';
38    /** @var string The student appealed the decision. */
39    public const APPEALED = 'appealed';
40    /** @var string Finished. */
41    public const CLOSED = 'closed';
42
43    /** @var array<string, string[]> Moves staff may make from each stage. Appeals are the student's. */
44    private const MOVES = [
45        self::REPORTED => [self::INVESTIGATING, self::CLOSED],
46        self::INVESTIGATING => [self::AWAITING, self::DECIDED, self::CLOSED],
47        self::AWAITING => [self::INVESTIGATING, self::DECIDED, self::CLOSED],
48        self::DECIDED => [self::INVESTIGATING, self::CLOSED],
49        self::APPEALED => [self::DECIDED, self::CLOSED],
50        self::CLOSED => [self::INVESTIGATING],
51    ];
52
53    /** @var string[] Possible decisions. */
54    private const OUTCOMES = ['nocase', 'warning', 'resubmit', 'markreduced', 'referred'];
55
56    /**
57     * All stages, in order.
58     *
59     * @return string[]
60     */
61    public static function stages(): array {
62        return array_keys(self::MOVES);
63    }
64
65    /**
66     * Stages staff can move a case to from this one.
67     *
68     * @param string $stage
69     * @return string[]
70     */
71    public static function next_stages(string $stage): array {
72        return self::MOVES[$stage] ?? [];
73    }
74
75    /**
76     * Whether staff can move a case between these stages.
77     *
78     * @param string $from
79     * @param string $to
80     * @return bool
81     */
82    public static function can_move(string $from, string $to): bool {
83        return in_array($to, self::next_stages($from), true);
84    }
85
86    /**
87     * Whether reaching this stage makes the case visible to the student.
88     *
89     * @param string $stage
90     * @return bool
91     */
92    public static function reveals(string $stage): bool {
93        return $stage === self::AWAITING || $stage === self::DECIDED;
94    }
95
96    /**
97     * Possible decisions.
98     *
99     * @return string[]
100     */
101    public static function outcomes(): array {
102        return self::OUTCOMES;
103    }
104
105    /**
106     * Whether this is a known decision.
107     *
108     * @param string $outcome
109     * @return bool
110     */
111    public static function is_outcome(string $outcome): bool {
112        return in_array($outcome, self::OUTCOMES, true);
113    }
114}