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