Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
31.43% covered (danger)
31.43%
88 / 280
44.44% covered (danger)
44.44%
8 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
Backend
31.43% covered (danger)
31.43%
88 / 280
44.44% covered (danger)
44.44%
8 / 18
2642.93
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 search
48.44% covered (danger)
48.44%
31 / 64
0.00% covered (danger)
0.00%
0 / 1
36.17
 retrieve
44.93% covered (danger)
44.93%
31 / 69
0.00% covered (danger)
0.00%
0 / 1
79.30
 paramBagToEBSCOSearchModel
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getRecordCollectionFactory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getQueryBuilder
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setQueryBuilder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 autocomplete
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 createRecordCollection
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAuthenticationToken
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
72
 getAutocompleteData
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
156
 getSessionToken
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 createEBSCOSession
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 isGuest
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 createSession
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
20
 getInfo
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
182
 setAuthManager
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setBackendType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * EDS API Backend
5 *
6 * PHP version 8
7 *
8 * Copyright (C) EBSCO Industries 2013
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  Search
25 * @author   Michelle Milton <mmilton@epnet.com>
26 * @author   Cornelius Amzar <cornelius.amzar@bsz-bw.de>
27 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
28 * @link     https://vufind.org
29 */
30
31namespace VuFindSearch\Backend\EDS;
32
33use Exception;
34use Laminas\Cache\Storage\StorageInterface as CacheAdapter;
35use Laminas\Config\Config;
36use Laminas\Session\Container as SessionContainer;
37use VuFindSearch\Backend\AbstractBackend;
38use VuFindSearch\Backend\Exception\BackendException;
39use VuFindSearch\ParamBag;
40use VuFindSearch\Query\AbstractQuery;
41use VuFindSearch\Response\RecordCollectionFactoryInterface;
42use VuFindSearch\Response\RecordCollectionInterface;
43
44use function in_array;
45
46/**
47 *  EDS API Backend
48 *
49 * @category VuFind
50 * @package  Search
51 * @author   Michelle Milton <mmilton@epnet.com>
52 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
53 * @link     https://vufind.org
54 */
55class Backend extends AbstractBackend
56{
57    /**
58     * Client user to make the actually requests to the EdsApi
59     *
60     * @var Connector
61     */
62    protected $client;
63
64    /**
65     * Query builder
66     *
67     * @var QueryBuilder
68     */
69    protected $queryBuilder;
70
71    /**
72     * User name for EBSCO EDS API account if using UID Authentication
73     *
74     * @var string
75     */
76    protected $userName;
77
78    /**
79     * Password for EBSCO EDS API account if using UID Authentication
80     *
81     * @var string
82     */
83    protected $password;
84
85    /**
86     * Profile for EBSCO EDS API account (may be overridden)
87     *
88     * @var string
89     */
90    protected $profile;
91
92    /**
93     * Default profile for EBSCO EDS API account (taken from initial config and
94     * never changed)
95     *
96     * @var string
97     */
98    protected $defaultProfile;
99
100    /**
101     * Whether or not to use IP Authentication for communication with the EDS API
102     *
103     * @var bool
104     */
105    protected $ipAuth;
106
107    /**
108     * Organization EDS API requests are being made for
109     *
110     * @var string
111     */
112    protected $orgId;
113
114    /**
115     * VuFind Authentication manager
116     *
117     * @var \VuFind\Auth\Manager
118     */
119    protected $authManager = null;
120
121    /**
122     * Object cache (for storing authentication tokens)
123     *
124     * @var CacheAdapter
125     */
126    protected $cache;
127
128    /**
129     * Session container
130     *
131     * @var SessionContainer
132     */
133    protected $session;
134
135    /**
136     * Is the current user a guest?
137     *
138     * @var bool
139     */
140    protected $isGuest;
141
142    /**
143     * Backend type
144     *
145     * @var string
146     */
147    protected $backendType = null;
148
149    /**
150     * Constructor.
151     *
152     * @param Connector                        $client  EdsApi client to use
153     * @param RecordCollectionFactoryInterface $factory Record collection factory
154     * @param CacheAdapter                     $cache   Object cache
155     * @param SessionContainer                 $session Session container
156     * @param Config                           $config  Object representing EDS.ini
157     * @param bool                             $isGuest Is the current user a guest?
158     */
159    public function __construct(
160        Connector $client,
161        RecordCollectionFactoryInterface $factory,
162        CacheAdapter $cache,
163        SessionContainer $session,
164        Config $config = null,
165        $isGuest = true
166    ) {
167        // Save dependencies/incoming parameters:
168        $this->client = $client;
169        $this->setRecordCollectionFactory($factory);
170        $this->cache = $cache;
171        $this->session = $session;
172        $this->isGuest = $isGuest;
173
174        // Extract key values from configuration:
175        $this->userName = $config->EBSCO_Account->user_name ?? null;
176        $this->password = $config->EBSCO_Account->password ?? null;
177        $this->ipAuth = $config->EBSCO_Account->ip_auth ?? false;
178        $this->profile = $config->EBSCO_Account->profile ?? null;
179        $this->orgId = $config->EBSCO_Account->organization_id ?? null;
180
181        // Save default profile value, since profile property may be overridden:
182        $this->defaultProfile = $this->profile;
183    }
184
185    /**
186     * Perform a search and return record collection.
187     *
188     * @param AbstractQuery $query  Search query
189     * @param int           $offset Search offset
190     * @param int           $limit  Search limit
191     * @param ParamBag      $params Search backend parameters
192     *
193     * @return \VuFindSearch\Response\RecordCollectionInterface
194     **/
195    public function search(
196        AbstractQuery $query,
197        $offset,
198        $limit,
199        ParamBag $params = null
200    ) {
201        // process EDS API communication tokens.
202        $authenticationToken = $this->getAuthenticationToken();
203        $sessionToken = $this->getSessionToken();
204        $this->debug(
205            "Authentication Token: $authenticationToken, SessionToken: $sessionToken"
206        );
207
208        // create query parameters from VuFind data
209        $queryString = $query->getAllTerms();
210        $paramsStr = implode('&', null !== $params ? $params->request() : []);
211        $this->debug(
212            "Query: $queryString, Limit: $limit, Offset: $offset"
213            . "Params: $paramsStr"
214        );
215
216        $baseParams = $this->getQueryBuilder()->build($query);
217        $paramsStr = implode('&', $baseParams->request());
218        $this->debug("BaseParams: $paramsStr ");
219        if (null !== $params) {
220            $baseParams->mergeWith($params);
221        }
222        $baseParams->set('resultsPerPage', $limit);
223        $page = $limit > 0 ? floor($offset / $limit) + 1 : 1;
224        $baseParams->set('pageNumber', $page);
225
226        $searchModel = $this->paramBagToEBSCOSearchModel($baseParams);
227        $qs = $searchModel->convertToQueryString();
228        $this->debug("Search Model query string: $qs");
229        try {
230            $response = $this->client
231                ->search($searchModel, $authenticationToken, $sessionToken);
232        } catch (ApiException $e) {
233            // if the auth or session token was invalid, try once more
234            switch ($e->getApiErrorCode()) {
235                case 104:
236                case 108:
237                case 109:
238                    try {
239                        // For error 104, retry auth token; for 108/9, retry sess
240                        // token:
241                        if ($e->getApiErrorCode() == 104) {
242                            $authenticationToken
243                                = $this->getAuthenticationToken(true);
244                        } else {
245                            $sessionToken = $this->getSessionToken(true);
246                        }
247                        $response = $this->client->search(
248                            $searchModel,
249                            $authenticationToken,
250                            $sessionToken
251                        );
252                    } catch (Exception $e) {
253                        throw new BackendException(
254                            $e->getMessage(),
255                            $e->getCode(),
256                            $e
257                        );
258                    }
259                    break;
260                case 138:
261                    // User requested unavailable deep search results; first extract
262                    // the next legal position from the error message:
263                    $parts
264                        = explode(' ', trim($e->getApiDetailedErrorDescription()));
265                    $legalPos = array_pop($parts);
266                    // Now calculate the legal page number and throw an exception so
267                    // the controller can fix it from here:
268                    $legalPage = floor($legalPos / $limit);
269                    throw new \VuFindSearch\Backend\Exception\DeepPagingException(
270                        $e->getMessage(),
271                        $e->getCode(),
272                        $legalPage,
273                        $e
274                    );
275                default:
276                    $response = [];
277                    break;
278            }
279        } catch (Exception $e) {
280            $this->debug('Exception found: ' . $e->getMessage());
281            throw new BackendException($e->getMessage(), $e->getCode(), $e);
282        }
283        $collection = $this->createRecordCollection($response);
284        $this->injectSourceIdentifier($collection);
285        return $collection;
286    }
287
288    /**
289     * Retrieve a single document.
290     *
291     * @param string   $id     Document identifier
292     * @param ParamBag $params Search backend parameters
293     *
294     * @return \VuFindSearch\Response\RecordCollectionInterface
295     */
296    public function retrieve($id, ParamBag $params = null)
297    {
298        $an = $dbId = $authenticationToken = $sessionToken = $hlTerms = null;
299        try {
300            $authenticationToken = $this->getAuthenticationToken();
301            // check to see if the profile is overridden
302            $overrideProfile = (null !== $params) ? $params->get('profile') : null;
303            if (isset($overrideProfile)) {
304                $this->profile = $overrideProfile;
305            }
306            $sessionToken = $this->getSessionToken();
307
308            if ('EDS' === $this->backendType) {
309                $parts = explode(',', $id, 2);
310                if (!isset($parts[1])) {
311                    throw new BackendException(
312                        'Retrieval id is not in the correct format.'
313                    );
314                }
315                [$dbId, $an] = $parts;
316                $hlTerms = (null !== $params)
317                    ? $params->get('highlightterms') : null;
318                $extras = [];
319                if (
320                    null !== $params
321                    && ($eBookFormat = $params->get('ebookpreferredformat'))
322                ) {
323                    $extras['ebookpreferredformat'] = $eBookFormat;
324                }
325                $response = $this->client->retrieveEdsItem(
326                    $an,
327                    $dbId,
328                    $authenticationToken,
329                    $sessionToken,
330                    $hlTerms,
331                    $extras
332                );
333            } elseif ('EPF' === $this->backendType) {
334                $pubId = $id;
335                $response = $this->client->retrieveEpfItem(
336                    $pubId,
337                    $authenticationToken,
338                    $sessionToken
339                );
340            } else {
341                throw new BackendException(
342                    'Unknown backendType: ' . $this->backendType
343                );
344            }
345        } catch (ApiException $e) {
346            // Error codes can be reviewed at
347            // https://connect.ebsco.com/s/article
348            //    /EBSCO-Discovery-Service-API-Reference-Guide-Error-Codes
349            // if the auth or session token was invalid, try once more
350            switch ($e->getApiErrorCode()) {
351                case 104:
352                case 108:
353                case 109:
354                    try {
355                        // For error 104, retry auth token; for 108/9, retry sess
356                        // token:
357                        if ($e->getApiErrorCode() == 104) {
358                            $authenticationToken
359                                = $this->getAuthenticationToken(true);
360                        } else {
361                            $sessionToken = $this->getSessionToken(true);
362                        }
363                        $response = $this->client->retrieve(
364                            $an,
365                            $dbId,
366                            $authenticationToken,
367                            $sessionToken,
368                            $hlTerms
369                        );
370                    } catch (Exception $e) {
371                        throw new BackendException(
372                            $e->getMessage(),
373                            $e->getCode(),
374                            $e
375                        );
376                    }
377                    break;
378                case 132:
379                case 133:
380                case 135:
381                    /* 132 Record not found
382                     * 133 Simultaneous User Limit Reached
383                     * 135 DbId not in profile
384                     * -> fall through to treat as "record not found"
385                     */
386                    $response = [];
387                    break;
388                default:
389                    throw $e;
390            }
391        }
392        $collection = $this->createRecordCollection(['Records' => $response]);
393        $this->injectSourceIdentifier($collection);
394        return $collection;
395    }
396
397    /**
398     * Convert a ParamBag to a EdsApi Search request object.
399     *
400     * @param ParamBag $params ParamBag to convert
401     *
402     * @return SearchRequestModel
403     */
404    protected function paramBagToEBSCOSearchModel(ParamBag $params)
405    {
406        $params = $params->getArrayCopy();
407        $options = [];
408        // Most parameters need to be flattened from array format, but a few
409        // should remain as arrays:
410        $arraySettings = [
411            'query', 'facets', 'filters', 'groupFilters', 'rangeFilters', 'limiters',
412        ];
413        foreach ($params as $key => $param) {
414            $options[$key] = in_array($key, $arraySettings)
415                ? $param : $param[0];
416        }
417        return new SearchRequestModel($options);
418    }
419
420    /**
421     * Return the record collection factory.
422     *
423     * Lazy loads a generic collection factory.
424     *
425     * @return RecordCollectionFactoryInterface
426     */
427    public function getRecordCollectionFactory()
428    {
429        return $this->collectionFactory;
430    }
431
432    /**
433     * Return query builder.
434     *
435     * Lazy loads an empty QueryBuilder if none was set.
436     *
437     * @return QueryBuilder
438     */
439    public function getQueryBuilder()
440    {
441        if (!$this->queryBuilder) {
442            $this->queryBuilder = new QueryBuilder();
443        }
444        return $this->queryBuilder;
445    }
446
447    /**
448     * Set the query builder.
449     *
450     * @param QueryBuilder $queryBuilder Query builder
451     *
452     * @return void
453     */
454    public function setQueryBuilder(QueryBuilder $queryBuilder)
455    {
456        $this->queryBuilder = $queryBuilder;
457    }
458
459    /**
460     * Get popular terms using the autocomplete API.
461     *
462     * @param string $query  Simple query string
463     * @param string $domain Autocomplete type (e.g. 'rawqueries' or 'holdings')
464     *
465     * @return array of terms
466     */
467    public function autocomplete($query, $domain = 'rawqueries')
468    {
469        return $this->client
470            ->autocomplete($query, $domain, $this->getAutocompleteData());
471    }
472
473    /// Internal API
474
475    /**
476     * Create record collection.
477     *
478     * @param array $records Records to process
479     *
480     * @return RecordCollectionInterface
481     */
482    protected function createRecordCollection($records)
483    {
484        return $this->getRecordCollectionFactory()->factory($records);
485    }
486
487    /**
488     * Obtain the authentication to use with the EDS API from cache if it exists. If
489     * not, then generate a new one.
490     *
491     * @param bool $isInvalid whether or not the the current token is invalid
492     *
493     * @return string
494     */
495    protected function getAuthenticationToken($isInvalid = false)
496    {
497        $token = null;
498        if ($this->ipAuth) {
499            return $token;
500        }
501        if ($isInvalid) {
502            $this->cache->setItem('edsAuthenticationToken', null);
503        }
504        $authTokenData = $this->cache->getItem('edsAuthenticationToken');
505        if (isset($authTokenData)) {
506            $currentToken = $authTokenData['token'] ?? '';
507            $expirationTime = $authTokenData['expiration'] ?? 0;
508            $this->debug(
509                'Cached Authentication data: '
510                . "$currentToken, expiration time: $expirationTime"
511            );
512
513            // Check to see if the token expiration time is greater than the current
514            // time. If the token is expired or within 5 minutes of expiring,
515            // generate a new one.
516            if (!empty($currentToken) && (time() <= ($expirationTime - (60 * 5)))) {
517                return $currentToken;
518            }
519        }
520
521        $username = $this->userName;
522        $password = $this->password;
523        $orgId = $this->orgId;
524        if (!empty($username) && !empty($password)) {
525            $this->debug(
526                'Calling Authenticate with username: '
527                . "$username, password: XXXXXXXX, orgid: $orgId "
528            );
529            $results = $this->client->authenticate($username, $password, $orgId);
530            $token = $results['AuthToken'];
531            $timeout = $results['AuthTimeout'] + time();
532            $authTokenData = ['token' => $token, 'expiration' => $timeout];
533            $this->cache->setItem('edsAuthenticationToken', $authTokenData);
534        }
535        return $token;
536    }
537
538    /**
539     * Obtain the autocomplete authentication to use with the EDS API from cache
540     * if it exists. If not, then generate a new set.
541     *
542     * @param bool $isInvalid whether or not the the current autocomplete data
543     * is invalid and should be regenerated
544     *
545     * @return array autocomplete data
546     */
547    protected function getAutocompleteData($isInvalid = false)
548    {
549        // Autocomplete is currently unsupported with IP authentication
550        if ($this->ipAuth) {
551            return null;
552        }
553        if ($isInvalid) {
554            $this->cache->setItem('edsAutocomplete', null);
555        }
556        $autocompleteData = $this->cache->getItem('edsAutocomplete');
557        if (!empty($autocompleteData)) {
558            $currentToken = $autocompleteData['token'] ?? '';
559            $expirationTime = $autocompleteData['expiration'] ?? 0;
560
561            // Check to see if the token expiration time is greater than the current
562            // time. If the token is expired or within 5 minutes of expiring,
563            // generate a new one.
564            if (!empty($currentToken) && (time() <= ($expirationTime - (60 * 5)))) {
565                return $autocompleteData;
566            }
567        }
568
569        $username = $this->userName;
570        $password = $this->password;
571        if (!empty($username) && !empty($password)) {
572            $results = $this->client
573                ->authenticate($username, $password, $this->orgId, ['autocomplete']);
574            $autoresult = $results['Autocomplete'] ?? [];
575            if (
576                isset($autoresult['Token']) && isset($autoresult['TokenTimeOut'])
577                && isset($autoresult['CustId']) && isset($autoresult['Url'])
578            ) {
579                $token = $autoresult['Token'];
580                $expiration = $autoresult['TokenTimeOut'] + time();
581                $custid = $autoresult['CustId'];
582                $url = $autoresult['Url'];
583
584                $autocompleteData = compact('token', 'expiration', 'url', 'custid');
585                // store token, expiration, url and custid in cache.
586                $this->cache->setItem('edsAutocomplete', $autocompleteData);
587            }
588        }
589        return $autocompleteData;
590    }
591
592    /**
593     * Obtain the session token from the Session container. If it doesn't exist,
594     * generate a new one.
595     *
596     * @param bool $isInvalid If a session token is invalid, generate a new one
597     * regardless of what is in the session container
598     *
599     * @return string
600     */
601    public function getSessionToken($isInvalid = false)
602    {
603        // check to see if the user has logged in/out between the creation
604        // of this session token and now
605        if (
606            !$isInvalid && !empty($this->session->sessionID)
607            && $this->session->sessionGuest == $this->isGuest()
608        ) {
609            return $this->session->sessionID;
610        }
611        return $this->createEBSCOSession();
612    }
613
614    /**
615     * Generate a new session token and store it in the Session container.
616     *
617     * @return string
618     */
619    protected function createEBSCOSession()
620    {
621        // if there is no profile passed, restore the default from the config file
622        $this->session->profileID = (null == $this->profile)
623            ? $this->defaultProfile : $this->profile;
624        $this->session->sessionGuest = $this->isGuest();
625        $this->session->sessionID = $this->createSession(
626            $this->session->sessionGuest,
627            $this->session->profileID
628        );
629        return $this->session->sessionID;
630    }
631
632    /**
633     * Is the current user a guest? If so, return 'y' else 'n'.
634     *
635     * @return string
636     */
637    protected function isGuest()
638    {
639        return $this->isGuest ? 'y' : 'n';
640    }
641
642    /**
643     * Obtain the session to use with the EDS API from cache if it exists. If not,
644     * then generate a new one.
645     *
646     * @param bool   $isGuest Whether or not this sesssion will be a guest session
647     * @param string $profile Authentication to use for generating a new session
648     * if necessary
649     *
650     * @return string
651     */
652    public function createSession($isGuest, $profile = '')
653    {
654        try {
655            $authToken = $this->getAuthenticationToken();
656            $results = $this->client->createSession($profile, $isGuest, $authToken);
657        } catch (ApiException $e) {
658            $errorCode = $e->getApiErrorCode();
659            $desc = $e->getApiErrorDescription();
660            $this->debug(
661                'Error in create session request. Error code: '
662                . "$errorCode, message: $desc, e: $e"
663            );
664            if ($e->getApiErrorCode() == 104) {
665                try {
666                    $authToken = $this->getAuthenticationToken(true);
667                    $results = $this->client
668                        ->createSession($this->profile, $isGuest, $authToken);
669                } catch (Exception $e) {
670                    throw new BackendException(
671                        $e->getMessage(),
672                        $e->getCode(),
673                        $e
674                    );
675                }
676            } else {
677                throw $e;
678            }
679        }
680        $sessionToken = $results['SessionToken'];
681        return $sessionToken;
682    }
683
684    /**
685     * Obtain data from the INFO method
686     *
687     * @param string $sessionToken Session token (optional)
688     *
689     * @return array
690     */
691    public function getInfo($sessionToken = null)
692    {
693        // Use a different cache key for guests, just in case info differs:
694        $cacheKey = $this->isGuest ? 'edsGuestInfo' : 'edsLoggedInInfo';
695        if ($data = $this->cache->getItem($cacheKey)) {
696            return $data;
697        }
698        $authenticationToken = $this->getAuthenticationToken();
699        if (null == $sessionToken) {
700            try {
701                $sessionToken = $this->getSessionToken();
702            } catch (ApiException $e) {
703                // Retry once to work around occasional 106 errors:
704                $sessionToken = $this->getSessionToken();
705            }
706        }
707        try {
708            $response = $this->client->info($authenticationToken, $sessionToken);
709        } catch (ApiException $e) {
710            // if the auth or session token was invalid, try once more
711            switch ($e->getApiErrorCode()) {
712                case 104:
713                case 108:
714                case 109:
715                    try {
716                        // For error 104, retry auth token; for 108/9, retry sess
717                        // token:
718                        if ($e->getApiErrorCode() == 104) {
719                            $authenticationToken
720                                = $this->getAuthenticationToken(true);
721                        } else {
722                            $sessionToken = $this->getSessionToken(true);
723                        }
724                        $response = $this->client
725                            ->info($authenticationToken, $sessionToken);
726                    } catch (Exception $e) {
727                        throw new BackendException(
728                            $e->getMessage(),
729                            $e->getCode(),
730                            $e
731                        );
732                    }
733                    break;
734                default:
735                    $response = [];
736            }
737        }
738        if (!empty($response)) {
739            $this->cache->setItem($cacheKey, $response);
740        }
741        return $response;
742    }
743
744    /**
745     * Set the VuFind Authentication Manager
746     *
747     * @param \VuFind\Auth\Manager $authManager Authentication Manager
748     *
749     * @return void
750     */
751    public function setAuthManager($authManager)
752    {
753        $this->authManager = $authManager;
754    }
755
756    /**
757     * Set the EBSCO backend type. Backend/EDS is used for both EDS and EPF.
758     *
759     * @param str $backendType 'EDS' or 'EPF'
760     *
761     * @return void
762     */
763    public function setBackendType($backendType)
764    {
765        $this->backendType = $backendType;
766    }
767}