From d67484d7e7a9287b5ef38518dcb929a4d55549e1 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Fri, 18 Mar 2016 10:45:55 -0400 Subject: [PATCH] =?UTF-8?q?Improved=20author=20indexing.=20-=20Allows=20mu?= =?UTF-8?q?ltiple=20primary=20authors,=20and=20better=20description=20of?= =?UTF-8?q?=20contributor=20roles.=20-=20Based=20on=20initial=20work=20by?= =?UTF-8?q?=20Ronan=20McHugh=20and=20the=20National=20Library=20of=20Irela?= =?UTF-8?q?nd=20team=20(VUFIND-542).=20-=20Expanded=20with=20significant?= =?UTF-8?q?=20assistance=20by=20Andr=C3=A9=20Lahmann.=20-=20For=20more=20d?= =?UTF-8?q?etailed=20development=20history,=20see=20pull=20request=20#354.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/vufind/Collection.ini | 2 +- config/vufind/author-classification.ini | 10 + config/vufind/facets.ini | 2 +- config/vufind/searches.ini | 4 +- config/vufind/searchspecs.yaml | 15 + import/index_scripts/author.bsh | 400 ++++++++++++++++++ import/marc.properties | 18 +- import/marc_local.properties | 11 + import/xsl/doaj.xsl | 19 +- import/xsl/dspace.xsl | 21 +- import/xsl/gsdl.xsl | 21 +- import/xsl/ndltd.xsl | 21 +- import/xsl/nlm_ojs.xsl | 21 +- import/xsl/ojs.xsl | 19 +- import/xsl/vudl_FOXML.xsl | 19 +- module/VuFind/src/VuFind/Config/Upgrade.php | 63 ++- .../VuFind/Controller/BrowseController.php | 2 +- .../VuFind/src/VuFind/Recommend/DPLATerms.php | 2 +- module/VuFind/src/VuFind/RecordDriver/EDS.php | 13 +- module/VuFind/src/VuFind/RecordDriver/EIT.php | 42 +- .../src/VuFind/RecordDriver/Pazpar2.php | 25 +- .../VuFind/src/VuFind/RecordDriver/Primo.php | 26 +- .../src/VuFind/RecordDriver/SolrDefault.php | 200 +++++++-- .../src/VuFind/RecordDriver/SolrMarc.php | 15 - .../VuFind/src/VuFind/RecordDriver/Summon.php | 35 +- .../src/VuFind/RecordDriver/WorldCat.php | 10 +- .../VuFind/src/VuFind/Search/Base/Params.php | 50 ++- .../VuFind/src/VuFind/Search/Solr/Params.php | 6 +- .../VuFind/Search/SolrAuthorFacets/Params.php | 2 +- .../Search/SolrAuthorFacets/Results.php | 8 +- .../src/VuFind/Search/UrlQueryHelper.php | 6 +- .../src/VuFind/View/Helper/Root/Browse.php | 2 +- .../VuFind/tests/fixtures/misc/testbug2.json | 3 +- .../src/VuFindTest/Config/UpgradeTest.php | 25 ++ .../fixtures/solr/response/morelikethis | 2 +- .../fixtures/solr/response/multi-record | 2 +- solr/biblio/conf/schema.xml | 31 +- .../templates/Recommend/CatalogResults.phtml | 14 +- .../templates/Recommend/RandomRecommend.phtml | 14 +- .../templates/Recommend/SummonResults.phtml | 11 +- .../RecordDriver/Pazpar2/result-list.phtml | 13 +- .../SolrDefault/collection-info.phtml | 14 +- .../SolrDefault/collection-record.phtml | 12 +- .../RecordDriver/SolrDefault/core.phtml | 32 +- .../RecordDriver/SolrDefault/list-entry.phtml | 6 +- .../SolrDefault/result-list.phtml | 13 +- .../RecordTab/similaritemscarousel.phtml | 4 +- .../templates/Related/Similar.phtml | 4 +- .../templates/ajax/resultgooglemapinfo.phtml | 6 +- .../templates/myresearch/checkedout.phtml | 4 +- .../templates/myresearch/holds.phtml | 4 +- .../templates/myresearch/illrequests.phtml | 4 +- .../myresearch/storageretrievalrequests.phtml | 4 +- .../RecordDriver/Pazpar2/result-list.phtml | 12 +- .../SolrDefault/collection-record.phtml | 14 +- .../RecordDriver/SolrDefault/core.phtml | 14 +- .../RecordDriver/SolrDefault/list-entry.phtml | 8 +- .../SolrDefault/result-list.phtml | 12 +- .../RecordTab/similaritemscarousel.phtml | 4 +- .../templates/myresearch/checkedout.phtml | 4 +- .../templates/myresearch/holds.phtml | 4 +- 61 files changed, 950 insertions(+), 454 deletions(-) create mode 100644 config/vufind/author-classification.ini create mode 100644 import/index_scripts/author.bsh diff --git a/config/vufind/Collection.ini b/config/vufind/Collection.ini index d664a03e43a..14c41850ae2 100644 --- a/config/vufind/Collection.ini +++ b/config/vufind/Collection.ini @@ -12,7 +12,7 @@ side[] = "CollectionSideFacets:Facets::Collection:true" [Facets] geographic_facet = Location topic_facet = Subjects -authorStr = Author +author_facet = Author hierarchy_parent_title = Subcollection genre_facet = Genre era_facet = Era diff --git a/config/vufind/author-classification.ini b/config/vufind/author-classification.ini new file mode 100644 index 00000000000..74e819f41fd --- /dev/null +++ b/config/vufind/author-classification.ini @@ -0,0 +1,10 @@ +[AuthorRoles] +firstAuthorRoles = author,adp,adapter,aut,author,cmp,composer,cre,creator,dub,dubious author,inv,inventor +secondAuthorRoles = act,actor,anm,animator,ann,annotator,arr,arranger,acp,art copyist,art,artist,ard,artistic director,aft,author of afterword, colophon, etc.,aud,author of dialog,aui,author of introduction, etc.,aus,author of screenplay, etc.,bjd,bookjacket designer,bpd,bookplate designer,cll,calligrapher,ctg,cartographer,chr,choreographer,cng,cinematographer,clb,collaborator,clr,colorist,cmm,commentator,cwt,commentator for written text,com,compiler,cpl,complainant,cpt,complainant-appellant,cpe,complainant-appellee,ccp,conceptor,cnd,conductor,cos,contestant,cot,contestant-appellant,coe,contestant-appellee,cts,contestee,ctt,contestee-appellant,cte,contestee-appellee,ctb,contributor,crp,correspondent,cst,costume designer,cov,cover designer,cur,curator of an exhibition,dnc,dancer,dtc,data contributor,dto,dedicator,dfd,defendant,dft,defendant-appellant,dfe,defendant-appellee,dln,delineator,dpc,depicted,dsr,designer,drt,director,dis,dissertant,drm,draftsman,edt,editor,elt,electrotyper,egr,engraver,etr,etcher,fac,facsimilist,fld,field director,flm,film editor,frg,forger,ilu,illuminator,ill,illustrator,ins,inscriber,itr,instrumentalist,ivr,interviewer,ldr,laboratory director,lsa,landscape architect,led,lead,lil,libelant,lit,libelant-appellant,lie,libelant-appellee,lel,libelee,let,libelee-appellant,lee,libelee-appellee,lbt,librettist,lgd,lighting designer,ltg,lithographer,lyr,lyricist,mrb,marbler,mte,metal-engraver,msd,musical director,mus,musician,nrt,narrator,opn,opponent,org,originator,pta,patent applicant,pth,patent holder,prf,performer,pht,photographer,ptf,plaintiff,ptt,plaintiff-appellant,pte,plaintiff-appellee,prt,printer,pop,printer of plates,prm,printmaker,pro,producer,pmn,production manager,prd,production personnel, prg,programmer,pdr,project director,pbd,publishing director,ppt,puppeteer,ren,renderer,rpt,reporter,rth,research team head,rtm,research team member,res,researcher,rsp,respondent,rst,respondent-appellant,rse,respondent-appellee,rpy,responsible party,rsg,restager,rev,reviewer,rbr,rubricator,sce,scenarist,sad,scientific advisor,scr,scribe,scl,sculptor,spy,second party,std,set designer,sng,singer,sds,sound designer,spk,speaker,stm,stage manager,str,stereotyper,stl,storyteller,sht,supporting host,ths,thesis advisor,trl,translator,tyd,type designer,tyg,typographer,vdg,videographer,voc,vocalist,wde,wood-engraver,wdc,woodcutter,wam,writer of accompanying material +nonCreativeRoles = anl,analyst,app,applicant,arc,architect,asg,assignee,asn,associated name,att,attributed name,auc,auctioneer,aqt,author in quotations or text extracts,ant,bibliographic antecedent,bnd,binder,bdd,binding designer,blw,blurb writer,bkd,book designer,bkp,book producer,bsl,bookseller,cns,censor,cli,client,col,collector,clt,collotyper,cmt,compositor,con,conservator,csl,consultant,csp,consultant to a project,ctr,contractor,cpc,copyright claimant,cph,copyright holder,crr,corrector,dtm,data manager,dte,dedicatee,dgg,degree grantor,dpt,depositor,dbp,distribution place,dst,distributor,dnr,donor,elg,electrician,eng,engineer,evp,event place,exp,expert,fpy,first party,fmo,former owner,fnd,funder,gis,geographic information specialist,hnr,honoree,hst,host,ive,interviewee,lbr,laboratory,len,lender,lse,licensee,lso,licensor,mfp,manufacture place,mfr,manufacturer,mrk,markup editor,mdc,metadata contact,mod,moderator,mon,monitor,mcp,music copyist,orm,organizer of meeting,oth,other,own,owner,ppm,papermaker,pat,patron,pma,permitting agency,plt,platemaker,prc,process contact,prp,production place,pfr,proofreader,pup,publication place,pbl,publisher,rcp,recipient,rce,recording engineer,red,redactor,rps,repository,sec,secretary,sgn,signer,spn,sponsor,stn,standards body,srv,surveyor,tch,teacher,tcd,technical director,trc,transcriber,uvp,university place,wit,witness + +; Relator terms from German cataloging guideline RAK - add these to the comma separated +; lists above, if needed. +;firstAuthorRoles = bearbeiter,bearb,komponist,komp,urheber,verfasser,verf +;secondAuthorRoles = herausgeber,hg,hrsg,illustrator,ill,mitarbeiter,mitarb,übersetzer,übers +;nonCreativeRoles = begründer,begr,redakteur,red diff --git a/config/vufind/facets.ini b/config/vufind/facets.ini index dfa2f65b036..d7df062bcdd 100644 --- a/config/vufind/facets.ini +++ b/config/vufind/facets.ini @@ -10,7 +10,7 @@ format = Format callnumber-first = "Call Number" ;dewey-hundreds = "Call Number" ;hierarchy_top_title = Collections -authorStr = Author +author_facet = Author language = Language genre_facet = Genre era_facet = Era diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini index 0a733e23f0e..ea8b83d2dd1 100644 --- a/config/vufind/searches.ini +++ b/config/vufind/searches.ini @@ -147,8 +147,8 @@ toc = adv_search_toc ; through the translation module and displayed on screen. ; ; Note: "year", "author" and "title" are special shortcut aliases for the -; "publishDateSort", "authorStr" and "title_sort" Solr fields; you can use -; either form in this file. +; "publishDateSort", "author_sort" and "title_sort" Solr fields; you can +; use either form in this file. [Sorting] relevance = sort_relevance year = sort_year diff --git a/config/vufind/searchspecs.yaml b/config/vufind/searchspecs.yaml index ce45d0caf13..aec0ae0a200 100644 --- a/config/vufind/searchspecs.yaml +++ b/config/vufind/searchspecs.yaml @@ -156,7 +156,10 @@ Author: - author^100 - author_fuller^50 - author2 + - author2_fuller - author_additional + - author_variant + - author2_variant QueryFields: author: - [onephrase, 350] @@ -170,10 +173,22 @@ Author: - [onephrase, 100] - [and, 50] - [or, ~] + author2_fuller: + - [onephrase, 100] + - [and, 50] + - [or, ~] author_additional: - [onephrase, 100] - [and, 50] - [or, ~] + author_variant: + - [onephrase, 100] + - [and, 50] + - [or, ~] + author2_variant: + - [onephrase, 100] + - [and, 50] + - [or, ~] ISN: DismaxFields: diff --git a/import/index_scripts/author.bsh b/import/index_scripts/author.bsh new file mode 100644 index 00000000000..c0cc4f1d1d9 --- /dev/null +++ b/import/index_scripts/author.bsh @@ -0,0 +1,400 @@ +import org.marc4j.marc.Record; +import org.marc4j.marc.DataField; +import org.solrmarc.index.UpdateDateTracker; +import org.ini4j.Ini; +import java.util.Arrays; + +// define the base level indexer so that its methods can be called from the script. +// note that the SolrIndexer code will set this value before the script methods are called. +org.solrmarc.index.SolrIndexer indexer = null; + +/** + * Check if a particular Datafield meets the specified relator requirements. + * @param authorField Field to analyze + * @param noRelatorAllowed Array of tag names which are allowed to be used with + * no declared relator. + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @return Boolean + */ +public Boolean authorHasAppropriateRelator(DataField authorField, + String[] noRelatorAllowed, String relatorConfig +) { + // get tag number from Field + String tag = authorField.getTag(); + List subfieldE = normalizeRelatorSubfieldList(authorField.getSubfields('e')); + List subfield4 = normalizeRelatorSubfieldList(authorField.getSubfields('4')); + + // if no relator is found, check to see if the current tag is in the "no + // relator allowed" list. + if (subfieldE.size() == 0 && subfield4.size() == 0) { + return Arrays.asList(noRelatorAllowed).contains(tag); + } + + // If we got this far, we need to figure out what type of relation they have + List permittedRoles = normalizeRelatorStringList(Arrays.asList(loadRelatorConfig(relatorConfig))); + for (int j = 0; j < subfield4.size(); j++) { + if (permittedRoles.contains(subfield4.get(j).getData())) { + return true; + } + } + for (int j = 0; j < subfieldE.size(); j++) { + if (permittedRoles.contains(subfieldE.get(j).getData())) { + return true; + } + } + return false; +} + +/** + * Parse a SolrMarc fieldspec into a map of tag name to set of subfield strings + * (note that we need to map to a set rather than a single string, because the + * same tag may repeat with different subfields to extract different sections + * of the same field into distinct values). + * + * @param tagList The field specification to parse + * @return HashMap + */ +public HashMap getParsedTagList(String tagList) +{ + String[] tags = tagList.split(":");//convert string input to array + HashMap tagMap = new HashMap(); + //cut tags array up into key/value pairs in hash map + Set currentSet; + for(int i = 0; i < tags.length; i++){ + String tag = tags[i].substring(0, 3); + if (!tagMap.containsKey(tag)) { + currentSet = new LinkedHashSet(); + tagMap.put(tag, currentSet); + } else { + currentSet = tagMap.get(tag); + } + currentSet.add(tags[i].substring(3)); + } + return tagMap; +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for separating different types of authors. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @param firstOnly Return first result only? + * @return List result + */ +public List getAuthorsFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig, Boolean firstOnly +) { + List result = new LinkedList(); + String[] noRelatorAllowed = acceptWithoutRelator.split(":"); + HashMap parsedTagList = getParsedTagList(tagList); + List fields = indexer.getFieldSetMatchingTagList(record, tagList); + Iterator fieldsIter = fields.iterator(); + if (fields != null){ + DataField authorField; + while (fieldsIter.hasNext()){ + authorField = (DataField) fieldsIter.next(); + //add all author types to the result set + if (authorHasAppropriateRelator(authorField, noRelatorAllowed, relatorConfig)) { + for (String subfields : parsedTagList.get(authorField.getTag())) { + String current = indexer.getDataFromVariableField(authorField, "["+subfields+"]", " ", false); + // TODO: we may eventually be able to use this line instead, + // but right now it's not handling separation between the + // subfields correctly, so it's commented out until that is + // fixed. + //String current = authorField.getSubfieldsAsString(subfields); + if (null != current) { + result.add(current); + if (firstOnly) { + return result; + } + } + } + } + } + } + return result; +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for separating different types of authors. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @return List result + */ +public List getAuthorsFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig +) { + // default firstOnly to false! + return getAuthorsFilteredByRelator( + record, tagList, acceptWithoutRelator, relatorConfig, false + ); +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for separating different types of authors. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @return String + */ +public String getFirstAuthorFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig +) { + List result = getAuthorsFilteredByRelator( + record, tagList, acceptWithoutRelator, relatorConfig, true + ); + for (String s : result) { + return s; + } + return null; +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for saving relators of authors separated by different + * types. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @param firstOnly Return first result only? + * @return List result + */ +public List getRelatorsFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig, Boolean firstOnly, + String defaultRelator +) { + List result = new LinkedList(); + String[] noRelatorAllowed = acceptWithoutRelator.split(":"); + HashMap parsedTagList = getParsedTagList(tagList); + List fields = indexer.getFieldSetMatchingTagList(record, tagList); + Iterator fieldsIter = fields.iterator(); + if (fields != null){ + DataField authorField; + while (fieldsIter.hasNext()){ + authorField = (DataField) fieldsIter.next(); + //add all author types to the result set + if (authorHasAppropriateRelator(authorField, noRelatorAllowed, relatorConfig)) { + List subfieldE = normalizeRelatorSubfieldList(authorField.getSubfields('e')); + List subfield4 = normalizeRelatorSubfieldList(authorField.getSubfields('4')); + + // get the first non-empty subfield + String relator = defaultRelator; + + // try subfield E first + for (int j = 0; j < subfieldE.size(); j++) { + if (!subfieldE.get(j).getData().isEmpty()) { + relator = subfieldE.get(j).getData(); + continue; + } + } + // try subfield 4 now and overwrite relator as subfield 4 is most important + for (int j = 0; j < subfield4.size(); j++) { + if (!subfield4.get(j).getData().isEmpty()) { + relator = subfield4.get(j).getData(); + continue; + } + } + + result.add(relator); + } + } + } + return result; +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for saving relators of authors separated by different + * types. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @return List result + */ +public List getRelatorsFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig +) { + // default firstOnly to false! + return getRelatorsFilteredByRelator( + record, tagList, acceptWithoutRelator, relatorConfig, false, "" + ); +} + +/** + * This method fetches relator definitions from ini file and casts them to an + * array. If a colon-delimited string is passed in, this will be directly parsed + * instead of resorting to .ini loading. + * + * @param setting Setting to load from .ini or colon-delimited list. + * @return String[] + */ +public String[] loadRelatorConfig(String setting) { + StringBuilder relators = new StringBuilder(); + + // check for pipe-delimited string + String[] relatorSettings = setting.split("\\|"); + for (String relatorSetting: relatorSettings) { + // check for colon-delimited string + String[] relatorArray = relatorSetting.split(":"); + if (relatorArray.length > 1) { + for (int i = 0; i < relatorArray.length; i++) { + relators.append(relatorArray[i]).append(","); + } + } else { + relators.append(indexer.getConfigSetting( + "author-classification.ini", "AuthorRoles", relatorSetting + )).append(","); + } + } + + return relators.toString().split(","); +} + +/** + * Normalizes the strings in a list. + * + * @param stringList List of strings to be normalized + * @return stringList Normalized List of strings + */ +public List normalizeRelatorStringList(List stringList) +{ + for (int j = 0; j < stringList.size(); j++) { + stringList.set( + j, + normalizeRelatorString(stringList.get(j)) + ); + } + return stringList; +} + +/** + * Normalizes the strings in a list of subfields. + * + * @param subfieldList List of subfields to be normalized + * @return subfieldList Normalized List of subfields + */ +public List normalizeRelatorSubfieldList(List subfieldList) +{ + for (int j = 0; j < subfieldList.size(); j++) { + subfieldList.get(j).setData( + normalizeRelatorString(subfieldList.get(j).getData()) + ); + } + return subfieldList; +} + +/** + * Normalizes a string + * + * @param string String to be normalized + * @return string + */ +public String normalizeRelatorString(String string) +{ + return string + .trim() + .toLowerCase() + .replaceAll("\\p{Punct}+", ""); //POSIX character class Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ +} + +/** + * Filter values retrieved using tagList to include only those whose relator + * values are acceptable. Used for separating different types of authors. + * + * @param record The record (fed in automatically) + * @param tagList The field specification to read + * @param acceptWithoutRelator Colon-delimited list of tags whose values should + * be accepted even if no relator subfield is defined + * @param relatorConfig The setting in author-classification.ini which + * defines which relator terms are acceptable (or a colon-delimited list) + * @param firstOnly Return first result only? + * @return List result + */ +public List getAuthorInitialsFilteredByRelator(Record record, String tagList, + String acceptWithoutRelator, String relatorConfig +) { + List authors = getAuthorsFilteredByRelator(record, tagList, acceptWithoutRelator, relatorConfig); + List result = new LinkedList(); + for (String author : authors) { + result.add(this.processInitials(author)); + } + return result; +} + +/** + * Takes a name and cuts it into initials + * @param authorName e.g. Yeats, William Butler + * @return initials e.g. w b y wb + */ +public String processInitials(String authorName) { + Boolean isPersonalName = false; + // we guess that if there is a comma before the end - this is a personal name + if ((authorName.indexOf(',') > 0) + && (authorName.indexOf(',') < authorName.length()-1)) { + isPersonalName = true; + } + // get rid of non-alphabet chars but keep hyphens and accents + authorName = authorName.replaceAll("[^\\p{L} -]", "").toLowerCase(); + String[] names = authorName.split(" "); //split into tokens on spaces + // if this is a personal name we'll reorganise to put lastname at the end + String result = ""; + if (isPersonalName) { + String lastName = names[0]; + for (int i = 0; i < names.length-1; i++) { + names[i] = names[i+1]; + } + names[names.length-1] = lastName; + } + // put all the initials together in a space separated string + for (String name : names) { + if (name.length() > 0) { + String initial = name.substring(0,1); + // if there is a hyphenated name, use both initials + if (name.indexOf('-') > 0) { + int pos = name.indexOf('-'); + String extra = name.substring(pos+1,pos+2); + initial = initial + " " + extra; + } + result += " " + initial; + } + } + // grab all initials and stick them together + String smushAll = result.replaceAll(" ", ""); + // if it's a long personal name, get all but the last initials as well + // e.g. wb for william butler yeats + if (names.length > 2 && isPersonalName) { + String smushPers = result.substring(0,result.length()-1).replaceAll(" ",""); + result = result + " " + smushPers; + } + // now we have initials separate and together + if (!result.trim().equals(smushAll)) { + result += " " + smushAll; + } + result = result.trim(); + return result; +} \ No newline at end of file diff --git a/import/marc.properties b/import/marc.properties index 9aa34aaed99..95de9d0d30b 100644 --- a/import/marc.properties +++ b/import/marc.properties @@ -17,12 +17,18 @@ allfields = custom, getAllSearchableFieldsAsSet(100, 900) language = 008[35-37]:041a:041d:041h:041j, language_map.properties format = custom, getFormat, format_map.properties -author = 100abcd, first -author_fuller = 100q, first -author-letter = 100a,first -author2 = 110ab:111ab:700abcd:710ab:711ab -author2-role = 700e:710e -author_additional = 505r +author = custom, getAuthorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles) +author_variant = custom, getAuthorInitialsFilteredByRelator(100a:700a,100,firstAuthorRoles) +author_fuller = custom, getAuthorsFilteredByRelator(100q:700q,100,firstAuthorRoles) +author_role = custom, getRelatorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles) +author2 = custom, getAuthorsFilteredByRelator(700abcd,700,secondAuthorRoles) +author2_variant = custom, getAuthorInitialsFilteredByRelator(700a,700,secondAuthorRoles) +author2_fuller = custom, getAuthorsFilteredByRelator(700q,700,secondAuthorRoles) +author2_role = custom, getRelatorsFilteredByRelator(700abcd,700,secondAuthorRoles) +author_corporate = custom, getAuthorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles) +author_corporate_role = custom, getRelatorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles) +author_sort = custom, getFirstAuthorFilteredByRelator(100abcd:110ab:111abc:700abcd,100:110:111:700,firstAuthorRoles) +author_additional = 505r title = 245ab, first title_sub = 245b, first diff --git a/import/marc_local.properties b/import/marc_local.properties index fd79d0e0e9c..e6f54a1d3bb 100644 --- a/import/marc_local.properties +++ b/import/marc_local.properties @@ -14,6 +14,17 @@ # (by default, the scripts have the same behavior as the built-in functions, # but the external scripts are easier to customize to your needs). #format = script(format.bsh), getFormat, format_map.properties +#author = script(author.bsh), getAuthorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles) +#author_variant = script(author.bsh), getAuthorInitialsFilteredByRelator(100a:700a,100,firstAuthorRoles) +#author_fuller = script(author.bsh), getAuthorsFilteredByRelator(100q:700q,100,firstAuthorRoles) +#author_role = script(author.bsh), getRelatorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles) +#author2 = script(author.bsh), getAuthorsFilteredByRelator(700abcd,700,secondAuthorRoles) +#author2_variant = script(author.bsh), getAuthorInitialsFilteredByRelator(700a,700,secondAuthorRoles) +#author2_fuller = script(author.bsh), getAuthorsFilteredByRelator(700q,700,secondAuthorRoles) +#author2_role = script(author.bsh), getRelatorsFilteredByRelator(700abcd,700,secondAuthorRoles) +#author_corporate = script(author.bsh), getAuthorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles) +#author_corporate_role = script(author.bsh), getRelatorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles) +#author_sort = script(author.bsh), getFirstAuthorFilteredByRelator(100abcd:110ab:111abc:700abcd,100:110:111:700,firstAuthorRoles) #callnumber-subject = script(callnumber.bsh), getCallNumberSubject(090a:050a), callnumber_subject_map.properties #callnumber-label = script(callnumber.bsh), getCallNumberLabel(090a:050a) #publisher = script(getpublishers.bsh), getPublishers diff --git a/import/xsl/doaj.xsl b/import/xsl/doaj.xsl index d5b91ce5d48..a77177fde69 100644 --- a/import/xsl/doaj.xsl +++ b/import/xsl/doaj.xsl @@ -65,22 +65,9 @@ <xsl:if test="//doaj:authors/doaj:author/doaj:name"> <xsl:for-each select="//doaj:authors/doaj:author/doaj:name"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/import/xsl/dspace.xsl b/import/xsl/dspace.xsl index a2072586cc3..6dcbd734b2e 100644 --- a/import/xsl/dspace.xsl +++ b/import/xsl/dspace.xsl @@ -81,7 +81,7 @@ <!-- ADVISOR / CONTRIBUTOR --> <xsl:if test="//dc:contributor[normalize-space()]"> - <field name="author_additional"> + <field name="author2"> <xsl:value-of select="//dc:contributor[normalize-space()]" /> </field> </xsl:if> @@ -97,22 +97,9 @@ <xsl:if test="//dc:creator"> <xsl:for-each select="//dc:creator"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/import/xsl/gsdl.xsl b/import/xsl/gsdl.xsl index 25dad4dd062..33f231fe91e 100644 --- a/import/xsl/gsdl.xsl +++ b/import/xsl/gsdl.xsl @@ -72,7 +72,7 @@ </xsl:if> <!-- ADVISOR / CONTRIBUTOR --> <xsl:if test="//dc:contributor[normalize-space()]"> - <field name="author_additional"> + <field name="author2"> <xsl:value-of select="//dc:contributor[normalize-space()]" /> </field> </xsl:if> @@ -81,22 +81,9 @@ <xsl:if test="//dc:creator"> <xsl:for-each select="//dc:creator"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/import/xsl/ndltd.xsl b/import/xsl/ndltd.xsl index 847c1ddb5b6..fbffa8938d8 100644 --- a/import/xsl/ndltd.xsl +++ b/import/xsl/ndltd.xsl @@ -148,7 +148,7 @@ <!-- ADVISOR / CONTRIBUTOR --> <xsl:if test="//dc:contributor[normalize-space()]"> - <field name="author_additional"> + <field name="author2"> <xsl:value-of select="//dc:contributor[normalize-space()]" /> </field> </xsl:if> @@ -158,22 +158,9 @@ <xsl:if test="//dc:creator"> <xsl:for-each select="//dc:creator"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/import/xsl/nlm_ojs.xsl b/import/xsl/nlm_ojs.xsl index 9528c0b9910..2f2e130ee20 100644 --- a/import/xsl/nlm_ojs.xsl +++ b/import/xsl/nlm_ojs.xsl @@ -127,7 +127,7 @@ <!-- ADVISOR / CONTRIBUTOR --> <xsl:for-each select="//nlm:contrib[@contrib-type='editor']/nlm:name"> - <field name="author_additional"> + <field name="author2"> <xsl:value-of select="nlm:surname[normalize-space()]" />, <xsl:value-of select="nlm:given-names[normalize-space()]" /> </field> </xsl:for-each> @@ -135,22 +135,9 @@ <!-- AUTHOR --> <xsl:for-each select="//nlm:contrib[@contrib-type='author']/nlm:name"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="nlm:surname[normalize-space()]" />, <xsl:value-of select="nlm:given-names[normalize-space()]" /> - </field> - <field name="author-letter"> - <xsl:value-of select="nlm:surname[normalize-space()]" />, <xsl:value-of select="nlm:given-names[normalize-space()]" /> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="nlm:surname[normalize-space()]" />, <xsl:value-of select="nlm:given-names[normalize-space()]" /> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="nlm:surname[normalize-space()]" />, <xsl:value-of select="nlm:given-names[normalize-space()]" /> + </field> </xsl:if> </xsl:for-each> diff --git a/import/xsl/ojs.xsl b/import/xsl/ojs.xsl index b817e0728fa..3d8a138b349 100644 --- a/import/xsl/ojs.xsl +++ b/import/xsl/ojs.xsl @@ -59,22 +59,9 @@ <xsl:if test="//dc:creator"> <xsl:for-each select="//dc:creator"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/import/xsl/vudl_FOXML.xsl b/import/xsl/vudl_FOXML.xsl index 7af5d1428fe..b8684694570 100644 --- a/import/xsl/vudl_FOXML.xsl +++ b/import/xsl/vudl_FOXML.xsl @@ -386,22 +386,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA <xsl:if test="$DC//dc:creator"> <xsl:for-each select="$DC//dc:creator"> <xsl:if test="normalize-space()"> - <!-- author is not a multi-valued field, so we'll put - first value there and subsequent values in author2. - --> - <xsl:if test="position()=1"> - <field name="author"> - <xsl:value-of select="normalize-space()"/> - </field> - <field name="author-letter"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> - <xsl:if test="position()>1"> - <field name="author2"> - <xsl:value-of select="normalize-space()"/> - </field> - </xsl:if> + <field name="author"> + <xsl:value-of select="normalize-space()"/> + </field> </xsl:if> </xsl:for-each> </xsl:if> diff --git a/module/VuFind/src/VuFind/Config/Upgrade.php b/module/VuFind/src/VuFind/Config/Upgrade.php index 2d768037e4f..1a4e4397e84 100644 --- a/module/VuFind/src/VuFind/Config/Upgrade.php +++ b/module/VuFind/src/VuFind/Config/Upgrade.php @@ -152,7 +152,7 @@ class Upgrade // and into other files. $this->upgradeConfig(); $this->upgradeAuthority(); - $this->upgradeFacets(); + $this->upgradeFacetsAndCollection(); $this->upgradeFulltext(); $this->upgradeReserves(); $this->upgradeSearches(); @@ -294,7 +294,7 @@ class Upgrade $configs = [ 'config.ini', 'authority.ini', 'facets.ini', 'reserves.ini', 'searches.ini', 'Summon.ini', 'WorldCat.ini', 'sms.ini', - 'Primo.ini', 'permissions.ini' + 'permissions.ini', 'Collection.ini', 'Primo.ini' ]; foreach ($configs as $config) { // Special case for config.ini, since we may need to overlay extra @@ -706,12 +706,62 @@ class Upgrade } /** - * Upgrade facets.ini. + * Change an array key. + * + * @param array $array Array to rewrite + * @param string $old Old key name + * @param string $new New key name + * + * @return array + */ + protected function changeArrayKey($array, $old, $new) + { + $newArr = []; + foreach ($array as $k => $v) { + if ($k === $old) { + $k = $new; + } + $newArr[$k] = $v; + } + return $newArr; + } + + /** + * Support method for upgradeFacetsAndCollection() - change the name of + * a facet field. + * + * @param string $old Old field name + * @param string $new New field name + * + * @return void + */ + protected function renameFacet($old, $new) + { + $didWork = false; + if (isset($this->newConfigs['facets.ini']['Results'][$old])) { + $this->newConfigs['facets.ini']['Results'] = $this->changeArrayKey( + $this->newConfigs['facets.ini']['Results'], $old, $new + ); + $didWork = true; + } + if (isset($this->newConfigs['Collection.ini']['Facets'][$old])) { + $this->newConfigs['Collection.ini']['Facets'] = $this->changeArrayKey( + $this->newConfigs['Collection.ini']['Facets'], $old, $new + ); + $didWork = true; + } + if ($didWork) { + $this->newConfigs['facets.ini']['LegacyFields'][$old] = $new; + } + } + + /** + * Upgrade facets.ini and Collection.ini (since these are tied together). * * @throws FileAccessException * @return void */ - protected function upgradeFacets() + protected function upgradeFacetsAndCollection() { // we want to retain the old installation's various facet groups // exactly as-is @@ -720,6 +770,7 @@ class Upgrade 'HomePage' ]; $this->applyOldSettings('facets.ini', $facetGroups); + $this->applyOldSettings('Collection.ini', ['Facets', 'Sort']); // fill in home page facets with advanced facets if missing: if (!isset($this->oldConfigs['facets.ini']['HomePage'])) { @@ -727,8 +778,12 @@ class Upgrade = $this->newConfigs['facets.ini']['Advanced']; } + // rename changed facets + $this->renameFacet('authorStr', 'author_facet'); + // save the file $this->saveModifiedConfig('facets.ini'); + $this->saveModifiedConfig('Collection.ini'); } /** diff --git a/module/VuFind/src/VuFind/Controller/BrowseController.php b/module/VuFind/src/VuFind/Controller/BrowseController.php index 0c1f783ab25..cd966ba0dbd 100644 --- a/module/VuFind/src/VuFind/Controller/BrowseController.php +++ b/module/VuFind/src/VuFind/Controller/BrowseController.php @@ -662,7 +662,7 @@ class BrowseController extends AbstractBase case 'lcc': return 'callnumber-first'; case 'author': - return 'authorStr'; + return 'author_facet'; case 'topic': return 'topic_facet'; case 'genre': diff --git a/module/VuFind/src/VuFind/Recommend/DPLATerms.php b/module/VuFind/src/VuFind/Recommend/DPLATerms.php index 19016b221ba..6f193739620 100644 --- a/module/VuFind/src/VuFind/Recommend/DPLATerms.php +++ b/module/VuFind/src/VuFind/Recommend/DPLATerms.php @@ -76,7 +76,7 @@ class DPLATerms implements RecommendInterface * @var array */ protected $formatMap = [ - 'authorStr' => 'sourceResource.creator', + 'author_facet' => 'sourceResource.creator', 'building' => 'provider.name', 'format' => 'sourceResource.format', 'geographic_facet' => 'sourceResource.spatial.region', diff --git a/module/VuFind/src/VuFind/RecordDriver/EDS.php b/module/VuFind/src/VuFind/RecordDriver/EDS.php index e65737b30b1..88960b9b20a 100644 --- a/module/VuFind/src/VuFind/RecordDriver/EDS.php +++ b/module/VuFind/src/VuFind/RecordDriver/EDS.php @@ -359,7 +359,7 @@ class EDS extends SolrDefault * * @return array */ - public function getAuthors() + public function getPrimaryAuthors() { $authors = []; if (isset($this->fields['RecordInfo']['BibRecord']['BibRelationships'])) { @@ -378,17 +378,6 @@ class EDS extends SolrDefault return $authors; } - /** - * Obtain the primary author of the record - * - * @return string - */ - public function getPrimaryAuthor() - { - $authors = $this->getAuthors(); - return empty($authors) ? '' : $authors[0]; - } - /** * Get the source of the record. * diff --git a/module/VuFind/src/VuFind/RecordDriver/EIT.php b/module/VuFind/src/VuFind/RecordDriver/EIT.php index bdce707f4cd..a239ad26e96 100644 --- a/module/VuFind/src/VuFind/RecordDriver/EIT.php +++ b/module/VuFind/src/VuFind/RecordDriver/EIT.php @@ -154,31 +154,6 @@ class EIT extends SolrDefault return []; } - /** - * Deduplicate author information into associative array with main/corporate/ - * secondary keys. - * - * @return array - */ - public function getDeduplicatedAuthors() - { - $authors = [ - 'main' => $this->getPrimaryAuthor(), - 'secondary' => $this->getSecondaryAuthors() - ]; - - // The secondary author array may contain a corporate or primary author; - // let's be sure we filter out duplicate values. - $duplicates = []; - if (!empty($authors['main'])) { - $duplicates[] = $authors['main']; - } - if (!empty($duplicates)) { - $authors['secondary'] = array_diff($authors['secondary'], $duplicates); - } - return $authors; - } - /** * Get the edition of the current record. * @@ -210,15 +185,15 @@ class EIT extends SolrDefault * * @return string */ - public function getPrimaryAuthor() + public function getPrimaryAuthors() { if (isset($this->controlInfo['artinfo']['aug']['au']) && is_array($this->controlInfo['artinfo']['aug']['au']) ) { - return $this->controlInfo['artinfo']['aug']['au']['0']; + return $this->controlInfo['artinfo']['aug']['au']; } else { return isset($this->controlInfo['artinfo']['aug']['au']) - ? $this->controlInfo['artinfo']['aug']['au'] : ''; + ? [$this->controlInfo['artinfo']['aug']['au']] : []; } } @@ -252,17 +227,6 @@ class EIT extends SolrDefault ? [$this->controlInfo['pubinfo']['pub']] : []; } - /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). - * - * @return array - */ - public function getSecondaryAuthors() - { - return is_array($this->controlInfo['artinfo']['aug']['au']) - ? $this->controlInfo['artinfo']['aug']['au'] : []; - } - /** * Get the short (pre-subtitle) title of the record. * diff --git a/module/VuFind/src/VuFind/RecordDriver/Pazpar2.php b/module/VuFind/src/VuFind/RecordDriver/Pazpar2.php index 39dcaaba9a5..cfd52206b8c 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Pazpar2.php +++ b/module/VuFind/src/VuFind/RecordDriver/Pazpar2.php @@ -133,16 +133,16 @@ class Pazpar2 extends SolrDefault } /** - * Get the main author of the record. + * Get the main authors of the record. * - * @return string + * @return array */ - public function getPrimaryAuthor() + public function getPrimaryAuthors() { - $authors = isset($this->pz2fields['md-author']) ? - $this->pz2fields['md-author'] : ''; + $authors = isset($this->pz2fields['md-author']) + ? $this->pz2fields['md-author'] : []; - return is_array($authors) ? $authors[0] : $authors; + return empty($authors) ? [] : (array)$authors; } /** @@ -180,19 +180,6 @@ class Pazpar2 extends SolrDefault [$this->pz2fields['md-date']] : []; } - /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). - * - * @return array - */ - public function getSecondaryAuthors() - { - $authors = isset($this->pz2fields['md-author']) ? - $this->pz2fields['md-author'] : ''; - - return is_array($authors) ? array_slice($authors, 1) : []; - } - /** * Get the full title of the record. * diff --git a/module/VuFind/src/VuFind/RecordDriver/Primo.php b/module/VuFind/src/VuFind/RecordDriver/Primo.php index 020728117ad..6345355eb4d 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Primo.php +++ b/module/VuFind/src/VuFind/RecordDriver/Primo.php @@ -67,32 +67,14 @@ class Primo extends SolrDefault } /** - * Get the main author of the record. - * - * @return string - */ - public function getPrimaryAuthor() - { - return isset($this->fields['creator'][0]) ? - $this->fields['creator'][0] : ''; - } - - /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). + * Get the main authors of the record. * * @return array */ - public function getSecondaryAuthors() + public function getPrimaryAuthors() { - $authors = []; - if (isset($this->fields['creator'])) { - for ($i = 1; $i < count($this->fields['creator']); $i++) { - if (isset($this->fields['creator'][$i])) { - $authors[] = $this->fields['creator'][$i]; - } - } - } - return $authors; + return isset($this->fields['creator']) + ? array_map('trim', $this->fields['creator']) : []; } /** diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php index 3a26d341e2a..68529bdf74a 100644 --- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php +++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php @@ -64,9 +64,9 @@ class SolrDefault extends AbstractBase * @var array */ protected $forbiddenSnippetFields = [ - 'author', 'author-letter', 'title', 'title_short', 'title_full', + 'author', 'title', 'title_short', 'title_full', 'title_full_unstemmed', 'title_auth', 'title_sub', 'spelling', 'id', - 'ctrlnum' + 'ctrlnum', 'author_variant', 'author2_variant' ]; /** @@ -382,14 +382,25 @@ class SolrDefault extends AbstractBase } /** - * Get the main corporate author (if any) for the record. + * Get the main corporate authors (if any) for the record. * - * @return string + * @return array */ - public function getCorporateAuthor() + public function getCorporateAuthors() { - // Not currently stored in the Solr index - return null; + return isset($this->fields['author_corporate']) ? + $this->fields['author_corporate'] : []; + } + + /** + * Get an array of all main corporate authors roles. + * + * @return array + */ + public function getCorporateAuthorsRoles() + { + return isset($this->fields['author_corporate_role']) ? + $this->fields['author_corporate_role'] : []; } /** @@ -414,27 +425,81 @@ class SolrDefault extends AbstractBase public function getDeduplicatedAuthors() { $authors = [ - 'main' => $this->getPrimaryAuthor(), - 'corporate' => $this->getCorporateAuthor(), - 'secondary' => $this->getSecondaryAuthors() + 'main' => $this->getAuthorRolesArray( + $this->getPrimaryAuthors(), + $this->getPrimaryAuthorsRoles() + ), + 'corporate' => $this->getAuthorRolesArray( + $this->getCorporateAuthors(), + $this->getCorporateAuthorsRoles() + ), + 'secondary' => $this->getAuthorRolesArray( + $this->getSecondaryAuthors(), + $this->getSecondaryAuthorsRoles() + ) ]; - // The secondary author array may contain a corporate or primary author; - // let's be sure we filter out duplicate values. - $duplicates = []; - if (!empty($authors['main'])) { - $duplicates[] = $authors['main']; - } - if (!empty($authors['corporate'])) { - $duplicates[] = $authors['corporate']; - } - if (!empty($duplicates)) { - $authors['secondary'] = array_diff($authors['secondary'], $duplicates); - } + // deduplicate + $dedup = function (&$array1, &$array2) { + if (!empty($array1) && !empty($array2)) { + foreach ($array1 as $author => $roles) { + if (isset($array2[$author])) { + $array1[$author] = array_merge( + $array1[$author], + $array2[$author] + ); + unset($array2[$author]); + } + } + } + }; + + $dedup($authors['main'], $authors['corporate']); + $dedup($authors['secondary'], $authors['corporate']); + $dedup($authors['main'], $authors['secondary']); + + $dedup_roles = function (&$array) { + foreach ($array as $author => $roles) { + if (is_array($roles)) { + $array[$author] = array_unique($roles); + } + } + }; + + $dedup_roles($authors['main']); + $dedup_roles($authors['secondary']); + $dedup_roles($authors['corporate']); return $authors; } + /** + * Helper function to restructure author arrays including relators + * + * @param array $authors Array of authors + * @param array $roles Array with relators of authors + * + * @return array + */ + protected function getAuthorRolesArray($authors = [], $roles = []) + { + $authorRolesArray = []; + + if (!empty($authors)) { + foreach ($authors as $index => $author) { + if (!isset($authorRolesArray[$author])) { + $authorRolesArray[$author] = []; + } + if (isset($roles[$index]) && !empty($roles[$index]) + ) { + $authorRolesArray[$author][] = $roles[$index]; + } + } + } + + return $authorRolesArray; + } + /** * Get the edition of the current record. * @@ -479,18 +544,41 @@ class SolrDefault extends AbstractBase } /** - * Get a highlighted author string, if available. + * Get highlighted author data, if available. * - * @return string + * @return array */ - public function getHighlightedAuthor() + public function getRawAuthorHighlights() { // Don't check for highlighted values if highlighting is disabled: - if (!$this->highlight) { - return ''; + return ($this->highlight && isset($this->highlightDetails['author'])) + ? $this->highlightDetails['author'] : []; + } + + /** + * Get primary author information with highlights applied (if applicable) + * + * @return array + */ + public function getPrimaryAuthorsWithHighlighting() + { + $highlights = []; + // Create a map of de-highlighted valeus => highlighted values. + foreach ($this->getRawAuthorHighlights() as $current) { + $dehighlighted = str_replace( + ['{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'], '', $current + ); + $highlights[$dehighlighted] = $current; + } + + // replace unhighlighted authors with highlighted versions where + // applicable: + $authors = []; + foreach ($this->getPrimaryAuthors() as $author) { + $authors[] = isset($highlights[$author]) + ? $highlights[$author] : $author; } - return (isset($this->highlightDetails['author'][0])) - ? $this->highlightDetails['author'][0] : ''; + return $authors; } /** @@ -956,9 +1044,32 @@ class SolrDefault extends AbstractBase * @return string */ public function getPrimaryAuthor() + { + $authors = $this->getPrimaryAuthors(); + return isset($authors[0]) ? $authors[0] : ''; + } + + /** + * Get the main authors of the record. + * + * @return array + */ + public function getPrimaryAuthors() { return isset($this->fields['author']) ? - $this->fields['author'] : ''; + $this->fields['author'] : []; + } + + /** + * Get an array of all main authors roles (complementing + * getSecondaryAuthorsRoles()). + * + * @return array + */ + public function getPrimaryAuthorsRoles() + { + return isset($this->fields['author_role']) ? + $this->fields['author_role'] : []; } /** @@ -1080,7 +1191,7 @@ class SolrDefault extends AbstractBase } /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). + * Get an array of all secondary authors (complementing getPrimaryAuthors()). * * @return array */ @@ -1090,6 +1201,18 @@ class SolrDefault extends AbstractBase $this->fields['author2'] : []; } + /** + * Get an array of all secondary authors roles (complementing + * getPrimaryAuthorsRoles()). + * + * @return array + */ + public function getSecondaryAuthorsRoles() + { + return isset($this->fields['author2_role']) ? + $this->fields['author2_role'] : []; + } + /** * Get an array of all series names containing the record. Array entries may * be either the name string, or an associative array with 'name' and 'number' @@ -1546,16 +1669,11 @@ class SolrDefault extends AbstractBase . 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd" />' ); $xml->addChild('title', htmlspecialchars($this->getTitle()), $dc); - $primary = $this->getPrimaryAuthor(); - if (!empty($primary)) { - $xml->addChild('creator', htmlspecialchars($primary), $dc); - } - $corporate = $this->getCorporateAuthor(); - if (!empty($corporate)) { - $xml->addChild('creator', htmlspecialchars($corporate), $dc); - } - foreach ($this->getSecondaryAuthors() as $current) { - $xml->addChild('creator', htmlspecialchars($current), $dc); + $authors = $this->getDeduplicatedAuthors(); + foreach ($authors as $list) { + foreach ((array)$list as $author) { + $xml->addChild('creator', htmlspecialchars($author), $dc); + } } foreach ($this->getLanguages() as $lang) { $xml->addChild('language', htmlspecialchars($lang), $dc); diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php index 714b1ebdd44..2d5b7e3d3fd 100644 --- a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php +++ b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php @@ -184,21 +184,6 @@ class SolrMarc extends SolrDefault return $this->getFieldArray('504'); } - /** - * Get the main corporate author (if any) for the record. - * - * @return string - */ - public function getCorporateAuthor() - { - // Try 110 first -- if none found, try 710 next. - $main = $this->getFirstFieldValue('110', ['a', 'b']); - if (!empty($main)) { - return $main; - } - return $this->getFirstFieldValue('710', ['a', 'b']); - } - /** * Return an array of all values extracted from the specified field/subfield * combination. If multiple subfields are specified and $concat is true, they diff --git a/module/VuFind/src/VuFind/RecordDriver/Summon.php b/module/VuFind/src/VuFind/RecordDriver/Summon.php index 4798feb4cab..edd572bc733 100644 --- a/module/VuFind/src/VuFind/RecordDriver/Summon.php +++ b/module/VuFind/src/VuFind/RecordDriver/Summon.php @@ -138,21 +138,15 @@ class Summon extends SolrDefault } /** - * Get a highlighted author string, if available. + * Get highlighted author data, if available. * - * @return string + * @return array */ - public function getHighlightedAuthor() + public function getRawAuthorHighlights() { - // Don't check for highlighted values if highlighting is disabled; - // also, don't try to highlight multi-author works, because it will - // cause display problems -- it's currently impossible to properly - // synchronize the 'Author' and 'Author_xml' lists. - if (!$this->highlight || count($this->fields['Author']) > 1) { - return ''; - } - return isset($this->fields['Author']) ? - $this->fields['Author'][0] : ''; + // Don't check for highlighted values if highlighting is disabled. + return ($this->highlight && isset($this->fields['Author'])) + ? $this->fields['Author'] : []; } /** @@ -282,17 +276,6 @@ class Summon extends SolrDefault $this->fields['PublicationPlace'] : []; } - /** - * Get the main author of the record. - * - * @return string - */ - public function getPrimaryAuthor() - { - return isset($this->fields['Author_xml'][0]['fullname']) ? - $this->fields['Author_xml'][0]['fullname'] : ''; - } - /** * Pass in a date converter * @@ -364,15 +347,15 @@ class Summon extends SolrDefault } /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). + * Get an array of all primary authors. * * @return array */ - public function getSecondaryAuthors() + public function getPrimaryAuthors() { $authors = []; if (isset($this->fields['Author_xml'])) { - for ($i = 1; $i < count($this->fields['Author_xml']); $i++) { + for ($i = 0; $i < count($this->fields['Author_xml']); $i++) { if (isset($this->fields['Author_xml'][$i]['fullname'])) { $authors[] = $this->fields['Author_xml'][$i]['fullname']; } diff --git a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php index 94bb76d7e2a..3614b2ccb03 100644 --- a/module/VuFind/src/VuFind/RecordDriver/WorldCat.php +++ b/module/VuFind/src/VuFind/RecordDriver/WorldCat.php @@ -183,13 +183,13 @@ class WorldCat extends SolrMarc } /** - * Get the main author of the record. + * Get the main authors of the record. * - * @return string + * @return array */ - public function getPrimaryAuthor() + public function getPrimaryAuthors() { - return $this->getFirstFieldValue('100', ['a']); + return [$this->getFirstFieldValue('100', ['a'])]; } /** @@ -279,7 +279,7 @@ class WorldCat extends SolrMarc } /** - * Get an array of all secondary authors (complementing getPrimaryAuthor()). + * Get an array of all secondary authors (complementing getPrimaryAuthors()). * * @return array */ diff --git a/module/VuFind/src/VuFind/Search/Base/Params.php b/module/VuFind/src/VuFind/Search/Base/Params.php index dd09f57a0ea..e5576fd1ed1 100644 --- a/module/VuFind/src/VuFind/Search/Base/Params.php +++ b/module/VuFind/src/VuFind/Search/Base/Params.php @@ -166,6 +166,13 @@ class Params implements ServiceLocatorAwareInterface */ protected $defaultsApplied = false; + /** + * Map of facet field aliases. + * + * @var array + */ + protected $facetAliases = []; + /** * Constructor * @@ -715,6 +722,33 @@ class Params implements ServiceLocatorAwareInterface return [$field, $value]; } + /** + * Given a facet field, return an array containing all aliases of that + * field. + * + * @param string $field Field to look up + * + * @return array + */ + public function getAliasesForFacetField($field) + { + // Account for field prefixes used for Boolean logic: + $prefix = substr($field, 0, 1); + if ($prefix === '-' || $prefix === '~') { + $rawField = substr($field, 1); + } else { + $prefix = ''; + $rawField = $field; + } + $fieldsToCheck = [$field]; + foreach ($this->facetAliases as $k => $v) { + if ($v === $rawField) { + $fieldsToCheck[] = $prefix . $k; + } + } + return $fieldsToCheck; + } + /** * Does the object already contain the specified filter? * @@ -727,10 +761,13 @@ class Params implements ServiceLocatorAwareInterface // Extract field and value from URL string: list($field, $value) = $this->parseFilter($filter); - if (isset($this->filterList[$field]) - && in_array($value, $this->filterList[$field]) - ) { - return true; + // Check all of the relevant fields for matches: + foreach ($this->getAliasesForFacetField($field) as $current) { + if (isset($this->filterList[$current]) + && in_array($value, $this->filterList[$current]) + ) { + return true; + } } return false; } @@ -885,6 +922,11 @@ class Params implements ServiceLocatorAwareInterface */ public function getFacetLabel($field) { + if (!isset($this->facetConfig[$field]) + && isset($this->facetAliases[$field]) + ) { + $field = $this->facetAliases[$field]; + } return isset($this->facetConfig[$field]) ? $this->facetConfig[$field] : 'unrecognized_facet_label'; } diff --git a/module/VuFind/src/VuFind/Search/Solr/Params.php b/module/VuFind/src/VuFind/Search/Solr/Params.php index 90bb181550c..30661c1b240 100644 --- a/module/VuFind/src/VuFind/Search/Solr/Params.php +++ b/module/VuFind/src/VuFind/Search/Solr/Params.php @@ -104,6 +104,9 @@ class Params extends \VuFind\Search\Base\Params ) { $this->setFacetLimit($config->Results_Settings->facet_limit); } + if (isset($config->LegacyFields)) { + $this->facetAliases = $config->LegacyFields->toArray(); + } if (isset($config->Results_Settings->facet_limit_by_field)) { foreach ($config->Results_Settings->facet_limit_by_field as $k => $v) { $this->facetLimitByField[$k] = $v; @@ -436,7 +439,8 @@ class Params extends \VuFind\Search\Base\Params static $table = [ 'year' => ['field' => 'publishDateSort', 'order' => 'desc'], 'publishDateSort' => ['field' => 'publishDateSort', 'order' => 'desc'], - 'author' => ['field' => 'authorStr', 'order' => 'asc'], + 'author' => ['field' => 'author_sort', 'order' => 'asc'], + 'authorStr' => ['field' => 'author_sort', 'order' => 'asc'], 'title' => ['field' => 'title_sort', 'order' => 'asc'], 'relevance' => ['field' => 'score', 'order' => 'desc'], 'callnumber' => ['field' => 'callnumber-sort', 'order' => 'asc'], diff --git a/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Params.php b/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Params.php index ed8a3b3b932..6a86791b3ac 100644 --- a/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Params.php +++ b/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Params.php @@ -52,7 +52,7 @@ class Params extends \VuFind\Search\Solr\Params // Force custom facet settings: $this->facetConfig = []; - $this->addFacet('authorStr'); + $this->addFacet('author_facet'); $this->setFacetOffset(($this->getPage() - 1) * $this->getLimit()); $this->setFacetLimit($this->getLimit() * 10); // Sorting - defaults to off with unlimited facets, so let's diff --git a/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Results.php b/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Results.php index 59fd0cba540..1d1e7e2c0d3 100644 --- a/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Results.php +++ b/module/VuFind/src/VuFind/Search/SolrAuthorFacets/Results.php @@ -55,14 +55,14 @@ class Results extends \VuFind\Search\Solr\Results $this->responseFacets = $collection->getFacets(); // Get the facets from which we will build our results: - $facets = $this->getFacetList(['authorStr' => null]); - if (isset($facets['authorStr'])) { + $facets = $this->getFacetList(['author_facet' => null]); + if (isset($facets['author_facet'])) { $params = $this->getParams(); $this->resultTotal = (($params->getPage() - 1) * $params->getLimit()) - + count($facets['authorStr']['list']); + + count($facets['author_facet']['list']); $this->results = array_slice( - $facets['authorStr']['list'], 0, $params->getLimit() + $facets['author_facet']['list'], 0, $params->getLimit() ); } } diff --git a/module/VuFind/src/VuFind/Search/UrlQueryHelper.php b/module/VuFind/src/VuFind/Search/UrlQueryHelper.php index 8d5010f988b..d88bfc0efe5 100644 --- a/module/VuFind/src/VuFind/Search/UrlQueryHelper.php +++ b/module/VuFind/src/VuFind/Search/UrlQueryHelper.php @@ -346,13 +346,17 @@ class UrlQueryHelper $field = '~' . $field; } + $fieldAliases = $this->params->getAliasesForFacetField($field); + // Remove the filter: $newFilter = []; if (isset($params['filter']) && is_array($params['filter'])) { foreach ($params['filter'] as $current) { list($currentField, $currentValue) = $this->params->parseFilter($current); - if ($currentField != $field || $currentValue != $value) { + if (!in_array($currentField, $fieldAliases) + || $currentValue != $value + ) { $newFilter[] = $current; } } diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Browse.php b/module/VuFind/src/VuFind/View/Helper/Root/Browse.php index 7a0b1bee3af..cad9b2b01f3 100644 --- a/module/VuFind/src/VuFind/View/Helper/Root/Browse.php +++ b/module/VuFind/src/VuFind/View/Helper/Root/Browse.php @@ -57,7 +57,7 @@ class Browse extends AbstractHelper case 'lcc': return 'callnumber-first'; case 'author': - return 'authorStr'; + return 'author_facet'; case 'topic': return 'topic_facet'; case 'genre': diff --git a/module/VuFind/tests/fixtures/misc/testbug2.json b/module/VuFind/tests/fixtures/misc/testbug2.json index 44a6715f25a..b80af3a35c4 100644 --- a/module/VuFind/tests/fixtures/misc/testbug2.json +++ b/module/VuFind/tests/fixtures/misc/testbug2.json @@ -16,7 +16,7 @@ "callnumber-first-code":"D", "callnumber-a":"DG848.15", "id":"testbug2", - "author":"Vico, Giambattista, 1668-1744.", + "author":["Vico, Giambattista, 1668-1744."], "title":"La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) /", "callnumber-subject-code":"DG", "spelling":"Vico, Giambattista, 1668-1744. Principum Neapolitanorum coniurationis anni MDCCI historia. Italian & Latin La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) / Giambattista Vico ; a cura di Claudia Pandolfi. Fictional edition. Morano : Centro di Studi Vichiani, 1992. 296 p. : ill. ; 24 cm. Opere di Giambattista Vico ; 2/1 Italian and Latin. Includes bibliographical references (p. [277]-281) and index. Sample abstract. April11phi Naples (Kingdom) History Spanish rule, 1442-1707 Sources. Pandolfi, Claudia. Vico, Giambattista, 1668-1744. Works. 1982 ; 2, pt. 1. http://fictional.com/sample/url", @@ -30,7 +30,6 @@ "title_sort":"congiura dei principi napoletani 1701 :(prima e seconda stesura)", "title_short":"La congiura dei Principi Napoletani 1701 :", "fullrecord":"01234cam a2200337Ma 4500001000900000005001700009008004100026020001500067035002300082040002500105041001800130043001200148050002400160049000900184100003600193240008100229245012500310250002300435260004700458300002900505490003800534500002300572504006600595520002100661590001500682651006500697700002300762800006300785856003600848994001200884\u001etestbug2\u001e20110419140028.0\u001e110214s1992 it a b 001 0 ita d\u001e \u001fa8820737493\u001e \u001fa(OCoLC)ocm30585539\u001e \u001faRBN\u001fcRBN\u001fdOCLCG\u001fdPVU\u001e1 \u001faita\u001falat\u001fhlat\u001e \u001fae-it---\u001e14\u001faDG848.15\u001fb.V53 1992\u001e \u001faPVUM\u001e1 \u001faVico, Giambattista,\u001fd1668-1744.\u001e10\u001faPrincipum Neapolitanorum coniurationis anni MDCCI historia.\u001flItalian & Latin\u001e13\u001faLa congiura dei Principi Napoletani 1701 :\u001fb(prima e seconda stesura) /\u001fcGiambattista Vico ; a cura di Claudia Pandolfi.\u001e \u001faFictional edition.\u001e \u001faMorano :\u001fbCentro di Studi Vichiani,\u001fc1992.\u001e \u001fa296 p. :\u001fbill. ;\u001fc24 cm.\u001e1 \u001faOpere di Giambattista Vico ;\u001fv2/1\u001e \u001faItalian and Latin.\u001e \u001faIncludes bibliographical references (p. [277]-281) and index.\u001e3 \u001faSample abstract.\u001e \u001faApril11phi\u001e 0\u001faNaples (Kingdom)\u001fxHistory\u001fySpanish rule, 1442-1707\u001fvSources.\u001e1 \u001faPandolfi, Claudia.\u001e1 \u001faVico, Giambattista,\u001fd1668-1744.\u001ftWorks.\u001ff1982 ;\u001fv2, pt. 1.\u001e40\u001fuhttp://fictional.com/sample/url\u001e \u001faC0\u001fbPVU\u001e\u001d", - "author-letter":"Vico, Giambattista,", "title_full":"La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) / Giambattista Vico ; a cura di Claudia Pandolfi.", "title_fullStr":"La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) / Giambattista Vico ; a cura di Claudia Pandolfi.", "title_full_unstemmed":"La congiura dei Principi Napoletani 1701 : (prima e seconda stesura) / Giambattista Vico ; a cura di Claudia Pandolfi.", diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php index d18487a9c8d..84fb5f2a694 100644 --- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php +++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php @@ -154,6 +154,31 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase $results['Summon.ini']['TopRecommendations'] ); + // Confirm that author facets have been upgraded appropriately. + $this->assertFalse(isset($results['facets.ini']['Results']['authorStr'])); + $this->assertFalse(isset($results['Collection.ini']['Facets']['authorStr'])); + $this->assertEquals( + 'Author', $results['facets.ini']['Results']['author_facet'] + ); + $this->assertEquals( + 'author_facet', $results['facets.ini']['LegacyFields']['authorStr'] + ); + // Collection.ini only exists after release 1.3: + if ((float)$version > 1.3) { + $this->assertEquals( + 'Author', $results['Collection.ini']['Facets']['author_facet'] + ); + } + // verify expected order of facet fields + $this->assertEquals( + [ + 'institution', 'building', 'format', 'callnumber-first', + 'author_facet', 'language', 'genre_facet', 'era_facet', + 'geographic_facet', 'publishDate' + ], + array_keys($results['facets.ini']['Results']) + ); + return ['configs' => $results, 'warnings' => $warnings]; } diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis b/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis index 6e2b0f14fd4..493e80ab0e7 100644 --- a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis +++ b/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/morelikethis @@ -3,5 +3,5 @@ Date: Thu, 11 Oct 2012 07:56:30 GMT Last-Modified: Thu, 11 Oct 2012 07:05:29 GMT Server: Jetty(6.1.11) -{"responseHeader":{"status":0,"QTime":22},"match":{"numFound":1,"start":0,"maxScore":14.28401,"docs":[{"genre":["Domestic fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["170 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"2001033643","callnumber-a":"PS3552.R878","publisher":["Feminist Press at the City University of New York,"],"id":"704640","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","The test /","Adult children of aging parents Fiction","Automobile drivers' tests Fiction","Fathers and daughters Fiction","Middle aged women Fiction","Older men Fiction"],"title":"The test /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","The test / Dorothy Bryant ; afterword by Barbara Horn.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 2001.","170 p. ; 22 cm.","Originally published: Ata Books, Berkeley, Calif., 1991.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","Includes bibliographical references (p. 169-170).","May06eng","Adult children of aging parents Fiction.","Automobile drivers' tests Fiction.","Fathers and daughters Fiction.","Middle aged women Fiction.","Older men Fiction.","Domestic fiction. lcsh","MAIN PS3552.R878 T47 2001"],"last_indexed":"2012-09-27T21:19:18Z","isbn":["1558612742 (pbk. : alk. paper)"],"callnumber-label":"PS3552","publishDate":["2001"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["47013195"],"topic":["Adult children of aging parents Fiction","Automobile drivers' tests Fiction","Fathers and daughters Fiction","Middle aged women Fiction","Older men Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"The test /","callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878T472001","topic_facet":["Adult children of aging parents","Automobile drivers' tests","Fathers and daughters","Middle aged women","Older men"],"format":["Book"],"title_sort":"test","title_short":"The test /","ctrlnum":["(OCoLC)ocm47013195"],"fullrecord":"01252cam a2200337 a 4500001000700000005001700007008004100024010001700065035002300082040003700105020003500142050002600177049000900203100002800212245006000240250002700300260007400327300002100401500006100422500011400483504005400597590001300651650004600664650004000710650003600750650003200786650002400818655002800842994001200870852003200882#30;704640#30;20060525093449.0#30;060508r20011991nyu b 000 1 eng #30; #31;a 2001033643#30; #31;a(OCoLC)ocm47013195#30; #31;aDLC#31;cDLC#31;dYDX#31;dOCLCQ#31;dBAKER#31;dPVU#30; #31;a1558612742 (pbk. : alk. paper)#30;00#31;aPS3552.R878#31;bT47 2001#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;14#31;aThe test /#31;cDorothy Bryant ; afterword by Barbara Horn.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c2001.#30; #31;a170 p. ;#31;c22 cm.#30; #31;aOriginally published: Ata Books, Berkeley, Calif., 1991.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aIncludes bibliographical references (p. 169-170).#30; #31;aMay06eng#30; 0#31;aAdult children of aging parents#31;vFiction.#30; 0#31;aAutomobile drivers' tests#31;vFiction.#30; 0#31;aFathers and daughters#31;vFiction.#30; 0#31;aMiddle aged women#31;vFiction.#30; 0#31;aOlder men#31;vFiction.#30; 7#31;aDomestic fiction.#31;2lcsh#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iT47 2001#30;#29;","first_indexed":"2012-09-27T21:19:18Z","author-letter":"Bryant, Dorothy,","language":["English"],"title_full":"The test / Dorothy Bryant ; afterword by Barbara Horn.","title_fullStr":"The test / Dorothy Bryant ; afterword by Barbara Horn.","title_full_unstemmed":"The test / Dorothy Bryant ; afterword by Barbara Horn.","genre_facet":["Fiction.","Domestic fiction."],"_version_":1446541939723730944,"score":14.28401}]},"response":{"numFound":1079840,"start":0,"maxScore":2.3629262,"docs":[{"genre":["Psychological fiction. lcsh","Feminist fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["186 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"97016088","callnumber-a":"PS3552.R878","publisher":["Feminist Press at the City University of New York,"],"id":"704635","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","Miss Giardino /","Italian American women Fiction","High school teachers Fiction","Retired teachers Fiction","Women teachers Fiction","Older women Fiction"],"title":"Miss Giardino /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 1997.","186 p. ; 22 cm.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","Includes bibliographical references (p. 181-185).","May06eng","Italian American women Fiction.","High school teachers Fiction.","Retired teachers Fiction.","Women teachers Fiction.","San Francisco (Calif.) Fiction.","Older women Fiction.","Psychological fiction. lcsh","Feminist fiction. lcsh","MAIN PS3552.R878 M5 1997"],"last_indexed":"2012-09-27T21:19:18Z","isbn":["1558611746 (pbk. : alk. paper)"],"callnumber-label":"PS3552","publishDate":["1997"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["36776451"],"topic":["Italian American women Fiction","High school teachers Fiction","Retired teachers Fiction","Women teachers Fiction","Older women Fiction"],"building":["Falvey Library"],"geographic":["San Francisco (Calif.) Fiction"],"callnumber-first":"P - Language and Literature","title_auth":"Miss Giardino /","geographic_facet":["San Francisco (Calif.)"],"callnumber":"PS3552.R878M51997","callnumber-subject":"PS - American Literature","topic_facet":["Italian American women","High school teachers","Retired teachers","Women teachers","Older women"],"format":["Book"],"title_sort":"miss giardino","title_short":"Miss Giardino /","ctrlnum":["(OCoLC)ocm36776451"],"fullrecord":"01267cam a2200361 a 4500001000700000005001700007008004100024010001700065035002300082040002500105020003500130043001200165050002500177049000900202100002800211245006400239250002700303260007400330300002100404500011400425504005400539590001300593650003700606650003500643650003100678650002900709651003700738650002600775655003300801655002800834994001200862852003100874#30;704635#30;20060525110908.0#30;060508r19971978nyu b 000 1 eng #30; #31;a 97016088 #30; #31;a(OCoLC)ocm36776451#30; #31;aDLC#31;cDLC#31;dBAKER#31;dPVU#30; #31;a1558611746 (pbk. : alk. paper)#30; #31;an-us-ca#30;00#31;aPS3552.R878#31;bM5 1997#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aMiss Giardino /#31;cDorothy Bryant ; afterword by Janet Zandy.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c1997.#30; #31;a186 p. ;#31;c22 cm.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aIncludes bibliographical references (p. 181-185).#30; #31;aMay06eng#30; 0#31;aItalian American women#31;vFiction.#30; 0#31;aHigh school teachers#31;vFiction.#30; 0#31;aRetired teachers#31;vFiction.#30; 0#31;aWomen teachers#31;vFiction.#30; 0#31;aSan Francisco (Calif.)#31;vFiction.#30; 0#31;aOlder women#31;vFiction.#30; 7#31;aPsychological fiction.#31;2lcsh#30; 7#31;aFeminist fiction.#31;2lcsh#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iM5 1997#30;#29;","first_indexed":"2012-09-27T21:19:18Z","author-letter":"Bryant, Dorothy,","language":["English"],"title_full":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","title_fullStr":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","title_full_unstemmed":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","genre_facet":["Fiction.","Psychological fiction.","Feminist fiction."],"_version_":1446541939715342336,"score":2.3629262},{"genre":["Psychological fiction. lcsh","Diary fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["265 p. ; 22 cm."],"dewey-tens":["810 - American literature in English"],"callnumber-a":"PS3552.R878","lccn":"97014405","callnumber-subject-code":"PS","dewey-hundreds":["800 - Literature"],"title_sub":"a novel /","publishDate":["1997"],"recordtype":"marc","topic":["Middle aged women California Education Fiction","Married women California Psychology Fiction"],"spellingShingle":["Middle aged women California Education Fiction","Married women California Psychology Fiction","Bryant, Dorothy, 1930-","Ella Price's journal : a novel /"],"geographic_facet":["California"],"callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878E431997","dewey-sort-browse":["813.00000000"],"format":["Book"],"title_short":"Ella Price's journal :","title_sort":"ella price's journal :a novel","fullrecord":"01121cam a2200313 a 4500001000700000005001700007008004100024010001700065035002000082040002300102020003600125020003500161043001200196050002600208082001600234049000900250100002800259245008600287250002700373260007400400300002100474500006500495504005000560650005500610650005200665655003300717655002500750852003200775#30;476297#30;19980910105451.0#30;980910r19971972nyu b 000 1 eng #30; #31;a 97014405 #30; #31;a(OCoLC)36767574#30; #31;aDLC#31;cDLC#31;dC#P#31;dPVU#30; #31;a1558611819 (cloth : alk. paper)#30; #31;a1558611754 (pbk. : alk. paper)#30; #31;an-us-ca#30;00#31;aPS3552.R878#31;bE43 1997#30;00#31;a813/.54#31;221#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aElla Price's journal :#31;ba novel /#31;cby Dorothy Bryant ; afterword by Barbara Horn.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c1997.#30; #31;a265 p. ;#31;c22 cm.#30; #31;a\"Originally published by J.B. Lippincott, 1972\"--T.p. verso.#30; #31;aIncludes bibliographical references (p. 264).#30; 0#31;aMiddle aged women#31;zCalifornia#31;xEducation#31;xFiction.#30; 0#31;aMarried women#31;zCalifornia#31;xPsychology#31;xFiction.#30; 7#31;aPsychological fiction.#31;2lcsh#30; 7#31;aDiary fiction.#31;2lcsh#30;0 #31;bMAIN#31;hPS3552.R878#31;iE43 1997#30;#29;","dewey-ones":["813 - American fiction in English"],"ctrlnum":["(OCoLC)36767574"],"marc_error":["Typo : Erroneous character found at end of leader [ 45e0 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"author-letter":"Bryant, Dorothy,","language":["English"],"dewey-raw":["813/.54"],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"publisher":["Feminist Press at the City University of New York,"],"id":"476297","author":"Bryant, Dorothy, 1930-","title":"Ella Price's journal : a novel /","spelling":["Bryant, Dorothy, 1930-","Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 1997.","265 p. ; 22 cm.","\"Originally published by J.B. Lippincott, 1972\"--T.p. verso.","Includes bibliographical references (p. 264).","Middle aged women California Education Fiction.","Married women California Psychology Fiction.","Psychological fiction. lcsh","Diary fiction. lcsh","MAIN PS3552.R878 E43 1997"],"last_indexed":"2012-09-27T19:12:22Z","isbn":["1558611819 (cloth : alk. paper)","1558611754 (pbk. : alk. paper)"],"callnumber-label":"PS3552","institution":["Villanova University"],"oclc_num":["36767574"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Ella Price's journal : a novel /","dewey-sort":"813.00000000","topic_facet":["Middle aged women","Married women","Education","Fiction.","Psychology"],"dewey-full":["813/.54"],"first_indexed":"2012-09-27T19:12:22Z","genre_facet":["Psychological fiction.","Diary fiction."],"title_full":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","title_fullStr":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","title_full_unstemmed":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","_version_":1446540985586679809,"score":2.1145177},{"edition":"1st ed.","physical":["303 p. : 1 map ; 23 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"93072365","callnumber-a":"PS3552.R878","publisher":["Ata Books,"],"id":"704643","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","Anita, Anita : Garibaldi of the New World : a novel /","Garibaldi, Anita, 1821?-1849 Fiction","Garibaldi, Giuseppe, 1807-1882 Fiction"],"title":"Anita, Anita : Garibaldi of the New World : a novel /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","1st ed.","Berkeley, Calif. : Ata Books, c1993.","303 p. : 1 map ; 23 cm.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","May06eng","Garibaldi, Anita, 1821?-1849 Fiction.","Garibaldi, Giuseppe, 1807-1882 Fiction.","MAIN PS3552.R878 A83 1993"],"title_sub":"Garibaldi of the New World : a novel /","last_indexed":"2012-09-27T21:19:18Z","isbn":["0931688175 (cloth) :","0931688183 (paper)"],"callnumber-label":"PS3552","era_facet":["1821?-1849","1807-1882"],"publishDate":["1993"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["29789196"],"topic":["Garibaldi, Anita, 1821?-1849 Fiction","Garibaldi, Giuseppe, 1807-1882 Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Anita, Anita : Garibaldi of the New World : a novel /","callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878A831993","format":["Book"],"title_sort":"anita, anita :garibaldi of the new world : a novel","title_short":"Anita, Anita :","ctrlnum":["(OCoLC)ocm29789196"],"fullrecord":"00957cam a2200277 a 4500001000700000005001700007008004100024010001700065035002300082040003000105020003300135020002300168050002600191049000900217100002800226245007900254250001200333260004300345300003000388500011400418590001300532600004400545600004600589994001200635852003200647#30;704643#30;20060525092525.0#30;060508s1993 caub 000 1 eng #30; #31;a 93072365 #30; #31;a(OCoLC)ocm29789196#30; #31;aDLC#31;cDLC#31;dOCL#31;dBAKER#31;dPVU#30; #31;a0931688175 (cloth) :#31;c$20.00#30; #31;a0931688183 (paper)#30;00#31;aPS3552.R878#31;bA83 1993#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aAnita, Anita :#31;bGaribaldi of the New World : a novel /#31;cby Dorothy Bryant.#30; #31;a1st ed.#30; #31;aBerkeley, Calif. :#31;bAta Books,#31;cc1993.#30; #31;a303 p. :#31;b1 map ;#31;c23 cm.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aMay06eng#30;10#31;aGaribaldi, Anita,#31;d1821?-1849#31;vFiction.#30;10#31;aGaribaldi, Giuseppe,#31;d1807-1882#31;vFiction.#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iA83 1993#30;#29;","first_indexed":"2012-09-27T21:19:18Z","author-letter":"Bryant, Dorothy,","language":["English"],"title_full":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","title_fullStr":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","title_full_unstemmed":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","genre_facet":["Fiction."],"_version_":1446541939727925248,"score":1.544408},{"edition":"1st ed.","physical":["144 p. : ill. ; 24 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"82073209","callnumber-a":"PS3552.R878","publisher":["Ata Books,"],"id":"704636","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","A day in San Francisco : a novel /","Parents of gays California San Francisco Fiction","Gay men California San Francisco Fiction","Parent and child Fiction"],"title":"A day in San Francisco : a novel /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","A day in San Francisco : a novel / by Dorothy Bryant.","1st ed.","Berkeley, Calif. : Ata Books, c1982.","144 p. : ill. ; 24 cm.","The Alfred S. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","May06eng","Parents of gays California San Francisco Fiction.","Gay men California San Francisco Fiction.","Parent and child Fiction.","San Francisco (Calif.) Fiction.","MAIN PS3552.R878 D3 1982"],"title_sub":"a novel /","last_indexed":"2012-09-27T21:19:18Z","isbn":["0931688094 :","0931688108 (pbk.) :"],"callnumber-label":"PS3552","publishDate":["1982"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["9094826"],"topic":["Parents of gays California San Francisco Fiction","Gay men California San Francisco Fiction","Parent and child Fiction"],"building":["Falvey Library"],"geographic":["San Francisco (Calif.) Fiction"],"callnumber-first":"P - Language and Literature","title_auth":"A day in San Francisco : a novel /","geographic_facet":["California","San Francisco","San Francisco (Calif.)"],"callnumber":"PS3552.R878D31982","callnumber-subject":"PS - American Literature","topic_facet":["Parents of gays","Gay men","Parent and child"],"format":["Book"],"title_sort":"day in san francisco :a novel","title_short":"A day in San Francisco :","ctrlnum":["(OCoLC)ocm09094826"],"fullrecord":"01072cam a2200313 a 4500001000700000005001700007008004100024010001700065035002300082040003500105020002500140020003100165043001200196050002500208049000900233100002800242245006000270250001200330260004300342300002900385500011400414590001300528650005700541650004900598650003100647651003700678994001200715852003100727#30;704636#30;20060525094305.0#30;060508s1982 caua 000 1 eng #30; #31;a 82073209 #30; #31;a(OCoLC)ocm09094826#30; #31;aDLC#31;cDLC#31;dGFK#31;dOCL#31;dOCLCQ#31;dPVU#30; #31;a0931688094 :#31;c$12.00#30; #31;a0931688108 (pbk.) :#31;c$6.00#30; #31;an-us-ca#30;0 #31;aPS3552.R878#31;bD3 1982#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;12#31;aA day in San Francisco :#31;ba novel /#31;cby Dorothy Bryant.#30; #31;a1st ed.#30; #31;aBerkeley, Calif. :#31;bAta Books,#31;cc1982.#30; #31;a144 p. :#31;bill. ;#31;c24 cm.#30; #31;aThe Alfred S. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aMay06eng#30; 0#31;aParents of gays#31;zCalifornia#31;zSan Francisco#31;vFiction.#30; 0#31;aGay men#31;zCalifornia#31;zSan Francisco#31;vFiction.#30; 0#31;aParent and child#31;vFiction.#30; 0#31;aSan Francisco (Calif.)#31;vFiction.#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iD3 1982#30;#29;","first_indexed":"2012-09-27T21:19:18Z","author-letter":"Bryant, Dorothy,","language":["English"],"title_full":"A day in San Francisco : a novel / by Dorothy Bryant.","title_fullStr":"A day in San Francisco : a novel / by Dorothy Bryant.","title_full_unstemmed":"A day in San Francisco : a novel / by Dorothy Bryant.","genre_facet":["Fiction."],"_version_":1446541939719536640,"score":1.5362269},{"genre":["Domestic fiction. lcsh"],"edition":"1st ed.","physical":["367 p. ; 22 cm."],"dewey-tens":["810 - American literature in English"],"callnumber-a":"PS3552.I74","lccn":"2001089763","callnumber-subject-code":"PS","dewey-hundreds":["800 - Literature"],"title_sub":"a novel /","publishDate":["2001"],"recordtype":"marc","topic":["Women college students Fiction","Children of military personnel Fiction","Americans Japan Okinawa-shi Fiction"],"spellingShingle":["Women college students Fiction","Children of military personnel Fiction","Americans Japan Okinawa-shi Fiction","Bird, Sarah.","The Yokota Officers Club : a novel /"],"geographic_facet":["Japan","Okinawa-shi","Okinawa-shi (Japan)"],"callnumber-subject":"PS - American Literature","callnumber":"PS3552.I74Y652001","dewey-sort-browse":["813.00000000"],"format":["Book"],"title_short":"The Yokota Officers Club :","title_sort":"yokota officers club :a novel","fullrecord":"00932cam a2200313 a 4500001000700000005001700007008004100024010001700065035002300082040001300105020001500118043002100133050002500154082001600179049000900195100001700204245005800221250001200279260006100291300002100352590001400373650003700387650004500424650004400469651003400513655002800547994001200575852003100587#30;576965#30;20020619143311.0#30;010406s2001 nyu 000 1 eng #30; #31;a 2001089763#30; #31;a(OCoLC)ocm47125699#30; #31;aDLC#31;cDLC#30; #31;a037541214X#30; #31;aa-ja---#31;an-us---#30;00#31;aPS3552.I74#31;bY65 2001#30;00#31;a813/.54#31;221#30; #31;aPVUM#30;1 #31;aBird, Sarah.#30;14#31;aThe Yokota Officers Club :#31;ba novel /#31;cby Sarah Bird.#30; #31;a1st ed.#30; #31;aNew York :#31;bKnopf :#31;bDistributed by Random House,#31;c2001.#30; #31;a367 p. ;#31;c22 cm.#30; #31;aJune02eng#30; 0#31;aWomen college students#31;vFiction.#30; 0#31;aChildren of military personnel#31;vFiction.#30; 0#31;aAmericans#31;zJapan#31;zOkinawa-shi#31;vFiction.#30; 0#31;aOkinawa-shi (Japan)#31;vFiction.#30; 7#31;aDomestic fiction.#31;2lcsh#30; #31;aE0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.I74#31;iY65 2001#30;#29;","dewey-ones":["813 - American fiction in English"],"ctrlnum":["(OCoLC)ocm47125699"],"marc_error":["Typo : Erroneous character found at end of leader [ 45e0 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"author-letter":"Bird, Sarah.","language":["English"],"dewey-raw":["813/.54"],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"publisher":["Knopf :"],"id":"576965","author":"Bird, Sarah.","title":"The Yokota Officers Club : a novel /","spelling":["Bird, Sarah.","The Yokota Officers Club : a novel / by Sarah Bird.","1st ed.","New York : Knopf : Distributed by Random House, 2001.","367 p. ; 22 cm.","June02eng","Women college students Fiction.","Children of military personnel Fiction.","Americans Japan Okinawa-shi Fiction.","Okinawa-shi (Japan) Fiction.","Domestic fiction. lcsh","MAIN PS3552.I74 Y65 2001"],"last_indexed":"2012-09-27T20:15:03Z","isbn":["037541214X"],"callnumber-label":"PS3552","institution":["Villanova University"],"oclc_num":["47125699"],"geographic":["Okinawa-shi (Japan) Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"The Yokota Officers Club : a novel /","dewey-sort":"813.00000000","topic_facet":["Women college students","Children of military personnel","Americans"],"dewey-full":["813/.54"],"first_indexed":"2012-09-27T20:15:03Z","genre_facet":["Fiction.","Domestic fiction."],"title_full":"The Yokota Officers Club : a novel / by Sarah Bird.","title_fullStr":"The Yokota Officers Club : a novel / by Sarah Bird.","title_full_unstemmed":"The Yokota Officers Club : a novel / by Sarah Bird.","_version_":1446541460167983104,"score":1.3638511}]}} +{"responseHeader":{"status":0,"QTime":22},"match":{"numFound":1,"start":0,"maxScore":14.28401,"docs":[{"genre":["Domestic fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["170 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"2001033643","callnumber-a":"PS3552.R878","publisher":["Feminist Press at the City University of New York,"],"id":"704640","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","The test /","Adult children of aging parents Fiction","Automobile drivers' tests Fiction","Fathers and daughters Fiction","Middle aged women Fiction","Older men Fiction"],"title":"The test /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","The test / Dorothy Bryant ; afterword by Barbara Horn.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 2001.","170 p. ; 22 cm.","Originally published: Ata Books, Berkeley, Calif., 1991.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","Includes bibliographical references (p. 169-170).","May06eng","Adult children of aging parents Fiction.","Automobile drivers' tests Fiction.","Fathers and daughters Fiction.","Middle aged women Fiction.","Older men Fiction.","Domestic fiction. lcsh","MAIN PS3552.R878 T47 2001"],"last_indexed":"2012-09-27T21:19:18Z","isbn":["1558612742 (pbk. : alk. paper)"],"callnumber-label":"PS3552","publishDate":["2001"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["47013195"],"topic":["Adult children of aging parents Fiction","Automobile drivers' tests Fiction","Fathers and daughters Fiction","Middle aged women Fiction","Older men Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"The test /","callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878T472001","topic_facet":["Adult children of aging parents","Automobile drivers' tests","Fathers and daughters","Middle aged women","Older men"],"format":["Book"],"title_sort":"test","title_short":"The test /","ctrlnum":["(OCoLC)ocm47013195"],"fullrecord":"01252cam a2200337 a 4500001000700000005001700007008004100024010001700065035002300082040003700105020003500142050002600177049000900203100002800212245006000240250002700300260007400327300002100401500006100422500011400483504005400597590001300651650004600664650004000710650003600750650003200786650002400818655002800842994001200870852003200882#30;704640#30;20060525093449.0#30;060508r20011991nyu b 000 1 eng #30; #31;a 2001033643#30; #31;a(OCoLC)ocm47013195#30; #31;aDLC#31;cDLC#31;dYDX#31;dOCLCQ#31;dBAKER#31;dPVU#30; #31;a1558612742 (pbk. : alk. paper)#30;00#31;aPS3552.R878#31;bT47 2001#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;14#31;aThe test /#31;cDorothy Bryant ; afterword by Barbara Horn.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c2001.#30; #31;a170 p. ;#31;c22 cm.#30; #31;aOriginally published: Ata Books, Berkeley, Calif., 1991.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aIncludes bibliographical references (p. 169-170).#30; #31;aMay06eng#30; 0#31;aAdult children of aging parents#31;vFiction.#30; 0#31;aAutomobile drivers' tests#31;vFiction.#30; 0#31;aFathers and daughters#31;vFiction.#30; 0#31;aMiddle aged women#31;vFiction.#30; 0#31;aOlder men#31;vFiction.#30; 7#31;aDomestic fiction.#31;2lcsh#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iT47 2001#30;#29;","first_indexed":"2012-09-27T21:19:18Z","language":["English"],"title_full":"The test / Dorothy Bryant ; afterword by Barbara Horn.","title_fullStr":"The test / Dorothy Bryant ; afterword by Barbara Horn.","title_full_unstemmed":"The test / Dorothy Bryant ; afterword by Barbara Horn.","genre_facet":["Fiction.","Domestic fiction."],"_version_":1446541939723730944,"score":14.28401}]},"response":{"numFound":1079840,"start":0,"maxScore":2.3629262,"docs":[{"genre":["Psychological fiction. lcsh","Feminist fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["186 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"97016088","callnumber-a":"PS3552.R878","publisher":["Feminist Press at the City University of New York,"],"id":"704635","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","Miss Giardino /","Italian American women Fiction","High school teachers Fiction","Retired teachers Fiction","Women teachers Fiction","Older women Fiction"],"title":"Miss Giardino /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 1997.","186 p. ; 22 cm.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","Includes bibliographical references (p. 181-185).","May06eng","Italian American women Fiction.","High school teachers Fiction.","Retired teachers Fiction.","Women teachers Fiction.","San Francisco (Calif.) Fiction.","Older women Fiction.","Psychological fiction. lcsh","Feminist fiction. lcsh","MAIN PS3552.R878 M5 1997"],"last_indexed":"2012-09-27T21:19:18Z","isbn":["1558611746 (pbk. : alk. paper)"],"callnumber-label":"PS3552","publishDate":["1997"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["36776451"],"topic":["Italian American women Fiction","High school teachers Fiction","Retired teachers Fiction","Women teachers Fiction","Older women Fiction"],"building":["Falvey Library"],"geographic":["San Francisco (Calif.) Fiction"],"callnumber-first":"P - Language and Literature","title_auth":"Miss Giardino /","geographic_facet":["San Francisco (Calif.)"],"callnumber":"PS3552.R878M51997","callnumber-subject":"PS - American Literature","topic_facet":["Italian American women","High school teachers","Retired teachers","Women teachers","Older women"],"format":["Book"],"title_sort":"miss giardino","title_short":"Miss Giardino /","ctrlnum":["(OCoLC)ocm36776451"],"fullrecord":"01267cam a2200361 a 4500001000700000005001700007008004100024010001700065035002300082040002500105020003500130043001200165050002500177049000900202100002800211245006400239250002700303260007400330300002100404500011400425504005400539590001300593650003700606650003500643650003100678650002900709651003700738650002600775655003300801655002800834994001200862852003100874#30;704635#30;20060525110908.0#30;060508r19971978nyu b 000 1 eng #30; #31;a 97016088 #30; #31;a(OCoLC)ocm36776451#30; #31;aDLC#31;cDLC#31;dBAKER#31;dPVU#30; #31;a1558611746 (pbk. : alk. paper)#30; #31;an-us-ca#30;00#31;aPS3552.R878#31;bM5 1997#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aMiss Giardino /#31;cDorothy Bryant ; afterword by Janet Zandy.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c1997.#30; #31;a186 p. ;#31;c22 cm.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aIncludes bibliographical references (p. 181-185).#30; #31;aMay06eng#30; 0#31;aItalian American women#31;vFiction.#30; 0#31;aHigh school teachers#31;vFiction.#30; 0#31;aRetired teachers#31;vFiction.#30; 0#31;aWomen teachers#31;vFiction.#30; 0#31;aSan Francisco (Calif.)#31;vFiction.#30; 0#31;aOlder women#31;vFiction.#30; 7#31;aPsychological fiction.#31;2lcsh#30; 7#31;aFeminist fiction.#31;2lcsh#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iM5 1997#30;#29;","first_indexed":"2012-09-27T21:19:18Z","language":["English"],"title_full":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","title_fullStr":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","title_full_unstemmed":"Miss Giardino / Dorothy Bryant ; afterword by Janet Zandy.","genre_facet":["Fiction.","Psychological fiction.","Feminist fiction."],"_version_":1446541939715342336,"score":2.3629262},{"genre":["Psychological fiction. lcsh","Diary fiction. lcsh"],"edition":"1st Feminist Press ed.","physical":["265 p. ; 22 cm."],"dewey-tens":["810 - American literature in English"],"callnumber-a":"PS3552.R878","lccn":"97014405","callnumber-subject-code":"PS","dewey-hundreds":["800 - Literature"],"title_sub":"a novel /","publishDate":["1997"],"recordtype":"marc","topic":["Middle aged women California Education Fiction","Married women California Psychology Fiction"],"spellingShingle":["Middle aged women California Education Fiction","Married women California Psychology Fiction","Bryant, Dorothy, 1930-","Ella Price's journal : a novel /"],"geographic_facet":["California"],"callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878E431997","dewey-sort-browse":["813.00000000"],"format":["Book"],"title_short":"Ella Price's journal :","title_sort":"ella price's journal :a novel","fullrecord":"01121cam a2200313 a 4500001000700000005001700007008004100024010001700065035002000082040002300102020003600125020003500161043001200196050002600208082001600234049000900250100002800259245008600287250002700373260007400400300002100474500006500495504005000560650005500610650005200665655003300717655002500750852003200775#30;476297#30;19980910105451.0#30;980910r19971972nyu b 000 1 eng #30; #31;a 97014405 #30; #31;a(OCoLC)36767574#30; #31;aDLC#31;cDLC#31;dC#P#31;dPVU#30; #31;a1558611819 (cloth : alk. paper)#30; #31;a1558611754 (pbk. : alk. paper)#30; #31;an-us-ca#30;00#31;aPS3552.R878#31;bE43 1997#30;00#31;a813/.54#31;221#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aElla Price's journal :#31;ba novel /#31;cby Dorothy Bryant ; afterword by Barbara Horn.#30; #31;a1st Feminist Press ed.#30; #31;aNew York :#31;bFeminist Press at the City University of New York,#31;c1997.#30; #31;a265 p. ;#31;c22 cm.#30; #31;a\"Originally published by J.B. Lippincott, 1972\"--T.p. verso.#30; #31;aIncludes bibliographical references (p. 264).#30; 0#31;aMiddle aged women#31;zCalifornia#31;xEducation#31;xFiction.#30; 0#31;aMarried women#31;zCalifornia#31;xPsychology#31;xFiction.#30; 7#31;aPsychological fiction.#31;2lcsh#30; 7#31;aDiary fiction.#31;2lcsh#30;0 #31;bMAIN#31;hPS3552.R878#31;iE43 1997#30;#29;","dewey-ones":["813 - American fiction in English"],"ctrlnum":["(OCoLC)36767574"],"marc_error":["Typo : Erroneous character found at end of leader [ 45e0 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"language":["English"],"dewey-raw":["813/.54"],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"publisher":["Feminist Press at the City University of New York,"],"id":"476297","author":"Bryant, Dorothy, 1930-","title":"Ella Price's journal : a novel /","spelling":["Bryant, Dorothy, 1930-","Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","1st Feminist Press ed.","New York : Feminist Press at the City University of New York, 1997.","265 p. ; 22 cm.","\"Originally published by J.B. Lippincott, 1972\"--T.p. verso.","Includes bibliographical references (p. 264).","Middle aged women California Education Fiction.","Married women California Psychology Fiction.","Psychological fiction. lcsh","Diary fiction. lcsh","MAIN PS3552.R878 E43 1997"],"last_indexed":"2012-09-27T19:12:22Z","isbn":["1558611819 (cloth : alk. paper)","1558611754 (pbk. : alk. paper)"],"callnumber-label":"PS3552","institution":["Villanova University"],"oclc_num":["36767574"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Ella Price's journal : a novel /","dewey-sort":"813.00000000","topic_facet":["Middle aged women","Married women","Education","Fiction.","Psychology"],"dewey-full":["813/.54"],"first_indexed":"2012-09-27T19:12:22Z","genre_facet":["Psychological fiction.","Diary fiction."],"title_full":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","title_fullStr":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","title_full_unstemmed":"Ella Price's journal : a novel / by Dorothy Bryant ; afterword by Barbara Horn.","_version_":1446540985586679809,"score":2.1145177},{"edition":"1st ed.","physical":["303 p. : 1 map ; 23 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"93072365","callnumber-a":"PS3552.R878","publisher":["Ata Books,"],"id":"704643","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","Anita, Anita : Garibaldi of the New World : a novel /","Garibaldi, Anita, 1821?-1849 Fiction","Garibaldi, Giuseppe, 1807-1882 Fiction"],"title":"Anita, Anita : Garibaldi of the New World : a novel /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","1st ed.","Berkeley, Calif. : Ata Books, c1993.","303 p. : 1 map ; 23 cm.","The Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","May06eng","Garibaldi, Anita, 1821?-1849 Fiction.","Garibaldi, Giuseppe, 1807-1882 Fiction.","MAIN PS3552.R878 A83 1993"],"title_sub":"Garibaldi of the New World : a novel /","last_indexed":"2012-09-27T21:19:18Z","isbn":["0931688175 (cloth) :","0931688183 (paper)"],"callnumber-label":"PS3552","era_facet":["1821?-1849","1807-1882"],"publishDate":["1993"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["29789196"],"topic":["Garibaldi, Anita, 1821?-1849 Fiction","Garibaldi, Giuseppe, 1807-1882 Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Anita, Anita : Garibaldi of the New World : a novel /","callnumber-subject":"PS - American Literature","callnumber":"PS3552.R878A831993","format":["Book"],"title_sort":"anita, anita :garibaldi of the new world : a novel","title_short":"Anita, Anita :","ctrlnum":["(OCoLC)ocm29789196"],"fullrecord":"00957cam a2200277 a 4500001000700000005001700007008004100024010001700065035002300082040003000105020003300135020002300168050002600191049000900217100002800226245007900254250001200333260004300345300003000388500011400418590001300532600004400545600004600589994001200635852003200647#30;704643#30;20060525092525.0#30;060508s1993 caub 000 1 eng #30; #31;a 93072365 #30; #31;a(OCoLC)ocm29789196#30; #31;aDLC#31;cDLC#31;dOCL#31;dBAKER#31;dPVU#30; #31;a0931688175 (cloth) :#31;c$20.00#30; #31;a0931688183 (paper)#30;00#31;aPS3552.R878#31;bA83 1993#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;10#31;aAnita, Anita :#31;bGaribaldi of the New World : a novel /#31;cby Dorothy Bryant.#30; #31;a1st ed.#30; #31;aBerkeley, Calif. :#31;bAta Books,#31;cc1993.#30; #31;a303 p. :#31;b1 map ;#31;c23 cm.#30; #31;aThe Alfred F. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aMay06eng#30;10#31;aGaribaldi, Anita,#31;d1821?-1849#31;vFiction.#30;10#31;aGaribaldi, Giuseppe,#31;d1807-1882#31;vFiction.#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iA83 1993#30;#29;","first_indexed":"2012-09-27T21:19:18Z","language":["English"],"title_full":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","title_fullStr":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","title_full_unstemmed":"Anita, Anita : Garibaldi of the New World : a novel / by Dorothy Bryant.","genre_facet":["Fiction."],"_version_":1446541939727925248,"score":1.544408},{"edition":"1st ed.","physical":["144 p. : ill. ; 24 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"82073209","callnumber-a":"PS3552.R878","publisher":["Ata Books,"],"id":"704636","author":"Bryant, Dorothy, 1930-","spellingShingle":["Bryant, Dorothy, 1930-","A day in San Francisco : a novel /","Parents of gays California San Francisco Fiction","Gay men California San Francisco Fiction","Parent and child Fiction"],"title":"A day in San Francisco : a novel /","callnumber-subject-code":"PS","spelling":["Bryant, Dorothy, 1930-","A day in San Francisco : a novel / by Dorothy Bryant.","1st ed.","Berkeley, Calif. : Ata Books, c1982.","144 p. : ill. ; 24 cm.","The Alfred S. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.","May06eng","Parents of gays California San Francisco Fiction.","Gay men California San Francisco Fiction.","Parent and child Fiction.","San Francisco (Calif.) Fiction.","MAIN PS3552.R878 D3 1982"],"title_sub":"a novel /","last_indexed":"2012-09-27T21:19:18Z","isbn":["0931688094 :","0931688108 (pbk.) :"],"callnumber-label":"PS3552","publishDate":["1982"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["9094826"],"topic":["Parents of gays California San Francisco Fiction","Gay men California San Francisco Fiction","Parent and child Fiction"],"building":["Falvey Library"],"geographic":["San Francisco (Calif.) Fiction"],"callnumber-first":"P - Language and Literature","title_auth":"A day in San Francisco : a novel /","geographic_facet":["California","San Francisco","San Francisco (Calif.)"],"callnumber":"PS3552.R878D31982","callnumber-subject":"PS - American Literature","topic_facet":["Parents of gays","Gay men","Parent and child"],"format":["Book"],"title_sort":"day in san francisco :a novel","title_short":"A day in San Francisco :","ctrlnum":["(OCoLC)ocm09094826"],"fullrecord":"01072cam a2200313 a 4500001000700000005001700007008004100024010001700065035002300082040003500105020002500140020003100165043001200196050002500208049000900233100002800242245006000270250001200330260004300342300002900385500011400414590001300528650005700541650004900598650003100647651003700678994001200715852003100727#30;704636#30;20060525094305.0#30;060508s1982 caua 000 1 eng #30; #31;a 82073209 #30; #31;a(OCoLC)ocm09094826#30; #31;aDLC#31;cDLC#31;dGFK#31;dOCL#31;dOCLCQ#31;dPVU#30; #31;a0931688094 :#31;c$12.00#30; #31;a0931688108 (pbk.) :#31;c$6.00#30; #31;an-us-ca#30;0 #31;aPS3552.R878#31;bD3 1982#30; #31;aPVUM#30;1 #31;aBryant, Dorothy,#31;d1930-#30;12#31;aA day in San Francisco :#31;ba novel /#31;cby Dorothy Bryant.#30; #31;a1st ed.#30; #31;aBerkeley, Calif. :#31;bAta Books,#31;cc1982.#30; #31;a144 p. :#31;bill. ;#31;c24 cm.#30; #31;aThe Alfred S. Mannella and Rose T. (Lauria) Mannella Endowed Library Fund donated by Alfred S. Mannella, '58.#30; #31;aMay06eng#30; 0#31;aParents of gays#31;zCalifornia#31;zSan Francisco#31;vFiction.#30; 0#31;aGay men#31;zCalifornia#31;zSan Francisco#31;vFiction.#30; 0#31;aParent and child#31;vFiction.#30; 0#31;aSan Francisco (Calif.)#31;vFiction.#30; #31;aC0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.R878#31;iD3 1982#30;#29;","first_indexed":"2012-09-27T21:19:18Z","language":["English"],"title_full":"A day in San Francisco : a novel / by Dorothy Bryant.","title_fullStr":"A day in San Francisco : a novel / by Dorothy Bryant.","title_full_unstemmed":"A day in San Francisco : a novel / by Dorothy Bryant.","genre_facet":["Fiction."],"_version_":1446541939719536640,"score":1.5362269},{"genre":["Domestic fiction. lcsh"],"edition":"1st ed.","physical":["367 p. ; 22 cm."],"dewey-tens":["810 - American literature in English"],"callnumber-a":"PS3552.I74","lccn":"2001089763","callnumber-subject-code":"PS","dewey-hundreds":["800 - Literature"],"title_sub":"a novel /","publishDate":["2001"],"recordtype":"marc","topic":["Women college students Fiction","Children of military personnel Fiction","Americans Japan Okinawa-shi Fiction"],"spellingShingle":["Women college students Fiction","Children of military personnel Fiction","Americans Japan Okinawa-shi Fiction","Bird, Sarah.","The Yokota Officers Club : a novel /"],"geographic_facet":["Japan","Okinawa-shi","Okinawa-shi (Japan)"],"callnumber-subject":"PS - American Literature","callnumber":"PS3552.I74Y652001","dewey-sort-browse":["813.00000000"],"format":["Book"],"title_short":"The Yokota Officers Club :","title_sort":"yokota officers club :a novel","fullrecord":"00932cam a2200313 a 4500001000700000005001700007008004100024010001700065035002300082040001300105020001500118043002100133050002500154082001600179049000900195100001700204245005800221250001200279260006100291300002100352590001400373650003700387650004500424650004400469651003400513655002800547994001200575852003100587#30;576965#30;20020619143311.0#30;010406s2001 nyu 000 1 eng #30; #31;a 2001089763#30; #31;a(OCoLC)ocm47125699#30; #31;aDLC#31;cDLC#30; #31;a037541214X#30; #31;aa-ja---#31;an-us---#30;00#31;aPS3552.I74#31;bY65 2001#30;00#31;a813/.54#31;221#30; #31;aPVUM#30;1 #31;aBird, Sarah.#30;14#31;aThe Yokota Officers Club :#31;ba novel /#31;cby Sarah Bird.#30; #31;a1st ed.#30; #31;aNew York :#31;bKnopf :#31;bDistributed by Random House,#31;c2001.#30; #31;a367 p. ;#31;c22 cm.#30; #31;aJune02eng#30; 0#31;aWomen college students#31;vFiction.#30; 0#31;aChildren of military personnel#31;vFiction.#30; 0#31;aAmericans#31;zJapan#31;zOkinawa-shi#31;vFiction.#30; 0#31;aOkinawa-shi (Japan)#31;vFiction.#30; 7#31;aDomestic fiction.#31;2lcsh#30; #31;aE0#31;bPVU#30;0 #31;bMAIN#31;hPS3552.I74#31;iY65 2001#30;#29;","dewey-ones":["813 - American fiction in English"],"ctrlnum":["(OCoLC)ocm47125699"],"marc_error":["Typo : Erroneous character found at end of leader [ 45e0 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"language":["English"],"dewey-raw":["813/.54"],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"publisher":["Knopf :"],"id":"576965","author":"Bird, Sarah.","title":"The Yokota Officers Club : a novel /","spelling":["Bird, Sarah.","The Yokota Officers Club : a novel / by Sarah Bird.","1st ed.","New York : Knopf : Distributed by Random House, 2001.","367 p. ; 22 cm.","June02eng","Women college students Fiction.","Children of military personnel Fiction.","Americans Japan Okinawa-shi Fiction.","Okinawa-shi (Japan) Fiction.","Domestic fiction. lcsh","MAIN PS3552.I74 Y65 2001"],"last_indexed":"2012-09-27T20:15:03Z","isbn":["037541214X"],"callnumber-label":"PS3552","institution":["Villanova University"],"oclc_num":["47125699"],"geographic":["Okinawa-shi (Japan) Fiction"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"The Yokota Officers Club : a novel /","dewey-sort":"813.00000000","topic_facet":["Women college students","Children of military personnel","Americans"],"dewey-full":["813/.54"],"first_indexed":"2012-09-27T20:15:03Z","genre_facet":["Fiction.","Domestic fiction."],"title_full":"The Yokota Officers Club : a novel / by Sarah Bird.","title_fullStr":"The Yokota Officers Club : a novel / by Sarah Bird.","title_full_unstemmed":"The Yokota Officers Club : a novel / by Sarah Bird.","_version_":1446541460167983104,"score":1.3638511}]}} diff --git a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record b/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record index ed1fba8a5df..d521e23bb62 100644 --- a/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record +++ b/module/VuFindSearch/tests/unit-tests/fixtures/solr/response/multi-record @@ -3,4 +3,4 @@ Date: Thu, 11 Oct 2012 07:56:30 GMT Last-Modified: Thu, 11 Oct 2012 07:05:29 GMT Server: Jetty(6.1.11) -{"responseHeader":{"status":0,"QTime":1,"params":{"q":"id:(12345 OR 125456 OR 234547)","json.nl":"arrarr","wt":"json"}},"response":{"numFound":3,"start":0,"docs":[{"physical":["viii, 163 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"F","dewey-tens":["010 - Bibliographies"],"collection":["Main Stacks"],"lccn":"79028077","callnumber-a":"F1411.A2N48","publisher":["Greenwood Press,"],"id":"12345","author":"Nawaz, Tawfique.","spellingShingle":["Nawaz, Tawfique.","The new international economic order : a bibliography /","International economic relations Bibliography"],"title":"The new international economic order : a bibliography /","callnumber-subject-code":"F","spelling":["Nawaz, Tawfique.","The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","Westport, Conn. : Greenwood Press, 1980.","viii, 163 p. ; 22 cm.","International economic relations Bibliography.","MAIN F1411.A2N48"],"title_sub":"a bibliography /","dewey-hundreds":["000 - Computer science, information & general works"],"last_indexed":"2012-09-27T14:51:17Z","isbn":["0313221111"],"callnumber-label":"F1411","publishDate":["1980"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["5831268"],"topic":["International economic relations Bibliography"],"building":["Falvey Library"],"callnumber-first":"F - General American History","title_auth":"The new international economic order : a bibliography /","dewey-sort":"016.33700000","dewey-sort-browse":["016.33700000"],"callnumber":"F1411.A2N48","callnumber-subject":"F - General American History","topic_facet":["International economic relations","Bibliography."],"format":["Book"],"title_sort":"new international economic order :a bibliography","title_short":"The new international economic order :","dewey-full":["016.337"],"ctrlnum":["ocm05831268 820113","(CaOTULAS)157328431"],"dewey-ones":["016 - Bibliographies of works on specific subjects"],"fullrecord":"00732cam a22002411a 4500001000600000008004100006010001700047020001500064035002300079035002400102035001300126040002400139049002000163050001800183082001200201099001600213100002100229245009200250260004700342300002700389650005200416852002200468#30;12345#30;791205s1980 ctu b 000 0 eng #30; #31;a 79028077 #30; #31;a0313221111#30; #31;aocm05831268 820113#30; #31;a(CaOTULAS)157328431#30; #31;900013296#30; #31;aDLC#31;cDLC#31;dm.c.#31;dPVU#30; #31;aPVUM#31;c[0480355]#30;0 #31;aF1411.A2#31;bN48#30; #31;a016.337#30;1 #31;aF1411.A2N48#30;1 #31;aNawaz, Tawfique.#30;14#31;aThe new international economic order :#31;ba bibliography /#31;c[compiled by] Tawfique Nawaz.#30; #31;aWestport, Conn. :#31;bGreenwood Press,#31;c1980.#30; #31;aviii, 163 p. ;#31;c22 cm.#30; 0#31;aInternational economic relations#31;xBibliography.#30;0 #31;bMAIN#31;hF1411.A2N48#30;#29;","first_indexed":"2012-09-27T14:51:17Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"author-letter":"Nawaz, Tawfique.","language":["English"],"title_full":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","title_fullStr":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","title_full_unstemmed":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","dewey-raw":["016.337"],"_version_":1446539186124357632},{"physical":["xv, 298 p. : ports. ; 23 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"57000890","callnumber-a":"PR4382.K54","publisher":["Routledge and K. Paul,"],"id":"125456","author":"Knight, George Wilson, 1897-","spellingShingle":["Knight, George Wilson, 1897-","Lord Byron's marriage ; the evidence of asterisks /","Byron, George Gordon Byron, Baron, 1788-1824 Marriage"],"title":"Lord Byron's marriage ; the evidence of asterisks /","callnumber-subject-code":"PR","spelling":["Knight, George Wilson, 1897-","Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","London : Routledge and K. Paul, [1957]","xv, 298 p. : ports. ; 23 cm.","Includes index.","Bibliography: p. xiii-xv.","Byron, George Gordon Byron, Baron, 1788-1824 Marriage.","MAIN PR4382.K54"],"title_sub":"the evidence of asterisks /","last_indexed":"2012-09-27T16:01:13Z","callnumber-label":"PR4382","era_facet":["1788-1824"],"publishDate":["1957"],"institution":["Villanova University"],"recordtype":"marc","topic":["Byron, George Gordon Byron, Baron, 1788-1824 Marriage"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Lord Byron's marriage ; the evidence of asterisks /","callnumber-subject":"PR - English Literature","callnumber":"PR4382.K54","topic_facet":["Marriage."],"format":["Book"],"title_sort":"lord byron's marriage ;the evidence of asterisks","title_short":"Lord Byron's marriage ;","ctrlnum":["(CaOTULAS)203368380"],"fullrecord":"00735cam a22002411a 4500001000700000008004100007010001700048035002400065035001300089040000700102043001200109049000900121050002200130099001500152100003400167245007900201260004500280300003500325500002000360504003000380600006200410852002100472#30;125456#30;900523s1957 enkc b 001 0beng d#30; #31;a 57000890 #30; #31;a(CaOTULAS)203368380#30; #31;900133275#30; #31;aLC#30; #31;ae-uk---#30; #31;aPVUM#30; 0#31;aPR4382#31;b.K54 1957#30;1 #31;aPR4382.K54#30;1 #31;aKnight, George Wilson,#31;d1897-#30;10#31;aLord Byron's marriage ;#31;bthe evidence of asterisks /#31;cby G. Wilson Knight.#30; #31;aLondon :#31;bRoutledge and K. Paul,#31;c[1957]#30; #31;axv, 298 p. :#31;bports. ;#31;c23 cm.#30; #31;aIncludes index.#30; #31;aBibliography: p. xiii-xv.#30;10#31;aByron, George Gordon Byron,#31;cBaron,#31;d1788-1824#31;xMarriage.#30;0 #31;bMAIN#31;hPR4382.K54#30;#29;","first_indexed":"2012-09-27T16:01:13Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"author-letter":"Knight, George Wilson,","language":["English"],"title_full":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","title_fullStr":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","title_full_unstemmed":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","_version_":1446539687921451008},{"edition":"[1st ed.]. -","physical":["xvii, 284 p.; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"79165402","callnumber-a":"PS3563.I423R4","publisher":["Farrar, Straus and Giroux,"],"id":"234547","author":"Mills, James, 1932-","spellingShingle":["Mills, James, 1932-","Report to the commissioner. -"],"title":"Report to the commissioner. -","callnumber-subject-code":"PZ","spelling":["Mills, James, 1932-","Report to the commissioner. -","[1st ed.]. -","New York: Farrar, Straus and Giroux, [1972]","xvii, 284 p.; 22 cm.","A novel.","MAIN PS3563.I423R4"],"last_indexed":"2012-09-27T17:00:08Z","isbn":["0374249407:"],"callnumber-label":"PZ4","publishDate":["1972"],"institution":["Villanova University"],"recordtype":"marc","building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Report to the commissioner. -","callnumber-subject":"PZ - Fiction","callnumber":"PS3563.I423R4","format":["Book"],"title_sort":"report to the commissioner. -","title_short":"Report to the commissioner. -","ctrlnum":["(CaOTULAS)203453340"],"fullrecord":"00608cam a22002291a 4500001000700000008004100007010001700048020002200065035002400087035001300111040000700124049000900131050003100140099001800171100002500189245003400214250001700248260005000265300002600315500001300341852002400354#30;234547#30;900804s1972 nyu 000 1 eng u#30; #31;a 79165402 #30; #31;a0374249407:#31;c6.95#30; #31;a(CaOTULAS)203453340#30; #31;900252111#30; #31;aLC#30; #31;aPVUM#30; 0#31;aPZ4.M6557#31;bRe#31;aPS3563.I423#30;1 #31;aPS3563.I423R4#30;1 #31;aMills, James,#31;d1932-#30;10#31;aReport to the commissioner. -#30; #31;a[1st ed.]. -#30; #31;aNew York:#31;bFarrar, Straus and Giroux,#31;c[1972]#30; #31;axvii, 284 p.;#31;c22 cm.#30; #31;aA novel.#30;0 #31;bMAIN#31;hPS3563.I423R4#30;#29;","first_indexed":"2012-09-27T17:00:08Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"author-letter":"Mills, James,","language":["English"],"title_full":"Report to the commissioner. -","title_fullStr":"Report to the commissioner. -","title_full_unstemmed":"Report to the commissioner. -","_version_":1446540071117258752}]}} +{"responseHeader":{"status":0,"QTime":1,"params":{"q":"id:(12345 OR 125456 OR 234547)","json.nl":"arrarr","wt":"json"}},"response":{"numFound":3,"start":0,"docs":[{"physical":["viii, 163 p. ; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"F","dewey-tens":["010 - Bibliographies"],"collection":["Main Stacks"],"lccn":"79028077","callnumber-a":"F1411.A2N48","publisher":["Greenwood Press,"],"id":"12345","author":"Nawaz, Tawfique.","spellingShingle":["Nawaz, Tawfique.","The new international economic order : a bibliography /","International economic relations Bibliography"],"title":"The new international economic order : a bibliography /","callnumber-subject-code":"F","spelling":["Nawaz, Tawfique.","The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","Westport, Conn. : Greenwood Press, 1980.","viii, 163 p. ; 22 cm.","International economic relations Bibliography.","MAIN F1411.A2N48"],"title_sub":"a bibliography /","dewey-hundreds":["000 - Computer science, information & general works"],"last_indexed":"2012-09-27T14:51:17Z","isbn":["0313221111"],"callnumber-label":"F1411","publishDate":["1980"],"institution":["Villanova University"],"recordtype":"marc","oclc_num":["5831268"],"topic":["International economic relations Bibliography"],"building":["Falvey Library"],"callnumber-first":"F - General American History","title_auth":"The new international economic order : a bibliography /","dewey-sort":"016.33700000","dewey-sort-browse":["016.33700000"],"callnumber":"F1411.A2N48","callnumber-subject":"F - General American History","topic_facet":["International economic relations","Bibliography."],"format":["Book"],"title_sort":"new international economic order :a bibliography","title_short":"The new international economic order :","dewey-full":["016.337"],"ctrlnum":["ocm05831268 820113","(CaOTULAS)157328431"],"dewey-ones":["016 - Bibliographies of works on specific subjects"],"fullrecord":"00732cam a22002411a 4500001000600000008004100006010001700047020001500064035002300079035002400102035001300126040002400139049002000163050001800183082001200201099001600213100002100229245009200250260004700342300002700389650005200416852002200468#30;12345#30;791205s1980 ctu b 000 0 eng #30; #31;a 79028077 #30; #31;a0313221111#30; #31;aocm05831268 820113#30; #31;a(CaOTULAS)157328431#30; #31;900013296#30; #31;aDLC#31;cDLC#31;dm.c.#31;dPVU#30; #31;aPVUM#31;c[0480355]#30;0 #31;aF1411.A2#31;bN48#30; #31;a016.337#30;1 #31;aF1411.A2N48#30;1 #31;aNawaz, Tawfique.#30;14#31;aThe new international economic order :#31;ba bibliography /#31;c[compiled by] Tawfique Nawaz.#30; #31;aWestport, Conn. :#31;bGreenwood Press,#31;c1980.#30; #31;aviii, 163 p. ;#31;c22 cm.#30; 0#31;aInternational economic relations#31;xBibliography.#30;0 #31;bMAIN#31;hF1411.A2N48#30;#29;","first_indexed":"2012-09-27T14:51:17Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"language":["English"],"title_full":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","title_fullStr":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","title_full_unstemmed":"The new international economic order : a bibliography / [compiled by] Tawfique Nawaz.","dewey-raw":["016.337"],"_version_":1446539186124357632},{"physical":["xv, 298 p. : ports. ; 23 cm."],"illustrated":"Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"57000890","callnumber-a":"PR4382.K54","publisher":["Routledge and K. Paul,"],"id":"125456","author":"Knight, George Wilson, 1897-","spellingShingle":["Knight, George Wilson, 1897-","Lord Byron's marriage ; the evidence of asterisks /","Byron, George Gordon Byron, Baron, 1788-1824 Marriage"],"title":"Lord Byron's marriage ; the evidence of asterisks /","callnumber-subject-code":"PR","spelling":["Knight, George Wilson, 1897-","Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","London : Routledge and K. Paul, [1957]","xv, 298 p. : ports. ; 23 cm.","Includes index.","Bibliography: p. xiii-xv.","Byron, George Gordon Byron, Baron, 1788-1824 Marriage.","MAIN PR4382.K54"],"title_sub":"the evidence of asterisks /","last_indexed":"2012-09-27T16:01:13Z","callnumber-label":"PR4382","era_facet":["1788-1824"],"publishDate":["1957"],"institution":["Villanova University"],"recordtype":"marc","topic":["Byron, George Gordon Byron, Baron, 1788-1824 Marriage"],"building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Lord Byron's marriage ; the evidence of asterisks /","callnumber-subject":"PR - English Literature","callnumber":"PR4382.K54","topic_facet":["Marriage."],"format":["Book"],"title_sort":"lord byron's marriage ;the evidence of asterisks","title_short":"Lord Byron's marriage ;","ctrlnum":["(CaOTULAS)203368380"],"fullrecord":"00735cam a22002411a 4500001000700000008004100007010001700048035002400065035001300089040000700102043001200109049000900121050002200130099001500152100003400167245007900201260004500280300003500325500002000360504003000380600006200410852002100472#30;125456#30;900523s1957 enkc b 001 0beng d#30; #31;a 57000890 #30; #31;a(CaOTULAS)203368380#30; #31;900133275#30; #31;aLC#30; #31;ae-uk---#30; #31;aPVUM#30; 0#31;aPR4382#31;b.K54 1957#30;1 #31;aPR4382.K54#30;1 #31;aKnight, George Wilson,#31;d1897-#30;10#31;aLord Byron's marriage ;#31;bthe evidence of asterisks /#31;cby G. Wilson Knight.#30; #31;aLondon :#31;bRoutledge and K. Paul,#31;c[1957]#30; #31;axv, 298 p. :#31;bports. ;#31;c23 cm.#30; #31;aIncludes index.#30; #31;aBibliography: p. xiii-xv.#30;10#31;aByron, George Gordon Byron,#31;cBaron,#31;d1788-1824#31;xMarriage.#30;0 #31;bMAIN#31;hPR4382.K54#30;#29;","first_indexed":"2012-09-27T16:01:13Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"language":["English"],"title_full":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","title_fullStr":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","title_full_unstemmed":"Lord Byron's marriage ; the evidence of asterisks / by G. Wilson Knight.","_version_":1446539687921451008},{"edition":"[1st ed.]. -","physical":["xvii, 284 p.; 22 cm."],"illustrated":"Not Illustrated","callnumber-first-code":"P","collection":["Main Stacks"],"lccn":"79165402","callnumber-a":"PS3563.I423R4","publisher":["Farrar, Straus and Giroux,"],"id":"234547","author":"Mills, James, 1932-","spellingShingle":["Mills, James, 1932-","Report to the commissioner. -"],"title":"Report to the commissioner. -","callnumber-subject-code":"PZ","spelling":["Mills, James, 1932-","Report to the commissioner. -","[1st ed.]. -","New York: Farrar, Straus and Giroux, [1972]","xvii, 284 p.; 22 cm.","A novel.","MAIN PS3563.I423R4"],"last_indexed":"2012-09-27T17:00:08Z","isbn":["0374249407:"],"callnumber-label":"PZ4","publishDate":["1972"],"institution":["Villanova University"],"recordtype":"marc","building":["Falvey Library"],"callnumber-first":"P - Language and Literature","title_auth":"Report to the commissioner. -","callnumber-subject":"PZ - Fiction","callnumber":"PS3563.I423R4","format":["Book"],"title_sort":"report to the commissioner. -","title_short":"Report to the commissioner. -","ctrlnum":["(CaOTULAS)203453340"],"fullrecord":"00608cam a22002291a 4500001000700000008004100007010001700048020002200065035002400087035001300111040000700124049000900131050003100140099001800171100002500189245003400214250001700248260005000265300002600315500001300341852002400354#30;234547#30;900804s1972 nyu 000 1 eng u#30; #31;a 79165402 #30; #31;a0374249407:#31;c6.95#30; #31;a(CaOTULAS)203453340#30; #31;900252111#30; #31;aLC#30; #31;aPVUM#30; 0#31;aPZ4.M6557#31;bRe#31;aPS3563.I423#30;1 #31;aPS3563.I423R4#30;1 #31;aMills, James,#31;d1932-#30;10#31;aReport to the commissioner. -#30; #31;a[1st ed.]. -#30; #31;aNew York:#31;bFarrar, Straus and Giroux,#31;c[1972]#30; #31;axvii, 284 p.;#31;c22 cm.#30; #31;aA novel.#30;0 #31;bMAIN#31;hPS3563.I423R4#30;#29;","first_indexed":"2012-09-27T17:00:08Z","marc_error":["Typo : Erroneous character found at end of leader [ 45 ]; changing them to the standard \"4500\" --- [ n/a : n/a ]"],"language":["English"],"title_full":"Report to the commissioner. -","title_fullStr":"Report to the commissioner. -","title_full_unstemmed":"Report to the commissioner. -","_version_":1446540071117258752}]}} diff --git a/solr/biblio/conf/schema.xml b/solr/biblio/conf/schema.xml index 300b3a10af9..0739b9a3ec4 100644 --- a/solr/biblio/conf/schema.xml +++ b/solr/biblio/conf/schema.xml @@ -119,9 +119,11 @@ <!-- Generic Fields --> <field name="language" type="string" indexed="true" stored="true" multiValued="true"/> <field name="format" type="string" indexed="true" stored="true" multiValued="true"/> - <field name="author" type="textProper" indexed="true" stored="true" termVectors="true"/> - <field name="author-letter" type="string" indexed="true" stored="true"/> - <field name="authorStr" type="textFacet" indexed="true" stored="false"/> + <field name="author" type="textProper" indexed="true" stored="true" multiValued="true" termVectors="true"/> + <field name="author_variant" type="text" indexed="true" stored="true" multiValued="true" termVectors="true"/> + <field name="author_role" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="author_facet" type="textFacet" indexed="true" stored="false" multiValued="true"/> + <field name="author_sort" type="string" indexed="true" stored="true"/> <field name="title" type="text" indexed="true" stored="true"/> <field name="title_sort" type="string" indexed="true" stored="true"/> <field name="title_sub" type="text" indexed="true" stored="true"/> @@ -160,11 +162,13 @@ <field name="dewey-raw" type="string" indexed="true" stored="true" multiValued="true" /> <field name="dewey-search" type="callnumberSearch" indexed="true" stored="true" multiValued="true" /> <field name="author2" type="textProper" indexed="true" stored="true" multiValued="true"/> - <field name="author2Str" type="string" indexed="true" stored="true" multiValued="true"/> - <field name="author2-role" type="string" indexed="true" stored="true" multiValued="true"/> - <field name="author_fuller" type="textProper" indexed="true" stored="true" /> + <field name="author2_variant" type="text" indexed="true" stored="true" multiValued="true"/> + <field name="author2_role" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="author_corporate" type="textProper" indexed="true" stored="true" multiValued="true"/> + <field name="author_corporate_role" type="string" indexed="true" stored="true" multiValued="true"/> + <field name="author_fuller" type="textProper" indexed="true" stored="true" multiValued="true" /> + <field name="author2_fuller" type="textProper" indexed="true" stored="true" multiValued="true" /> <field name="author_additional" type="textProper" indexed="true" stored="true" multiValued="true"/> - <field name="author_additionalStr" type="string" indexed="true" stored="true" multiValued="true"/> <field name="title_alt" type="text" indexed="true" stored="true" multiValued="true"/> <field name="title_old" type="text" indexed="true" stored="true" multiValued="true"/> <field name="title_new" type="text" indexed="true" stored="true" multiValued="true"/> @@ -236,17 +240,18 @@ <!-- CopyFields for Faceting on Text --> <copyField source="title_full" dest="title_fullStr"/> <copyField source="title_full" dest="title_full_unstemmed"/> - <copyField source="author" dest="authorStr"/> - <copyField source="author2" dest="author2Str"/> - <copyField source="author_additional" dest="author_additionalStr"/> + <copyField source="author" dest="author_facet"/> + <copyField source="author2" dest="author_facet"/> + <copyField source="author_corporate" dest="author_facet"/> <copyField source="publisher" dest="publisherStr"/> <copyField source="topic" dest="topic_unstemmed"/> <copyField source="allfields" dest="allfields_unstemmed"/> <copyField source="fulltext" dest="fulltext_unstemmed"/> <!-- CopyFields for Alphabetic Browse --> - <copyField source="topic" dest="topic_browse"/> - <copyField source="author" dest="author_browse"/> - <copyField source="author2" dest="author_browse"/> + <copyField source="topic" dest="topic_browse"/> + <copyField source="author" dest="author_browse"/> + <copyField source="author2" dest="author_browse"/> + <copyField source="author_corporate" dest="author_browse"/> <!-- CopyFields for All Fields --> <copyField source="format" dest="allfields"/> <copyField source="format" dest="allfields_unstemmed"/> diff --git a/themes/bootstrap3/templates/Recommend/CatalogResults.phtml b/themes/bootstrap3/templates/Recommend/CatalogResults.phtml index 6b168699983..d1a0ba51157 100644 --- a/themes/bootstrap3/templates/Recommend/CatalogResults.phtml +++ b/themes/bootstrap3/templates/Recommend/CatalogResults.phtml @@ -8,24 +8,18 @@ <?=$this->record($driver)->getTitleHtml()?> </a> <? $summDate = $driver->getPublicationDates(); ?> - <? $summAuthor = $driver->getPrimaryAuthor(); ?> - <? if (!empty($summDate) || !empty($summAuthor)): ?> + <? $summAuthors = $driver->getPrimaryAuthorsWithHighlighting(); ?> + <? if (!empty($summDate) || !empty($summAuthors)): ?> <? if (!empty($summDate)): ?> <br/> <span class="small author"> <?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($summDate[0])?>) </span> <? endif; ?> - <? if (!empty($summAuthor)): ?> + <? if (!empty($summAuthors)): ?> <br/> <span class="small"><?=$this->transEsc('By')?></span> - <a class="small date" href="<?=$this->record($driver)->getLink('author', $summAuthor)?>"> - <? - $summHighlightedAuthor = $driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?></a> + <a class="small date" href="<?=$this->record($driver)->getLink('author', $this->highlight($summAuthors[0], null, true, false))?>"><?=$this->highlight($summAuthors[0])?></a><? if (count($summAuthors) > 1): ?><span class="small">, <?=$this->transEsc('more_authors_abbrev')?></span><? endif; ?> <? endif; ?> <? endif; ?> </li> diff --git a/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml b/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml index 4b3fc494bc8..07e745113c1 100644 --- a/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml +++ b/themes/bootstrap3/templates/Recommend/RandomRecommend.phtml @@ -15,19 +15,19 @@ <? $formats = $driver->getFormats(); $format = isset($formats[0]) ? $formats[0] : ''; ?> <a href="<?=$this->recordLink()->getUrl($driver)?>" class="title <?=$this->record($driver)->getFormatClass($format)?> clearfix"> <?=$this->record($driver)->getTitleHtml()?> - <? $summAuthor = $driver->getPrimaryAuthor(); ?> - <span class="small<? if (!empty($summAuthor)): ?> pull-right flip<? endif; ?>"> + <? $summAuthors = $driver->getPrimaryAuthors(); ?> + <span class="small<? if (!empty($summAuthors)): ?> pull-right flip<? endif; ?>"> <? $summDate = $driver->getPublicationDates(); ?> <? if (!empty($summDate)): ?> <?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($summDate[0])?>) <? endif; ?> </span> </a> - <? if (!empty($summAuthor)): ?> - <a class="small text-right" href="<?=$this->record($driver)->getLink('author', $summAuthor)?>"> - <span><?=$this->transEsc('By')?></span> - <?=$this->escapeHtml($summAuthor)?> - </a> + <? if (!empty($summAuthors)): ?> + <span class="small text-right"> + <?=$this->transEsc('By')?> + <a href="<?=$this->record($driver)->getLink('author', $summAuthors[0])?>"><?=$this->escapeHtml($summAuthors[0])?></a><? if (count($summAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> + </span> <? endif; ?> </li> <? endforeach; ?> diff --git a/themes/bootstrap3/templates/Recommend/SummonResults.phtml b/themes/bootstrap3/templates/Recommend/SummonResults.phtml index 93918cd32d6..b86702cb741 100644 --- a/themes/bootstrap3/templates/Recommend/SummonResults.phtml +++ b/themes/bootstrap3/templates/Recommend/SummonResults.phtml @@ -8,17 +8,10 @@ <a href="<?=$this->recordLink()->getUrl($driver)?>" class="title <?=$this->record($driver)->getFormatClass($format)?>"> <?=$this->record($driver)->getTitleHtml()?> </a> - <? $summAuthor = $driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> + <? $summAuthors = $driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?> <span class="small"> <?=$this->transEsc('by')?> - <a href="<?=$this->record($driver)->getLink('author', $summAuthor)?>"> - <? - $summHighlightedAuthor = $driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?> - </a> + <a href="<?=$this->record($driver)->getLink('author', $this->highlight($summAuthors[0], null, true, false))?>"><?=$this->highlight($summAuthors[0])?></a><? if (count($summAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> </span> <? endif; ?> </span> diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml index 756a40089bc..7bb554ef9ee 100644 --- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml +++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml @@ -20,14 +20,11 @@ </div> <div> - <? $summAuthor = $this->driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> - <?=$this->transEsc('by')?> - <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><? - $summHighlightedAuthor = $this->driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?></a> + <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?> + <?=$this->transEsc('by')?> + <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?> + <a href="<?=$this->record($this->driver)->getLink('author', $this->highlight($summAuthor, null, true, false))?>"><?=$this->highlight($summAuthor)?></a><?=$i + 1 < $authorCount ? ',' : ''?> + <? endforeach; ?> <? endif; ?> <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?> diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml index f1a2b1cf134..fd5bc8a049f 100644 --- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml +++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml @@ -45,15 +45,19 @@ <? $authors = $this->driver->getDeduplicatedAuthors(); ?> <? if (isset($authors['main']) && !empty($authors['main'])): ?> <tr> - <th><?=$this->transEsc('Main Author')?>: </th> - <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></td> + <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th> + <td> + <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?> + </td> </tr> <? endif; ?> <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?> <tr> - <th><?=$this->transEsc('Corporate Author')?>: </th> - <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></td> + <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th> + <td> + <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?> + </td> </tr> <? endif; ?> @@ -61,7 +65,7 @@ <tr> <th><?=$this->transEsc('Other Authors')?>: </th> <td> - <? $i = 0; foreach ($authors['secondary'] as $field): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $field)?>"><?=$this->escapeHtml($field)?></a><? endforeach; ?> + <? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?> </td> </tr> <? endif; ?> diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml index 4b3cda6b49d..528895de85d 100644 --- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml +++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml @@ -13,15 +13,19 @@ <? $authors = $this->driver->getDeduplicatedAuthors(); ?> <? if (isset($authors['main']) && !empty($authors['main'])): ?> <tr valign="top"> - <th><?=$this->transEsc('Main Author')?>: </th> - <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></td> + <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th> + <td> + <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?> + </td> </tr> <? endif; ?> <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?> <tr valign="top"> - <th><?=$this->transEsc('Corporate Author')?>: </th> - <td><a href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></td> + <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th> + <td> + <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?> + </td> </tr> <? endif; ?> diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml index 8f093c9aa84..e19b42fcf9a 100644 --- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml +++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml @@ -97,26 +97,30 @@ <? $authors = $this->driver->getDeduplicatedAuthors(); ?> <? if (isset($authors['main']) && !empty($authors['main'])): ?> - <tr> - <th><?=$this->transEsc('Main Author')?>: </th> - <td property="author"><a href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></td> - </tr> + <tr> + <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th> + <td> + <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><span property="author"><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?></span><? endforeach; ?> + </td> + </tr> <? endif; ?> <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?> - <tr> - <th><?=$this->transEsc('Corporate Author')?>: </th> - <td property="creator"><a href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></td> - </tr> + <tr> + <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th> + <td> + <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><span property="creator"><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?></span><? endforeach; ?> + </td> + </tr> <? endif; ?> <? if (isset($authors['secondary']) && !empty($authors['secondary'])): ?> - <tr> - <th><?=$this->transEsc('Other Authors')?>: </th> - <td> - <? $i = 0; foreach ($authors['secondary'] as $field): ?><?=($i++ == 0)?'':', '?><span property="contributor"><a href="<?=$this->record($this->driver)->getLink('author', $field)?>"><?=$this->escapeHtml($field)?></a></span><? endforeach; ?> - </td> - </tr> + <tr> + <th><?=$this->transEsc('Other Authors')?>: </th> + <td> + <? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><span property="contributor"><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?></span><? endforeach; ?> + </td> + </tr> <? endif; ?> <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?> diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml index ee16101e01f..6596ef3cb9a 100644 --- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml +++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml @@ -39,9 +39,11 @@ <? if($this->driver->isCollection()): ?> <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?> <? else: ?> - <? $summAuthor = $this->driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> + <? $summAuthors = $this->driver->getPrimaryAuthors(); if (!empty($summAuthors)): ?> <?=$this->transEsc('by')?> - <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><?=$this->escapeHtml($summAuthor)?></a> + <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?> + <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><?=$this->escapeHtml($summAuthor)?></a><?=($i + 1 < $authorCount ? ';' : '') ?> + <? endforeach; ?> <? endif; ?> <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?> diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml index fd35c274fe5..f0f1e73f2ed 100644 --- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml +++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml @@ -18,14 +18,11 @@ <? if($this->driver->isCollection()): ?> <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?> <? else: ?> - <? $summAuthor = $this->driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> - <?=$this->transEsc('by')?> - <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><? - $summHighlightedAuthor = $this->driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?></a> + <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?> + <?=$this->transEsc('by')?> + <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?> + <a href="<?=$this->record($this->driver)->getLink('author', $this->highlight($summAuthor, null, true, false))?>"><?=$this->highlight($summAuthor)?></a><?=$i + 1 < $authorCount ? ',' : ''?> + <? endforeach; ?> <? endif; ?> <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?> diff --git a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml index 9318d625a27..1c75d365d4d 100644 --- a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml +++ b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml @@ -24,8 +24,8 @@ <? $formats = $data->getFormats(); ?> <i class="fa fa-x<? if (count($formats) > 0): ?> fa-<?=preg_replace('/[^a-z0-9]/', '', strtolower($formats[0]))?>" title="<?=$formats[0] ?><? endif; ?>"></i> <b><?=$this->escapeHtml($data->getTitle())?></b> - <? $author = $data->getPrimaryAuthor(); if (!empty($author)): ?> - <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($author);?> + <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?> + <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> <? endif; ?> <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?> <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>) diff --git a/themes/bootstrap3/templates/Related/Similar.phtml b/themes/bootstrap3/templates/Related/Similar.phtml index 12ef7a4d218..40280a0fdc7 100644 --- a/themes/bootstrap3/templates/Related/Similar.phtml +++ b/themes/bootstrap3/templates/Related/Similar.phtml @@ -9,8 +9,8 @@ <a href="<?=$this->recordLink()->getUrl($data)?>"> <?=$this->escapeHtml($data->getTitle())?> </a> - <? $author = $data->getPrimaryAuthor(); if (!empty($author)): ?> - <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($author);?> + <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?> + <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> <? endif; ?> <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?> <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>) diff --git a/themes/bootstrap3/templates/ajax/resultgooglemapinfo.phtml b/themes/bootstrap3/templates/ajax/resultgooglemapinfo.phtml index d0dd116f96f..193957ee40b 100644 --- a/themes/bootstrap3/templates/ajax/resultgooglemapinfo.phtml +++ b/themes/bootstrap3/templates/ajax/resultgooglemapinfo.phtml @@ -9,10 +9,10 @@ <? if ($thumb = $this->record($record)->getThumbnail()): ?><img class="mapInfoResultThumbImg" src="<?=$this->escapeHtmlAttr($thumb) ?>"/><? endif; ?> </div> - • <a href="<?=$this->recordLink()->getUrl($record)?>"><?=$record->getTitle() ?></a> - <? if(strlen($record->getPrimaryAuthor()) > 0): ?> + • <a href="<?=$this->recordLink()->getUrl($record)?>"><?=($title = $record->getTitle()) ? $title : $this->transEsc('Title not available') ?></a> + <? $authors = $record->getPrimaryAuthors(); if (!empty($authors)): ?> <span class="small"> - <?=$this->transEsc('by') ?> <a href="<?=$this->url('author-home')?>?author=<?=urlencode($record->getPrimaryAuthor())?>"><?=$this->escapeHtml($record->getPrimaryAuthor())?></a> + <?=$this->transEsc('by')?> <a href="<?=$this->record($record)->getLink('author', $authors[0])?>"><?=$this->escapeHtml($authors[0]);?></a><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> </span><br/> <? endif; ?> diff --git a/themes/bootstrap3/templates/myresearch/checkedout.phtml b/themes/bootstrap3/templates/myresearch/checkedout.phtml index 24b85895a3e..313ae5a7adb 100644 --- a/themes/bootstrap3/templates/myresearch/checkedout.phtml +++ b/themes/bootstrap3/templates/myresearch/checkedout.phtml @@ -94,9 +94,9 @@ echo $this->transEsc('Title not available'); } ?><br/> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> <?=$this->transEsc('by')?>: - <a href="<?=$this->record($resource)->getLink('author', $listAuthor)?>"><?=$this->escapeHtml($listAuthor)?></a><br/> + <a href="<?=$this->record($resource)->getLink('author', $listAuthors[0])?>"><?=$this->escapeHtml($listAuthors[0])?></a><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?><br/> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> <?=str_replace('class="', 'class="label label-info ', $this->record($resource)->getFormatList())?> diff --git a/themes/bootstrap3/templates/myresearch/holds.phtml b/themes/bootstrap3/templates/myresearch/holds.phtml index 1b816ecd7d9..eb62a799b57 100644 --- a/themes/bootstrap3/templates/myresearch/holds.phtml +++ b/themes/bootstrap3/templates/myresearch/holds.phtml @@ -78,9 +78,9 @@ echo $this->transEsc('Title not available'); } ?><br/> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> <?=$this->transEsc('by')?>: - <a href="<?=$this->record($resource)->getLink('author', $listAuthor)?>"><?=$this->escapeHtml($listAuthor)?></a><br/> + <a href="<?=$this->record($resource)->getLink('author', $listAuthors[0])?>"><?=$this->escapeHtml($listAuthors[0])?></a><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?><br/> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> diff --git a/themes/bootstrap3/templates/myresearch/illrequests.phtml b/themes/bootstrap3/templates/myresearch/illrequests.phtml index 2fe75afa400..f4b35e80131 100644 --- a/themes/bootstrap3/templates/myresearch/illrequests.phtml +++ b/themes/bootstrap3/templates/myresearch/illrequests.phtml @@ -79,9 +79,9 @@ echo $this->transEsc('Title not available'); } ?><br/> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> <?=$this->transEsc('by')?>: - <a href="<?=$this->record($resource)->getLink('author', $listAuthor)?>"><?=$this->escapeHtml($listAuthor)?></a><br/> + <a href="<?=$this->record($resource)->getLink('author', $listAuthors[0])?>"><?=$this->escapeHtml($listAuthors[0])?></a><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?><br/> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> diff --git a/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml b/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml index 500bf3024a8..2e47c9316c1 100644 --- a/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml +++ b/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml @@ -76,9 +76,9 @@ echo $this->transEsc('Title not available'); } ?><br/> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> <?=$this->transEsc('by')?>: - <a href="<?=$this->record($resource)->getLink('author', $listAuthor)?>"><?=$this->escapeHtml($listAuthor)?></a><br/> + <a href="<?=$this->record($resource)->getLink('author', $listAuthors[0])?>"><?=$this->escapeHtml($listAuthors[0])?></a><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?><br/> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml index 1abaaba9d24..cf6ace0c90d 100644 --- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml +++ b/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml @@ -2,13 +2,11 @@ <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>"> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" /> <h3><?=$this->record($this->driver)->getTitleHtml()?></h3> - <? $summAuthor = $this->driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> - <p><?=$this->transEsc('by')?> <? - $summHighlightedAuthor = $this->driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?> + <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?> + <p><?=$this->transEsc('by')?> + <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?> + <?=$this->highlight($summAuthor)?><?=$i + 1 < $authorCount ? ';' : ''?> + <? endforeach; ?></p> <? endif; ?> <? $locations = $this->driver->getProviders(); if (!empty($locations)): ?> <p><strong><?=$this->transEsc('Provider')?>:</strong> <?=$this->escapeHtml(implode(', ', $locations))?></p> diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml index 7ceb7ade4d7..916453d1dfc 100644 --- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml +++ b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml @@ -10,13 +10,17 @@ <? $authors = $this->driver->getDeduplicatedAuthors(); ?> <? if (isset($authors['main']) && !empty($authors['main'])): ?> - <dt><?=$this->transEsc('Main Author')?>: </dt> - <dd><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></dd> + <dt><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </dt> + <dd> + <p><? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p> + </dd> <? endif; ?> <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?> - <dt><?=$this->transEsc('Corporate Author')?>: </dt> - <dd><p><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></p></dd> + <dt><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </dt> + <dd> + <p><? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p> + </dd> <? endif; ?> <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?> @@ -48,4 +52,4 @@ <? endforeach; ?> </dd> <? endif; ?> -</table> \ No newline at end of file +</dl> \ No newline at end of file diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml index b1d9bf18f97..cf00bc8d312 100644 --- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml +++ b/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml @@ -48,8 +48,10 @@ <? $authors = $this->driver->getDeduplicatedAuthors(); ?> <? if (isset($authors['main']) && !empty($authors['main'])): ?> - <dt><?=$this->transEsc('Main Author')?>: </dt> - <dd><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['main'])?>"><?=$this->escapeHtml($authors['main'])?></a></dd> + <dt><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </dt> + <dd> + <p><? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p> + </dd> <? endif; ?> <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?> @@ -95,14 +97,16 @@ <? endif; ?> <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?> - <dt><?=$this->transEsc('Corporate Author')?>: </dt> - <dd><p><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $authors['corporate'])?>"><?=$this->escapeHtml($authors['corporate'])?></a></p></dd> + <dt><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </dt> + <dd> + <p><? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p> + </dd> <? endif; ?> <? if (isset($authors['secondary']) && !empty($authors['secondary'])): ?> <dt><?=$this->transEsc('Other Authors')?>: </dt> <dd> - <p><? $i = 0; foreach ($authors['secondary'] as $field): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $field)?>"><?=$this->escapeHtml($field)?></a><? endforeach; ?></p> + <p><? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p> </dd> <? endif; ?> diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml index c638ad6162b..f0084a3a352 100644 --- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml +++ b/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml @@ -15,8 +15,12 @@ <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>"> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" /> <h3><?=$this->record($this->driver)->getTitleHtml()?></h3> - <? $listAuthor = $this->driver->getPrimaryAuthor(); if (!empty($listAuthor)): ?> - <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthor)?></p> + <? $listAuthors = $this->driver->getPrimaryAuthors(); if (!empty($listAuthors)): ?> + <p><?=$this->transEsc('by')?> + <? $authorCount = count($listAuthors); foreach ($listAuthors as $i => $listAuthor): ?> + <?=$this->escapeHtml($listAuthor) . ($i + 1 < $authorCount ? ';' : '') ?> + <? endforeach; ?> + </p> <? endif; ?> <? $listTags = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags( $list_id, // get tags for all lists if no single list is selected diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml index 5492f2c0354..2cf0b32238e 100644 --- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml +++ b/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml @@ -2,13 +2,11 @@ <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>"> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" /> <h3><?=$this->record($this->driver)->getTitleHtml()?></h3> - <? $summAuthor = $this->driver->getPrimaryAuthor(); if (!empty($summAuthor)): ?> - <p><?=$this->transEsc('by')?> <? - $summHighlightedAuthor = $this->driver->getHighlightedAuthor(); - echo !empty($summHighlightedAuthor) - ? $this->highlight($summHighlightedAuthor) - : $this->escapeHtml($summAuthor); - ?> + <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?> + <p><?=$this->transEsc('by')?> + <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?> + <?=$this->highlight($summAuthor)?><?=$i + 1 < $authorCount ? ';' : ''?> + <? endforeach; ?></p> <? endif; ?> <? if ($this->driver->supportsAjaxStatus()): ?> <p class="callnumAndLocation"> diff --git a/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml b/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml index 847c57ac01e..7a1c9bb01d6 100644 --- a/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml +++ b/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml @@ -15,8 +15,8 @@ <? $formats = $data->getFormats(); ?> <i class="fa fa-x<? if (count($formats) > 0): ?> fa-<?=preg_replace('/[^a-z0-9]/', '', strtolower($formats[0]))?>" title="<?=$formats[0] ?><? endif; ?>"></i> <b><?=$this->escapeHtml($data->getTitle())?></b> - <? $author = $data->getPrimaryAuthor(); if (!empty($author)): ?> - <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($author);?> + <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?> + <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?> <? endif; ?> <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?> <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>) diff --git a/themes/jquerymobile/templates/myresearch/checkedout.phtml b/themes/jquerymobile/templates/myresearch/checkedout.phtml index 14ee8f9b5b3..a8263f937aa 100644 --- a/themes/jquerymobile/templates/myresearch/checkedout.phtml +++ b/themes/jquerymobile/templates/myresearch/checkedout.phtml @@ -69,8 +69,8 @@ ?> <div class="result"> <h3><?=$title?></h3> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> - <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthor)?></p> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> + <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthors[0])?><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?></p> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> <?=$this->record($resource)->getFormatList()?> diff --git a/themes/jquerymobile/templates/myresearch/holds.phtml b/themes/jquerymobile/templates/myresearch/holds.phtml index ed6ae2e0741..1c10f0bb304 100644 --- a/themes/jquerymobile/templates/myresearch/holds.phtml +++ b/themes/jquerymobile/templates/myresearch/holds.phtml @@ -44,8 +44,8 @@ ?> <div class="result"> <h3><?=$title?></h3> - <? $listAuthor = $resource->getPrimaryAuthor(); if (!empty($listAuthor)): ?> - <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthor)?></p> + <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?> + <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthors[0])?><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?></p> <? endif; ?> <? $formats = $resource->getFormats(); if (count($formats) > 0): ?> <?=$this->record($resource)->getFormatList()?> -- GitLab