Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.00% covered (success)
90.00%
18 / 20
80.00% covered (warning)
80.00%
8 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
PermissionStatus
90.00% covered (success)
90.00%
18 / 20
80.00% covered (warning)
80.00%
8 / 10
13.17
0.00% covered (danger)
0.00%
0 / 1
 getBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isBlocked
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setBlock
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 newEmpty
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toLegacyErrorArray
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setRateLimitExceeded
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isRateLimitExceeded
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPermission
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPermission
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 throwErrorPageError
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\Permissions;
22
23use ErrorPageError;
24use MediaWiki\Block\Block;
25use PermissionsError;
26use StatusValue;
27use ThrottledError;
28use UserBlockedError;
29
30/**
31 * A StatusValue for permission errors.
32 *
33 * @todo Add compat code for PermissionManager::getPermissionErrors
34 *       and additional info about user blocks.
35 *
36 * @unstable
37 * @since 1.36
38 */
39class PermissionStatus extends StatusValue {
40
41    /** @var ?Block */
42    private $block = null;
43
44    /** @var bool */
45    private $rateLimitExceeded = false;
46
47    /** @var ?string */
48    private $permission = null;
49
50    /**
51     * Returns the user block that contributed to permissions being denied,
52     * if such a block was provided via setBlock().
53     *
54     * This is intended to be used to provide additional information to the user that
55     * allows them to determine the reason for them being denied an action.
56     *
57     * @since 1.37
58     *
59     * @return ?Block
60     */
61    public function getBlock(): ?Block {
62        return $this->block;
63    }
64
65    /**
66     * Returns true when permissions were denied because the user is blocked.
67     *
68     * @since 1.41
69     *
70     * @return bool
71     */
72    public function isBlocked(): bool {
73        return $this->block !== null;
74    }
75
76    /**
77     * @since 1.37
78     * @internal
79     * @param Block $block
80     */
81    public function setBlock( Block $block ): void {
82        $this->block = $block;
83        $this->setOK( false );
84    }
85
86    /**
87     * @return static
88     */
89    public static function newEmpty() {
90        return new static();
91    }
92
93    /**
94     * Returns this permission status in legacy error array format.
95     *
96     * @see PermissionManager::getPermissionErrors()
97     *
98     * @return array[]
99     */
100    public function toLegacyErrorArray(): array {
101        return $this->getStatusArray();
102    }
103
104    /**
105     * Call this to indicate that the user is over the rate limit for some action.
106     * @since 1.41
107     * @internal
108     * Will cause isRateLimited() to return true.
109     */
110    public function setRateLimitExceeded() {
111        $this->rateLimitExceeded = true;
112        $this->fatal( 'actionthrottledtext' );
113    }
114
115    /**
116     * Whether the user is over the rate limit for some action.
117     * @since 1.41
118     * @return bool True if setRateLimitExceeded() was called.
119     */
120    public function isRateLimitExceeded(): bool {
121        return $this->rateLimitExceeded;
122    }
123
124    /**
125     * Sets the name of the permission that is being checked.
126     *
127     * @since 1.41
128     * @internal
129     * Will cause isRateLimited() to return true.
130     */
131    public function setPermission( string $permission ) {
132        $this->permission = $permission;
133    }
134
135    /**
136     * Returns the name of the permission that was being checked.
137     *
138     * @return string|null The permission, of known
139     * @since 1.41
140     */
141    public function getPermission(): ?string {
142        return $this->permission;
143    }
144
145    /**
146     * Will throw an appropriate ErrorPageError if isOK() returns false.
147     * If isOK() returns true, this method does nothing.
148     *
149     * This is a convenience method for use in user interaction code,
150     * such as subclasses of SpecialPage.
151     *
152     * @unstable Introduced in 1.41, but unstable since the future of ErrorPageError is unclear (T281935).
153     *
154     * @throws ErrorPageError
155     * @return void
156     */
157    public function throwErrorPageError(): void {
158        if ( $this->isOK() ) {
159            return;
160        }
161
162        $block = $this->getBlock();
163        if ( $block ) {
164            throw new UserBlockedError( $block );
165        }
166
167        if ( $this->isRateLimitExceeded() ) {
168            throw new ThrottledError();
169        }
170
171        $messages = $this->getStatusArray( 'error' );
172
173        throw new PermissionsError( $this->permission, $messages );
174    }
175
176}