Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 104
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
MathQueryObject
0.00% covered (danger)
0.00%
0 / 104
0.00% covered (danger)
0.00%
0 / 16
1260
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setQueryId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 saveToDatabase
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
20
 exportTexDocument
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 newQueryFromEquationRow
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryId
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getTeXQuery
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getCQuery
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getPQuery
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 injectQvar
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
132
 getLaTeXMLCMMLSettings
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getLaTeXMLPMLSettings
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 generateContentQueryString
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 generatePresentationQueryString
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getXQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setXQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3use MediaWiki\Extension\Math\MathLaTeXML;
4use MediaWiki\Logger\LoggerFactory;
5use MediaWiki\MediaWikiServices;
6use MediaWiki\Title\Title;
7
8class 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
127TeX;
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}