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