Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
MathEngineRest
0.00% covered (danger)
0.00%
0 / 79
0.00% covered (danger)
0.00%
0 / 15
702
0.00% covered (danger)
0.00%
0 / 1
 doPost
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
12
 getBackendUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setBackendUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getSize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResultSet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRelevanceMap
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setQuery
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 postQuery
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 processMathResults
n/a
0 / 0
n/a
0 / 0
0
 getPostData
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 processResults
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
42
 getType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 resetResults
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3use MediaWiki\Logger\LoggerFactory;
4use MediaWiki\MediaWikiServices;
5
6/**
7 * MediaWiki MathSearch extension
8 *
9 * (c) 2014 Moritz Schubotz
10 * GPLv2 license; info in main package.
11 *
12 * @file
13 * @ingroup extensions
14 */
15abstract class MathEngineRest {
16    /** @var MathQueryObject the query to be answered */
17    protected $query;
18    /** @var string */
19    protected $type = "mws";
20    /** @var int|false */
21    protected $size = false;
22    /** @var array<int,array<string,array[]>> */
23    protected $resultSet = [];
24    /** @var int[] */
25    protected $relevanceMap = [];
26    /** @var string */
27    protected $backendUrl = "http://localhost:9090";
28
29    protected static function doPost( $url, $postData ) {
30        $res = MediaWikiServices::getInstance()->getHttpRequestFactory()
31            ->post( $url, [ "postData" => $postData, "timeout" => 60 ] );
32        if ( $res === false ) {
33            if ( function_exists( 'curl_init' ) ) {
34                $handle = curl_init();
35                $options = [
36                    CURLOPT_URL => $url,
37                    CURLOPT_CUSTOMREQUEST => 'POST', // GET POST PUT PATCH DELETE HEAD OPTIONS
38                ];
39                // TODO: Figure out how not to write the error in a message and not in top of the output page
40                curl_setopt_array( $handle, $options );
41                $details = curl_exec( $handle );
42            } else {
43                $details = "curl is not installed.";
44            }
45            LoggerFactory::getInstance(
46                'MathSearch'
47            )->error( 'Nothing retrieved from $url. Check if server is running. Error:' .
48                var_export( $details, true ) );
49            return false;
50        } else {
51            return $res;
52        }
53    }
54
55    /**
56     * @return string
57     */
58    public function getBackendUrl() {
59        return $this->backendUrl;
60    }
61
62    /**
63     * @param string $backendUrl
64     */
65    public function setBackendUrl( $backendUrl ) {
66        $this->backendUrl = $backendUrl;
67    }
68
69    /**
70     * @return MathQueryObject
71     */
72    public function getQuery() {
73        return $this->query;
74    }
75
76    /**
77     * @param MathQueryObject|null $query
78     * @param bool|string $url
79     */
80    function __construct( $query = null, $url = false ) {
81        $this->query = $query;
82        if ( $url ) {
83            $this->setBackendUrl( $url );
84        }
85    }
86
87    /**
88     * @return int|false
89     */
90    public function getSize() {
91        return $this->size;
92    }
93
94    /**
95     * @return array<int,array<string,array[]>>
96     */
97    public function getResultSet() {
98        return $this->resultSet;
99    }
100
101    /**
102     * @return int[]
103     */
104    public function getRelevanceMap() {
105        return $this->relevanceMap;
106    }
107
108    /**
109     * @param MathQueryObject $query
110     * @return $this
111     */
112    public function setQuery( MathQueryObject $query ) {
113        $this->query = $query;
114        return $this;
115    }
116
117    /**
118     * Posts the query to mwsd and evaluates the result data
119     * @return bool
120     */
121    function postQuery() {
122        $numProcess = 30000;
123        $postData = $this->getPostData( $numProcess );
124        $res = self::doPost( $this->backendUrl, $postData );
125        if ( $res === false ) {
126            return false;
127        } else {
128            return $this->processResults( $res, $numProcess );
129        }
130    }
131
132    /**
133     * @param SimpleXMLElement $xmlRoot
134     */
135    abstract function processMathResults( $xmlRoot );
136
137    /**
138     * @param int $numProcess
139     * @return string
140     */
141    protected function getPostData( $numProcess ) {
142        global $wgMathDebug;
143        if ( $this->query->getXQuery() ) {
144            return $this->query->getXQuery();
145        } else {
146            $tmp =
147                str_replace( "answsize=\"30\"", "answsize=\"$numProcess\" totalreq=\"yes\"",
148                    $this->getQuery()->getCQuery() );
149            $postData = str_replace( "m:", "", $tmp );
150            if ( $wgMathDebug ) {
151                LoggerFactory::getInstance( 'MathSearch' )->debug( 'MWS query:' . $postData );
152                return $postData;
153            }
154            return $postData;
155        }
156    }
157
158    /**
159     * @param string $res
160     * @param int $numProcess
161     * @return bool
162     */
163    protected function processResults( $res, $numProcess ) {
164        try {
165            $xres = new SimpleXMLElement( $res );
166        } catch ( Exception $e ) {
167            LoggerFactory::getInstance( 'MathSearch' )->error( 'No valid XMLRESUSLT' . $res );
168            return false;
169        }
170
171        $this->size = (int)$xres["total"];
172        LoggerFactory::getInstance(
173            'MathSearch'
174        )->warning( $this->size . " results retrieved from $this->backendUrl." );
175        if ( $this->size == 0 ) {
176            return true;
177        }
178        $this->relevanceMap = [];
179        $this->resultSet = [];
180        $this->processMathResults( $xres );
181        if ( $this->size >= $numProcess ) {
182            ini_set( 'memory_limit', '256M' );
183            for ( $i = $numProcess; $i <= $this->size; $i += $numProcess ) {
184                $query = str_replace( "limitmin=\"0\" ", "limitmin=\"$i\" ", $this->postData );
185                $res = MediaWikiServices::getInstance()->getHttpRequestFactory()
186                    ->post( $this->backendUrl, [ "postData" => $query, "timeout" => 60 ] );
187                LoggerFactory::getInstance( 'mathsearch' )->debug( 'MWS query:' . $query );
188                if ( $res == false ) {
189                    LoggerFactory::getInstance(
190                        'MathSearch'
191                    )->error( "Nothing retrieved from $this->backendUrl. Check if mwsd is running there" );
192                    return false;
193                }
194                $xres = new SimpleXMLElement( $res );
195                $this->processMathResults( $xres );
196            }
197        }
198        return true;
199    }
200
201    /**
202     * @return string
203     */
204    public function getType() {
205        return $this->type;
206    }
207
208    /**
209     * @param string $type
210     */
211    public function setType( $type ) {
212        $this->type = $type;
213    }
214
215    public function resetResults() {
216        $this->size = false;
217        $this->resultSet = [];
218        $this->relevanceMap = [];
219    }
220
221}