Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 95 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
SpecialThanks | |
0.00% |
0 / 95 |
|
0.00% |
0 / 10 |
1122 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
doesWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setParameter | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
132 | |||
getFormFields | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
preHtml | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
56 | |||
alterForm | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
20 | |||
getDisplayFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onSubmit | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
20 | |||
onSuccess | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Thanks; |
4 | |
5 | use MediaWiki\Api\ApiMain; |
6 | use MediaWiki\Api\ApiUsageException; |
7 | use MediaWiki\HTMLForm\HTMLForm; |
8 | use MediaWiki\Linker\Linker; |
9 | use MediaWiki\Request\DerivativeRequest; |
10 | use MediaWiki\SpecialPage\FormSpecialPage; |
11 | use MediaWiki\Status\Status; |
12 | use MediaWiki\User\UserFactory; |
13 | use MediaWiki\User\UserRigorOptions; |
14 | |
15 | class SpecialThanks extends FormSpecialPage { |
16 | |
17 | /** |
18 | * API result |
19 | */ |
20 | protected array $result; |
21 | |
22 | /** |
23 | * 'rev' for revision, 'log' for log entry, or 'flow' for Flow comment, |
24 | * null if no ID is specified |
25 | */ |
26 | protected ?string $type; |
27 | |
28 | /** |
29 | * Revision or Log ID ('0' = invalid) or Flow UUID |
30 | */ |
31 | protected ?string $id; |
32 | |
33 | private UserFactory $userFactory; |
34 | |
35 | public function __construct( UserFactory $userFactory ) { |
36 | parent::__construct( 'Thanks' ); |
37 | $this->userFactory = $userFactory; |
38 | $this->id = null; |
39 | } |
40 | |
41 | public function doesWrites(): bool { |
42 | return true; |
43 | } |
44 | |
45 | /** |
46 | * Set the type and ID or UUID of the request. |
47 | * @param string $par The subpage name. |
48 | */ |
49 | protected function setParameter( $par ) { |
50 | if ( $par === null || $par === '' ) { |
51 | $this->type = null; |
52 | return; |
53 | } |
54 | |
55 | $tokens = explode( '/', $par ); |
56 | if ( $tokens[0] === 'Flow' ) { |
57 | if ( count( $tokens ) === 1 || $tokens[1] === '' ) { |
58 | $this->type = null; |
59 | return; |
60 | } |
61 | $this->type = 'flow'; |
62 | $this->id = $tokens[1]; |
63 | return; |
64 | } |
65 | |
66 | if ( strtolower( $tokens[0] ) === 'log' ) { |
67 | $this->type = 'log'; |
68 | // Make sure there's a numeric ID specified as the subpage. |
69 | if ( count( $tokens ) === 1 || $tokens[1] === '' || !( ctype_digit( $tokens[1] ) ) ) { |
70 | $this->id = '0'; |
71 | return; |
72 | } |
73 | $this->id = $tokens[1]; |
74 | return; |
75 | } |
76 | |
77 | $this->type = 'rev'; |
78 | if ( !( ctype_digit( $par ) ) ) { // Revision ID is not an integer. |
79 | $this->id = '0'; |
80 | return; |
81 | } |
82 | |
83 | $this->id = $par; |
84 | } |
85 | |
86 | /** |
87 | * HTMLForm fields |
88 | * @return string[][] |
89 | */ |
90 | protected function getFormFields(): array { |
91 | return [ |
92 | 'id' => [ |
93 | 'id' => 'mw-thanks-form-id', |
94 | 'name' => 'id', |
95 | 'type' => 'hidden', |
96 | 'default' => $this->id ?? '' |
97 | ], |
98 | 'type' => [ |
99 | 'id' => 'mw-thanks-form-type', |
100 | 'name' => 'type', |
101 | 'type' => 'hidden', |
102 | 'default' => $this->type ?? '', |
103 | ], |
104 | ]; |
105 | } |
106 | |
107 | /** |
108 | * Return the confirmation or error message. |
109 | */ |
110 | protected function preHtml(): string { |
111 | if ( $this->type === null ) { |
112 | $msgKey = 'thanks-error-no-id-specified'; |
113 | } elseif ( $this->type === 'rev' && $this->id === '0' ) { |
114 | $msgKey = 'thanks-error-invalidrevision'; |
115 | } elseif ( $this->type === 'log' && $this->id === '0' ) { |
116 | $msgKey = 'thanks-error-invalid-log-id'; |
117 | } elseif ( $this->type === 'flow' ) { |
118 | $msgKey = 'flow-thanks-confirmation-special'; |
119 | } else { |
120 | // The following messages are used here |
121 | // * thanks-confirmation-special-rev |
122 | // * thanks-confirmation-special-log |
123 | $msgKey = 'thanks-confirmation-special-' . $this->type; |
124 | } |
125 | return '<p>' . $this->msg( $msgKey )->escaped() . '</p>'; |
126 | } |
127 | |
128 | /** |
129 | * Format the submission form. |
130 | * @param HTMLForm $form The form object to modify. |
131 | */ |
132 | protected function alterForm( HTMLForm $form ) { |
133 | if ( $this->type === null |
134 | || ( in_array( $this->type, [ 'rev', 'log', ] ) && $this->id === '0' ) |
135 | ) { |
136 | $form->suppressDefaultSubmit( true ); |
137 | } else { |
138 | $form->setSubmitText( $this->msg( 'thanks-submit' )->escaped() ); |
139 | } |
140 | } |
141 | |
142 | protected function getDisplayFormat(): string { |
143 | return 'ooui'; |
144 | } |
145 | |
146 | /** |
147 | * Call the API internally. |
148 | * @param string[] $data The form data. |
149 | */ |
150 | public function onSubmit( array $data ): Status { |
151 | if ( !isset( $data['id'] ) ) { |
152 | return Status::newFatal( 'thanks-error-invalidrevision' ); |
153 | } |
154 | |
155 | if ( in_array( $this->type, [ 'rev', 'log' ] ) ) { |
156 | $requestData = [ |
157 | 'action' => 'thank', |
158 | $this->type => (int)$data['id'], |
159 | 'source' => 'specialpage', |
160 | 'token' => $this->getOutput()->getCsrfTokenSet()->getToken(), |
161 | ]; |
162 | } else { |
163 | $requestData = [ |
164 | 'action' => 'flowthank', |
165 | 'postid' => $data['id'], |
166 | 'token' => $this->getOutput()->getCsrfTokenSet()->getToken(), |
167 | ]; |
168 | } |
169 | |
170 | $request = new DerivativeRequest( |
171 | $this->getRequest(), |
172 | $requestData, |
173 | true // posted |
174 | ); |
175 | |
176 | $api = new ApiMain( |
177 | $request, |
178 | true // enable write mode |
179 | ); |
180 | |
181 | try { |
182 | $api->execute(); |
183 | } catch ( ApiUsageException $e ) { |
184 | return Status::wrap( $e->getStatusValue() ); |
185 | } |
186 | |
187 | $this->result = $api->getResult()->getResultData( [ 'result' ] ); |
188 | return Status::newGood(); |
189 | } |
190 | |
191 | /** |
192 | * Display a message to the user. |
193 | */ |
194 | public function onSuccess() { |
195 | $sender = $this->getUser(); |
196 | $recipient = $this->userFactory->newFromName( $this->result['recipient'], UserRigorOptions::RIGOR_NONE ); |
197 | $link = Linker::userLink( $recipient->getId(), $recipient->getName() ); |
198 | |
199 | if ( in_array( $this->type, [ 'rev', 'log' ] ) ) { |
200 | $msgKey = 'thanks-thanked-notice'; |
201 | } else { |
202 | $msgKey = 'flow-thanks-thanked-notice'; |
203 | } |
204 | $msg = $this->msg( $msgKey ) |
205 | ->rawParams( $link ) |
206 | ->params( $recipient->getName(), $sender->getName() ); |
207 | $this->getOutput()->addHTML( $msg->parse() ); |
208 | } |
209 | |
210 | public function isListed(): bool { |
211 | return false; |
212 | } |
213 | } |