Skip to content
Snippets Groups Projects
Commit f7cfbf27 authored by Dorian Merz's avatar Dorian Merz
Browse files

refs #17681 [master] introduce FincLibero to master

* move uncritial functions (according refs #17230) to finc module
* clarifies imports
parent f11b6649
Branches
Tags
No related merge requests found
...@@ -73,12 +73,14 @@ $config = [ ...@@ -73,12 +73,14 @@ $config = [
'finc\ILS\Driver\FincILS' => 'finc\ILS\Driver\Factory::getFincILS', 'finc\ILS\Driver\FincILS' => 'finc\ILS\Driver\Factory::getFincILS',
'finc\ILS\Driver\PAIA' => 'finc\ILS\Driver\Factory::getPAIA', 'finc\ILS\Driver\PAIA' => 'finc\ILS\Driver\Factory::getPAIA',
//finctheca is deprecated: Remove when Bibliotheca support ends //finctheca is deprecated: Remove when Bibliotheca support ends
'finc\ILS\Driver\FincTheca' => 'finc\ILS\Driver\Factory::GetFincTheca' 'finc\ILS\Driver\FincTheca' => 'finc\ILS\Driver\Factory::getFincTheca',
'finc\ILS\Driver\FincLibero' => 'finc\ILS\Driver\Factory::getFincLibero',
], ],
'aliases' => [ 'aliases' => [
'fincils' => 'finc\ILS\Driver\FincILS', 'fincils' => 'finc\ILS\Driver\FincILS',
'paia' => 'finc\ILS\Driver\PAIA', 'paia' => 'finc\ILS\Driver\PAIA',
'finctheca' => 'finc\ILS\Driver\FincTheca', 'finctheca' => 'finc\ILS\Driver\FincTheca',
'finclibero' => 'finc\ILS\Driver\FincLibero'
], ],
], ],
'recommend' => [ 'recommend' => [
......
...@@ -133,4 +133,39 @@ class Factory ...@@ -133,4 +133,39 @@ class Factory
return $fl; return $fl;
} }
/**
* Factory for FincLibero driver.
*
* @param \Psr\Container\ContainerInterface $container Service manager.
*
* @return FincLibero
*/
public static function getFincLibero(ContainerInterface $container)
{
$factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory($container->get('VuFind\ProxyConfig'));
$callback = function (& $wrapped, $proxy) use ($container) {
$wrapped = $container->get('ZfcRbac\Service\AuthorizationService');
$proxy->setProxyInitializer(null);
};
$fl = new FincLibero(
$container->get('VuFind\DateConverter'),
$container->get('VuFind\SessionManager'),
$container->get('VuFind\RecordLoader'),
$container->get('VuFind\Search'),
$container->get('VuFind\Config')->get('config'),
$factory->createProxy('ZfcRbac\Service\AuthorizationService', $callback)
);
$fl->setCacheStorage(
$container->get('VuFind\CacheManager')->getCache('object')
);
$fl->staticStatusRules = $container->get('VuFind\YamlReader')->get('StaticStatusRules.yaml');
return $fl;
}
} }
...@@ -1688,4 +1688,17 @@ class FincILS extends PAIA implements LoggerAwareInterface ...@@ -1688,4 +1688,17 @@ class FincILS extends PAIA implements LoggerAwareInterface
throw new ILSException($e->getMessage()); throw new ILSException($e->getMessage());
} }
} }
/**
* Helper function to filter certain limitations.
*
* @param array $limitations An item's limitations.
* @return mixed
*/
protected function filterNonFunctionalLimitations($limitations)
{
//standard behavior is: do nothing
// overriden in FincLibero
return $limitations;
}
} }
<?php
/**
* Finc specific Libero ILS Driver for VuFind, using PAIA, DAIA and LiberoDing
* services.
*
* PHP version 5
*
* Copyright (C) Leipzig University Library 2015.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @category VuFind2
* @package ILS_Drivers
* @author André Lahmann <lahmann@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
*/
namespace finc\ILS\Driver;
use VuFind\I18n\Translator\TranslatorAwareTrait;
use VuFind\I18n\Translator\TranslatorAwareInterface,
VuFind\Exception\ILS as ILSException;
/**
* Finc specific Libero ILS Driver for VuFind, using PAIA, DAIA and LiberoDing
* services.
*
* @category VuFind2
* @package ILS_Drivers
* @author André Lahmann <lahmann@ub.uni-leipzig.de>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link http://vufind.org/wiki/vufind2:building_an_ils_driver Wiki
*/
class FincLibero extends FincILS implements TranslatorAwareInterface
{
const DELETE_NOTIFICATIONS_SUCCESS = '1';
const DELETE_NOTIFICATIONS_ERROR = '0';
use LiberoDingTrait;
use TranslatorAwareTrait;
/**
* Contains after init() is done all the limitations that are configured in the
* FincLibero.ini as being used for triggering actions etc (e.g.:
* requestableLimitations).
*
* @var array
*/
protected $configuredLimitations = [];
/**
* Limitations that will trigger the placeStorageRetrievalRequest action
*
* @var array
*/
protected $requestableLimitations = [];
/**
* Limitations that will trigger the placeHold action
*
* @var array
*/
protected $holdableLimitations = [];
/**
* Limitations that will trigger a recall action (currently not used).
*
* @var array
*/
protected $recallableLimitations = [];
/**
* Limitations that will identify the item for being bound to another item.
*
* @var array
*/
protected $awlLimitations = [];
/**
* Patterns that will identify limitations as pickUpLocations
*
* @var array
*/
protected $pickUpLocationPatterns = [];
/**
* URIs that will be used for stack views
*
* @var array
*/
protected $stackURIs = [];
/**
* URIs that will be used for reading room views
*
* @var array
*/
protected $readingRoomURIs = [];
/**
* Helper function to extract the Namespace from the DAIA URI prefix.
*
* @return string
*/
public function getDaiaIdPrefixNamespace()
{
return preg_quote(substr($this->daiaIdPrefix, 0, strpos($this->daiaIdPrefix, ':')+1));
}
/**
* FincLibero specific overrides of PAIA methods
*/
/**
* Place Hold
*
* Attempts to place a hold or recall on a particular item and returns
* an array with result details
*
* Make a request on a specific record
*
* @param array $holdDetails An array of item and patron data
*
* @return mixed An array of data on the request including
* whether or not it was successful and a system message (if available)
*/
public function placeHold($holdDetails)
{
$item = $holdDetails['item_id'];
$patron = $holdDetails['patron'];
$doc = [];
$doc['item'] = stripslashes($item);
if ($confirm = $this->getConfirmations($holdDetails)) {
$doc["confirm"] = $confirm;
}
$post_data['doc'][] = $doc;
try {
$array_response = $this->paiaPostAsArray(
'core/'.$patron['cat_username'].'/request', $post_data
);
} catch (Exception $e) {
$this->debug($e->getMessage());
return [
'success' => false,
'sysMessage' => $e->getMessage(),
];
}
$details = [];
if (array_key_exists('error', $array_response)) {
$details = [
'success' => false,
'sysMessage' => $array_response['error_description']
];
} else {
$elements = $array_response['doc'];
foreach ($elements as $element) {
if (array_key_exists('error', $element)) {
$details = [
'success' => false,
'sysMessage' => $element['error']
];
} else {
// FincLibero supports more expressive responses from paialibero
// which should be shown instead to the user (localIlsStatus)
$details = [
'success' => true,
'sysMessage' => isset($element['localIlsStatus'])
? $element['localIlsStatus'] : 'Successfully requested'
];
// if caching is enabled for DAIA remove the cached data for the
// current item otherwise the changed status will not be shown
// before the cache expires
if ($this->daiaCacheEnabled) {
$this->removeCachedData($holdDetails['doc_id']);
}
if ($this->paiaCacheEnabled) {
$this->removeCachedData($patron['cat_username']);
}
}
}
}
return $details;
}
/**
* PAIA authentication function with custom signature -- libraryuserid added for
* Libero Id
*
* @param string $username Username
* @param string $password Password
* @param string $libraryuserid Libero ID
*
* @return mixed Associative array of patron info on successful login,
* null on unsuccessful login, PEAR_Error on error.
* @throws ILSException
*/
protected function paiaLogin($username, $password, $libraryuserid = null)
{
// perform full PAIA auth and get patron info
$post_data = [
"username" => $username,
"password" => $password,
"grant_type" => "password",
"scope" => self::SCOPE_READ_PATRON . " " .
self::SCOPE_READ_FEES . " " .
self::SCOPE_READ_ITEMS . " " .
self::SCOPE_WRITE_ITEMS . " " .
self::SCOPE_CHANGE_PASSWORD
];
// Customization for internal Libero Id
if (isset($libraryuserid)) {
$post_data['libraryuserid'] = $libraryuserid;
}
$responseJson = $this->paiaPostRequest('auth/login', $post_data);
try {
$responseArray = $this->paiaParseJsonAsArray($responseJson);
} catch (Exception $e) {
// all error handling is done in paiaHandleErrors so pass on the excpetion
throw $e;
}
if (!isset($responseArray['access_token'])) {
throw new ILSException(
'Unknown error! Access denied.'
);
} elseif (!isset($responseArray['patron'])) {
throw new ILSException(
'Login credentials accepted, but got no patron ID?!?'
);
} else {
// at least access_token and patron got returned which is sufficient for
// us, now save all to session
$session = $this->getSession();
// as we do not store the password in the database, write it to the
// session (but only if we are not using root-login
if ($libraryuserid === null) {
$session->cat_password = $password;
}
$session->patron
= isset($responseArray['patron'])
? $responseArray['patron'] : null;
$session->access_token
= isset($responseArray['access_token'])
? $responseArray['access_token'] : null;
$session->scope
= isset($responseArray['scope'])
? explode(' ', $responseArray['scope']) : null;
$session->expires
= isset($responseArray['expires_in'])
? (time() + ($responseArray['expires_in'])) : null;
// Customization for internal Libero Id
$session->borrower_id
= isset($responseArray['borrower_id'])
? $responseArray['borrower_id'] : null;
return true;
}
}
/**
* PAIA helper function to map session data to return value of patronLogin()
*
* @param $details Patron details returned by patronLogin
* @param $password Patron cataloge password
* @return mixed
*/
protected function enrichUserDetails($details, $password, $username = null)
{
$details = parent::enrichUserDetails($details, $password, $username);
// store also the Libero Id
$session = $this->getSession();
$details['borrower_id'] = $session->borrower_id;
return $this->enrichWithUserRestrictions($details);
}
/**
* Determines for each of the tokens in @param $details['type'] whether it is
* configured to be a restriction type (as configured in FincLibero.ini
* [General] userRestrictionMessagePatterns) and saves positive matches in
* $details['restrictions'].
*
* @param $details patron details
* @return mixed modified patron details
*/
protected function enrichWithUserRestrictions($details)
{
//early return
if (!isset($details['type'])
|| empty($details['type'])
|| !isset($this->config['General']['userRestrictionMessagePatterns'])
) {
return $details;
}
foreach ($this->config['General']['userRestrictionMessagePatterns'] as $pattern) {
foreach ($details['type'] as $type) {
if (preg_match($pattern, $type)) {
$details['restrictions'][] = 'UserRestrictionMessages::' . $type;
}
}
}
return $details;
}
/**
* FincLibero specific overrides of DAIA methods
*/
/**
* Returns an array with status information for provided item.
*
* @param array $item Array with DAIA item data
*
* @return array
*/
protected function getItemStatus($item)
{
$return = parent::getItemStatus($item);
$return['awlRecordId'] = $this->getBoundItemId($item);
// is this item bound with another item?
if ($return['awlRecordId'] != null) {
// overwrite any existing link settings as we need to order this item
// via the bound item
$return['addLink'] =
$return['addStorageRetrievalRequestLink'] =
$return['addILLRequestLink'] =
$return['addEmailHoldLink'] = false;
$return['awlRecordStatus'] =
current($this->getStatus($return['awlRecordId']));
}
// add all item specific information from DAIA field about to item_notes
// (https://intern.finc.info/issues/7863)
$about = (isset($item['about'])) ? [$item['about']] : [];
$return['item_notes'] = array_unique(
array_merge(
(array) $return['status'],
$return['item_notes'],
$about
)
);
return $return;
}
/**
* Helper function to return an appropriate status string for current item
*
* @param $item
* @return string
*/
protected function getStatusString($item)
{
return isset($item['localIlsStatus']) ? $item['localIlsStatus'] : '';
}
/**
* FincLibero specific implementation that adds pickUpLocations and the content
* of EmailHold limitations to the customData array.
*
* @param array $item A DAIA item.
* @return array
*/
protected function getCustomData($item)
{
$customData = [];
foreach (['available', 'unavailable'] as $availability) {
if (isset($item[$availability])) {
foreach ($item[$availability] as $available) {
if (isset($available['service'])
&& in_array($available['service'], ['presentation', 'loan'])
) {
// deal with pickuplocations
if (isset($available['limitation'])
&& $pickUpLocations = $this->filterPickUpLocations(
$available['limitation']
)
) {
// if we have limitations qualifying for pickUpLocations,
// save those in customData
$customData['pickUpLocations'] = $pickUpLocations;
} elseif (!isset($customData['pickUpLocations']) && isset($item['department'])) {
// if we have no explicit limitations qualifying for
// pickUpLocations, assume the item's department as single
// pickUpLocation
$customData['pickUpLocations'] = [
[
'locationID' => $item['department']['id'],
'locationDisplay' => $item['department']['content']
]
];
}
// deal with EmailHold information
if (isset($available['limitation'])) {
foreach ($available['limitation'] as $limitation) {
$criteria = $this->getEmailHoldValidationCriteria();
// we assume that each configured criteria for
// EmailHold will provide information (if existent in
// current item) supposed to be passed to the view
// via customData array
foreach ($criteria as $key => $value) {
if ($this->checkEmailHoldValidationCriteria(
[$key=>$limitation['id']])
) {
$customData['emailHoldLimitationContent'][] = $limitation['content'];
}
}
}
}
}
}
}
}
return $customData;
}
/**
* Returns the value of item.storage.content (e.g. to be used in VuFind
* getStatus/getHolding array as location)
*
* @param array $item Array with DAIA item data
*
* @return string
*/
protected function getItemDepartment($item)
{
return $this->translate(parent::getItemDepartment($item));
}
/**
* Returns the evaluated values of the provided limitations element -- FincLibero
* specific implementation preprocesses limitations by filtering the non
* functional limitations (i.e. limitations that are used for triggering actions
* etc.)
*
* @param array $limitations Array with DAIA limitation data
*
* @return array
*/
protected function getItemLimitationContent($limitations)
{
return parent::getItemLimitationContent(
$this->filterNonFunctionalLimitations($limitations)
);
}
/**
* Returns the evaluated values of the provided limitations element -- FincLibero
* specific implementation preprocesses limitations by filtering the non
* functional limitations (i.e. limitations that are used for triggering actions
* etc.)
*
* @param array $limitations Array with DAIA limitation data
*
* @return array
*/
protected function getItemLimitationTypes($limitations)
{
return parent::getItemLimitationTypes(
$this->filterNonFunctionalLimitations($limitations)
);
}
/**
* FincLibero specific MyReSearch views
*/
/**
* Custom FincLibero-method to return items with properties:
* - document.status = 4
* - document.storage und document.storageid != Lesesaal/Magazin
*
* @param array $patron Array returned from patronLogin()
*
* @return array
*/
public function getMyMediaReadyToPickup($patron)
{
// filters for getMyMediaReadyToPickup are:
// status = 4 - provided (the document is ready to be used by the patron)
// document.storage und document.storageid != Lesesaal/Magazin
$filter = [
'status' => [4],
/*'exclude' => [
'storageid' => $this->stackURIs
],*/
'endtime' => null,
'regex' => ['item' => "/^(".$this->getDaiaIdPrefixNamespace().").*$/"]
];
// get items-docs for given filters
$items = $this->paiaGetItems($patron, $filter);
return $this->mapPaiaItems($items, 'myHoldsMapping');
}
/**
* Custom FincLibero-method to return items with properties:
* - document.status = 3
* - document.endtime = 0
*
* @param array $patron Array returned from patronLogin()
*
* @return array
*/
public function getMyPermanentLoans($patron)
{
// filters for getMyPermanentLoans are:
// status = 3 - held (the document is on loan by the patron)
// endtime = 0
$filter = [
'status' => [3],
'endtime' => null,
'regex' => ['item' => "/^(".$this->getDaiaIdPrefixNamespace().").*$/"]
];
// get items-docs for given filters
$items = $this->paiaGetItems($patron, $filter);
return $this->mapPaiaItems(
$this->itemFieldSort($items, 'starttime', SORT_DESC),
'myTransactionsMapping'
);
}
/**
* Customized getMyHolds for FincLibero to return items with properties:
* - document.status = 1 (reserved)
* - document.storage und document.storageid != Magazin
* - document.endtime = Rückgabedatum (not NULL!)
*
* @param array $patron Array returned from patronLogin()
*
* @return array
*/
public function getMyHolds($patron)
{
// filters for getMyHolds are:
// status = 1 - reserved
$filter = [
'status' => [1,2],
'regex' => ['item' => "/^(".$this->getDaiaIdPrefixNamespace().").*$/"]
];
// get items-docs for given filters
$items = $this->paiaGetItems($patron, $filter);
return $this->mapPaiaItems($items, 'myHoldsMapping');
}
/**
* Customized getMyTransactions for FincLibero to return items with properties:
* - document.status = 3 (held)
* - document.item = UBL:*
* - document.starttime = Ausleihdatum
* - document.endtime = Rückgabedatum (not NULL!)
*
* @param array $patron Array returned from patronLogin()
*
* @return array
*/
public function getMyTransactions($patron)
{
// filters for getMyPermanentLoans are:
// status = 3 - held (the document is on loan by the patron)
// endtime != null
$filter = [
'status' => [3],
'exclude' => ['endtime' => null],
'regex' => ['item' => "/^(".$this->getDaiaIdPrefixNamespace().").*$/"]
];
// get items-docs for given filters
$items = $this->paiaGetItems($patron, $filter);
return $this->mapPaiaItems(
$this->itemFieldSort($items, 'endtime'),
'myTransactionsMapping'
);
}
/**
* @param $patron
* @param null $messageIdList
* @param null $toDate won't work here
* @throws ILSException
* @return TRUE on success, FALSE otherwise
*/
public function removeMySystemMessages(
$patron,
$messageIdList = null,
$toDate = null
)
{
return $this->paiaRemoveSystemMessages($patron,$messageIdList);
}
/**
* FincLibero specific helper functions
*/
/**
* Helper function to filter certain limitations.
*
* @param array $limitations An item's limitations.
* @return mixed
*/
protected function filterNonFunctionalLimitations($limitations)
{
// remove the configured limitations from the current set of limitations
foreach ($this->configuredLimitations as $configuredLimitation) {
foreach ($limitations as $key => $limitation) {
if (isset($limitation['id'])
&& in_array($limitation['id'], $this->{$configuredLimitation})
) {
unset($limitations[$key]);
}
}
}
// remove all known pickUpLocations from the current set of limitations
$pickUpLocations = $this->filterPickUpLocations($limitations);
foreach ($limitations as $key => $limitation) {
if (isset($limitation['id'])) {
foreach ($pickUpLocations as $pickup) {
if ($limitation['id'] == $pickup['locationID']) {
unset($limitations[$key]);
}
}
}
}
return $limitations;
}
/**
* Helper function to compile upon init() a set of limitations that can be used
* for filtering.
*
* @param string $limitation An URI identifying a limitation
*/
protected function setConfiguredLimitation($limitation)
{
if (is_string($limitation)) {
$this->configuredLimitations[] = $limitation;
}
}
/**
* Helper function to filter PickUpLocations from given limitations based on
* pattern configured in ILS ini
*
* @param array $limitations An item's limitations
* @return array
*/
protected function filterPickUpLocations($limitations)
{
$pickUpLocations = [];
// return array(locationID=>URI, locationDisplay=>Content)
foreach ($limitations as $limitation) {
if (isset($limitation['id'])) {
foreach ($this->pickUpLocationPatterns as $pattern) {
if (preg_match($pattern, $limitation['id'])
&& !(filter_var($limitation['id'], FILTER_VALIDATE_URL) === false)
) {
$pickUpLocations[] = [
'locationID' => $limitation['id'],
'locationDisplay' => isset($limitation['content'])
? $limitation['content'] : $limitation['id'],
];
}
}
}
}
return $pickUpLocations;
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment