Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 90 |
|
0.00% |
0 / 11 |
CRAP | |
0.00% |
0 / 1 |
CreditsAction | |
0.00% |
0 / 90 |
|
0.00% |
0 / 11 |
1332 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDescription | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onView | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
getCredits | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
getAuthor | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 | |||
canShowRealUserName | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getContributors | |
0.00% |
0 / 41 |
|
0.00% |
0 / 1 |
240 | |||
link | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
userLink | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
othersLink | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Formats credits for articles |
4 | * |
5 | * Copyright 2004, Evan Prodromou <evan@wikitravel.org>. |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
20 | * |
21 | * @file |
22 | * @ingroup Actions |
23 | * @author <evan@wikitravel.org> |
24 | */ |
25 | |
26 | use MediaWiki\Context\IContextSource; |
27 | use MediaWiki\Html\Html; |
28 | use MediaWiki\Linker\Linker; |
29 | use MediaWiki\Linker\LinkRenderer; |
30 | use MediaWiki\MainConfigNames; |
31 | use MediaWiki\User\User; |
32 | use MediaWiki\User\UserFactory; |
33 | use MediaWiki\User\UserRigorOptions; |
34 | |
35 | /** |
36 | * @ingroup Actions |
37 | */ |
38 | class CreditsAction extends FormlessAction { |
39 | |
40 | private LinkRenderer $linkRenderer; |
41 | private UserFactory $userFactory; |
42 | |
43 | /** |
44 | * @param Article $article |
45 | * @param IContextSource $context |
46 | * @param LinkRenderer $linkRenderer |
47 | * @param UserFactory $userFactory |
48 | */ |
49 | public function __construct( |
50 | Article $article, |
51 | IContextSource $context, |
52 | LinkRenderer $linkRenderer, |
53 | UserFactory $userFactory |
54 | ) { |
55 | parent::__construct( $article, $context ); |
56 | $this->linkRenderer = $linkRenderer; |
57 | $this->userFactory = $userFactory; |
58 | } |
59 | |
60 | public function getName() { |
61 | return 'credits'; |
62 | } |
63 | |
64 | protected function getDescription() { |
65 | return $this->msg( 'creditspage' )->escaped(); |
66 | } |
67 | |
68 | /** |
69 | * This is largely cadged from PageHistory::history |
70 | * |
71 | * @return string HTML |
72 | */ |
73 | public function onView() { |
74 | $this->getOutput()->addModuleStyles( [ |
75 | 'mediawiki.action.styles', |
76 | ] ); |
77 | |
78 | if ( $this->getWikiPage()->getId() === 0 ) { |
79 | $s = $this->msg( 'nocredits' )->parse(); |
80 | } else { |
81 | $s = $this->getCredits( -1 ); |
82 | } |
83 | |
84 | return Html::rawElement( 'div', [ 'id' => 'mw-credits' ], $s ); |
85 | } |
86 | |
87 | /** |
88 | * Get a list of contributors |
89 | * |
90 | * @param int $cnt Maximum list of contributors to show |
91 | * @param bool $showIfMax Whether to contributors if there more than $cnt |
92 | * @return string Html |
93 | */ |
94 | public function getCredits( $cnt, $showIfMax = true ) { |
95 | $s = ''; |
96 | |
97 | if ( $cnt !== 0 ) { |
98 | $s = $this->getAuthor(); |
99 | if ( $cnt > 1 || $cnt < 0 ) { |
100 | $s .= ' ' . $this->getContributors( $cnt - 1, $showIfMax ); |
101 | } |
102 | } |
103 | |
104 | return $s; |
105 | } |
106 | |
107 | /** |
108 | * Get the last author with the last modification time |
109 | * |
110 | * @return string HTML |
111 | */ |
112 | private function getAuthor() { |
113 | $page = $this->getWikiPage(); |
114 | $user = $this->userFactory->newFromName( $page->getUserText(), UserRigorOptions::RIGOR_NONE ); |
115 | |
116 | $timestamp = $page->getTimestamp(); |
117 | if ( $timestamp ) { |
118 | $lang = $this->getLanguage(); |
119 | $d = $lang->date( $page->getTimestamp(), true ); |
120 | $t = $lang->time( $page->getTimestamp(), true ); |
121 | } else { |
122 | $d = ''; |
123 | $t = ''; |
124 | } |
125 | |
126 | return $this->msg( 'lastmodifiedatby', $d, $t )->rawParams( |
127 | // @phan-suppress-next-line PhanTypeMismatchArgumentNullable RIGOR_NONE never returns null |
128 | $this->userLink( $user ) )->params( $user->getName() )->escaped(); |
129 | } |
130 | |
131 | /** |
132 | * Whether we can display the user's real name (not a hidden pref) |
133 | * |
134 | * @since 1.24 |
135 | * @return bool |
136 | */ |
137 | protected function canShowRealUserName() { |
138 | $hiddenPrefs = $this->context->getConfig()->get( MainConfigNames::HiddenPrefs ); |
139 | return !in_array( 'realname', $hiddenPrefs ); |
140 | } |
141 | |
142 | /** |
143 | * Get a list of contributors of $article |
144 | * @param int $cnt Maximum list of contributors to show |
145 | * @param bool $showIfMax Whether to contributors if there more than $cnt |
146 | * @return string Html |
147 | */ |
148 | protected function getContributors( $cnt, $showIfMax ) { |
149 | $contributors = $this->getWikiPage()->getContributors(); |
150 | |
151 | $others_link = false; |
152 | |
153 | # Hmm... too many to fit! |
154 | if ( $cnt > 0 && $contributors->count() > $cnt ) { |
155 | $others_link = $this->othersLink(); |
156 | if ( !$showIfMax ) { |
157 | return $this->msg( 'othercontribs' )->rawParams( |
158 | $others_link )->params( $contributors->count() )->escaped(); |
159 | } |
160 | } |
161 | |
162 | $real_names = []; |
163 | $user_names = []; |
164 | $anon_ips = []; |
165 | |
166 | # Sift for real versus user names |
167 | /** @var User $user */ |
168 | foreach ( $contributors as $user ) { |
169 | $cnt--; |
170 | if ( $user->isRegistered() ) { |
171 | $link = $this->link( $user ); |
172 | if ( $this->canShowRealUserName() && $user->getRealName() ) { |
173 | $real_names[] = $link; |
174 | } else { |
175 | $user_names[] = $link; |
176 | } |
177 | } else { |
178 | $anon_ips[] = $this->link( $user ); |
179 | } |
180 | |
181 | if ( $cnt === 0 ) { |
182 | break; |
183 | } |
184 | } |
185 | |
186 | $lang = $this->getLanguage(); |
187 | |
188 | if ( count( $real_names ) ) { |
189 | $real = $lang->listToText( $real_names ); |
190 | } else { |
191 | $real = false; |
192 | } |
193 | |
194 | # "ThisSite user(s) A, B and C" |
195 | if ( count( $user_names ) ) { |
196 | $user = $this->msg( 'siteusers' )->rawParams( $lang->listToText( $user_names ) )->params( |
197 | count( $user_names ) )->escaped(); |
198 | } else { |
199 | $user = false; |
200 | } |
201 | |
202 | if ( count( $anon_ips ) ) { |
203 | $anon = $this->msg( 'anonusers' )->rawParams( $lang->listToText( $anon_ips ) )->params( |
204 | count( $anon_ips ) )->escaped(); |
205 | } else { |
206 | $anon = false; |
207 | } |
208 | |
209 | # This is the big list, all mooshed together. We sift for blank strings |
210 | $fullList = []; |
211 | foreach ( [ $real, $user, $anon, $others_link ] as $s ) { |
212 | if ( $s !== false ) { |
213 | $fullList[] = $s; |
214 | } |
215 | } |
216 | |
217 | $count = count( $fullList ); |
218 | |
219 | # "Based on work by ..." |
220 | return $count |
221 | ? $this->msg( 'othercontribs' )->rawParams( |
222 | $lang->listToText( $fullList ) )->params( $count )->escaped() |
223 | : ''; |
224 | } |
225 | |
226 | /** |
227 | * Get a link to $user's user page |
228 | * @param User $user |
229 | * @return string Html |
230 | */ |
231 | protected function link( User $user ) { |
232 | if ( $this->canShowRealUserName() && !$user->isAnon() ) { |
233 | $real = $user->getRealName(); |
234 | if ( $real === '' ) { |
235 | $real = $user->getName(); |
236 | } |
237 | } else { |
238 | $real = $user->getName(); |
239 | } |
240 | |
241 | return Linker::userLink( $user->getId(), $user->getName(), $real ); |
242 | } |
243 | |
244 | /** |
245 | * Get a link to $user's user page |
246 | * @param User $user |
247 | * @return string Html |
248 | */ |
249 | protected function userLink( User $user ) { |
250 | $link = $this->link( $user ); |
251 | if ( $user->isAnon() ) { |
252 | return $this->msg( 'anonuser' )->rawParams( $link )->parse(); |
253 | } elseif ( $this->canShowRealUserName() && $user->getRealName() ) { |
254 | return $link; |
255 | } else { |
256 | return $this->msg( 'siteuser' )->rawParams( $link )->params( $user->getName() )->escaped(); |
257 | } |
258 | } |
259 | |
260 | /** |
261 | * Get a link to action=credits of $article page |
262 | * @return string HTML link |
263 | */ |
264 | protected function othersLink() { |
265 | return $this->linkRenderer->makeKnownLink( |
266 | $this->getTitle(), |
267 | $this->msg( 'others' )->text(), |
268 | [], |
269 | [ 'action' => 'credits' ] |
270 | ); |
271 | } |
272 | } |