Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 190 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
SpecialUploadResult | |
0.00% |
0 / 190 |
|
0.00% |
0 / 12 |
1056 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
formatErrors | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
12 | |||
printRunSelector | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
12 | |||
runSelectorFilter | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
runValidatorFilter | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
runFileCheck | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
20 | |||
processInput | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
printResultRow | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
12 | |||
displayFeedback | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
20 | |||
displayFormulaFeedback | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
20 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | use MediaWiki\MediaWikiServices; |
4 | |
5 | /** |
6 | * Lets the user import a CSV file with the results |
7 | * |
8 | * @author Moritz Schubotz |
9 | * @author Yaron Koren (This class is based on DT_ImportCSV from the DataTransfer extension) |
10 | */ |
11 | class SpecialUploadResult extends SpecialPage { |
12 | |
13 | /** @var ImportCsv */ |
14 | private $importer; |
15 | /** @var bool|int|string */ |
16 | protected $runId = false; |
17 | |
18 | /** |
19 | * @param string $name |
20 | */ |
21 | public function __construct( $name = 'MathUpload' ) { |
22 | $listed = (bool)$this->getConfig()->get( 'MathWmcServer' ); |
23 | parent::__construct( $name, 'mathwmcsubmit', $listed ); |
24 | } |
25 | |
26 | /** |
27 | * @param string[] $errors |
28 | * |
29 | * @return string |
30 | */ |
31 | private static function formatErrors( $errors ) { |
32 | return wfMessage( 'math-wmc-Warnings' )->text() . "<br />" . implode( "<br />", $errors ); |
33 | } |
34 | |
35 | /** |
36 | * @param null|string $query |
37 | * |
38 | * @throws PermissionsError |
39 | */ |
40 | function execute( $query ) { |
41 | $this->setHeaders(); |
42 | if ( !$this->getUser()->isAllowed( 'mathwmcsubmit' ) || |
43 | !$this->getConfig()->get( 'MathUploadEnabled' ) |
44 | ) { |
45 | throw new PermissionsError( 'mathwmcsubmit' ); |
46 | } |
47 | |
48 | $this->getOutput()->addWikiTextAsInterface( $this->msg( 'math-wmc-Introduction' )->text() ); |
49 | $this->importer = new ImportCsv( $this->getUser() ); |
50 | $formDescriptor = $this->printRunSelector(); |
51 | $formDescriptor['File'] = [ |
52 | 'label-message' => 'math-wmc-FileLabel', |
53 | 'help-message' => 'math-wmc-FileHelp', |
54 | 'class' => 'HTMLTextField', |
55 | 'type' => 'file', |
56 | 'required' => true, |
57 | 'validation-callback' => [ $this, 'runFileCheck' ], |
58 | ]; |
59 | $formDescriptor['displayFormulae'] = [ |
60 | 'label-message' => 'math-wmc-display-formulae-label', |
61 | 'help-message' => 'math-wmc-display-formulae-help', |
62 | 'type' => 'check', |
63 | ]; |
64 | $formDescriptor['attachResults'] = [ |
65 | 'label-message' => 'math-wmc-attach-results-label', |
66 | 'help-message' => 'math-wmc-attach-results-help', |
67 | 'type' => 'check', |
68 | ]; |
69 | $htmlForm = new HTMLForm( $formDescriptor, $this->getContext() ); |
70 | $htmlForm->setSubmitCallback( [ $this, 'processInput' ] ); |
71 | $htmlForm->show(); |
72 | } |
73 | |
74 | /** |
75 | * @param string $type |
76 | * |
77 | * @return array |
78 | */ |
79 | protected function printRunSelector( $type = 'selectorother' ) { |
80 | // If $wgMathWmcServer is unset there's no math_wmc_runs table to query |
81 | if ( !$this->getConfig()->get( 'MathWmcServer' ) ) { |
82 | return []; |
83 | } |
84 | |
85 | $dbr = MediaWikiServices::getInstance() |
86 | ->getConnectionProvider() |
87 | ->getReplicaDatabase(); |
88 | $formFields = []; |
89 | $options = []; |
90 | $uID = $this->getUser()->getId(); |
91 | $res = $dbr->select( 'math_wmc_runs', [ 'runName', 'runId' ], |
92 | [ 'isDraft' => true, 'userID' => $uID ] ); |
93 | foreach ( $res as $row ) { |
94 | $options[ $row->runName . " (" . $row->runId . ")" ] = $row->runId; |
95 | } |
96 | // Probably we want to add more fields in the future |
97 | $formFields['run'] = [ |
98 | 'type' => $type, |
99 | 'label-message' => 'math-wmc-SelectRun', |
100 | 'options' => $options, |
101 | 'required' => true, |
102 | 'help-message' => 'math-wmc-SelectRunHelp', |
103 | 'filter-callback' => [ $this, 'runSelectorFilter' ], |
104 | 'validation-callback' => [ $this, 'runValidatorFilter' ], |
105 | // 'section' => 'math-wmc-SectionRun' |
106 | ]; |
107 | return $formFields; |
108 | } |
109 | |
110 | /** |
111 | * @param string $run |
112 | * |
113 | * @return bool|int|string |
114 | */ |
115 | function runSelectorFilter( $run ) { |
116 | if ( $run == '' ) { |
117 | return date( 'Y-m-d H:i:s (e)' ); |
118 | } |
119 | $this->runId = $this->importer->validateRunId( $run ); |
120 | $warnings = $this->importer->getWarnings(); |
121 | if ( $warnings ) { |
122 | echo "bad wqarni"; |
123 | foreach ( $warnings as $warning ) { |
124 | $this->getOutput()->addWikiTextAsInterface( $warning ); |
125 | } |
126 | } |
127 | return $run; |
128 | } |
129 | |
130 | /** |
131 | * @return bool|string |
132 | */ |
133 | function runValidatorFilter() { |
134 | $dbr = MediaWikiServices::getInstance() |
135 | ->getConnectionProvider() |
136 | ->getReplicaDatabase(); |
137 | $uID = $this->getUser()->getId(); |
138 | $res = $dbr->selectField( 'math_wmc_runs', 'runName', |
139 | [ 'isDraft' => true, 'userID' => $uID, 'runId' => $this->runId ] ); |
140 | if ( !$res ) { |
141 | return $this->msg( 'math-wmc-SelectRunHelp' )->text(); |
142 | } else { |
143 | return true; |
144 | } |
145 | } |
146 | |
147 | /** |
148 | * @return bool|null|string |
149 | */ |
150 | function runFileCheck() { |
151 | $out = $this->getOutput(); |
152 | |
153 | $uploadResult = ImportStreamSource::newFromUpload( 'wpFile' ); |
154 | |
155 | if ( !$uploadResult->isOK() ) { |
156 | return $uploadResult->getWikiText(); |
157 | } |
158 | |
159 | /** @var ImportStreamSource $source */ |
160 | $source = $uploadResult->value; |
161 | |
162 | $out->addWikiMsg( 'math-wmc-importing' ); |
163 | // FIXME: ImportStreamSource::$mHandle is private! |
164 | $error_msg = $this->importer->importFromFile( $source->mHandle ); |
165 | |
166 | if ( $error_msg !== null ) { |
167 | return $error_msg; |
168 | } |
169 | if ( count( $this->importer->getWarnings() ) ) { |
170 | $out->addWikiTextAsInterface( self::formatErrors( $this->importer->getWarnings() ) ); |
171 | } |
172 | |
173 | return true; |
174 | } |
175 | |
176 | /** |
177 | * @return bool |
178 | */ |
179 | function processInput() { |
180 | $this->getOutput()->addWikiMsg( "math-wmc-SubmissionSuccess" ); |
181 | $this->importer->setOverwrite( !$this->getRequest()->getBool( "wpattachResults" ) ); |
182 | $this->importer->processInput(); |
183 | // TODO: Find adequate API call |
184 | $this->getOutput()->addHTML( '<table border="1" style="width:100%"> |
185 | <tr> |
186 | <th>queryId</th> |
187 | <th>formulaId</th> |
188 | <th>rank</th> |
189 | <th>rendering</th> |
190 | </tr>' ); |
191 | foreach ( $this->importer->getResults() as $result ) { |
192 | $this->printResultRow( $result ); |
193 | } |
194 | $this->getOutput()->addHTML( '</table>' ); |
195 | $this->displayFeedback(); |
196 | return true; |
197 | } |
198 | |
199 | /** |
200 | * @param array $row |
201 | */ |
202 | private function printResultRow( $row ) { |
203 | $md5 = MathObject::hash2md5( $row['math_inputhash'] ); |
204 | if ( $this->getRequest()->getBool( "wpdisplayFormulae" ) ) { |
205 | $this->getOutput()->addModuleStyles( [ 'ext.math.styles' ] ); |
206 | $renderer = MediaWikiServices::getInstance() |
207 | ->get( 'Math.RendererFactory' ) |
208 | ->getFromHash( $md5 ); |
209 | if ( $renderer->render() ) { |
210 | $renderedMath = $renderer->getHtmlOutput(); |
211 | } else { |
212 | $renderedMath = $md5; |
213 | } |
214 | } else { |
215 | $renderedMath = $md5; |
216 | } |
217 | $formulaId = MathSearchHooks::generateMathAnchorString( $row['oldId'], $row['fId'] ); |
218 | $revisionRecord = MediaWikiServices::getInstance() |
219 | ->getRevisionLookup() |
220 | ->getRevisionById( $row['oldId'] ); |
221 | $title = Title::newFromLinkTarget( $revisionRecord->getPageAsLinkTarget() ); |
222 | $link = $title->getLinkURL() . $formulaId; |
223 | $this->getOutput()->addHTML( "<tr><td>{$row['qId']}</td><td><a href=\"$link\" >$formulaId</a></td> |
224 | <td>{$row['rank']}</td><td>$renderedMath</td></tr>" ); |
225 | } |
226 | |
227 | private function displayFeedback() { |
228 | $runId = $this->runId; |
229 | $dbr = MediaWikiServices::getInstance() |
230 | ->getConnectionProvider() |
231 | ->getReplicaDatabase(); |
232 | $res = $dbr->select( |
233 | [ 'l' => 'math_wmc_rank_levels', 'r' => 'math_wmc_ref', 'math_wmc_results' ], |
234 | [ |
235 | 'count(DISTINCT `r`.`qId`) AS `c`', |
236 | '`l`.`level` AS `level`' |
237 | ], |
238 | [ |
239 | "(`math_wmc_results`.`rank` <= `l`.`level`)", |
240 | 'runId' => $runId, |
241 | '`math_wmc_results`.`oldId` = `r`.`oldId`', |
242 | '`math_wmc_results`.`qId` = `r`.`qId`' |
243 | ], |
244 | __METHOD__, |
245 | [ |
246 | 'GROUP BY' => '`l`.`level`', |
247 | 'ORDER BY' => 'count(DISTINCT `r`.`qId`) DESC' |
248 | ] |
249 | ); |
250 | if ( !$res || $res->numRows() == 0 ) { |
251 | $this->getOutput()->addWikiTextAsInterface( "Score is 0. Check your submission" ); |
252 | return; |
253 | } else { |
254 | $this->getOutput()->addWikiTextAsInterface( |
255 | "'''Scored in " . $res->numRows() . " evaluation levels'''" |
256 | ); |
257 | } |
258 | |
259 | $this->getOutput()->addHTML( '<table border="1" style="width:100%"> |
260 | <tr> |
261 | <th>number of correct results</th> |
262 | <th>rank cutoff</th> |
263 | </tr>' ); |
264 | foreach ( $res as $result ) { |
265 | $c = $result->c; |
266 | $l = $result->level; |
267 | $this->getOutput()->addHTML( " |
268 | <tr> |
269 | <td>$c</td> |
270 | <td>$l</td> |
271 | </tr>" ); |
272 | } |
273 | $this->getOutput()->addHTML( '</table>' ); |
274 | } |
275 | |
276 | private function displayFormulaFeedback() { |
277 | $runId = $this->runId; |
278 | $dbr = MediaWikiServices::getInstance() |
279 | ->getConnectionProvider() |
280 | ->getReplicaDatabase(); |
281 | $res = $dbr->select( |
282 | [ 'l' => 'math_wmc_rank_levels', 'r' => 'math_wmc_ref', 'math_wmc_results' ], |
283 | [ |
284 | 'count(DISTINCT `r`.`qId`) AS `c`', |
285 | '`l`.`level` AS `level`' |
286 | ], |
287 | [ |
288 | "(`math_wmc_results`.`rank` <= `l`.`level`)", |
289 | 'runId' => $runId, |
290 | '`math_wmc_results`.`oldId` = `r`.`oldId`', |
291 | '`math_wmc_results`.`qId` = `r`.`qId`', |
292 | '`math_wmc_results`.`fId` = `r`.`fId`', |
293 | ], |
294 | __METHOD__, |
295 | [ |
296 | 'GROUP BY' => '`l`.`level`', |
297 | 'ORDER BY' => 'count(DISTINCT `r`.`qId`) DESC' |
298 | ] |
299 | ); |
300 | if ( !$res || $res->numRows() == 0 ) { |
301 | $this->getOutput()->addWikiTextAsInterface( "Score is 0. Check your submission" ); |
302 | return; |
303 | } else { |
304 | $this->getOutput()->addWikiTextAsInterface( |
305 | "'''Scored in " . $res->numRows() . " evaluation levels'''" |
306 | ); |
307 | } |
308 | |
309 | $this->getOutput()->addHTML( '<table border="1" style="width:100%"> |
310 | <tr> |
311 | <th>number of correct results</th> |
312 | <th>rank cutoff</th> |
313 | </tr>' ); |
314 | foreach ( $res as $result ) { |
315 | $c = $result->c; |
316 | $l = $result->level; |
317 | $this->getOutput()->addHTML( " |
318 | <tr> |
319 | <td>$c</td> |
320 | <td>$l</td> |
321 | </tr>" ); |
322 | } |
323 | $this->getOutput()->addHTML( '</table>' ); |
324 | } |
325 | |
326 | protected function getGroupName() { |
327 | return 'mathsearch'; |
328 | } |
329 | } |