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;
6
7class 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
126TeX;
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}