diff --git a/config/vufind/config.ini b/config/vufind/config.ini index ee89f318f56..93dd5c50276 100644 --- a/config/vufind/config.ini +++ b/config/vufind/config.ini @@ -2158,11 +2158,18 @@ includeSchemaOrgMetadata = true [AlphaBrowse] ; This setting controls how many headings are displayed on each page of results: page_size = 20 + ; How many headings to show before the match (or the spot where the match ; would have been found). Default is 0 for backwards compatibility. rows_before = 0 + +; For topic browse, controls the separator to place between terms when +; displaying topic headings. Defaults to " > " if not set. +;topic_browse_separator = " > " + ; highlight the match row (or spot where match would have been)? default false highlighting = false + ; AlphaBrowse results are not subject to dynamic filtering. If you have default ; filters defined in searches.ini, you most likely will want to disable them when ; users navigate from browse results to search results, to ensure that the result @@ -2171,12 +2178,14 @@ highlighting = false ; rather than NARROW search results, you will likely want to change this setting ; to false to avoid inconsistencies. bypass_default_filters = true + ; SEE ALSO: the General/includeAlphaBrowse setting in searchbox.ini, for including ; alphabrowse options in the main search drop-down options. ; This section controls the order and content of the browse type menu in the ; Alphabetic Browse module. The key is the browse index to use, the value is the ; string to display to the user (subject to translation). + [AlphaBrowse_Types] topic = "By Topic" author = "By Author" diff --git a/import/browse-indexing.jar b/import/browse-indexing.jar index 0fad614df73..6961817e0d9 100644 Binary files a/import/browse-indexing.jar and b/import/browse-indexing.jar differ diff --git a/import/index_java/src/org/vufind/index/FieldSpecTools.java b/import/index_java/src/org/vufind/index/FieldSpecTools.java index 1e780e9acb4..98b996663a0 100644 --- a/import/index_java/src/org/vufind/index/FieldSpecTools.java +++ b/import/index_java/src/org/vufind/index/FieldSpecTools.java @@ -32,6 +32,8 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.Matcher; import java.util.Set; /** @@ -137,4 +139,35 @@ protected static final String getFieldData(DataField dataField, String subfieldC return result.length() > 0 ? result.toString() : null; } + + + private static Pattern unicodeEscape = Pattern.compile("(?i)\\\\u([0-9a-f]{4})"); + + /** + * Retrieves all subfields from a record, separated by a specified UTF-8 delimiter. + * + * This method takes a MARC record and a specification for the fields to extract, and returns + * a set of strings representing the subfields found, concatenated with a specified separator. + * The separator can include Unicode escape sequences, which will be converted to their corresponding + * characters. + * + * @param record the MARC record from which to extract subfields. + * @param fieldSpec a string specifying the fields and subfields to retrieve. + * @param separatorWithEscapes a string representing the delimiter to use between subfields, + * which can contain Unicode escape sequences in the format \\uXXXX. + * @return a set of strings with the concatenated subfields, separated by the given delimiter. + */ + public static Set getAllSubfieldsUTF8Delimited(final Record record, String fieldSpec, String separatorWithEscapes) + { + StringBuilder separator = new StringBuilder(separatorWithEscapes); + Matcher m = unicodeEscape.matcher(separator); + + while (m.find()) { + int codepoint = Integer.parseInt(m.group(1), 16); + separator.replace(m.start(), m.end(), new String(Character.toChars(codepoint))); + m.reset(); + } + + return org.solrmarc.index.SolrIndexer.instance().getAllSubfields(record, fieldSpec, separator.toString()); + } } diff --git a/import/marc.properties b/import/marc.properties index 41cbab91fe7..7600e95734f 100644 --- a/import/marc.properties +++ b/import/marc.properties @@ -92,6 +92,7 @@ callnumber-sort = custom, getLCSortable(099ab:090ab:050ab) callnumber-raw = 099ab:090ab:050ab topic = custom, getAllSubfields(600:610:611:630:650:653:656, " ") +topic_browse = custom, getAllSubfieldsUTF8Delimited(600:610:611:630:650:653:656, "\u2002") genre = custom, getAllSubfields(655, " ") geographic = custom, getAllSubfields(651, " ") era = custom, getAllSubfields(648, " ") diff --git a/index-alphabetic-browse.bat b/index-alphabetic-browse.bat index b150375e829..e50ae1e336a 100644 --- a/index-alphabetic-browse.bat +++ b/index-alphabetic-browse.bat @@ -86,7 +86,7 @@ mkdir "%index_dir%" rem These parameters should match the ones in solr/vufind/biblio/conf/solrconfig.xml - BrowseRequestHandler call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse hierarchy hierarchy_browse call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse title title_fullStr 1 "-Dbib_field_iterator=org.vufind.solr.indexing.StoredFieldIterator -Dsortfield=title_sort -Dvaluefield=title_fullStr -Dbrowse.normalizer=org.vufind.util.TitleNormalizer" -call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse topic topic_browse +call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse topic topic_browse 0 "-Dbrowse.normalizer=org.vufind.util.TopicNormalizer" call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse author author_browse call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse lcc callnumber-raw 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer" call %VUFIND_HOME%\index-alphabetic-browse.bat build_browse dewey dewey-raw 1 "-Dbrowse.normalizer=org.vufind.util.DeweyCallNormalizer" diff --git a/index-alphabetic-browse.sh b/index-alphabetic-browse.sh index 5cdad59e2c8..e61c62ba496 100755 --- a/index-alphabetic-browse.sh +++ b/index-alphabetic-browse.sh @@ -131,7 +131,7 @@ function build_browse # These parameters should match the ones in solr/vufind/biblio/conf/solrconfig.xml - BrowseRequestHandler build_browse "hierarchy" "hierarchy_browse" build_browse "title" "title_fullStr" 1 "-Dbib_field_iterator=org.vufind.solr.indexing.StoredFieldIterator -Dsortfield=title_sort -Dvaluefield=title_fullStr -Dbrowse.normalizer=org.vufind.util.TitleNormalizer" -build_browse "topic" "topic_browse" +build_browse "topic" "topic_browse" 0 "-Dbrowse.normalizer=org.vufind.util.TopicNormalizer" build_browse "author" "author_browse" build_browse "lcc" "callnumber-raw" 1 "-Dbrowse.normalizer=org.vufind.util.LCCallNormalizer" build_browse "dewey" "dewey-raw" 1 "-Dbrowse.normalizer=org.vufind.util.DeweyCallNormalizer" diff --git a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php index b7fa1b7995c..75f769f1c3c 100644 --- a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php +++ b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php @@ -177,6 +177,11 @@ protected function addResultsToView( $view->prevpage = $page - 1; } } + + if ($view->source === 'topic') { + $this->applyTopicDelimiters($result); + } + $view->result = $result; // set up highlighting: page 0 contains match location @@ -185,6 +190,26 @@ protected function addResultsToView( } } + /** + * Applies topic delimiters to the 'heading' field of each item in the browse results. + * + * @param array $result The result array containing 'Browse' items to be modified. + * + * @return void + */ + protected function applyTopicDelimiters(&$result): void + { + $config = $this->getConfig(); + + foreach ($result['Browse']['items'] as &$item) { + $item['heading'] = str_replace( + "\u{2002}", + ($config->AlphaBrowse->topic_browse_separator ?? ' > '), + $item['heading'] + ); + } + } + /** * Apply highlighting settings to the view based on the result set. * diff --git a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php index ca241e0b8b4..3be01b3fca0 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php @@ -84,7 +84,7 @@ public function getUrl($source, $item) $query = [ 'type' => ucwords($source) . 'Browse', - 'lookfor' => $this->escapeForSolr($item['heading']), + 'lookfor' => $this->escapeForSolr($item['sort_key']), ]; if ($this->options['bypass_default_filters'] ?? true) { $query['dfApplied'] = 1; diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/AlphaBrowseTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/AlphaBrowseTest.php index 3d06796fc09..2f61c0b9bb5 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/AlphaBrowseTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/AlphaBrowseTest.php @@ -91,7 +91,7 @@ public function testGetUrlWithMultipleRecordsAndDefaultSettings(): void ] ); $helper = $this->getHelper($url); - $item = ['heading' => 'xyzzy', 'count' => 2]; + $item = ['heading' => 'xyzzy', 'sort_key' => 'xyzzy', 'count' => 2]; $this->assertEquals('foo', $helper->getUrl('title', $item)); } @@ -112,7 +112,7 @@ public function testGetUrlWithSingleRecordAndDefaultSettings(): void ] ); $helper = $this->getHelper($url); - $item = ['heading' => 'xyzzy', 'count' => 1]; + $item = ['heading' => 'xyzzy', 'sort_key' => 'xyzzy', 'count' => 1]; $this->assertEquals('foo', $helper->getUrl('title', $item)); } @@ -131,7 +131,7 @@ public function testGetUrlEscapesQuotes(): void ] ); $helper = $this->getHelper($url); - $item = ['heading' => '"xyzzy"', 'count' => 100]; + $item = ['heading' => '"xyzzy"', 'sort_key' => '"xyzzy"', 'count' => 100]; $this->assertEquals('foo', $helper->getUrl('title', $item)); } @@ -150,7 +150,7 @@ public function testGetUrlAppliesFilterBypassSetting(): void ] ); $helper = $this->getHelper($url, ['bypass_default_filters' => false]); - $item = ['heading' => 'xyzzy', 'count' => 100]; + $item = ['heading' => 'xyzzy', 'sort_key' => 'xyzzy', 'count' => 100]; $this->assertEquals('foo', $helper->getUrl('title', $item)); } } diff --git a/solr/vufind/biblio/conf/schema.xml b/solr/vufind/biblio/conf/schema.xml index 87313ab9cb5..ca8165d3a09 100644 --- a/solr/vufind/biblio/conf/schema.xml +++ b/solr/vufind/biblio/conf/schema.xml @@ -265,7 +265,6 @@ - diff --git a/solr/vufind/jars/browse-handler.jar b/solr/vufind/jars/browse-handler.jar index 89401de8c4c..542b8e086a8 100644 Binary files a/solr/vufind/jars/browse-handler.jar and b/solr/vufind/jars/browse-handler.jar differ