Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
8.93% |
5 / 56 |
|
0.00% |
0 / 13 |
CRAP | |
0.00% |
0 / 1 |
Connector | |
8.93% |
5 / 56 |
|
0.00% |
0 / 13 |
497.09 | |
0.00% |
0 / 1 |
__construct | |
71.43% |
5 / 7 |
|
0.00% |
0 / 1 |
3.21 | |||
init | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
query | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
72 | |||
send | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
6 | |||
ping | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
record | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
search | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
session | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
settings | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
show | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
stat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
termlist | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
bytarget | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Central class for connecting to Pazpar2 resources used by VuFind. |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2011. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package Connection |
25 | * @author Chris Hallberg <challber@villanova.edu> |
26 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
27 | * @link https://vufind.org/wiki/development:architecture Wiki |
28 | */ |
29 | |
30 | namespace VuFindSearch\Backend\Pazpar2; |
31 | |
32 | use Laminas\Http\Client; |
33 | use Laminas\Http\Request; |
34 | use VuFindSearch\Backend\Exception\HttpErrorException; |
35 | use VuFindSearch\ParamBag; |
36 | |
37 | /** |
38 | * Central class for connecting to resources used by VuFind. |
39 | * |
40 | * @category VuFind |
41 | * @package Connection |
42 | * @author Chris Hallberg <challber@villanova.edu> |
43 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
44 | * @link https://vufind.org/wiki/development:architecture Wiki |
45 | */ |
46 | class Connector implements \Laminas\Log\LoggerAwareInterface |
47 | { |
48 | use \VuFind\Log\LoggerAwareTrait; |
49 | |
50 | /** |
51 | * Base url for searches |
52 | * |
53 | * @var string |
54 | */ |
55 | protected $base; |
56 | |
57 | /** |
58 | * The HTTP_Request object used for REST transactions |
59 | * |
60 | * @var Client |
61 | */ |
62 | protected $client; |
63 | |
64 | /** |
65 | * Session ID |
66 | * |
67 | * @var string |
68 | */ |
69 | protected $session = false; |
70 | |
71 | /** |
72 | * Constructor |
73 | * |
74 | * @param string $base Base URL for Pazpar2 |
75 | * @param Client $client An HTTP client object |
76 | * @param bool $autoInit Should we auto-initialize the Pazpar2 connection? |
77 | */ |
78 | public function __construct($base, Client $client, $autoInit = false) |
79 | { |
80 | $this->base = $base; |
81 | if (empty($this->base)) { |
82 | throw new \Exception('Missing Pazpar2 base URL.'); |
83 | } |
84 | |
85 | $this->client = $client; |
86 | $this->client->setMethod(Request::METHOD_GET); // always use GET |
87 | |
88 | if ($autoInit) { |
89 | $this->init(); |
90 | } |
91 | } |
92 | |
93 | /** |
94 | * Initializes a session. Returns session ID to be used in subsequent requests. |
95 | * Adds session to the base |
96 | * |
97 | * @return session id |
98 | */ |
99 | public function init() |
100 | { |
101 | $this->session = false; // clear any existing session |
102 | $session = $this->query('init'); |
103 | if (!isset($session->session)) { |
104 | throw new \Exception('Session initialization failed.'); |
105 | } |
106 | $this->session = $session->session; |
107 | return $session; |
108 | } |
109 | |
110 | /** |
111 | * Requests and receives information from pazpar |
112 | * |
113 | * @param string $command the command to be executed |
114 | * @param ParamBag $data optional extra data |
115 | * |
116 | * @return SimpleXMLElement Response |
117 | */ |
118 | protected function query($command, ParamBag $data = null) |
119 | { |
120 | // If we don't have a session as long as we're not being explict |
121 | if (!$this->session && $command !== 'init') { |
122 | $this->init(); |
123 | } |
124 | |
125 | // Don't change input when manipulating parameters: |
126 | $params = (null === $data) ? new ParamBag() : clone $data; |
127 | |
128 | // Add session and command: |
129 | if ($this->session) { |
130 | $params->set('session', $this->session); |
131 | } |
132 | $params->set('command', $command); |
133 | |
134 | $this->client->setUri($this->base . '?' . implode('&', $params->request())); |
135 | $xmlStr = $this->send($this->client); |
136 | $xml = simplexml_load_string($xmlStr); |
137 | |
138 | // If our session has expired, start a new session |
139 | if ( |
140 | $command !== 'init' |
141 | && $xml->session == $this->session && isset($this->session) |
142 | ) { |
143 | $this->init(); |
144 | return $this->query($command, $data); |
145 | } |
146 | return $xml; |
147 | } |
148 | |
149 | /** |
150 | * Send a request and return the response. |
151 | * |
152 | * @param Client $client Prepare HTTP client |
153 | * |
154 | * @return string Response body |
155 | * |
156 | * @throws \VuFindSearch\Backend\Exception\RemoteErrorException Server |
157 | * signaled a server error (HTTP 5xx) |
158 | * @throws \VuFindSearch\Backend\Exception\RequestErrorException Server |
159 | * signaled a client error (HTTP 4xx) |
160 | */ |
161 | protected function send(Client $client) |
162 | { |
163 | $this->debug( |
164 | sprintf('=> %s %s', $client->getMethod(), $client->getUri()) |
165 | ); |
166 | |
167 | $time = microtime(true); |
168 | $response = $client->send(); |
169 | $time = microtime(true) - $time; |
170 | |
171 | $this->debug( |
172 | sprintf( |
173 | '<= %s %s', |
174 | $response->getStatusCode(), |
175 | $response->getReasonPhrase() |
176 | ), |
177 | ['time' => $time] |
178 | ); |
179 | |
180 | if (!$response->isSuccess()) { |
181 | throw HttpErrorException::createFromResponse($response); |
182 | } |
183 | return $response->getBody(); |
184 | } |
185 | |
186 | /** |
187 | * Keeps a session alive. An idle session will time out after one minute. |
188 | * The ping command can be used to keep the session alive absent other activity. |
189 | * It is suggested that any browser client have a simple alarm handler |
190 | * which sends a ping every 50 seconds or so once a session has been initialized |
191 | * |
192 | * @return void |
193 | */ |
194 | public function ping() |
195 | { |
196 | $this->query('ping'); |
197 | } |
198 | |
199 | /** |
200 | * Retrieves a detailed record. |
201 | * Unlike the show command, this command returns |
202 | * metadata records before merging takes place. |
203 | * |
204 | * @param string $id array of options as described above |
205 | * |
206 | * @return associative array of XML data |
207 | */ |
208 | public function record($id) |
209 | { |
210 | return $this->query('record', new ParamBag(['id' => $id])); |
211 | } |
212 | |
213 | /** |
214 | * Launches a search. |
215 | * |
216 | * Option (default): |
217 | * - query : search string ('') |
218 | * - filter : setting+operator+args pairs, such as 'pz:id=4|17, pz:id~3' |
219 | * - limit : Narrows the search by one or more fields (typically facets) |
220 | * as name=arg1|arg2| pairs separated by comma (none) |
221 | * - startrecs : int (0) |
222 | * - maxrecs : int (100) |
223 | * |
224 | * TODO: Make the array more useful to get the correct format? |
225 | * |
226 | * @param ParamBag $options array of options as described above |
227 | * |
228 | * @return associative array of XML data |
229 | */ |
230 | public function search(ParamBag $options = null) |
231 | { |
232 | return $this->query('search', $options); |
233 | } |
234 | |
235 | /** |
236 | * Return session id |
237 | * |
238 | * @return session id |
239 | */ |
240 | public function session() |
241 | { |
242 | return $this->session; |
243 | } |
244 | |
245 | /** |
246 | * Applies settings to this session |
247 | * Each setting parameter has the form name[target]=value |
248 | * |
249 | * TODO: Make the array more useful to get the correct format? |
250 | * |
251 | * @param string $settings settings to be sets |
252 | * |
253 | * @return bool Success/failure status |
254 | */ |
255 | public function settings($settings = false) |
256 | { |
257 | if ($settings === false) { |
258 | return false; |
259 | } |
260 | $set = $this->query('settings', $settings); |
261 | return $set->status == 'OK'; |
262 | } |
263 | |
264 | /** |
265 | * Proper alias of results |
266 | * |
267 | * Options (default): |
268 | * - start : int (0) |
269 | * - num : int (20) |
270 | * - block : 1 = wait until enough records are found (0) |
271 | * - sort : column:1 [increasing] or 0 [decreasing] (none) |
272 | * |
273 | * @param ParamBag $options array of options as described above |
274 | * |
275 | * @return array Associative array of XML data |
276 | */ |
277 | public function show(ParamBag $options = null) |
278 | { |
279 | return $this->query('show', $options); |
280 | } |
281 | |
282 | /** |
283 | * Provides status information about an ongoing search. |
284 | * |
285 | * @return associative array of XML data |
286 | */ |
287 | public function stat() |
288 | { |
289 | return $this->query('stat'); |
290 | } |
291 | |
292 | /** |
293 | * Retrieves term list(s). |
294 | * |
295 | * Options (default): |
296 | * - name : comma-separated list of termlist names (all termlists) |
297 | * - num : maximum number of entries to return (15) |
298 | * |
299 | * @param ParamBag $options array of options as described above |
300 | * |
301 | * @return array Associative array of XML data |
302 | */ |
303 | public function termlist(ParamBag $options = null) |
304 | { |
305 | return $this->query('termlist', $options); |
306 | } |
307 | |
308 | /** |
309 | * Returns information about the status of each active client. |
310 | * |
311 | * @param string $id client id |
312 | * |
313 | * @return array Associative array of XML data |
314 | */ |
315 | public function bytarget($id) |
316 | { |
317 | return $this->query('bytarget', new ParamBag(['id' => $id])); |
318 | } |
319 | } |