diff --git a/local/alpha/config/vufind/searchspecs.yaml b/local/alpha/config/vufind/searchspecs.yaml new file mode 100644 index 0000000000000000000000000000000000000000..498d584b19e72b391ed788ed137285df3a5880f6 --- /dev/null +++ b/local/alpha/config/vufind/searchspecs.yaml @@ -0,0 +1,739 @@ +--- +# Listing of search types and their component parts and weights. +# +# Format is: +# searchType: +# # CustomMunge is an optional section to define custom pre-processing of +# # user input. See below for details of munge actions. +# CustomMunge: +# MungeName1: +# - [action1, actionParams] +# - [action2, actionParams] +# - [action3, actionParams] +# MungeName2: +# - [action1, actionParams] +# # DismaxFields is optional and defines the fields sent to the Dismax handler +# # when we are able to use it. QueryFields will be used for advanced +# # searches that Dismax cannot support. QueryFields is always used if no +# # DismaxFields section is defined. +# DismaxFields: +# - field1^boost +# - field2^boost +# - field3^boost +# # DismaxParams is optional and allows you to override default Dismax settings +# # (i.e. mm / bf) on a search-by-search basis. Enclose the parameter values +# # in quotes for proper behavior. If you want global default values for these +# # settings, you can edit the appropriate search handler in +# # solr/biblio/conf/solrconfig.xml. +# DismaxParams: +# - [param1_name, param1_value] +# - [param2_name, param2_value] +# - [param3_name, param3_value] +# # This optional setting may be used to specify which Dismax handler to use. By +# # default, VuFind provides two options: dismax (for the old, standard +# # Dismax) and edismax (for Extended Dismax). You can also configure your own +# # in solrconfig.xml, but VuFind relies on the name "edismax" to identify an +# # Extended Dismax handler. If you omit this setting, the default value from +# # the default_dismax_handler setting in the [Index] section of config.ini +# # will be used. +# DismaxHandler: dismax|edismax +# # QueryFields define the fields we are searching when not using Dismax; VuFind +# # detects queries that will not work with Dismax and switches to QueryFields +# # as needed. +# QueryFields: +# SolrField: +# - [howToMungeSearchstring, weight] +# - [differentMunge, weight] +# DifferentSolrField: +# - [howToMunge, weight] +# # The optional FilterQuery section allows you to AND a static query to the +# # dynamic query generated using the QueryFields; see JournalTitle below +# # for an example. This is applied whether we use DismaxFields or +# # QueryFields. +# FilterQuery: (optional Lucene filter query) +# ExactSettings: +# DismaxFields: ... +# QueryFields: ... +# # All the same settings as above, but for exact searches, i.e. search terms +# # enclosed in quotes. Allows different fields or weights for exact +# # searches. See below for commented-out examples. +# +# ...etc. +# +#----------------------------------------------------------------------------------- +# +# Within the QueryFields area, fields are OR'd together, unless they're in an +# anonymous array with a numeric instead of alphanumeric key, in which case the +# first element is a two-value array that tells us what the type (AND or OR) and +# weight of the whole group should be. +# +# So, given: +# +# test: +# QueryFields: +# A: +# - [onephrase, 500] +# - [and, 200] +# B: +# - [and, 100] +# - [or, 50] +# # Start an anonymous array to group; first element indicates AND grouping +# # and a weight of 50 +# 0: +# 0: +# - AND +# - 50 +# C: +# - [onephrase, 200] +# D: +# - [onephrase, 300] +# # Note the "not" attached to the field name as a minus, and the use of ~ +# # to mean null ("no special weight") +# -E: +# - [or, ~] +# D: +# - [or, 100] +# +# ...and the search string +# +# test "one two" +# +# ...we'd get +# +# (A:"test one two"^500 OR +# A:(test AND "one two")^ 200 OR +# B:(test AND "one two")^100 OR +# B:(test OR "one two")^50 +# ( +# C:("test one two")^200 AND +# D:"test one two"^300 AND +# -E:(test OR "one two") +# )^50 OR +# D:(test OR "one two")^100 +# ) +# +#----------------------------------------------------------------------------------- +# +# Munge types are based on the original Solr.php code, and consist of: +# +# onephrase: eliminate all quotes and do it as a single phrase. +# testing "one two" +# ...becomes ("testing one two") +# +# and: AND the terms together +# testing "one two" +# ...becomes (testing AND "one two") +# +# or: OR the terms together +# testing "one two" +# ...becomes (testing OR "one two") +# +# identity: Use the search as-is +# testing "one two" +# ...becomes (testing "one two") +# +# Additional Munge types can be defined in the CustomMunge section. Each array +# entry under CustomMunge defines a new named munge type. Each array entry under +# the name of the munge type specifies a string manipulation operation. Operations +# will be applied in the order listed, and different operations take different +# numbers of parameters. +# +# Munge operations: +# +# [append, text] - Append text to the end of the user's search string +# [lowercase] - Convert string to lowercase +# [preg_replace, pattern, replacement] - Perform a regular expression replace +# using the preg_replace() PHP function. If you use backreferences in your +# replacement phrase, be sure to escape dollar signs (i.e. \$1, not $1). +# [uppercase] - Convert string to uppercase +# +# See the CallNumber search below for an example of custom munging in action. +#----------------------------------------------------------------------------------- + +# These searches use Dismax when possible: +Author: + DismaxParams: + - [bf , ord(publishDateSort)^10] + DismaxFields: + - author^400 + - author2^300 + - author_id^100 + - author_ref^150 + - author_corp^200 + - author_corp2^200 + - author_corp_ref^150 + - author_orig^200 + - author2_orig^200 + - author_corp_orig^200 + - author_corp2_orig^200 + QueryFields: + - author: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author2: + - [onephrase, 100] + - [and, 50] + - [or, ~] + - author_ref: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp2: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp_ref: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author2_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp2_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_id: + - [onephrase, 450] + - [and, 300] + - [or, 200] + +ISN: +# DismaxFields: +# - isbn +# - issn +# - ismn + QueryFields: + - issn: + - [and, 100] + - [or, ~] + - isbn: + - [and, 100] + - [or, ~] + - ismn: + - [and, 100] + - [or, ~] + +Signatur: + DismaxParams: + - [mm, 0] + DismaxFields: + - callnumber_ISIL + QueryFields: + - callnumber_ISIL: + - [or, ~] + # - [and, 100] + # - [or, ~] + +Barcode: + DismaxParams: + - [mm, 0] + DismaxFields: + - barcode_ISIL + QueryFields: + - barcode_ISIL: + #- [and, 100] + - [or, ~] + +Subject: + DismaxFields: + - topic_unstemmed^150 + - topic^100 + - topic_id^100 + - topic_ref^100 + #- geographic^50 + #- genre^50 + #- era + QueryFields: + - topic_unstemmed: + - [onephrase, 350] + - [and, 150] + - [or, ~] + - topic: + - [onephrase, 300] + - [and, 100] + - [or, ~] + - topic_ref: + - [onephrase, 100] + - [and, 50] + - [or, ~] + - topic_id: + - [onephrase, 100] + - [and, 50] + - [or, ~] + #- geographic: + # - [onephrase, 300] + # - [and, 100] + # - [or, ~] + #- genre: + # - [onephrase, 300] + # - [and, 100] + # - [or, ~] + #- era: + # - [and, 100] + # - [or, ~] +# ExactSettings: +# DismaxFields: +# - topic_unstemmed^150 +# QueryFields: +# - topic_unstemmed: +# - [onephrase, 350] +# - [and, 150] +# - [or, ~] + +# This field definition is a compromise that supports both journal-level and +# article-level data. The disadvantage is that hits in article titles will +# be mixed in. If you are building a purely article-oriented index, you should +# customize this to remove all of the title_* fields and focus entirely on the +# container_title field. +JournalTitle: + DismaxFields: + - title_short^500 + - title_full_unstemmed^450 + - title_full^400 + - title^300 + - title_alt^200 + - title_new^100 + - title_old + - series^100 + - series2 + QueryFields: + - title_short: + - [onephrase, 500] + - title_full_unstemmed: + - [onephrase, 450] + - [and, 400] + - title_full: + - [onephrase, 400] + - title: + - [onephrase, 300] + - [and, 250] + - title_alt: + - [and, 200] + - title_new: + - [and, 100] + - title_old: + - [and, ~] + - series: + - [onephrase, 100] + - [and, 50] + - series2: + - [onephrase, 50] + - [and , ~] + FilterQuery: "format:Journal" +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^450 +# QueryFields: +# - title_full_unstemmed: +# - [onephrase, 450] +# - [and, 400] +# FilterQuery: "format:Journal OR format:Article" + +Title: + DismaxParams: + - [mm, 3] + - [bf , ord(publishDateSort)^10] + DismaxFields: +# - title_sub^200 +# - title_short^300 + - title_full_unstemmed^150 + - title_full^100 + - title^900 + - title_alt^200 + - title_new^100 + - title_old + - title_orig^400 + - series^100 + - series2 + - series_orig^100 + QueryFields: + - title_short: + - [onephrase, 500] + - title_full_unstemmed: + - [onephrase, 150] + - [and, 100] + - title_full: + - [onephrase, 100] + - title: + - [onephrase, 300] + - [and, 250] + - title_alt: + - [and, 200] + - title_new: + - [and, 100] + - title_old: + - [and, ~] + - title_orig: + - [onephrase, 500] + - [and, 200] + - series: + - [onephrase, 100] + - [and, 50] + - series2: + - [onephrase, 50] + - [and , ~] + - series_orig: + - [onephrase, 100] + - [and, 50] +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^450 +# QueryFields: +# - title_full_unstemmed: +# - [onephrase, 450] +# - [and, 400] + +Series: + DismaxFields: + - series^100 + - series2 + - series_orig^100 + QueryFields: + - series: + - [onephrase, 500] + - [and, 200] + - [or, 100] + - series2: + - [onephrase, 50] + - [and, 50] + - [or, ~] + - series_orig: + - [onephrase, 500] + - [and, 200] + - [or, 100] + +Series2: + DismaxFields: + - series2 + QueryFields: + - series2: + - [onephrase, 200] + - [and, 50] + +AllFields: + DismaxParams: + - [mm, 3] + - [bf , ord(publishDateSort)^10] + - [bf , "if(exists(query({!v='source_id:0'})),10,1)^1000"] +# - [bf, "if(exists(query({!v='access_facet:Local*'})),10,1)^1000"] + DismaxFields: + - title_short^1000 + - title_full_unstemmed^1000 + - title_full^400 + - title^500 + - title_alt^200 + - title_new^100 + - title_orig^500 + - series^50 + - series2^30 + - series_orig^50 + - author^500 + - author_corp^300 + - author2^400 + - author_corp2^100 + - author_ref^500 + - author_corp_ref^500 + - author_orig^300 + - author2_orig^300 + - author_corp_orig^300 + - author_corp2_orig^100 + - topic_ref^10 + - contents^10 + - topic_unstemmed^15 + - topic^10 + - geographic^10 + - genre^10 + - rvk_label + - allfields_unstemmed^10 + - allfields + - fulltext + - isbn + - issn + - ismn + + QueryFields: + 0: + 0: + - OR + - 50 + title_short: + - [onephrase, 1000] + title_full_unstemmed: + - [onephrase, 1000] + - [and, 500] + title_full: + - [onephrase, 400] + title: + - [onephrase, 300] + - [and, 250] + title_alt: + - [and, 200] + title_new: + - [and, 100] + title_orig: + - [onephrase, 500] + - [and, 400] + series: + - [onephrase, 300] + - [and, 100] + series2: + - [and, 30] + series_orig: + - [onephrase, 200] + - [and, 100] + author: + - [onephrase, 500] + - [and, 250] + author_ref: + - [onephrase, 250] + - [and, 250] + - [or, 250] + author_corp_ref: + - [onephrase, 250] + - [and, 250] + - [or, 250] + author_orig: + - [onephrase, 500] + - [and, 250] + author2_orig: + - [and, 50] + author_corp_orig: + - [onephrase, 500] + - [and, 400] + author_corp2_orig: + - [and, 50] + author_corp: + - [onephrase, 500] + - [and, 400] + author2: + - [and, 50] + author_corp2: + - [and, 50] + contents: + - [and, 10] + topic_unstemmed: + - [onephrase, 55] + - [and, 50] + topic: + - [onephrase, 50] + topic_ref: + - [onephrase, 10] + - [and, 5] + - [or, 5] + topic_id: + - [onephrase, 50] + - [and, 25] + allfields_unstemmed: + - [or, 10] + allfields: + - [or, ~] + fulltext: + - [or, ~] + rvk_label: + - [onephrase, 500] + - [and, 250] + - [or, 250] + isbn: + - [onephrase, 500] + issn: + - [onephrase, 500] + ismn: + - [onephrase, 500] + imprint: + - [onephrase, 500] + +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^600 +# - topic_unstemmed^550 +# - allfields_unstemmed^10 +# - fulltext_unstemmed^10 +# - isbn +# - issn +# QueryFields: +# title_full_unstemmed: +# - [onephrase, 600] +# - [and, 500] +# topic_unstemmed: +# - [onephrase, 550] +# - [and, 500] +# allfields_unstemmed: +# - [or, 10] +# fulltext_unstemmed: +# - [or, 10] +# isbn: +# - [onephrase, ~] +# issn: +# - [onephrase, ~] + +# These are advanced searches that never use Dismax: +id: + QueryFields: + - id: + - [onephrase, ~] + +# Fields for exact matches originating from alphabetic browse +ids: + QueryFields: + - id: + - [or, ~] + +TopicBrowse: + QueryFields: + - topic_browse: + - [onephrase, ~] + +AuthorBrowse: + QueryFields: + - author_browse: + - [onephrase, ~] + +TitleBrowse: + QueryFields: + - title_full: + - [onephrase, ~] + +DeweyBrowse: + QueryFields: + - dewey-raw: + - [onephrase, ~] + +LccBrowse: + QueryFields: + - callnumber-a: + - [onephrase, ~] + + + +# CallNumber: + # We use two similar munges here -- one for exact matches, which will get + # a very high boost factor, and one for left-anchored wildcard searches, + # which will return a larger number of hits at a lower boost. + #CustomMunge: + #callnumber_exact: + #- [uppercase] + # Strip whitespace and quotes: + #- [preg_replace, '/[ "]/', ""] + # Escape colons (unescape first to avoid double-escapes): + #- [preg_replace, "/(\\\:)/", ':'] + #- [preg_replace, '/:/', '\:'] + # Strip pre-existing trailing asterisks: + #- [preg_replace, "/\*+$/", ""] + #callnumber_fuzzy: + #- [uppercase] + # Strip whitespace and quotes: + #- [preg_replace, '/[ "]/', ""] + # Escape colons (unescape first to avoid double-escapes): + #- [preg_replace, "/(\\\:)/", ':'] + #- [preg_replace, '/:/', '\:'] + # Strip pre-existing trailing asterisks, then add a new one: + #- [preg_replace, "/\*+$/", ""] + #- [append, "*"] + QueryFields: + callnumber-search: + - [callnumber_exact, 1000] + - [callnumber_fuzzy, ~] + dewey-search: + - [callnumber_exact, 1000] + - [callnumber_fuzzy, ~] + +publisher: + DismaxFields: + - publisher^100 + QueryFields: + - publisher: + - [and, 100] + - [or, ~] + +year: + DismaxFields: + - publishDate^100 + QueryFields: + - publishDate: + - [and, 100] + - [or, ~] + +language: + QueryFields: + - language: + - [and, ~] + +toc: + DismaxFields: + - contents^100 + QueryFields: + - contents: + - [and, 100] + - [or, ~] + +topic: + QueryFields: + - topic: + - [and, 50] + - topic_facet: + - [and, ~] + +geographic: + QueryFields: + - geographic: + - [and, 50] + - geographic_facet: + - [and ~] + +genre: + QueryFields: + - genre: + - [and, 50] + - genre_facet: + - [and, ~] + +era: + QueryFields: + - era: + - [and, ~] + +oclc_num: + CustomMunge: + oclc_num: + - [preg_replace, "/[^0-9]/", ""] + # trim leading zeroes: + - [preg_replace, "/^0*/", ""] + QueryFields: + - oclc_num: + - [oclc_num, ~] + +rvk: + DismaxFields: + - rvk_facet^100 + QueryFields: + - rvk_facet: + - [and, 50] + - [or, 50] + +rvk_path: + QueryFields: + - rvk_path: + - [onephrase, ~] + +multipart: + DismaxFields: + - multipart_link^100 + QueryFields: + - multipart_link: + - [and, 50] + - [or, 50] diff --git a/local/config/vufind/FincILS.ini b/local/config/vufind/FincILS.ini index 97cc44775e7f960081e56db570caed0d9142ed49..54c5658be2c405813eb79cb6a65c2a75c6e8e9cc 100644 --- a/local/config/vufind/FincILS.ini +++ b/local/config/vufind/FincILS.ini @@ -44,7 +44,6 @@ ; DE-Gla 1 ;baseUrl = http://139.18.19.238:9080/daiatheca/daia/ -;ilsIdentifier = "record_id" ;daiaIdPrefix = "DE-Gla1:ppn:" ;ilsIdentifier = "record_id" ;multiQuery = true diff --git a/local/config/vufind/HierarchyDefault.ini b/local/config/vufind/HierarchyDefault.ini index e2b00196c47af1f367622eea42a6321af43a98b4..3c0a202431083521cedf451212a3839cfd6027f8 100644 --- a/local/config/vufind/HierarchyDefault.ini +++ b/local/config/vufind/HierarchyDefault.ini @@ -4,7 +4,7 @@ ; All - any record with is_hierarchy set ; Top - any record where is_hierarchy = hierarchy_top ; None - never link to the collection module -link_type = "Top" +link_type = "None" [HierarchyTree] ; Are hierarchy trees visible? -- true or false (default false) diff --git a/local/config/vufind/config.ini b/local/config/vufind/config.ini index 5eb66cc7d53c87887828be085f00fbb7cafb0f79..a82829020628cf1d8dbd75389a43bb4eaf965917 100644 --- a/local/config/vufind/config.ini +++ b/local/config/vufind/config.ini @@ -1212,9 +1212,9 @@ HMACkey = mySuperSecretValue ; field of the Solr index. driver = Default ; Should we display hierarchy trees? (default = false) -;showTree = true +showTree = true ; "Search within trees" can be disabled here if set to "false" (default = true) -search = true +search = false ; You can limit the number of search results highlighted when searching the tree; ; a limit is recommended if you have large trees, as otherwise large numbers of ; results can cause performance problems. If treeSearchLimit is -1 or not set, @@ -1318,22 +1318,38 @@ max_tag_length = 64 ;isil[] = "DE-15-292" ;bik = "952000-4" -; This section contains all site related customization for finc -;[CustomSite] -; Combine more formats to one css class. If false first format entry will taken -; to display icon symbol -;combinedIcons = false -;namespace = ubl - ; This section contains all index related customizations for finc -;[CustomIndex] -; Special settings to control single instances of libaries within one vufind -; installation. -;indexExtension = "de15" ; for solr index of hmt +[CustomIndex] +; The indexExtension allows to select library specific index fields (e.g. +; barcode_{indexExtension}, callnumber_{indexExtension}, format_{indexExtension} +; etc.). +;indexExtension = "de15" + ; take general format field of Solr index. If false it takes the format fields ; with index extension defined above. ;generalFormats = true ;for ubl & htwk it should be true +; This mapping allows access to library specific Marc fields identified by the +; library namespace (defined in localMarcFieldOfLibraryNamespace) +localMarcFieldOfLibraryMapping[] = "ubl:969" +localMarcFieldOfLibraryMapping[] = "hmt:970" +localMarcFieldOfLibraryMapping[] = "che:971" +localMarcFieldOfLibraryMapping[] = "tuf:972" +localMarcFieldOfLibraryMapping[] = "htw:973" +localMarcFieldOfLibraryMapping[] = "htwk:974" +localMarcFieldOfLibraryMapping[] = "zwi:975" +localMarcFieldOfLibraryMapping[] = "zit:976" +localMarcFieldOfLibraryMapping[] = "hfm:977" +localMarcFieldOfLibraryMapping[] = "hfbk:978" +localMarcFieldOfLibraryMapping[] = "hgb:979" +localMarcFieldOfLibraryMapping[] = "skd:983" +localMarcFieldOfLibraryMapping[] = "slub:984" +localMarcFieldOfLibraryMapping[] = "bas:985" + +; Namespace to select the correct library specific Marc field from the +; localMarcFieldOfLibraryMapping +;localMarcFieldOfLibraryNamespace = "ubl" + ; This section configures the form for patrdon driven acquisition suggestions. ;[Acquisition] ; Email address to receive the acquisition suggestions diff --git a/local/config/vufind/searchspecs.yaml b/local/config/vufind/searchspecs.yaml index 52fd75dd3abb411fe66adf7216baf21d0a1bf530..498d584b19e72b391ed788ed137285df3a5880f6 100644 --- a/local/config/vufind/searchspecs.yaml +++ b/local/config/vufind/searchspecs.yaml @@ -155,11 +155,12 @@ Author: DismaxParams: - [bf , ord(publishDateSort)^10] DismaxFields: - - author^200 - - author2^200 + - author^400 + - author2^300 - author_id^100 - author_ref^150 - author_corp^200 + - author_corp2^200 - author_corp_ref^150 - author_orig^200 - author2_orig^200 @@ -182,6 +183,10 @@ Author: - [onephrase, 350] - [and, 200] - [or, 100] + - author_corp2: + - [onephrase, 350] + - [and, 200] + - [or, 100] - author_corp_ref: - [onephrase, 350] - [and, 200] @@ -227,9 +232,9 @@ Signatur: DismaxParams: - [mm, 0] DismaxFields: - - signatur + - callnumber_ISIL QueryFields: - - signatur: + - callnumber_ISIL: - [or, ~] # - [and, 100] # - [or, ~] @@ -238,9 +243,9 @@ Barcode: DismaxParams: - [mm, 0] DismaxFields: - - barcode + - barcode_ISIL QueryFields: - - barcode: + - barcode_ISIL: #- [and, 100] - [or, ~] @@ -263,12 +268,12 @@ Subject: - [and, 100] - [or, ~] - topic_ref: - - [onephrase, 300] - - [and, 100] + - [onephrase, 100] + - [and, 50] - [or, ~] - topic_id: - - [onephrase, 300] - - [and, 100] + - [onephrase, 100] + - [and, 50] - [or, ~] #- geographic: # - [onephrase, 300] @@ -341,6 +346,7 @@ JournalTitle: Title: DismaxParams: + - [mm, 3] - [bf , ord(publishDateSort)^10] DismaxFields: # - title_sub^200 @@ -423,9 +429,11 @@ AllFields: DismaxParams: - [mm, 3] - [bf , ord(publishDateSort)^10] + - [bf , "if(exists(query({!v='source_id:0'})),10,1)^1000"] +# - [bf, "if(exists(query({!v='access_facet:Local*'})),10,1)^1000"] DismaxFields: - - title_short^750 - - title_full_unstemmed^600 + - title_short^1000 + - title_full_unstemmed^1000 - title_full^400 - title^500 - title_alt^200 @@ -434,24 +442,22 @@ AllFields: - series^50 - series2^30 - series_orig^50 - - author^300 - - author_id^100 + - author^500 - author_corp^300 - - author2^300 + - author2^400 - author_corp2^100 - - author_fuller^150 - author_ref^500 - author_corp_ref^500 - author_orig^300 - author2_orig^300 - author_corp_orig^300 - author_corp2_orig^100 - - topic_ref^500 + - topic_ref^10 - contents^10 - - topic_unstemmed^550 - - topic^500 - - geographic^300 - - genre^300 + - topic_unstemmed^15 + - topic^10 + - geographic^10 + - genre^10 - rvk_label - allfields_unstemmed^10 - allfields @@ -459,16 +465,16 @@ AllFields: - isbn - issn - ismn - - rsn + QueryFields: 0: 0: - OR - 50 title_short: - - [onephrase, 750] + - [onephrase, 1000] title_full_unstemmed: - - [onephrase, 600] + - [onephrase, 1000] - [and, 500] title_full: - [onephrase, 400] @@ -493,15 +499,12 @@ AllFields: author: - [onephrase, 500] - [and, 250] - author_id: - - [onephrase, 50] - - [and, 25] author_ref: - - [onephrase, 500] + - [onephrase, 250] - [and, 250] - [or, 250] author_corp_ref: - - [onephrase, 500] + - [onephrase, 250] - [and, 250] - [or, 250] author_orig: @@ -524,14 +527,14 @@ AllFields: contents: - [and, 10] topic_unstemmed: - - [onephrase, 550] - - [and, 500] + - [onephrase, 55] + - [and, 50] topic: - - [onephrase, 500] + - [onephrase, 50] topic_ref: - - [onephrase, 500] - - [and, 250] - - [or, 250] + - [onephrase, 10] + - [and, 5] + - [or, 5] topic_id: - [onephrase, 50] - [and, 25] @@ -541,12 +544,19 @@ AllFields: - [or, ~] fulltext: - [or, ~] + rvk_label: + - [onephrase, 500] + - [and, 250] + - [or, 250] isbn: - [onephrase, 500] issn: - [onephrase, 500] ismn: - [onephrase, 500] + imprint: + - [onephrase, 500] + # ExactSettings: # DismaxFields: # - title_full_unstemmed^600 diff --git a/local/dev/config/vufind/searchspecs.yaml.sample b/local/dev/config/vufind/searchspecs.yaml.sample new file mode 100644 index 0000000000000000000000000000000000000000..498d584b19e72b391ed788ed137285df3a5880f6 --- /dev/null +++ b/local/dev/config/vufind/searchspecs.yaml.sample @@ -0,0 +1,739 @@ +--- +# Listing of search types and their component parts and weights. +# +# Format is: +# searchType: +# # CustomMunge is an optional section to define custom pre-processing of +# # user input. See below for details of munge actions. +# CustomMunge: +# MungeName1: +# - [action1, actionParams] +# - [action2, actionParams] +# - [action3, actionParams] +# MungeName2: +# - [action1, actionParams] +# # DismaxFields is optional and defines the fields sent to the Dismax handler +# # when we are able to use it. QueryFields will be used for advanced +# # searches that Dismax cannot support. QueryFields is always used if no +# # DismaxFields section is defined. +# DismaxFields: +# - field1^boost +# - field2^boost +# - field3^boost +# # DismaxParams is optional and allows you to override default Dismax settings +# # (i.e. mm / bf) on a search-by-search basis. Enclose the parameter values +# # in quotes for proper behavior. If you want global default values for these +# # settings, you can edit the appropriate search handler in +# # solr/biblio/conf/solrconfig.xml. +# DismaxParams: +# - [param1_name, param1_value] +# - [param2_name, param2_value] +# - [param3_name, param3_value] +# # This optional setting may be used to specify which Dismax handler to use. By +# # default, VuFind provides two options: dismax (for the old, standard +# # Dismax) and edismax (for Extended Dismax). You can also configure your own +# # in solrconfig.xml, but VuFind relies on the name "edismax" to identify an +# # Extended Dismax handler. If you omit this setting, the default value from +# # the default_dismax_handler setting in the [Index] section of config.ini +# # will be used. +# DismaxHandler: dismax|edismax +# # QueryFields define the fields we are searching when not using Dismax; VuFind +# # detects queries that will not work with Dismax and switches to QueryFields +# # as needed. +# QueryFields: +# SolrField: +# - [howToMungeSearchstring, weight] +# - [differentMunge, weight] +# DifferentSolrField: +# - [howToMunge, weight] +# # The optional FilterQuery section allows you to AND a static query to the +# # dynamic query generated using the QueryFields; see JournalTitle below +# # for an example. This is applied whether we use DismaxFields or +# # QueryFields. +# FilterQuery: (optional Lucene filter query) +# ExactSettings: +# DismaxFields: ... +# QueryFields: ... +# # All the same settings as above, but for exact searches, i.e. search terms +# # enclosed in quotes. Allows different fields or weights for exact +# # searches. See below for commented-out examples. +# +# ...etc. +# +#----------------------------------------------------------------------------------- +# +# Within the QueryFields area, fields are OR'd together, unless they're in an +# anonymous array with a numeric instead of alphanumeric key, in which case the +# first element is a two-value array that tells us what the type (AND or OR) and +# weight of the whole group should be. +# +# So, given: +# +# test: +# QueryFields: +# A: +# - [onephrase, 500] +# - [and, 200] +# B: +# - [and, 100] +# - [or, 50] +# # Start an anonymous array to group; first element indicates AND grouping +# # and a weight of 50 +# 0: +# 0: +# - AND +# - 50 +# C: +# - [onephrase, 200] +# D: +# - [onephrase, 300] +# # Note the "not" attached to the field name as a minus, and the use of ~ +# # to mean null ("no special weight") +# -E: +# - [or, ~] +# D: +# - [or, 100] +# +# ...and the search string +# +# test "one two" +# +# ...we'd get +# +# (A:"test one two"^500 OR +# A:(test AND "one two")^ 200 OR +# B:(test AND "one two")^100 OR +# B:(test OR "one two")^50 +# ( +# C:("test one two")^200 AND +# D:"test one two"^300 AND +# -E:(test OR "one two") +# )^50 OR +# D:(test OR "one two")^100 +# ) +# +#----------------------------------------------------------------------------------- +# +# Munge types are based on the original Solr.php code, and consist of: +# +# onephrase: eliminate all quotes and do it as a single phrase. +# testing "one two" +# ...becomes ("testing one two") +# +# and: AND the terms together +# testing "one two" +# ...becomes (testing AND "one two") +# +# or: OR the terms together +# testing "one two" +# ...becomes (testing OR "one two") +# +# identity: Use the search as-is +# testing "one two" +# ...becomes (testing "one two") +# +# Additional Munge types can be defined in the CustomMunge section. Each array +# entry under CustomMunge defines a new named munge type. Each array entry under +# the name of the munge type specifies a string manipulation operation. Operations +# will be applied in the order listed, and different operations take different +# numbers of parameters. +# +# Munge operations: +# +# [append, text] - Append text to the end of the user's search string +# [lowercase] - Convert string to lowercase +# [preg_replace, pattern, replacement] - Perform a regular expression replace +# using the preg_replace() PHP function. If you use backreferences in your +# replacement phrase, be sure to escape dollar signs (i.e. \$1, not $1). +# [uppercase] - Convert string to uppercase +# +# See the CallNumber search below for an example of custom munging in action. +#----------------------------------------------------------------------------------- + +# These searches use Dismax when possible: +Author: + DismaxParams: + - [bf , ord(publishDateSort)^10] + DismaxFields: + - author^400 + - author2^300 + - author_id^100 + - author_ref^150 + - author_corp^200 + - author_corp2^200 + - author_corp_ref^150 + - author_orig^200 + - author2_orig^200 + - author_corp_orig^200 + - author_corp2_orig^200 + QueryFields: + - author: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author2: + - [onephrase, 100] + - [and, 50] + - [or, ~] + - author_ref: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp2: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp_ref: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author2_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_corp2_orig: + - [onephrase, 350] + - [and, 200] + - [or, 100] + - author_id: + - [onephrase, 450] + - [and, 300] + - [or, 200] + +ISN: +# DismaxFields: +# - isbn +# - issn +# - ismn + QueryFields: + - issn: + - [and, 100] + - [or, ~] + - isbn: + - [and, 100] + - [or, ~] + - ismn: + - [and, 100] + - [or, ~] + +Signatur: + DismaxParams: + - [mm, 0] + DismaxFields: + - callnumber_ISIL + QueryFields: + - callnumber_ISIL: + - [or, ~] + # - [and, 100] + # - [or, ~] + +Barcode: + DismaxParams: + - [mm, 0] + DismaxFields: + - barcode_ISIL + QueryFields: + - barcode_ISIL: + #- [and, 100] + - [or, ~] + +Subject: + DismaxFields: + - topic_unstemmed^150 + - topic^100 + - topic_id^100 + - topic_ref^100 + #- geographic^50 + #- genre^50 + #- era + QueryFields: + - topic_unstemmed: + - [onephrase, 350] + - [and, 150] + - [or, ~] + - topic: + - [onephrase, 300] + - [and, 100] + - [or, ~] + - topic_ref: + - [onephrase, 100] + - [and, 50] + - [or, ~] + - topic_id: + - [onephrase, 100] + - [and, 50] + - [or, ~] + #- geographic: + # - [onephrase, 300] + # - [and, 100] + # - [or, ~] + #- genre: + # - [onephrase, 300] + # - [and, 100] + # - [or, ~] + #- era: + # - [and, 100] + # - [or, ~] +# ExactSettings: +# DismaxFields: +# - topic_unstemmed^150 +# QueryFields: +# - topic_unstemmed: +# - [onephrase, 350] +# - [and, 150] +# - [or, ~] + +# This field definition is a compromise that supports both journal-level and +# article-level data. The disadvantage is that hits in article titles will +# be mixed in. If you are building a purely article-oriented index, you should +# customize this to remove all of the title_* fields and focus entirely on the +# container_title field. +JournalTitle: + DismaxFields: + - title_short^500 + - title_full_unstemmed^450 + - title_full^400 + - title^300 + - title_alt^200 + - title_new^100 + - title_old + - series^100 + - series2 + QueryFields: + - title_short: + - [onephrase, 500] + - title_full_unstemmed: + - [onephrase, 450] + - [and, 400] + - title_full: + - [onephrase, 400] + - title: + - [onephrase, 300] + - [and, 250] + - title_alt: + - [and, 200] + - title_new: + - [and, 100] + - title_old: + - [and, ~] + - series: + - [onephrase, 100] + - [and, 50] + - series2: + - [onephrase, 50] + - [and , ~] + FilterQuery: "format:Journal" +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^450 +# QueryFields: +# - title_full_unstemmed: +# - [onephrase, 450] +# - [and, 400] +# FilterQuery: "format:Journal OR format:Article" + +Title: + DismaxParams: + - [mm, 3] + - [bf , ord(publishDateSort)^10] + DismaxFields: +# - title_sub^200 +# - title_short^300 + - title_full_unstemmed^150 + - title_full^100 + - title^900 + - title_alt^200 + - title_new^100 + - title_old + - title_orig^400 + - series^100 + - series2 + - series_orig^100 + QueryFields: + - title_short: + - [onephrase, 500] + - title_full_unstemmed: + - [onephrase, 150] + - [and, 100] + - title_full: + - [onephrase, 100] + - title: + - [onephrase, 300] + - [and, 250] + - title_alt: + - [and, 200] + - title_new: + - [and, 100] + - title_old: + - [and, ~] + - title_orig: + - [onephrase, 500] + - [and, 200] + - series: + - [onephrase, 100] + - [and, 50] + - series2: + - [onephrase, 50] + - [and , ~] + - series_orig: + - [onephrase, 100] + - [and, 50] +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^450 +# QueryFields: +# - title_full_unstemmed: +# - [onephrase, 450] +# - [and, 400] + +Series: + DismaxFields: + - series^100 + - series2 + - series_orig^100 + QueryFields: + - series: + - [onephrase, 500] + - [and, 200] + - [or, 100] + - series2: + - [onephrase, 50] + - [and, 50] + - [or, ~] + - series_orig: + - [onephrase, 500] + - [and, 200] + - [or, 100] + +Series2: + DismaxFields: + - series2 + QueryFields: + - series2: + - [onephrase, 200] + - [and, 50] + +AllFields: + DismaxParams: + - [mm, 3] + - [bf , ord(publishDateSort)^10] + - [bf , "if(exists(query({!v='source_id:0'})),10,1)^1000"] +# - [bf, "if(exists(query({!v='access_facet:Local*'})),10,1)^1000"] + DismaxFields: + - title_short^1000 + - title_full_unstemmed^1000 + - title_full^400 + - title^500 + - title_alt^200 + - title_new^100 + - title_orig^500 + - series^50 + - series2^30 + - series_orig^50 + - author^500 + - author_corp^300 + - author2^400 + - author_corp2^100 + - author_ref^500 + - author_corp_ref^500 + - author_orig^300 + - author2_orig^300 + - author_corp_orig^300 + - author_corp2_orig^100 + - topic_ref^10 + - contents^10 + - topic_unstemmed^15 + - topic^10 + - geographic^10 + - genre^10 + - rvk_label + - allfields_unstemmed^10 + - allfields + - fulltext + - isbn + - issn + - ismn + + QueryFields: + 0: + 0: + - OR + - 50 + title_short: + - [onephrase, 1000] + title_full_unstemmed: + - [onephrase, 1000] + - [and, 500] + title_full: + - [onephrase, 400] + title: + - [onephrase, 300] + - [and, 250] + title_alt: + - [and, 200] + title_new: + - [and, 100] + title_orig: + - [onephrase, 500] + - [and, 400] + series: + - [onephrase, 300] + - [and, 100] + series2: + - [and, 30] + series_orig: + - [onephrase, 200] + - [and, 100] + author: + - [onephrase, 500] + - [and, 250] + author_ref: + - [onephrase, 250] + - [and, 250] + - [or, 250] + author_corp_ref: + - [onephrase, 250] + - [and, 250] + - [or, 250] + author_orig: + - [onephrase, 500] + - [and, 250] + author2_orig: + - [and, 50] + author_corp_orig: + - [onephrase, 500] + - [and, 400] + author_corp2_orig: + - [and, 50] + author_corp: + - [onephrase, 500] + - [and, 400] + author2: + - [and, 50] + author_corp2: + - [and, 50] + contents: + - [and, 10] + topic_unstemmed: + - [onephrase, 55] + - [and, 50] + topic: + - [onephrase, 50] + topic_ref: + - [onephrase, 10] + - [and, 5] + - [or, 5] + topic_id: + - [onephrase, 50] + - [and, 25] + allfields_unstemmed: + - [or, 10] + allfields: + - [or, ~] + fulltext: + - [or, ~] + rvk_label: + - [onephrase, 500] + - [and, 250] + - [or, 250] + isbn: + - [onephrase, 500] + issn: + - [onephrase, 500] + ismn: + - [onephrase, 500] + imprint: + - [onephrase, 500] + +# ExactSettings: +# DismaxFields: +# - title_full_unstemmed^600 +# - topic_unstemmed^550 +# - allfields_unstemmed^10 +# - fulltext_unstemmed^10 +# - isbn +# - issn +# QueryFields: +# title_full_unstemmed: +# - [onephrase, 600] +# - [and, 500] +# topic_unstemmed: +# - [onephrase, 550] +# - [and, 500] +# allfields_unstemmed: +# - [or, 10] +# fulltext_unstemmed: +# - [or, 10] +# isbn: +# - [onephrase, ~] +# issn: +# - [onephrase, ~] + +# These are advanced searches that never use Dismax: +id: + QueryFields: + - id: + - [onephrase, ~] + +# Fields for exact matches originating from alphabetic browse +ids: + QueryFields: + - id: + - [or, ~] + +TopicBrowse: + QueryFields: + - topic_browse: + - [onephrase, ~] + +AuthorBrowse: + QueryFields: + - author_browse: + - [onephrase, ~] + +TitleBrowse: + QueryFields: + - title_full: + - [onephrase, ~] + +DeweyBrowse: + QueryFields: + - dewey-raw: + - [onephrase, ~] + +LccBrowse: + QueryFields: + - callnumber-a: + - [onephrase, ~] + + + +# CallNumber: + # We use two similar munges here -- one for exact matches, which will get + # a very high boost factor, and one for left-anchored wildcard searches, + # which will return a larger number of hits at a lower boost. + #CustomMunge: + #callnumber_exact: + #- [uppercase] + # Strip whitespace and quotes: + #- [preg_replace, '/[ "]/', ""] + # Escape colons (unescape first to avoid double-escapes): + #- [preg_replace, "/(\\\:)/", ':'] + #- [preg_replace, '/:/', '\:'] + # Strip pre-existing trailing asterisks: + #- [preg_replace, "/\*+$/", ""] + #callnumber_fuzzy: + #- [uppercase] + # Strip whitespace and quotes: + #- [preg_replace, '/[ "]/', ""] + # Escape colons (unescape first to avoid double-escapes): + #- [preg_replace, "/(\\\:)/", ':'] + #- [preg_replace, '/:/', '\:'] + # Strip pre-existing trailing asterisks, then add a new one: + #- [preg_replace, "/\*+$/", ""] + #- [append, "*"] + QueryFields: + callnumber-search: + - [callnumber_exact, 1000] + - [callnumber_fuzzy, ~] + dewey-search: + - [callnumber_exact, 1000] + - [callnumber_fuzzy, ~] + +publisher: + DismaxFields: + - publisher^100 + QueryFields: + - publisher: + - [and, 100] + - [or, ~] + +year: + DismaxFields: + - publishDate^100 + QueryFields: + - publishDate: + - [and, 100] + - [or, ~] + +language: + QueryFields: + - language: + - [and, ~] + +toc: + DismaxFields: + - contents^100 + QueryFields: + - contents: + - [and, 100] + - [or, ~] + +topic: + QueryFields: + - topic: + - [and, 50] + - topic_facet: + - [and, ~] + +geographic: + QueryFields: + - geographic: + - [and, 50] + - geographic_facet: + - [and ~] + +genre: + QueryFields: + - genre: + - [and, 50] + - genre_facet: + - [and, ~] + +era: + QueryFields: + - era: + - [and, ~] + +oclc_num: + CustomMunge: + oclc_num: + - [preg_replace, "/[^0-9]/", ""] + # trim leading zeroes: + - [preg_replace, "/^0*/", ""] + QueryFields: + - oclc_num: + - [oclc_num, ~] + +rvk: + DismaxFields: + - rvk_facet^100 + QueryFields: + - rvk_facet: + - [and, 50] + - [or, 50] + +rvk_path: + QueryFields: + - rvk_path: + - [onephrase, ~] + +multipart: + DismaxFields: + - multipart_link^100 + QueryFields: + - multipart_link: + - [and, 50] + - [or, 50] diff --git a/local/languages/de.ini b/local/languages/de.ini index 3efd85b389af925eef3a3289f53526793e0a5ffe..3881f0e818b832a676d9fe69bdbfbdd7c78a9a40 100644 --- a/local/languages/de.ini +++ b/local/languages/de.ini @@ -252,7 +252,6 @@ Close = "Schließen" Code = Fehlercode Collection mode = "" Comment = "Kommentar" -Comments = Lesermeinungen combined search (OR) = "Kombinierte Suche (OR)" Confirm = Bestätigen Confirm with your password = "Bestätigen Sie mit Ihrem Passwort" diff --git a/module/finc/config/module.config.php b/module/finc/config/module.config.php index 80cd4926de58e8bc18b75a4794107085dcab48a4..178586187b7814c13843e7e407c1d345348c345a 100644 --- a/module/finc/config/module.config.php +++ b/module/finc/config/module.config.php @@ -17,6 +17,7 @@ $config = [ 'ils_driver' => [ 'factories' => [ 'fincils' => 'finc\ILS\Driver\Factory::getFincILS', + 'daia' => 'finc\ILS\Driver\Factory::getDAIA', 'paia' => 'finc\ILS\Driver\Factory::getPAIA', ], ], diff --git a/module/finc/src/finc/ILS/Driver/DAIA.php b/module/finc/src/finc/ILS/Driver/DAIA.php new file mode 100644 index 0000000000000000000000000000000000000000..30bf450ded0b0490c72ff382db211ba89f43ad6b --- /dev/null +++ b/module/finc/src/finc/ILS/Driver/DAIA.php @@ -0,0 +1,283 @@ +<?php +/** + * ILS Driver for VuFind to query availability information via DAIA. + * + * Based on the proof-of-concept-driver by Till Kinstler, GBV. + * Relaunch of the daia driver developed by Oliver Goldschmidt. + * + * PHP version 5 + * + * Copyright (C) Jochen Lienhard 2014. + * + * 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 Jochen Lienhard <lienhard@ub.uni-freiburg.de> + * @author Oliver Goldschmidt <o.goldschmidt@tu-harburg.de> + * @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; + +/** + * ILS Driver for VuFind to query availability information via DAIA. + * + * @category VuFind2 + * @package ILS_Drivers + * @author Jochen Lienhard <lienhard@ub.uni-freiburg.de> + * @author Oliver Goldschmidt <o.goldschmidt@tu-harburg.de> + * @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 DAIA extends \VuFind\ILS\Driver\DAIA +{ + + /** + * Parse an array with DAIA status information. + * + * @param string $id Record id for the DAIA array. + * @param array $daiaArray Array with raw DAIA status information. + * + * @return array Array with VuFind compatible status information. + */ + protected function parseDaiaArray($id, $daiaArray) + { + $doc_id = null; + $doc_href = null; + if (array_key_exists('id', $daiaArray)) { + $doc_id = $daiaArray['id']; + } + if (array_key_exists('href', $daiaArray)) { + // url of the document (not needed for VuFind) + $doc_href = $daiaArray['href']; + } + if (array_key_exists('message', $daiaArray)) { + // log messages for debugging + $this->logMessages($daiaArray['message'], 'document'); + } + // if one or more items exist, iterate and build result-item + if (array_key_exists('item', $daiaArray)) { + $number = 0; + foreach ($daiaArray['item'] as $item) { + $result_item = []; + $result_item['id'] = $id; + $result_item['item_id'] = $item['id']; + // custom DAIA field used in getHoldLink() + $result_item['ilslink'] + = (isset($item['href']) ? $item['href'] : $doc_href); + // count items + $number++; + $result_item['number'] = $this->getItemNumber($item, $number); + // set default value for barcode + $result_item['barcode'] = $this->getItemBarcode($item); + // set default value for reserve + $result_item['reserve'] = $this->getItemReserveStatus($item); + // get callnumber + $result_item['callnumber'] = $this->getItemCallnumber($item); + // get location + $result_item['location'] = $this->getItemLocation($item); + // get location link + $result_item['locationhref'] = $this->getItemLocationLink($item); + // get location + $result_item['storage'] = $this->getItemStorage($item); + // status and availability will be calculated in own function + $result_item = $this->getItemStatus($item) + $result_item; + // add result_item to the result array + $result[] = $result_item; + } // end iteration on item + } + + return $result; + } + + /** + * Returns an array with status information for provided item. + * + * @param array $item Array with DAIA item data + * + * @return array + */ + protected function getItemStatus($item) + { + $availability = false; + $status = ''; // status cannot be null as this will crash the translator + $duedate = null; + $availableLink = ''; + $queue = ''; + $notes = []; + if (array_key_exists('available', $item)) { + // check if item is loanable or presentation + foreach ($item['available'] as $available) { + // attribute service can be set once or not + if (isset($available['service']) + && in_array( + $available['service'], + ['loan', 'presentation', 'openaccess'] + ) + ) { + // set item available if service is loan, presentation or + // openaccess + $availability = true; + if ($available['service'] == 'loan' + && isset($available['service']['href']) + ) { + // save the link to the ils if we have a href for loan + // service + $availableLink = $available['service']['href']; + } + } + + // use limitation element for status string + if (isset($available['limitation'])) { + $notes = array_merge($notes, $this->getItemLimitation($available['limitation'])); + } + + // log messages for debugging + if (isset($available['message'])) { + $this->logMessages($available['message'], 'item->available'); + } + } + } + if (array_key_exists('unavailable', $item)) { + foreach ($item['unavailable'] as $unavailable) { + // attribute service can be set once or not + if (isset($unavailable['service']) + && in_array( + $unavailable['service'], + ['loan', 'presentation', 'openaccess'] + ) + ) { + if ($unavailable['service'] == 'loan' + && isset($unavailable['service']['href']) + ) { + //save the link to the ils if we have a href for loan service + } + + // use limitation element for status string + if (isset($unavailable['limitation'])) { + $notes = array_merge($notes, $this + ->getItemLimitation($unavailable['limitation'])); + } + } + // attribute expected is mandatory for unavailable element + if (isset($unavailable['expected'])) { + try { + $duedate = $this->dateConverter + ->convertToDisplayDate( + 'Y-m-d', $unavailable['expected'] + ); + } catch (\Exception $e) { + $this->debug('Date conversion failed: ' . $e->getMessage()); + $duedate = null; + } + } + + // attribute queue can be set + if (isset($unavailable['queue'])) { + $queue = $unavailable['queue']; + } + + // log messages for debugging + if (isset($unavailable['message'])) { + $this->logMessages($unavailable['message'], 'item->unavailable'); + } + } + } + + /*'availability' => '0', + 'status' => '', // string - needs to be computed from availability info + 'duedate' => '', // if checked_out else null + 'returnDate' => '', // false if not recently returned(?) + 'requests_placed' => '', // total number of placed holds + 'is_holdable' => false, // place holding possible?*/ + + if (!empty($availableLink)) { + $return['ilslink'] = $availableLink; + } + + $return['notes'] = $notes; + $return['status'] = $status; + $return['availability'] = $availability; + $return['duedate'] = $duedate; + $return['requests_placed'] = $queue; + + return $return; + } + + /** + * Returns the evaluated value of the provided limitation element + * + * @param array $limitations Array with DAIA limitation data + * + * @return array + */ + protected function getItemLimitation($limitations) + { + $itemLimitation = []; + foreach ($limitations as $limitation) { + // return the first limitation with content set + if (isset($limitation['content'])) { + $itemLimitation[] = $limitation['content']; + } + } + return $itemLimitation; + } + + /** + * Returns the value for "location" in VuFind getStatus/getHolding array + * + * @param array $item Array with DAIA item data + * + * @return string + */ + protected function getItemLocation($item) + { + $location = ''; + + if (isset($item['department']) + && isset($item['department']['content']) + ) { + $location .= (empty($location) + ? $item['department']['content'] + : ' - ' . $item['department']['content']); + } + + return (empty($location) ? 'Unknown' : $location); + } + + /** + * Returns the value for "location" in VuFind getStatus/getHolding array + * + * @param array $item Array with DAIA item data + * + * @return string + */ + protected function getItemStorage($item) + { + $storage = ''; + + if (isset($item['storage']) + && isset($item['storage']['content']) + ) { + $storage .= (empty($storage) + ? $item['storage']['content'] + : ' - ' . $item['storage']['content']); + } + + return (empty($storage) ? 'Unknown' : $storage); + } +} diff --git a/module/finc/src/finc/ILS/Driver/FincILS.php b/module/finc/src/finc/ILS/Driver/FincILS.php index 6d762837a0cffda3f4af1bfa8987a8ad786f45d2..7a3cdb66a60b9a5c21b4479cd4d4b8d5c5695dc1 100644 --- a/module/finc/src/finc/ILS/Driver/FincILS.php +++ b/module/finc/src/finc/ILS/Driver/FincILS.php @@ -233,7 +233,7 @@ class FincILS extends PAIA implements LoggerAwareInterface // if we already have a session with access_token and patron id, try to get // patron info with session data - if (isset($this->session->expires) && microtime() < $this->session->expires) { + if (isset($this->session->expires) && $this->session->expires > time()) { try { return $enrichUserDetails( $this->paiaGetUserDetails(($this->session->patron === 'root' ? $username : $this->session->patron)), @@ -304,9 +304,9 @@ class FincILS extends PAIA implements LoggerAwareInterface case 'regex' : // check regex filters $regexCounter = 0; - foreach ($filterValue as $regexKey => $regexValue) { - if (!(isset($doc[$regexKey]) - && preg_match($regexValue, $doc[$regexKey])) + foreach ($filterValue as $regexField => $regexPattern) { + if (isset($doc[$regexField]) + && preg_match($regexPattern, $doc[$regexField]) === 1 ) { $regexCounter++; } @@ -341,6 +341,69 @@ class FincILS extends PAIA implements LoggerAwareInterface return []; } + /** + * PAIA helper function to allow customization of mapping from PAIA response to + * VuFind ILS-method return values. + * + * @param array $items Array of PAIA items to be mapped + * @param string $mapping String identifying a custom mapping-method + * + * @return array + */ + protected function mapPaiaItems($items, $mapping) + { + return $this->postprocessPaiaItems( + parent::mapPaiaItems($items, $mapping) + ); + } + + /** + * Helper function to postprocess the PAIA items for display in catalog (e.g. retrieve + * fincid etc.). + * + * @param array $items Array of PAIA items to be postprocessed + * + * @return mixed + */ + protected function postprocessPaiaItems($items) + { + // regex pattern for item_id (e.g. UBL:barcode:0008911555) + $idPattern = '/^([]A-Za-z0-9_\-]*):(%s):(.*)$/'; + + // item_id identifier - Solr field mapping + $identifier = [ + 'barcode' => 'barcode' . + (isset($this->mainConfig->CustomIndex->indexExtension) + ? '_'.$this->mainConfig->CustomIndex->indexExtension : ''), + 'fincid' => 'id', + 'ppn' => 'record_id' + ]; + + // try item_id with defined regex pattern and identifiers and use Solr to + // retrieve fincid on match + $ilsIdentifier = function ($itemId) use ($identifier, $idPattern) { + foreach ($identifier as $key => $value) { + $matches = []; + if (preg_match(sprintf($idPattern, $key), $itemId, $matches)) { + return $this->_getFincId($matches[3], $value); + } + } + }; + + // iterate trough given items + foreach ($items as &$item) { + if (isset($item['id']) && empty($item['id']) && !empty($item['item_id'])) { + $ilsId = $ilsIdentifier($item['item_id']); + if ($ilsId != null) { + $item['id'] = $ilsId; + $item['source'] = 'Solr'; + } + } + } + + return $items; + } + /** * Get the Record-Object from the RecordDriver. * @@ -435,12 +498,18 @@ class FincILS extends PAIA implements LoggerAwareInterface /** * Get the identifier for the record which will be used for ILS interaction * - * @param string $id Document to look up. + * @param string $id Document to look up. + * @param string $ilsIdentifier Identifier to override config settings. * * @return string $ilsRecordId */ - private function _getILSRecordId($id) + private function _getILSRecordId($id, $ilsIdentifier = null) { + // override ilsIdentifier set in ILS driver config + if ($ilsIdentifier != null) { + $this->ilsIdentifier = $ilsIdentifier; + } + //get the ILS-specific recordId if ($this->ilsIdentifier != "default") { @@ -488,17 +557,18 @@ class FincILS extends PAIA implements LoggerAwareInterface /** * Get the identifiers for multiple records * - * @param array $ids Documents to look up. + * @param array $ids Documents to look up. + * @param string $ilsIdentifier Identifier to override config settings. * * @return array $ilsRecordIds */ - private function _getILSRecordIds($ids) + private function _getILSRecordIds($ids, $ilsIdentifier = null) { $ilsRecordIds = []; if (is_array($ids)) { foreach ($ids as $id) { - $ilsRecordIds[] = $this->_getILSRecordId($id); + $ilsRecordIds[] = $this->_getILSRecordId($id, $ilsIdentifier); } return $ilsRecordIds; @@ -510,12 +580,18 @@ class FincILS extends PAIA implements LoggerAwareInterface /** * Get the finc id of the record with the given ilsIdentifier value * - * @param string $ilsId Document to look up. + * @param string $ilsId Document to look up. + * @param string $ilsIdentifier Identifier to override config settings. * * @return string $fincId if ilsIdentifier is configured, otherwise $ilsId */ - private function _getFincId($ilsId) + private function _getFincId($ilsId, $ilsIdentifier = null) { + // override ilsIdentifier set in ILS driver config + if ($ilsIdentifier != null) { + $this->ilsIdentifier = $ilsIdentifier; + } + if ($this->ilsIdentifier != "default") { // different ilsIdentifier is configured, retrieve fincid try { diff --git a/module/finc/src/finc/ILS/Driver/PAIA.php b/module/finc/src/finc/ILS/Driver/PAIA.php index 2cde98d7e2a29a7689d3c9027f2ca264060a3017..29b4aafe98db67f28b944542e3cca72b7acd2ef4 100644 --- a/module/finc/src/finc/ILS/Driver/PAIA.php +++ b/module/finc/src/finc/ILS/Driver/PAIA.php @@ -51,7 +51,7 @@ use VuFind\Exception\ILS as ILSException, * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link http://vufind.org/wiki/building_an_ils_driver Wiki */ -class PAIA extends \VuFind\ILS\Driver\DAIA implements +class PAIA extends DAIA implements HttpServiceAwareInterface, LoggerAwareInterface { use \VuFindHttp\HttpServiceAwareTrait; @@ -608,9 +608,7 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements // if we already have a session with access_token and patron id, try to get // patron info with session data - if (isset($this->session->expires) - && microtime() < $this->session->expires - ) { + if (isset($this->session->expires) && $this->session->expires > time()) { try { return $enrichUserDetails( $this->paiaGetUserDetails($this->session->patron), @@ -962,6 +960,9 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements // about (0..1) textual description of the document $result['title'] = (isset($doc['about']) ? $doc['about'] : null); + // label (0..1) call number, shelf mark or similar item label + $result['callnumber'] = (isset($doc['label']) ? $doc['label'] : null); // PAIA custom field + if (in_array($doc['status'], [1, 2])) { // status == 1 => starttime: when the document was reserved // status == 2 => starttime: when the document was ordered @@ -978,6 +979,7 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements $result['available'] = true; } + // Optional VuFind fields /* $result['reqnum'] = null; $result['volume'] = null; @@ -988,9 +990,6 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements $result['upc'] = null; */ - //'message' => $loans_response['doc'][$i]['label'], - //'callnumber' => $loans_response['doc'][$i]['label'], - $results[] = $result; } @@ -1033,9 +1032,6 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements // about (0..1) textual description of the document $result['title'] = (isset($doc['about']) ? $doc['about'] : null); - // label (0..1) call number, shelf mark or similar item label - $result['barcode'] = (isset($doc['label']) ? $doc['label'] : null); - // queue (0..1) number of waiting requests for the document or item $result['request'] = (isset($doc['queue']) ? $doc['queue'] : null); @@ -1067,7 +1063,12 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements // storageid (0..1) location URI + // label (0..1) call number, shelf mark or similar item label + $result['callnumber'] = (isset($doc['label']) ? $doc['label'] : null); // PAIA custom field + + // Optional VuFind fields /* + $result['barcode'] = null; $result['dueStatus'] = null; $result['renewLimit'] = "1"; $result['volume'] = null; @@ -1292,8 +1293,8 @@ class PAIA extends \VuFind\ILS\Driver\DAIA implements = isset($responseArray['scope']) ? explode(' ', $responseArray['scope']) : null; $this->session->expires - = isset($responseArray['expires']) - ? (microtime() + ($responseArray['expires']*1000)) : null; + = isset($responseArray['expires_in']) + ? (time() + ($responseArray['expires_in'])) : null; return true; } diff --git a/module/finc/src/finc/RecordDriver/SolrDefault.php b/module/finc/src/finc/RecordDriver/SolrDefault.php index f619e72812bdc8e46ba0d0f03c92309c23f16b8d..ce4b3bbd46c7f33a7faa28009313b85ec46962c1 100644 --- a/module/finc/src/finc/RecordDriver/SolrDefault.php +++ b/module/finc/src/finc/RecordDriver/SolrDefault.php @@ -52,4 +52,33 @@ class SolrDefault extends \VuFind\RecordDriver\SolrDefault implements { use \VuFind\Log\LoggerAwareTrait; use SolrDefaultFincTrait; + + /** + * Index extension used for dynamic fields + * + * @var string + */ + protected $indexExtension = ''; + + /** + * Constructor + * + * @param \Zend\Config\Config $mainConfig VuFind main configuration (omit for + * built-in defaults) + * @param \Zend\Config\Config $recordConfig Record-specific configuration file + * (omit to use $mainConfig as $recordConfig) + * @param \Zend\Config\Config $searchSettings Search-specific configuration file + */ + public function __construct($mainConfig = null, $recordConfig = null, + $searchSettings = null + ) + { + parent::__construct($mainConfig, $recordConfig, $searchSettings); + + if (isset($this->mainConfig->CustomIndex->indexExtension)) { + $this->indexExtension = $this->mainConfig->CustomIndex->indexExtension; + } else { + $this->debug('Index extension for custom index not set!'); + } + } } diff --git a/module/finc/src/finc/RecordDriver/SolrDefaultFincTrait.php b/module/finc/src/finc/RecordDriver/SolrDefaultFincTrait.php index 0ec2e010c52d06a3f9b346350d31ffd1685166bf..2e27f68e0f28b284c103e5e742d891fed3b7760d 100644 --- a/module/finc/src/finc/RecordDriver/SolrDefaultFincTrait.php +++ b/module/finc/src/finc/RecordDriver/SolrDefaultFincTrait.php @@ -50,6 +50,18 @@ use VuFindSearch\ParamBag; trait SolrDefaultFincTrait { + /** + * Get all call numbers associated with the record (empty string if none). + * + * @return array + */ + public function getCallNumbers() + { + return isset($this->fields['callnumber_' . $this->indexExtension]) + ? $this->fields['callnumber_' . $this->indexExtension] + : parent::getCallNumbers(); + } + /** * Return the custom index field local_heading if indexExtension is set. * If indexExtension is set local_heading_{indexExtension} is returned, diff --git a/module/finc/src/finc/RecordDriver/SolrMarcFinc.php b/module/finc/src/finc/RecordDriver/SolrMarcFinc.php index 593d00a7f4a9dcf4d35599560c68b97d3ab2037f..13422d421147c490f817cc71441036e800facb8c 100644 --- a/module/finc/src/finc/RecordDriver/SolrMarcFinc.php +++ b/module/finc/src/finc/RecordDriver/SolrMarcFinc.php @@ -77,6 +77,7 @@ class SolrMarcFinc extends SolrMarc { parent::__construct($mainConfig, $recordConfig, $searchSettings); + // get the isil set in InstitutionInfo in config.ini if (isset($mainConfig->InstitutionInfo->isil) && count($mainConfig->InstitutionInfo->isil) > 0 ) { @@ -85,26 +86,5 @@ class SolrMarcFinc extends SolrMarc $this->debug('InstitutionInfo setting: isil is missing.'); } - if (isset($this->mainConfig->CustomSite->namespace)) { - // map for marc fields - $map = [ - 'che' => '971', - 'hgb' => '979', - 'hfbk' => '978', - 'hfm' => '977', - 'hmt' => '970', - 'htw' => '973', - 'htwk' => '974', - 'tuf' => '972', - 'ubl' => '969', - 'zit' => '976', - 'zwi' => '975', - ]; - $this->localMarcFieldOfLibrary - = isset($map[$this->mainConfig->CustomSite->namespace]) ? - $map[$this->mainConfig->CustomSite->namespace] : null; - } else { - $this->debug('Namespace setting for localMarcField is missing.'); - } } } \ No newline at end of file diff --git a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php index 381e4f21ec63a187914f952ac09dbbc97ad4924e..282ae50c007957d21bf5f4e14ed7d01df18057d2 100644 --- a/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php +++ b/module/finc/src/finc/RecordDriver/SolrMarcFincTrait.php @@ -168,6 +168,7 @@ trait SolrMarcFincTrait * * @return array Return fields. * @access public + * @deprecated (https://intern.finc.info/issues/6324) * @link https://intern.finc.info/issues/2639 */ public function getLocalCallnumber() @@ -198,6 +199,7 @@ trait SolrMarcFincTrait * * @return array * @access protected + * @deprecated (https://intern.finc.info/issues/6324) */ protected function getLocalCallnumbersByLibrary() { @@ -237,7 +239,7 @@ trait SolrMarcFincTrait protected function getLocalGivenCallnumber() { $retval = []; - $arrSignatur = $this->getFieldArray($this->localMarcFieldOfLibrary, ['i']); + $arrSignatur = $this->getFieldArray($this->getLocalMarcFieldOfLibrary(), ['i']); foreach ($arrSignatur as $signatur) { foreach ($this->isil as $code) { @@ -425,8 +427,8 @@ trait SolrMarcFincTrait */ protected function getLocalAccessNumber() { - if (null != $this->localMarcFieldOfLibrary) { - return $this->getFieldArray($this->localMarcFieldOfLibrary, ['o']); + if (null != $this->getLocalMarcFieldOfLibrary()) { + return $this->getFieldArray($this->getLocalMarcFieldOfLibrary(), ['o']); } return []; } @@ -483,8 +485,8 @@ trait SolrMarcFincTrait */ public function getLocalFormat() { - if (null != $this->localMarcFieldOfLibrary) { - if (count($localformat = $this->getFieldArray($this->localMarcFieldOfLibrary, ['c'])) > 0) { + if (null != $this->getLocalMarcFieldOfLibrary()) { + if (count($localformat = $this->getFieldArray($this->getLocalMarcFieldOfLibrary(), ['c'])) > 0) { foreach ($localformat as &$line) { if ($line != "") { $line = trim('local_format_' . strtolower($line)); @@ -497,6 +499,39 @@ trait SolrMarcFincTrait return []; } + /** + * Returns lazily the library specific Marc field configured by CustomIndex + * settings in config.ini + * + * @return mixed + * @link https://intern.finc.info/issues/7063 + */ + protected function getLocalMarcFieldOfLibrary() + { + // return the library specific Marc field if its already set + if ($this->localMarcFieldOfLibrary != null) { + return $this->localMarcFieldOfLibrary; + } + + // get the library specific Marc field configured by CustomIndex settings in + // config.ini + if (isset($this->mainConfig->CustomIndex->localMarcFieldOfLibraryNamespace)) { + $namespace = $this->mainConfig->CustomIndex->localMarcFieldOfLibraryNamespace; + if (isset($this->mainConfig->CustomIndex->localMarcFieldOfLibraryMapping)) { + foreach ($this->mainConfig->CustomIndex->localMarcFieldOfLibraryMapping as $mappingValue) { + list ($ns, $fn) = explode(':', $mappingValue); + if (trim($ns) == trim($namespace)) { + $this->localMarcFieldOfLibrary = $fn; + break; + } + } + } + } else { + $this->debug('Namespace setting for localMarcField is missing.'); + } + return $this->localMarcFieldOfLibrary; + } + /** * Return a local notice via an consortial defined field with subfield $k. * Marc field depends on library e.g. 970 for HMT or 972 for TUBAF. @@ -507,8 +542,8 @@ trait SolrMarcFincTrait */ protected function getLocalNotice() { - if (null != $this->localMarcFieldOfLibrary) { - return $this->getFieldArray($this->localMarcFieldOfLibrary, ['k']); + if (null != $this->getLocalMarcFieldOfLibrary()) { + return $this->getFieldArray($this->getLocalMarcFieldOfLibrary(), ['k']); } return []; } @@ -667,8 +702,8 @@ trait SolrMarcFincTrait */ protected function getPurchaseInformation() { - if (null != $this->localMarcFieldOfLibrary) { - if ($this->getFirstFieldValue($this->localMarcFieldOfLibrary, ['m']) == 'e') { + if (null != $this->getLocalMarcFieldOfLibrary()) { + if ($this->getFirstFieldValue($this->getLocalMarcFieldOfLibrary(), ['m']) == 'e') { return true; } } @@ -700,9 +735,9 @@ trait SolrMarcFincTrait protected function getUDKs() { $array = []; - if (null != $this->localMarcFieldOfLibrary) { + if (null != $this->getLocalMarcFieldOfLibrary()) { - $udk = $this->getMarcRecord()->getFields($this->localMarcFieldOfLibrary); + $udk = $this->getMarcRecord()->getFields($this->getLocalMarcFieldOfLibrary()); // if not return void value if (!$udk) { return $array; diff --git a/module/finc/src/finc/RecordDriver/SolrMarcRemoteFinc.php b/module/finc/src/finc/RecordDriver/SolrMarcRemoteFinc.php index ce8fe5b4f26cd4e768af0af4ee81e5e71a8e0ef6..7cd6d44a6ad325740998c552ec6a5160baac5bb5 100644 --- a/module/finc/src/finc/RecordDriver/SolrMarcRemoteFinc.php +++ b/module/finc/src/finc/RecordDriver/SolrMarcRemoteFinc.php @@ -86,27 +86,5 @@ class SolrMarcRemoteFinc extends SolrMarcRemote } else { $this->debug('InstitutionInfo setting: isil is missing.'); } - - if (isset($this->mainConfig->CustomSite->namespace)) { - // map for marc fields - $map = [ - 'che' => '971', - 'hgb' => '979', - 'hfbk' => '978', - 'hfm' => '977', - 'hmt' => '970', - 'htw' => '973', - 'htwk' => '974', - 'tuf' => '972', - 'ubl' => '969', - 'zit' => '976', - 'zwi' => '975', - ]; - $this->localMarcFieldOfLibrary - = isset($map[$this->mainConfig->CustomSite->namespace]) ? - $map[$this->mainConfig->CustomSite->namespace] : null; - } else { - $this->debug('Namespace setting for localMarcField is missing.'); - } } } diff --git a/themes/finc/scss/default.scss b/themes/finc/scss/default.scss index 56772ee60a7f74d2b6ec2aeeb5aba6edfcfde3c8..e9d557ae0261ad4c3b18aa2030a473e9017d9221 100644 --- a/themes/finc/scss/default.scss +++ b/themes/finc/scss/default.scss @@ -45,10 +45,33 @@ } // RECORD VIEW +// TABS +// Table width +.tabs-content table { + width:100%; +} +// Holdings +// Insert line break before Vormerken buttons +.holdings-tab { + line-height: 1.75rem; + td { + vertical-align: top; + } + td span:after { + content: "\a "; + white-space: pre; + } + // remove excessive bottom margins above order buttons + ul {margin-bottom: 0} + .button { + margin-top: .5rem; + } +} // Internformat .pace-car th {min-width: 10%} -// Footer + +// FOOTER .powered-by { img { height: 1.75em; diff --git a/themes/finc/templates/RecordDriver/SolrAI/core.phtml b/themes/finc/templates/RecordDriver/SolrAI/core.phtml index c8f694fe552b3ac064eeeb0bd9f2f596bcc92da4..333ade8e09afb7091e41c904531076e342eef2cf 100644 --- a/themes/finc/templates/RecordDriver/SolrAI/core.phtml +++ b/themes/finc/templates/RecordDriver/SolrAI/core.phtml @@ -137,11 +137,10 @@ if($loggedin = $this->auth()->isLoggedIn()) { <tr> <th><?=$this->transEsc('In')?>: </th> <td> - <? $issns = $aidatain['issns']; if (!empty($issns)): ?> + <? $jtitle = $aidatain['jtitle']; $issns = $aidatain['issns']; if (!empty($issns)): ?> <a href="<?=$this->record($this->driver)->getLinkISN($issns)?>"> - <? $jtitle = $aidatain['jtitle']; - if (!empty($jtitle)): ?><?=$this->escapeHtml($jtitle)?><? endif; ?> - </a><? endif; ?><? $volume = $aidatain['volume']; if (!empty($volume)): ?>, <?=$this->escapeHtml($volume) ?><? endif; ?><? $date = $aidatain['date']; if (!empty($date)): ?><? if (empty($volume)): ?>, <? endif; ?>(<?=$this->escapeHtml($date) ?>)<? endif; ?><? $issue = $aidatain['issue']; if (!empty($issue)): ?>, <?=$this->escapeHtml($issue) ?><? endif; ?><? $pages = $aidatain['pages']; if (!empty($pages)): ?>, <?=$this->transEsc('p.')?> <?=$this->escapeHtml($pages) ?><? endif; ?> + <? if (!empty($jtitle)): ?><?=$this->escapeHtml($jtitle)?><? endif; ?> + </a><? elseif (!empty($jtitle)): ?><?=$this->escapeHtml($jtitle)?><? endif; ?><? $volume = $aidatain['volume']; if (!empty($volume)): ?><? if (empty($jtitle)): ?>, <? endif; ?><?=$this->escapeHtml($volume) ?><? endif; ?><? $date = $aidatain['date']; if (!empty($date)): ?><? if (empty($volume)): ?>, <? endif; ?>(<?=$this->escapeHtml($date) ?>)<? endif; ?><? $issue = $aidatain['issue']; if (!empty($issue)): ?>, <?=$this->escapeHtml($issue) ?><? endif; ?><? $pages = $aidatain['pages']; if (!empty($pages)): ?>, <?=$this->transEsc('p.')?> <?=$this->escapeHtml($pages) ?><? endif; ?> </td> </tr> <? endif; ?> diff --git a/themes/finc/templates/RecordTab/holdingsils.phtml b/themes/finc/templates/RecordTab/holdingsils.phtml new file mode 100644 index 0000000000000000000000000000000000000000..2fbb8267d4a842b750cffc23781d6beaee33a49d --- /dev/null +++ b/themes/finc/templates/RecordTab/holdingsils.phtml @@ -0,0 +1,168 @@ +<!-- recordTab - HOLDINGSILS.phtml --> +<? + // Set up convenience variables: + $account = $this->auth()->getManager(); + $user = $account->isLoggedIn(); + $holdings = $this->driver->getRealTimeHoldings(); + $openUrl = $this->openUrl($this->driver, 'holdings'); + $openUrlActive = $openUrl->isActive(); + // Account for replace_other_urls setting + $urls = $this->record($this->driver)->getLinkDetails($openUrlActive); + $offlineMode = $this->ils()->getOfflineMode(); + // Set page title. + $this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb()); +?> + +<?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?> + +<? if ($offlineMode == "ils-offline"): ?> + <div data-alert class="alert-box warning" tabindex="0" aria-live="assertive" role="dialogalert"> + <h2><?=$this->transEsc('ils_offline_title')?></h2> + <p><strong><?=$this->transEsc('ils_offline_status')?></strong></p> + <p><?=$this->transEsc('ils_offline_holdings_message')?></p> + <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?> + <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p> + </div> +<? endif; ?> +<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings)) || $this->ils()->getTitleHoldsMode() == 'driver'): ?> + <? if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?> + <? if (!$user): ?> + <div data-alert class="alert-box info" tabindex="0" aria-live="assertive" role="dialogalert"> + <a href="<?=$this->recordLink()->getTabUrl($this->driver, 'Holdings')?>?login=true&catalogLogin=true"><?=$this->transEsc("Login")?></a> <?=$this->transEsc("hold_login")?> + </div> + <? elseif (!$user->cat_username): ?> + <div data-alert class="alert-box info" tabindex="0" aria-live="assertive" role="dialogalert"> + <?=$this->translate("hold_profile_html", array('%%url%%' => $this->recordLink()->getTabUrl($this->driver, 'Holdings') . '?catalogLogin=true'))?> + </div> + <? endif; ?> + <? endif; ?> +<? endif; ?> +<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?> + <a class="placehold modal-link button small" title="<?=$this->transEsc('request_place_text')?>" href="<?=$this->recordLink()->getRequestUrl($holdingTitleHold)?>"><i class="fa fa-flag"></i> <?=$this->transEsc('title_hold_place')?></a> +<? endif; ?> +<? if (!empty($urls) || $openUrlActive): ?> + <h3><?=$this->transEsc("Internet")?></h3> + <? if (!empty($urls)): ?> + <? foreach ($urls as $current): ?> + <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/> + <? endforeach; ?> + <? endif; ?> + <? if ($openUrlActive): ?><?=$openUrl->renderTemplate()?><? endif; ?> +<? endif; ?> +<? foreach ($holdings as $holding): ?> + <h3> + <? $locationText = $this->transEsc('location_' . $holding['location'], array(), $holding['location']); ?> + <? if (isset($holding['locationhref']) && $holding['locationhref']): ?> + <a href="<?=$holding['locationhref']?>" target="_blank"><?=$locationText?></a> + <? else: ?> + <?=$locationText?> + <? endif; ?> + </h3> +<table class="table" summary="<?=$this->transEsc('Holdings details from')?> <?=$this->transEsc($holding['location'])?>"> + <tr> + <th><?=$this->transEsc("Availability")?></th> + <th><?=$this->transEsc("Details")?></th> + </tr> + <? foreach ($holding['items'] as $row): ?> + <? $check = (isset($row['check']) && $row['check']); ?> + <? $checkStorageRetrievalRequest = (isset($row['checkStorageRetrievalRequest']) && $row['checkStorageRetrievalRequest']); ?> + <? $checkILLRequest = (isset($row['checkILLRequest']) && $row['checkILLRequest']); ?> + <? if (isset($row['barcode']) && $row['barcode'] != ""): ?> + <tr vocab="http://schema.org/" typeof="Offer"> + <td> + <? if ($row['availability']): ?> + <? /* Begin Available Items (Holds) */ ?> + <span class="label success"><?=$this->transEsc("Available")?><link property="availability" href="http://schema.org/InStock" /></span> + <? else: ?> + <? /* Begin Unavailable Items (Recalls) */ ?> + <span class="label alert"><?=empty($row['status'])?$this->transEsc("Unavailable"):$this->transEsc($row['status'])?><link property="availability" href="http://schema.org/OutOfStock" /></span> + <? endif; ?> + </td> + <td> + <? if ($row['reserve'] == "Y"): ?> + <link property="availability" href="http://schema.org/InStoreOnly" /> + <?=$this->transEsc("On Reserve - Ask at Circulation Desk")?><br /> + <? endif; ?> + <? if (isset($row['use_unknown_message']) && $row['use_unknown_message']): ?> + <span class="label secondary"><?=$this->transEsc("status_unknown_message")?></span> + <? else: ?> + <? if (isset($row['callnumber'])): ?> + <span class="callnumber"><?=$this->transEsc("Call Number")?>: <?=$row['callnumber']?></span> + <? endif; ?> + <? if (isset($row['storage']) && $row['storage'] != 'Unknown'): ?> + <span class="storage"><?=$this->transEsc("Location")?>: <?=$row['storage']?></span> + <? endif; ?> + <? if ($row['availability']): ?> + <? /* Begin Available Items (Holds) */ ?> + <? if (isset($row['notes'])): ?> + <span class="notes"><?=$this->transEsc("Notes")?>:</span> + <ul class="notes"> + <? foreach ($row['notes'] as $note): ?> + <li><?=$note?></li> + <? endforeach; ?> + </ul> + <? endif; ?> + <? if (isset($row['link']) && $row['link']): ?> + <a class="<?=$check ? 'checkRequest ' : ''?>inlineblock modal-link placehold hide-for-print" href="<?=$this->recordLink()->getRequestUrl($row['link'])?>" title="<?=$this->transEsc($check ? "Check Hold" : "Place a Hold")?>"><i class="fa fa-flag"></i> <?=$this->transEsc($check ? "Check Hold" : "Place a Hold")?></a> + <? endif; ?> + <? if (isset($row['storageRetrievalRequestLink']) && $row['storageRetrievalRequestLink']): ?> + <a class="<?=$checkStorageRetrievalRequest ? 'checkStorageRetrievalRequest ' : ''?>modal-link placeStorageRetrievalRequest" href="<?=$this->recordLink()->getRequestUrl($row['storageRetrievalRequestLink'])?>" title="<?=$this->transEsc($checkStorageRetrievalRequest ? "storage_retrieval_request_check_text" : "storage_retrieval_request_place_text")?>"><i class="fa fa-flag"></i> <?=$this->transEsc($checkStorageRetrievalRequest ? "storage_retrieval_request_check_text" : "storage_retrieval_request_place_text")?></a> + <? endif; ?> + <? if (isset($row['ILLRequestLink']) && $row['ILLRequestLink']): ?> + <a class="<?=$checkILLRequest ? 'checkILLRequest ' : ''?>inlineblock modal-link placeILLRequest" href="<?=$this->recordLink()->getRequestUrl($row['ILLRequestLink'])?>" title="<?=$this->transEsc($checkILLRequest ? "ill_request_check_text" : "ill_request_place_text")?>"><i class="fa fa-flag"></i> <?=$this->transEsc($checkILLRequest ? "ill_request_check_text" : "ill_request_place_text")?></a> + <? endif; ?> + <? else: ?> + <? /* Begin Unavailable Items (Recalls) */ ?> + <span class="label alert"><?=empty($row['status'])?$this->transEsc("Unavailable"):$this->transEsc($row['status'])?><link property="availability" href="http://schema.org/OutOfStock" /></span> + <? if (isset($row['returnDate']) && $row['returnDate']): ?>– <span class="small"><?=$this->escapeHtml($row['returnDate'])?></span><? endif; ?> + <? if (isset($row['duedate']) && $row['duedate']): ?> + – <span class="small"><?=$this->transEsc("Due")?>: <?=$this->escapeHtml($row['duedate'])?></span> + <? endif; ?> + <? if (isset($row['requests_placed']) && $row['requests_placed'] > 0): ?> + <span><?=$this->transEsc("Requests")?>: <?=$this->escapeHtml($row['requests_placed'])?></span> + <? endif; ?> + <? if (isset($row['link']) && $row['link']): ?> + <a class="<?=$check ? 'checkRequest' : ''?> modal-link inlineblock placehold hide-for-print" href="<?=$this->recordLink()->getRequestUrl($row['link'])?>"><i class="fa fa-flag"></i> <?=$this->transEsc($check ? "Check Recall" : "Recall This")?></a> + <? endif; ?> + <? endif; ?> + <? endif; ?> + <? /* Embed item structured data: library, barcode, call number */ ?> + <? if ($row['location']): ?> + <meta property="seller" content="<?=$this->escapeHtmlAttr($row['location'])?>" /> + <? endif; ?> + <? if ($row['barcode']): ?> + <meta property="serialNumber" content="<?=$this->escapeHtmlAttr($row['barcode'])?>" /> + <? endif; ?> + <? if ($row['callnumber']): ?> + <meta property="sku" content="<?=$this->escapeHtmlAttr($row['callnumber'])?>" /> + <? endif; ?> + <? /* Declare that the item is to be borrowed, not for sale */ ?> + <link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut" /> + <link property="itemOffered" href="#record" /> + </td> + </tr> + <? endif; ?> + <? endforeach; ?> + <? if (!empty($holding['purchase_history'])): ?> + <tr> + <th><?=$this->transEsc("Most Recent Received Issues")?>:</th> + <td> + <? foreach ($holding['purchase_history'] as $current): ?> + <?=$this->escapeHtml($current['issue'])?><br/> + <? endforeach; ?> + </td> + </tr> + <? endif; ?> +</table> +<? endforeach; ?> + +<? $history = $this->driver->getRealTimeHistory(); ?> +<? if (is_array($history) && !empty($history)): ?> +<h3><?=$this->transEsc("Most Recent Received Issues")?></h3> +<table class="table"> + <? foreach ($history as $row): ?> + <tr><td><?=$this->escapeHtml($row['issue'])?></td></tr> + <? endforeach; ?> +</table> +<? endif; ?> +<!-- recordTab - HOLDINGSILS.phtml end --> \ No newline at end of file diff --git a/themes/finc/templates/record/view.phtml b/themes/finc/templates/record/view.phtml index 13e1d1a98ca0541ace1c7eb1fcac3822a9227d7b..e631a70fe9e35b839b107c5f08aac53f23e9bfc5 100644 --- a/themes/finc/templates/record/view.phtml +++ b/themes/finc/templates/record/view.phtml @@ -81,7 +81,7 @@ <div class="tabs-content" id="record-tabs"> <? if (!$this->ajaxTabs || !isset($activeTabObj) || !$activeTabObj->supportsAjax()): ?> - <div class="content active" id="<?=$this->activeTab?>-tab"> + <div class="content active <?=$this->activeTab?>-tab"> <?=isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : ''?> </div> <? endif; ?> diff --git a/themes/foundation5/templates/record/view.phtml b/themes/foundation5/templates/record/view.phtml index db711cfe888075ecb686866e8627c6865547e171..41dbd12e18357ebfba5dec9cb27b5883ff34afa3 100644 --- a/themes/foundation5/templates/record/view.phtml +++ b/themes/foundation5/templates/record/view.phtml @@ -81,7 +81,7 @@ $this->layout()->title = $this->driver->getShortTitle(); <div class="tabs-content" id="record-tabs"> <? if (!$this->ajaxTabs || !isset($activeTabObj) || !$activeTabObj->supportsAjax()): ?> - <div class="content active" id="<?=$this->activeTab?>-tab"> + <div class="content active <?=$this->activeTab?>-tab"> <?=isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : ''?> </div> <? endif; ?>