Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 104 |
|
0.00% |
0 / 16 |
CRAP | |
0.00% |
0 / 1 |
MathQueryObject | |
0.00% |
0 / 104 |
|
0.00% |
0 / 16 |
1260 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setQueryId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
saveToDatabase | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
20 | |||
exportTexDocument | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
2 | |||
newQueryFromEquationRow | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getQueryId | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getTeXQuery | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getCQuery | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getPQuery | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
injectQvar | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
132 | |||
getLaTeXMLCMMLSettings | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getLaTeXMLPMLSettings | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
generateContentQueryString | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
generatePresentationQueryString | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
getXQuery | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setXQuery | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | use MediaWiki\Extension\Math\MathLaTeXML; |
4 | use MediaWiki\Logger\LoggerFactory; |
5 | use MediaWiki\MediaWikiServices; |
6 | use MediaWiki\Title\Title; |
7 | |
8 | class MathQueryObject extends MathObject { |
9 | |
10 | private const MIN_DEPTH = 0; |
11 | private const SELECTIVITY_QVAR = 0.1; |
12 | |
13 | /** @var int */ |
14 | private $queryID = false; |
15 | /** @var string */ |
16 | private $texquery; |
17 | /** @var string|null|false */ |
18 | private $cquery = false; |
19 | /** @var string|false */ |
20 | private $pquery = false; |
21 | /** @var string */ |
22 | private $xQuery = ''; |
23 | /** @var int */ |
24 | private $qVarCount = 0; |
25 | |
26 | /* ToDo: Update to new format |
27 | <code> |
28 | latexmlc --whatsin=fragment --path=$(LLIB) \ |
29 | --preamble=$(LLIB)/pre.tex --postamble=$(LLIB)/post.tex \ |
30 | --format=xml --cmml --pmml --preload=[ids]latexml.sty \ |
31 | --stylesheet=$(LLIB)/ntcir11-topic.xsl \ |
32 | --destination=$@ --log=$(basename $<).ltxlog $< |
33 | </code> see http://kwarc.info/kohlhase/event/NTCIR11/ |
34 | */ |
35 | private const PMML_SETTINGS = [ |
36 | 'format' => 'xml', |
37 | 'whatsin' => 'math', |
38 | 'whatsout' => 'math', |
39 | 'pmml', |
40 | 'nodefaultresources', |
41 | 'preload' => [ |
42 | 'LaTeX.pool', |
43 | 'article.cls', |
44 | 'amsmath.sty', |
45 | 'amsthm.sty', |
46 | 'amstext.sty', |
47 | 'amssymb.sty', |
48 | 'eucal.sty', |
49 | '[dvipsnames]xcolor.sty', |
50 | 'url.sty', |
51 | 'hyperref.sty', |
52 | 'mws.sty', |
53 | // '[ids]latexml.sty', |
54 | 'texvc' |
55 | ], |
56 | ]; |
57 | |
58 | /** |
59 | * @param string $texquery the TeX-like search input |
60 | */ |
61 | public function __construct( $texquery = '' ) { |
62 | $this->texquery = $texquery; |
63 | } |
64 | |
65 | /** |
66 | * Set the query id |
67 | * @param int $id |
68 | */ |
69 | public function setQueryId( $id ) { |
70 | $this->queryID = $id; |
71 | } |
72 | |
73 | /** |
74 | * @param bool $overwrite |
75 | * |
76 | * @return bool |
77 | */ |
78 | public function saveToDatabase( $overwrite = false ) { |
79 | global $wgMathWmcServer; |
80 | // If $wgMathWmcServer is unset there's no math_wmc_ref table to update |
81 | if ( !$wgMathWmcServer ) { |
82 | return false; |
83 | } |
84 | |
85 | $fields = [ |
86 | 'qId' => $this->queryID, |
87 | 'oldId' => $this->getRevisionID(), |
88 | 'fId' => $this->getAnchorID(), |
89 | 'texQuery' => $this->getTeXQuery(), |
90 | 'qVarCount' => $this->qVarCount, |
91 | 'isDraft' => true, |
92 | 'math_inputhash' => $this->getInputHash() |
93 | ]; // Store the inputhash just to be sure. |
94 | $dbw = MediaWikiServices::getInstance() |
95 | ->getConnectionProvider() |
96 | ->getPrimaryDatabase(); |
97 | // Overwrite draft queries only. |
98 | if ( $dbw->selectField( |
99 | 'math_wmc_ref', 'isDraft', [ 'qId' => $this->queryID ] |
100 | ) && $overwrite ) { |
101 | return $dbw->update( 'math_wmc_ref', $fields, [ 'qId' => $this->queryID ] ); |
102 | } else { |
103 | return $dbw->insert( 'math_wmc_ref', $fields ); |
104 | } |
105 | } |
106 | |
107 | public function exportTexDocument() { |
108 | $texInput = htmlspecialchars( $this->getUserInputTex() ); |
109 | $texInputComment = preg_replace( "/[\n\r]/", "\n%", $texInput ); |
110 | $title = Title::newFromID( $this->getRevisionID() ); |
111 | $absUrl = |
112 | $title->getFullURL( [ "oldid" => $title->getLatestRevID() ] ) . |
113 | MathSearchHooks::generateMathAnchorString( $title->getLatestRevID(), $this->getAnchorID(), '' ); |
114 | return <<<TeX |
115 | \begin{topic}{{$this->getPageTitle()}-{$this->getAnchorID()}} |
116 | \begin{fquery}\${$this->getTeXQuery()}\$\end{fquery} |
117 | \begin{private} |
118 | \begin{relevance} |
119 | find result similar to Formula {$this->getAnchorID()} on page {$this->getPageTitle()}: |
120 | %\href{{$absUrl}}{\${$texInputComment}\$} |
121 | \end{relevance} |
122 | \examplehit{{$absUrl}} |
123 | \contributor{Moritz Schubotz} |
124 | \end{private} |
125 | \end{topic} |
126 | |
127 | TeX; |
128 | } |
129 | |
130 | /** |
131 | * @param stdClass $rpage |
132 | * @param bool|int $queryID |
133 | * @return \self |
134 | */ |
135 | public static function newQueryFromEquationRow( $rpage, $queryID = false ) { |
136 | /** @var self $instance */ |
137 | $instance = self::constructformpagerow( $rpage ); |
138 | $instance->setQueryId( $queryID ); |
139 | return $instance; |
140 | } |
141 | |
142 | /** |
143 | * Returns the queryId. If not set a random query id will be generated. |
144 | * @return int |
145 | */ |
146 | public function getQueryId() { |
147 | if ( $this->queryID === false ) { |
148 | $this->queryID = rand(); |
149 | } |
150 | return $this->queryID; |
151 | } |
152 | |
153 | /** |
154 | * Returns the tex query string. |
155 | * If not set a query id will be generated. |
156 | * @return string |
157 | */ |
158 | public function getTeXQuery() { |
159 | if ( $this->texquery == false ) { |
160 | $this->injectQvar(); |
161 | } |
162 | return $this->texquery; |
163 | } |
164 | |
165 | /** |
166 | * Returns the ContentMathML expression. |
167 | * If not set a random query id will be generated based on the TeXQuery. |
168 | * @return string|null |
169 | */ |
170 | public function getCQuery() { |
171 | if ( $this->cquery === false ) { |
172 | $this->generateContentQueryString(); |
173 | } |
174 | return $this->cquery; |
175 | } |
176 | |
177 | /** |
178 | * Returns the PresentationMathML expression. |
179 | * If not set a random query id will be generated based on the TeXQuery. |
180 | * @return string |
181 | */ |
182 | public function getPQuery() { |
183 | if ( $this->pquery === false ) { |
184 | $this->generatePresentationQueryString(); |
185 | } |
186 | return $this->pquery; |
187 | } |
188 | |
189 | public function injectQvar() { |
190 | $out = ""; |
191 | $level = 0; |
192 | $qVarLevel = PHP_INT_MAX; |
193 | $qVarNo = 0; |
194 | foreach ( str_split( $this->getTex() ) as $currentchar ) { |
195 | switch ( $currentchar ) { |
196 | case '{': |
197 | $level++; |
198 | if ( $level >= self::MIN_DEPTH && $level < $qVarLevel ) { |
199 | if ( ( self::SELECTIVITY_QVAR * $level ) > ( mt_rand() / mt_getrandmax() ) ) { |
200 | $qVarLevel = $level; |
201 | $out .= "{?{x" . $qVarNo++ . "}"; |
202 | } else { |
203 | $out .= '{'; |
204 | } |
205 | } elseif ( $level < $qVarLevel ) { |
206 | $out .= '{'; |
207 | } |
208 | break; |
209 | case '}': |
210 | $level--; |
211 | if ( $level < $qVarLevel ) { |
212 | $qVarLevel = PHP_INT_MAX; |
213 | $out .= "}"; |
214 | } |
215 | break; |
216 | default: |
217 | if ( $level < $qVarLevel ) { |
218 | $out .= $currentchar; |
219 | } |
220 | } |
221 | } |
222 | $this->qVarCount = $qVarNo; |
223 | $this->texquery = $out; |
224 | return $out; |
225 | } |
226 | |
227 | public function getLaTeXMLCMMLSettings() { |
228 | global $wgMathDefaultLaTeXMLSetting; |
229 | $cSettings = $wgMathDefaultLaTeXMLSetting; |
230 | $cSettings['preload'][] = 'mws.sty'; |
231 | $cSettings['stylesheet'] = 'MWSquery.xsl'; |
232 | return $cSettings; |
233 | } |
234 | |
235 | public function getLaTeXMLPMLSettings() { |
236 | global $wgMathDefaultLaTeXMLSetting; |
237 | $cSettings = array_diff( $wgMathDefaultLaTeXMLSetting, [ 'cmml' ] ); |
238 | $cSettings['preload'][] = 'mws.sty'; |
239 | $cSettings['stylesheet'] = 'MWSquery.xsl'; |
240 | return $cSettings; |
241 | } |
242 | |
243 | /** |
244 | * @return string|null |
245 | */ |
246 | public function generateContentQueryString() { |
247 | $renderer = new MathLaTeXML( $this->getTeXQuery() ); |
248 | $renderer->setLaTeXMLSettings( $this->getLaTeXMLCMMLSettings() ); |
249 | $renderer->setAllowedRootElements( [ 'query' ] ); |
250 | if ( $renderer->render( true ) ) { |
251 | $this->cquery = $renderer->getMathml(); |
252 | return $this->cquery; |
253 | } else { |
254 | LoggerFactory::getInstance( |
255 | 'MathSearch' |
256 | )->error( 'error during generation of query string' . $renderer->getLastError() ); |
257 | } |
258 | } |
259 | |
260 | /** |
261 | * @return string |
262 | */ |
263 | public function generatePresentationQueryString() { |
264 | $renderer = new MathLaTeXML( $this->getTeXQuery() ); |
265 | // $renderer->setXMLValidaton( false ); |
266 | // $renderer->setAllowedRootElements( array( 'query' ) ); |
267 | $renderer->setLaTeXMLSettings( self::PMML_SETTINGS ); |
268 | if ( $renderer->render( true ) ) { |
269 | $this->pquery = $renderer->getMathml(); |
270 | return $this->pquery; |
271 | } else { |
272 | echo $renderer->getLastError(); |
273 | return $renderer->getLastError(); |
274 | } |
275 | } |
276 | |
277 | /** |
278 | * @return string |
279 | */ |
280 | public function getXQuery() { |
281 | return $this->xQuery; |
282 | } |
283 | |
284 | /** |
285 | * @param string $xQuery |
286 | */ |
287 | public function setXQuery( $xQuery ) { |
288 | $this->xQuery = $xQuery; |
289 | } |
290 | } |