Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.92% |
47 / 49 |
|
83.33% |
5 / 6 |
CRAP | |
0.00% |
0 / 1 |
GrantsLocalization | |
95.92% |
47 / 49 |
|
83.33% |
5 / 6 |
17 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getGrantDescription | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
getGrantDescriptions | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getGrantDescriptionsWithClasses | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
4 | |||
getGrantsLink | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
getGrantsWikiText | |
84.62% |
11 / 13 |
|
0.00% |
0 / 1 |
5.09 |
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 | |
21 | namespace MediaWiki\Permissions; |
22 | |
23 | use HtmlArmor; |
24 | use Language; |
25 | use MediaWiki\Html\Html; |
26 | use MediaWiki\Languages\LanguageFactory; |
27 | use MediaWiki\Linker\LinkRenderer; |
28 | use MediaWiki\SpecialPage\SpecialPage; |
29 | |
30 | /** |
31 | * This separate service is needed because the ::getGrantsLink method requires a LinkRenderer |
32 | * and if we tried to inject a LinkRenderer into the GrantsInfo service, it would result in |
33 | * recursive service instantiation for sessions using the BotPasswordSessionProvider, as a |
34 | * result of injecting the LinkRenderer when trying to use a GrantsInfo method that doesn't |
35 | * even need it. |
36 | * |
37 | * @since 1.38 |
38 | */ |
39 | class GrantsLocalization { |
40 | /** @var GrantsInfo */ |
41 | private $grantsInfo; |
42 | |
43 | /** @var LinkRenderer */ |
44 | private $linkRenderer; |
45 | |
46 | /** @var LanguageFactory */ |
47 | private $languageFactory; |
48 | |
49 | /** @var Language */ |
50 | private $contentLanguage; |
51 | |
52 | /** |
53 | * @param GrantsInfo $grantsInfo |
54 | * @param LinkRenderer $linkRenderer |
55 | * @param LanguageFactory $languageFactory |
56 | * @param Language $contentLanguage |
57 | */ |
58 | public function __construct( |
59 | GrantsInfo $grantsInfo, |
60 | LinkRenderer $linkRenderer, |
61 | LanguageFactory $languageFactory, |
62 | Language $contentLanguage |
63 | ) { |
64 | $this->grantsInfo = $grantsInfo; |
65 | $this->linkRenderer = $linkRenderer; |
66 | $this->languageFactory = $languageFactory; |
67 | $this->contentLanguage = $contentLanguage; |
68 | } |
69 | |
70 | /** |
71 | * Fetch the description of the grant. |
72 | * @param string $grant |
73 | * @param Language|string|null $lang |
74 | * @return string Grant description |
75 | */ |
76 | public function getGrantDescription( string $grant, $lang = null ): string { |
77 | // Give grep a chance to find the usages: |
78 | // grant-blockusers, grant-createeditmovepage, grant-delete, |
79 | // grant-editinterface, grant-editmycssjs, grant-editmywatchlist, |
80 | // grant-editsiteconfig, grant-editpage, grant-editprotected, |
81 | // grant-highvolume, grant-oversight, grant-patrol, grant-protect, |
82 | // grant-rollback, grant-sendemail, grant-uploadeditmovefile, |
83 | // grant-uploadfile, grant-basic, grant-viewdeleted, |
84 | // grant-viewmywatchlist, grant-createaccount, grant-mergehistory, |
85 | // grant-import |
86 | |
87 | // TODO: replace wfMessage with something that can be injected like TextFormatter |
88 | $msg = wfMessage( "grant-$grant" ); |
89 | |
90 | if ( $lang ) { |
91 | $msg->inLanguage( $lang ); |
92 | } |
93 | |
94 | if ( !$msg->exists() ) { |
95 | $msg = $lang |
96 | ? wfMessage( 'grant-generic', $grant )->inLanguage( $lang ) |
97 | : wfMessage( 'grant-generic', $grant ); |
98 | } |
99 | |
100 | return $msg->text(); |
101 | } |
102 | |
103 | /** |
104 | * Fetch the descriptions for the grants. |
105 | * @param string[] $grants |
106 | * @param Language|string|null $lang |
107 | * @return string[] Corresponding grant descriptions, keyed by grant name |
108 | */ |
109 | public function getGrantDescriptions( array $grants, $lang = null ): array { |
110 | $ret = []; |
111 | |
112 | foreach ( $grants as $grant ) { |
113 | $ret[$grant] = $this->getGrantDescription( $grant, $lang ); |
114 | } |
115 | return $ret; |
116 | } |
117 | |
118 | /** |
119 | * Fetch the descriptions for the grants, like getGrantDescriptions, but with HTML classes |
120 | * for styling. The HTML is wikitext-compatible. |
121 | * @param string[] $grants |
122 | * @param Language|string|null $lang |
123 | * @return string[] Grant description HTML for each grant, in the same order |
124 | */ |
125 | public function getGrantDescriptionsWithClasses( array $grants, $lang = null ): array { |
126 | $riskGroupsByGrant = $this->grantsInfo->getRiskGroupsByGrant( 'unknown' ); |
127 | $grantDescriptions = $this->getGrantDescriptions( $grants, $lang ); |
128 | $results = []; |
129 | foreach ( $grantDescriptions as $grant => $description ) { |
130 | $riskGroup = $riskGroupsByGrant[$grant] ?? 'unknown'; |
131 | // Messages used here: grantriskgroup-vandalism, grantriskgroup-security, |
132 | // grantriskgroup-internal |
133 | $riskGroupMsg = wfMessage( "grantriskgroup-$riskGroup" ); |
134 | if ( $lang ) { |
135 | $riskGroupMsg->inLanguage( $lang ); |
136 | } |
137 | if ( $riskGroupMsg->exists() ) { |
138 | $riskDescription = $riskGroupMsg->text(); |
139 | } else { |
140 | $riskDescription = ''; |
141 | } |
142 | $results[] = htmlspecialchars( $description ) . ' ' . |
143 | Html::element( 'span', [ 'class' => "mw-grant mw-grantriskgroup-$riskGroup" ], $riskDescription ); |
144 | } |
145 | return $results; |
146 | } |
147 | |
148 | /** |
149 | * Generate a link to Special:ListGrants for a particular grant name. |
150 | * |
151 | * This can be used to link end users to a full description of what |
152 | * rights they are giving when they authorize a grant. |
153 | * |
154 | * @param string $grant the grant name |
155 | * @param Language|string|null $lang |
156 | * @return string (proto-relative) HTML link |
157 | */ |
158 | public function getGrantsLink( string $grant, $lang = null ): string { |
159 | $riskGroupsByGrant = $this->grantsInfo->getRiskGroupsByGrant( 'unknown' ); |
160 | $riskGroup = $riskGroupsByGrant[$grant] ?? 'unknown'; |
161 | return $this->linkRenderer->makeKnownLink( |
162 | SpecialPage::getTitleFor( 'Listgrants', false, $grant ), |
163 | new HtmlArmor( $this->getGrantDescriptionsWithClasses( [ $grant ], $lang )[ 0 ] ) |
164 | ); |
165 | } |
166 | |
167 | /** |
168 | * Generate wikitext to display a list of grants. It will be in the format |
169 | * * <grant-group-$group> |
170 | * : <grant-$grant>; <grant-$grant>; ... |
171 | * * ... |
172 | * with some HTML classes for styling. |
173 | * @param string[]|null $grantsFilter If non-null, only display these grants. |
174 | * @param Language|string|null $lang |
175 | * @return string Wikitext |
176 | */ |
177 | public function getGrantsWikiText( $grantsFilter, $lang = null ): string { |
178 | if ( is_string( $lang ) ) { |
179 | $lang = $this->languageFactory->getLanguage( $lang ); |
180 | } elseif ( $lang === null ) { |
181 | $lang = $this->contentLanguage; |
182 | } |
183 | |
184 | $s = ''; |
185 | foreach ( $this->grantsInfo->getGrantGroups( $grantsFilter ) as $group => $grants ) { |
186 | if ( $group === 'hidden' ) { |
187 | continue; // implicitly granted |
188 | } |
189 | $grantDescriptionsWithClasses = $this->getGrantDescriptionsWithClasses( $grants, $lang ); |
190 | // Give grep a chance to find the usages: |
191 | // grant-group-page-interaction, grant-group-file-interaction |
192 | // grant-group-watchlist-interaction, grant-group-email, |
193 | // grant-group-high-volume, grant-group-customization, |
194 | // grant-group-administration, grant-group-private-information, |
195 | // grant-group-other |
196 | $s .= "*<span class=\"mw-grantgroup\">" . |
197 | // TODO: replace wfMessage with something that can be injected like TextFormatter |
198 | wfMessage( "grant-group-$group" )->inLanguage( $lang )->text() . "</span>\n"; |
199 | $s .= ":" . $lang->semicolonList( $grantDescriptionsWithClasses ) . "\n"; |
200 | } |
201 | return "$s\n"; |
202 | } |
203 | } |