This posting documents how I wrote and edited a couple of VUFind record drivers and Smarty templates for the “Portal” of the Catholic Research Resources Alliance. In writing this posting I hope to support any developer coming behind me as well as inform the wider open source community on how VUFind works.
The heart of my problem is that the Portal is essentially a union catalog — an aggregation of metadata from a number of archives and libraries. Search results do not come from a single institution but a multitude. Search results need to display specific information about locations — information describing what library owns each item, what institution hosts the library, and the call number of selected items. Out-of-the-box VUFind is designed to dynamically query a library’s integrated library system (ILS), but I deemed this too complicated for our purposes. Too many different systems. Too expensive in both time and energy.
Consequently, my problem is, “How do I display location information in a multi-library environment?”
The solution includes three parts: 1) exploiting the indexer (Solr) supporting VUFind, 2) creating and editing VUFind record drivers, and 3) editing Smarty templates.
Exploiting the indexer
The first part of the solution was documented in a previous posting where I described how metadata in the form of MARC records and EAD files is being indexed with Solr. To summarize, as each record is fed to Solr, three bits of information are saved in the index: 1) the type of data being indexed, 2) the name of the library holding the index item, and 3) the name of the institution hosting the library. This part works well and is pretty much divorced from the internal workings of VUFind.
Creating and editing record drivers
The second part of the solution was about creating and editing VUFind record drivers. VUFind is designed to branch to alternative sets of code based on the value of a Solr field called record type. In the case of our Portal, a record type may be “marc” or “ead”. VUFind handles MARC out-of-the-box. As documented in the VUFind wiki, to handle things other than MARC a record driver needed to be created. This is what I did, and in our case the driver is called EadRecord.php.
The astute PHP programmer will see that the driver inherits the vast majority of its functionality from the IndexRecord.php; EadRecord.php only overrides two methods. The first (
getURLs) reads the value of the fullrecord field, uses an XPath expression to extract all the URLs from the fullrecord field, and returns the URLs as an associative array. The second method (
getHoldings) is almost an exact duplicate of getHoldings from IndexRecord.php, but creates two new Smarty tokens (CRRALibrary and CRRAInstitution). Like the URLs, the values for these tokens are pulled directly from the fullrecord field.
Next I needed to edit the MarcRecord.php and IndexRecord.php record drivers. Editing MarcRecord.php was trivial. All I had to do was turn off a Boolean value. Specifically, I had to denote the value of
summAjaxStatus as false because I did not want VUFind to try to query a remote ILS for holdings information. (I think this sort of thing ought to be configuration setting in config.ini, but that is for another time.)
Editing IndexRecord.php was almost as easy. Just like EadRecord.php, I needed to create two new Smarty tokens (CRRALibrary and CRRAInstitution) and stuff them into templates. This was done in the
getSearchResult methods. Additionally, in
getHoldings, I needed to create a third token — summCallNo to hold call numbers. Again, just like EadRecord.php, this was done by pulling values out of the fullrecord field. Very, very nice.
The last part of the solution was editing the Smarty templates. This was done by adding my newly created tokens (CRRALibrary, CRRAInstitution, and summCallNo) in both result.tpl and holdings.tpl. I find Smarty to be a bit obtuse because it requires the developer to understand YASS (“Yet Another Scripting Syntax”). Personally, I don’t think logic such as if-then statements should exist in template files. Logic belongs in code.
In retrospect, the whole process from indexing to display was pretty efficient. Gather metadata. Parse it. Feed it to indexer. Search. Get results. Parse (something else). Fill templates. Display. In order for this process to be maintainable, I need to hope things like IndexRecord.php and MarcRecord.php do not change over upgrades. As new versions of VUFind come along I will replace the IndexRecord.php and MarcRecord.php with my versions as well as drop in EadRecord.php. Unfortunately, I don’t think I can guarantee zero changes in IndexRecord.php and MarcRecord.php. These are gotchas I will need to expect. Similarly, I added new logic to my template files. Another thing to keep in mind but not as detrimental as changes to the record drivers.
Finally, I want to publically acknowledge Demian Katz’s assistance. He outlined what needed to be done clearly and suscinctly, both in writting as well as verbally. His description of VUFind’s architecture was very understandable, especially for this Perl programmer. He knows the application very well. Thank you.