Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
UserGroupRestrictions
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
8 / 8
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 newFromSpecValidated
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
5
 getMemberConditions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUpdaterConditions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 canBeIgnored
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 continuouslyEnforced
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 hasAnyConditions
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 allowsAutomaticDemotion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/*
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\User;
8
9/**
10 * Represents the restrictions defined for a restricted user group.
11 *
12 * @since 1.46
13 */
14class UserGroupRestrictions {
15
16    private readonly array $memberConditions;
17    private readonly array $updaterConditions;
18    private readonly bool $canBeIgnored;
19    private readonly bool $demote;
20
21    /**
22     * @param array $restrictionSpec The restriction specification for a group, typically coming from values
23     *   defined in $wgRestrictedGroups. All keys in this array are optional. The default values are:
24     *   - memberConditions: empty array (meaning no restrictions)
25     *   - updaterConditions: empty array (meaning no restrictions)
26     *   - canBeIgnored: false
27     *   - demote: false
28     */
29    public function __construct( array $restrictionSpec ) {
30        $memberConditions = $restrictionSpec['memberConditions'] ?? [];
31        if ( !is_array( $memberConditions ) ) {
32            $memberConditions = [ $memberConditions ];
33        }
34        $this->memberConditions = $memberConditions;
35
36        $updaterConditions = $restrictionSpec['updaterConditions'] ?? [];
37        if ( !is_array( $updaterConditions ) ) {
38            $updaterConditions = [ $updaterConditions ];
39        }
40        $this->updaterConditions = $updaterConditions;
41
42        $this->canBeIgnored = $restrictionSpec['canBeIgnored'] ?? false;
43        $this->demote = $restrictionSpec['demote'] ?? false;
44    }
45
46    /**
47     * Creates a new object representing user group restriction, but first, it validates the conditions.
48     * Invalid conditions are ignored, and effectively treated as if there was no condition of the given kind.
49     */
50    public static function newFromSpecValidated(
51        array $spec,
52        UserRequirementsConditionValidator $validator
53    ): UserGroupRestrictions {
54        if ( isset( $spec['memberConditions'] ) && !$validator->isValid( $spec['memberConditions'] ) ) {
55            unset( $spec['memberConditions'] );
56        }
57        if ( isset( $spec['updaterConditions'] ) && !$validator->isValid( $spec['updaterConditions'] ) ) {
58            unset( $spec['updaterConditions'] );
59        }
60        return new self( $spec );
61    }
62
63    public function getMemberConditions(): array {
64        return $this->memberConditions;
65    }
66
67    public function getUpdaterConditions(): array {
68        return $this->updaterConditions;
69    }
70
71    public function canBeIgnored(): bool {
72        return $this->canBeIgnored;
73    }
74
75    /**
76     * Checks if this group restrictions can be continuously enforced. This is the case if conditions for member
77     * are specified, and it's impossible to ignore the restrictions.
78     */
79    public function continuouslyEnforced(): bool {
80        return !$this->canBeIgnored() && $this->getMemberConditions() !== [];
81    }
82
83    /**
84     * Checks if there are conditions defined for this group, either for members or updaters.
85     * If there are no conditions, then the group is effectively not restricted.
86     */
87    public function hasAnyConditions(): bool {
88        return $this->getMemberConditions() !== [] || $this->getUpdaterConditions() !== [];
89    }
90
91    /**
92     * Checks if this group allows for automatic demotion of its members if they no longer meet the conditions
93     * for membership.
94     */
95    public function allowsAutomaticDemotion(): bool {
96        return $this->continuouslyEnforced() && $this->demote;
97    }
98}