Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
52.94% |
36 / 68 |
|
20.00% |
1 / 5 |
CRAP | |
0.00% |
0 / 1 |
LibGuides | |
52.94% |
36 / 68 |
|
20.00% |
1 / 5 |
42.68 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getAccounts | |
75.00% |
6 / 8 |
|
0.00% |
0 / 1 |
3.14 | |||
getAZ | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
12 | |||
authenticateAndSetHeaders | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
4.00 | |||
doGet | |
36.36% |
12 / 33 |
|
0.00% |
0 / 1 |
11.44 |
1 | <?php |
2 | |
3 | /** |
4 | * LibGuides API connection class. |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2023. |
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 Demian Katz <demian.katz@villanova.edu> |
26 | * @author Brent Palmer <brent-palmer@icpl.org> |
27 | * @author Maccabee Levine <msl321@lehigh.edu> |
28 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
29 | * @link https://vufind.org |
30 | */ |
31 | |
32 | namespace VuFind\Connection; |
33 | |
34 | use Exception; |
35 | use Laminas\Log\LoggerAwareInterface; |
36 | |
37 | /** |
38 | * LibGuides API connection class. |
39 | * |
40 | * Note: This is for the LibGuides API used by the LibGuidesProfile recommendation service, |
41 | * this is *not* for the LibGuides search widget "API" used by the LibGuides and LibGuidesAZ |
42 | * data sources. |
43 | * |
44 | * Closely adapted from VuFind\DigitalContent\OverdriveConnector. |
45 | * |
46 | * @category VuFind |
47 | * @package Connection |
48 | * @author Demian Katz <demian.katz@villanova.edu> |
49 | * @author Brent Palmer <brent-palmer@icpl.org> |
50 | * @author Maccabee Levine <msl321@lehigh.edu> |
51 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
52 | * @link https://vufind.org |
53 | */ |
54 | class LibGuides implements |
55 | OauthServiceInterface, |
56 | \VuFindHttp\HttpServiceAwareInterface, |
57 | LoggerAwareInterface |
58 | { |
59 | use OauthServiceTrait; |
60 | use \VuFindHttp\HttpServiceAwareTrait; |
61 | use \VuFind\Log\LoggerAwareTrait { |
62 | logError as error; |
63 | } |
64 | |
65 | /** |
66 | * HTTP Client |
67 | * |
68 | * @var \Laminas\Http\HttpClient |
69 | */ |
70 | protected $client; |
71 | |
72 | /** |
73 | * Base URL of the LibGuides API |
74 | * |
75 | * @var string |
76 | */ |
77 | protected $baseUrl; |
78 | |
79 | /** |
80 | * Client ID for a client_credentials grant |
81 | * |
82 | * @var string |
83 | */ |
84 | protected $clientId; |
85 | |
86 | /** |
87 | * Client Secret for a client_credentials grant |
88 | * |
89 | * @var string |
90 | */ |
91 | protected $clientSecret; |
92 | |
93 | /** |
94 | * User agent to send in header |
95 | * |
96 | * @var string |
97 | */ |
98 | protected $userAgent = 'VuFind'; |
99 | |
100 | /** |
101 | * Constructor |
102 | * |
103 | * @param Config $config LibGuides API configuration object |
104 | * @param \Laminas\Http\Client $client HTTP client |
105 | * |
106 | * @link https://ask.springshare.com/libguides/faq/873#api-auth |
107 | */ |
108 | public function __construct( |
109 | $config, |
110 | $client |
111 | ) { |
112 | $this->client = $client; |
113 | $this->baseUrl = $config->General->api_base_url; |
114 | $this->clientId = $config->General->client_id; |
115 | $this->clientSecret = $config->General->client_secret; |
116 | } |
117 | |
118 | /** |
119 | * Load all LibGuides accounts. |
120 | * |
121 | * @return object|null A JSON object of all LibGuides accounts, or null |
122 | * if an error occurs |
123 | */ |
124 | public function getAccounts() |
125 | { |
126 | if (!$this->authenticateAndSetHeaders()) { |
127 | return null; |
128 | } |
129 | |
130 | $result = $this->doGet( |
131 | $this->baseUrl . '/accounts?expand=profile,subjects' |
132 | ); |
133 | |
134 | if (isset($result->errorCode)) { |
135 | return null; |
136 | } |
137 | return $result; |
138 | } |
139 | |
140 | /** |
141 | * Load all LibGuides AZ databases. |
142 | * |
143 | * @return object|null A JSON object of all LibGuides databases, or null |
144 | * if an error occurs |
145 | */ |
146 | public function getAZ() |
147 | { |
148 | if (!$this->authenticateAndSetHeaders()) { |
149 | return null; |
150 | } |
151 | |
152 | $result = $this->doGet( |
153 | $this->baseUrl . '/az?expand=az_props' |
154 | ); |
155 | |
156 | if (isset($result->errorCode)) { |
157 | return null; |
158 | } |
159 | return $result; |
160 | } |
161 | |
162 | /** |
163 | * Authenticate to the LibGuides API and set authentication headers. |
164 | * |
165 | * @return bool Indicates if authentication succeeded. |
166 | */ |
167 | protected function authenticateAndSetHeaders() |
168 | { |
169 | $tokenData = $this->authenticateWithClientCredentials( |
170 | $this->baseUrl . '/oauth/token', |
171 | $this->clientId, |
172 | $this->clientSecret |
173 | ); |
174 | if (!$tokenData) { |
175 | return false; |
176 | } |
177 | |
178 | $headers = []; |
179 | if ( |
180 | isset($tokenData->token_type) |
181 | && isset($tokenData->access_token) |
182 | ) { |
183 | $headers[] = "Authorization: {$tokenData->token_type} " |
184 | . $tokenData->access_token; |
185 | } |
186 | $headers[] = 'User-Agent: ' . $this->userAgent; |
187 | |
188 | $this->client->setHeaders($headers); |
189 | |
190 | return true; |
191 | } |
192 | |
193 | /** |
194 | * Perform a GET request to the LibGuides API. |
195 | * |
196 | * @param string $url Full request url |
197 | * |
198 | * @return object|null A JSON object of the response data, or null if an error occurs |
199 | */ |
200 | protected function doGet($url) |
201 | { |
202 | $this->client->setMethod('GET'); |
203 | $this->client->setUri($url); |
204 | try { |
205 | $response = $this->client->send(); |
206 | } catch (Exception $ex) { |
207 | $this->error( |
208 | 'Exception during request: ' . |
209 | $ex->getMessage() |
210 | ); |
211 | return null; |
212 | } |
213 | |
214 | if ($response->isServerError()) { |
215 | $this->error( |
216 | 'LibGuides API HTTP Error: ' . |
217 | $response->getStatusCode() |
218 | ); |
219 | $this->debug('Request: ' . $this->client->getRequest()); |
220 | $this->debug('Response: ' . $this->client->getResponse()); |
221 | return null; |
222 | } |
223 | $body = $response->getBody(); |
224 | $returnVal = json_decode($body); |
225 | $this->debug( |
226 | 'Return from LibGuides API Call: ' . $this->varDump($returnVal) |
227 | ); |
228 | if ($returnVal != null) { |
229 | if (isset($returnVal->errorCode)) { |
230 | // In some cases, this should be returned perhaps... |
231 | $this->error('LibGuides Error: ' . $returnVal->errorCode); |
232 | } |
233 | return $returnVal; |
234 | } else { |
235 | $this->error( |
236 | 'LibGuides API Error: Nothing returned from API call.' |
237 | ); |
238 | $this->debug( |
239 | 'Body return from LibGuides API Call: ' . $this->varDump($body) |
240 | ); |
241 | } |
242 | return null; |
243 | } |
244 | } |