Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
61.34% |
73 / 119 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
PageToolsComponent | |
61.34% |
73 / 119 |
|
0.00% |
0 / 5 |
86.51 | |
0.00% |
0 / 1 |
__construct | |
92.98% |
53 / 57 |
|
0.00% |
0 / 1 |
8.02 | |||
getDiscussionSwitch | |
44.44% |
8 / 18 |
|
0.00% |
0 / 1 |
12.17 | |||
getLastEdit | |
17.65% |
3 / 17 |
|
0.00% |
0 / 1 |
18.96 | |||
getContentNavButtons | |
42.86% |
9 / 21 |
|
0.00% |
0 / 1 |
33.58 | |||
getButtonForContentAction | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 |
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 | * |
17 | * @file |
18 | */ |
19 | namespace MediaWiki\Skin\WikimediaApiPortal\Component; |
20 | |
21 | use MediaWiki\Context\IContextSource; |
22 | use MediaWiki\Permissions\PermissionManager; |
23 | use MediaWiki\Title\Title; |
24 | use MediaWiki\User\User; |
25 | use OOUI\ButtonGroupWidget; |
26 | use OOUI\ButtonWidget; |
27 | use Wikimedia\Message\IMessageFormatterFactory; |
28 | |
29 | class PageToolsComponent extends MessageComponent { |
30 | // Allowed page actions with config overrides |
31 | private const PAGE_TOOLS_ALLOWED_LIST = [ |
32 | 'views' => [ |
33 | 'edit' => [ |
34 | 'visible' => [ 'view' ], |
35 | 'icon' => 'edit', |
36 | 'group' => 'primary', |
37 | ], |
38 | ], |
39 | 'actions' => [ |
40 | 'move' => [ |
41 | 'visible' => [ 'view' ], |
42 | 'group' => 'secondary', |
43 | |
44 | ], |
45 | 'delete' => [ |
46 | 'visible' => [ 'view' ], |
47 | 'flags' => 'destructive', |
48 | 'group' => 'secondary', |
49 | ], |
50 | ], |
51 | ]; |
52 | |
53 | /** |
54 | * @param IMessageFormatterFactory $messageFormatterFactory |
55 | * @param IContextSource $contextSource |
56 | * @param PermissionManager $permissionManager |
57 | * @param string $requestedAction |
58 | * @param array $actions |
59 | * @param bool $mobile |
60 | */ |
61 | public function __construct( |
62 | IMessageFormatterFactory $messageFormatterFactory, |
63 | IContextSource $contextSource, |
64 | PermissionManager $permissionManager, |
65 | string $requestedAction, |
66 | array $actions, |
67 | bool $mobile |
68 | ) { |
69 | parent::__construct( |
70 | $mobile ? 'PageToolsMobile' : 'PageTools', |
71 | $messageFormatterFactory, |
72 | $contextSource |
73 | ); |
74 | |
75 | if ( $requestedAction !== 'view' && $requestedAction !== 'history' ) { |
76 | $this->args = null; |
77 | return; |
78 | } |
79 | |
80 | $title = $contextSource->getTitle(); |
81 | |
82 | if ( $title->isSpecialPage() ) { |
83 | $this->args = null; |
84 | return; |
85 | } |
86 | |
87 | $user = $contextSource->getUser(); |
88 | |
89 | if ( $mobile ) { |
90 | $buttons = $this->getContentNavButtons( |
91 | $title, |
92 | $user, |
93 | $permissionManager, |
94 | $requestedAction, |
95 | 'all', |
96 | $actions, |
97 | [ 'framed' => true ] |
98 | ); |
99 | |
100 | $this->args = [ |
101 | 'html-discussionSwitch' => $this->getDiscussionSwitch( |
102 | $title, |
103 | $requestedAction, |
104 | $actions |
105 | ), |
106 | 'html-lastEdit' => $this->getLastEdit( $requestedAction, $contextSource, $actions ) ?: '', |
107 | 'html-buttons' => new ButtonGroupWidget( [ 'items' => $buttons ] ), |
108 | ]; |
109 | |
110 | } else { |
111 | $primary = $this->getContentNavButtons( |
112 | $title, |
113 | $user, |
114 | $permissionManager, |
115 | $requestedAction, |
116 | 'primary', $actions |
117 | ); |
118 | $secondary = $this->getContentNavButtons( |
119 | $title, |
120 | $user, |
121 | $permissionManager, |
122 | $requestedAction, |
123 | 'secondary', |
124 | $actions |
125 | ); |
126 | |
127 | $this->args = [ |
128 | 'html-discussionSwitch' => $this->getDiscussionSwitch( |
129 | $title, |
130 | $requestedAction, |
131 | $actions |
132 | ) ?: '', |
133 | 'html-lastEdit' => $this->getLastEdit( $requestedAction, $contextSource, $actions ), |
134 | 'html-primaryButtons' => new ButtonGroupWidget( [ 'items' => $primary ] ), |
135 | 'secondaryButtons' => $secondary, |
136 | ]; |
137 | } |
138 | } |
139 | |
140 | /** |
141 | * @param Title $title |
142 | * @param string $requestedAction |
143 | * @param array $actions |
144 | * @return ?ButtonWidget |
145 | */ |
146 | private function getDiscussionSwitch( |
147 | Title $title, |
148 | string $requestedAction, |
149 | array $actions |
150 | ): ?ButtonWidget { |
151 | if ( $requestedAction === 'view' ) { |
152 | if ( $title->isTalkPage() ) { |
153 | if ( isset( $actions['namespaces']['main'] ) ) { |
154 | return $this->getButtonForContentAction( $actions['namespaces']['main'], [ |
155 | 'icon' => 'arrowPrevious', |
156 | 'label' => $this->formatMessage( 'wikimediaapiportal-skin-return-to-page-label' ) |
157 | ] ); |
158 | } |
159 | } elseif ( isset( $actions['namespaces']['talk'] ) ) { |
160 | return $this->getButtonForContentAction( |
161 | $actions['namespaces']['talk'], |
162 | [ 'icon' => 'speechBubbles' ] |
163 | ); |
164 | } |
165 | } elseif ( $requestedAction === 'history' ) { |
166 | return $this->getButtonForContentAction( $actions['views']['view'], [ |
167 | 'icon' => 'arrowPrevious', |
168 | 'label' => $this->formatMessage( 'wikimediaapiportal-skin-return-to-page-label' ) |
169 | ] ); |
170 | } |
171 | return null; |
172 | } |
173 | |
174 | /** |
175 | * @param string $requestedAction |
176 | * @param IContextSource $contextSource |
177 | * @param array $actions |
178 | * @return ?ButtonWidget |
179 | */ |
180 | private function getLastEdit( |
181 | string $requestedAction, |
182 | IContextSource $contextSource, |
183 | array $actions |
184 | ): ?ButtonWidget { |
185 | if ( $requestedAction !== 'view' ) { |
186 | return null; |
187 | } |
188 | |
189 | if ( !isset( $actions['views']['history'] ) ) { |
190 | return null; |
191 | } |
192 | |
193 | $title = $contextSource->getTitle(); |
194 | |
195 | if ( !$title->exists() ) { |
196 | return null; |
197 | } |
198 | |
199 | $lastTouched = $title->getTouched(); |
200 | if ( $lastTouched === null ) { |
201 | return null; |
202 | } |
203 | |
204 | return $this->getButtonForContentAction( $actions['views']['history'], [ |
205 | 'icon' => 'history', |
206 | 'label' => $this->formatMessage( |
207 | 'wikimediaapiportal-skin-updated-ts-label', |
208 | [ $contextSource->getLanguage()->userDate( $lastTouched, $contextSource->getUser() ) ] |
209 | ) |
210 | ] ); |
211 | } |
212 | |
213 | /** |
214 | * Get OOUI widgets for available content actions. Helper for PageToolsComponent. |
215 | * @param Title $title |
216 | * @param User $user |
217 | * @param PermissionManager $permissionManager |
218 | * @param string $requestedAction |
219 | * @param string $group One of 'primary', 'secondary', or 'all' |
220 | * @param array $actions |
221 | * @param array $oouiOptions |
222 | * @return ButtonWidget[] |
223 | */ |
224 | private function getContentNavButtons( |
225 | Title $title, |
226 | User $user, |
227 | PermissionManager $permissionManager, |
228 | string $requestedAction, |
229 | string $group, |
230 | array $actions, |
231 | array $oouiOptions = [] |
232 | ): array { |
233 | if ( !$actions ) { |
234 | return []; |
235 | } |
236 | |
237 | if ( !$permissionManager->userHasRight( $user, 'edit-docs' ) ) { |
238 | $actions['actions'] = []; |
239 | } |
240 | |
241 | if ( !$permissionManager->userHasRight( $user, 'edit-docs' ) && !$title->isTalkPage() ) { |
242 | return []; |
243 | } |
244 | |
245 | $buttons = []; |
246 | foreach ( $actions as $sectionKey => $section ) { |
247 | foreach ( $section as $actionKey => $action ) { |
248 | if ( !isset( self::PAGE_TOOLS_ALLOWED_LIST[$sectionKey][$actionKey] ) ) { |
249 | continue; |
250 | } |
251 | |
252 | $allowedListData = self::PAGE_TOOLS_ALLOWED_LIST[$sectionKey][$actionKey]; |
253 | if ( $group !== 'all' && $group !== $allowedListData['group'] ) { |
254 | continue; |
255 | } |
256 | if ( !in_array( $requestedAction, $allowedListData['visible'] ) ) { |
257 | continue; |
258 | } |
259 | |
260 | $buttons[] = $this->getButtonForContentAction( $action, array_merge( |
261 | $allowedListData, |
262 | $oouiOptions |
263 | ) ); |
264 | } |
265 | } |
266 | |
267 | return $buttons; |
268 | } |
269 | |
270 | /** |
271 | * Helper for PageToolsComponent. |
272 | * |
273 | * @param array $action Data from 'content_navigation' entry |
274 | * @param array $oouiOptions Override |
275 | * @return ButtonWidget |
276 | */ |
277 | private function getButtonForContentAction( |
278 | array $action, |
279 | $oouiOptions = [] |
280 | ): ButtonWidget { |
281 | return new ButtonWidget( $oouiOptions + [ |
282 | 'id' => $action['id'], |
283 | 'href' => $action['href'], |
284 | 'label' => $action['text'], |
285 | 'framed' => false, |
286 | ] ); |
287 | } |
288 | } |