III Bib # to ASIN to Cover Art

azImgSrc-1.0.tar.gz

I’ve written a PHP script that takes a III Bib # and, using amazon’s REST interface, it tries it’s darnedest to find the ASIN for that item. It will then store that Bib#-ASIN pair in a database. After that, it will cache the small, medium and large cover images associated with that ASIN in another database table and display whichever one you want.

This script requires the latest version of the III-XMLOPAC class (1.6), PEAR::DB, MySQL (of course) and PHP5 (or PHP4 with SimpleXML). In addition to that, you’ll need to have your own Amazon Dev token, etc.

Essentially, I wanted a way to get more cover art into the catalog. If you currently use Syndetics, you’ll know that you almost never get any cover art for CDs and DVDs. My solution was to write this. Just to warn you, though, this script will not return ASINs and cover art for all the items in your collection. Far from it. There is about a 30% hit-rate. I could easily get that higher, but then accuracy drops off, and I want 100% accuracy.

So, I plan on working with this script, massaging the search to figure out ways to get that 30% up. Please feel free to hack away at it yourselves too, but bear in mind, that I’m looking for accuracy above all else. If you’re really interested in how I’m determining an accurate hit, take a look at the code. Basically, I’m doing an initial search, then I match the UPC number on the amazon record to the stdnum info from the Bib record. Doing it this way, I haven’t seen a wrong match yet.

Incidentally, here is a hit list with images from this script:

To use it, you’d basically do something like this:

<?php
 
$bibnum = "123456";
echo  '<img src="/azImgSrc.php?bnum=' . $bibnum . '">';
 
?>

As a side bonus, you’ll have a nice table with Bib#-to-ASIN data. You can even manually add data to that table to ensure your favorite records have images associated with them.

III-XMLOPAC class update 1.6

[update] iii-xmlopac-1.7.tar.gz [/update]

I really love that Casey keeps adding functionality to the III XMLOPAC class. I've incorporated his latest function that grabs alternate ISBN numbers from OCLC's xISBN service into 1.6.

Because of his function, however, I've changed the way get_opac_data() is called. The change is completely backward compatible, so don't worry about anything breaking after you upgrade. The new prototype looks like this:

<?php
$bibinfo = get_opac_data($bibnum, $extend = NULL);
 
// Of course, you can just call it like this:
$bibinfo = get_opac_data($bibnum);
?>

Essentially, Casey's function will only be called if $extend is TRUE (or some value). I've implemented it this way because this class gets some heavy use and I don't want it polling OCLC every time I grab a bib record. I envision the $extend flag to be used in cases where external web services are queried. By default, those features will be disabled.

Also, in 1.6, I've fixed a pretty bad bug that would often times return an invalid ISBN. I've broken that bad ISBN number off into the "stdnum" key instead.

If you're using this class, you definitely should upgrade to 1.6.

[update]
Actually, grab version 1.7. I didn't add a test to make sure a record has an ISBN before it's shunted to Casey's function. As such, you might get a PHP warning depending on your error report settings. Nothing major, just an annoyance, 1.7 fixes that.
[/update]

AADL RSS feeds extended to all catalog searches

I have to admit that getting this to work was born out of my own selfish motivations. I really wanted a way to get a jump on requesting some of the more popular items and thought, short of mugging someone in collection development, this would be the most fruitful way of going about it.

In the first iteration of this enhancement, RSS feeds were only available for hitlists generated by a keyword search. I do 90% of my searches using keyword, but thought that the feature really ought to be extended to all search types. The problem with doing so, however, is wrangling enough information from the catalog and URL to determine a) what kind of search it is, and b) what the search term is. The III catalog poses a couple of challenges to this. First, the III catalog seems to oscillate between GET and POST variables as you navigate through the OPAC. This makes it quite difficult to reliably put your finger on the right data. Second, each search type seems to be handled in its own special way. Again, this makes it difficult to generate reliable results.

So the solution was to create a set of "rules" in the code that is applied to each page of the catalog. These rules basically score the content and return a "best guess" which can then be applied toward RSS generation. It's goofy, but again, that's what we have to work with!

The result looks something like this in the catalog:

And something like this in NetNewsWire (My RSS reader):

I had an evil thought to write a piece of software that loops continuously, automatically requesting new items in an RSS feed. That way I'd be sure to be the first one in the hold queue. I don't think doing that is ethically sound, but it does raise the question, what are we going to do about the people who find ways to take advantage of this new technology at the expense of others? Library 2.0, like Web 2.0 is most certainly going to widen the gap between the techno-savvy and non techno-savvy. The 'nons' are going to get left behind. It's our responsibility to coax those users into using these services and technologies. We're probably in the best possible position to do that because local citizens and community members are the main users on our sites and they have a vested interest in the services we provide.

Enhanced Patron History

One of my recent projects has been to enable patron check-out histories on our website. I had been a little apprehensive about it for several reasons. First, because all of our ILS functionality must be either duplicated, or passed through Drupal, I felt that this was going to pose some serious logistical problems. Getting information from point A to point B quickly and securely using our model can be tricky, doubly so, given that the back-end can be a nightmare of non-standard mish-mash. Second, because patron check-out history is a more complex beast than, say, simply displaying current checkouts. And third, because III's check-out history is so dull and useless, I wanted to add some additional functionality such as filtering, searching, and, of course, RSS feeds.

There are several components to the patron history system. The opt-in mechanism is controlled by Drupal's profile module, which allows you to create custom, user-specific preferences. I've consolidated ours together on the patron account page, it looks like this:

A patron can easily maintain their preference set via Drupal's nice profile option interface. All I had to do was write a hook into that particular profile option that controls the behavior of the patron history middleware.

Which brings me to the next major component. The patron history middleware. This is where I interface with the III server and perform all the history-related stuff. Getting the data from III actually was less of a tour-de-force than I thought it might be. If you're interested in details, email me.
The middleware ensures that all history data gets siphoned through a function that adds material code, record summary and author info then is stored in our own mysql database. This allows us to do things like search history data by title, author, keywords and filter by material type.

The last component was the actual UI that is presented to the user. It basically brings together the functionality made possible in the middleware (the items in this history were just for testing):

The point of sharing this with you? To illustrate that we can do a much better job than the vendor itself. Yes, we can figure it out, and we will. I didn't have an API to work with when I did this, and searching patron history is not even an option in III, nor are RSS feeds of patron history (and RSS feeds of custom patron history searches). How great it would be to have the proper tools to do this kind of work.

I'm reminded of Stephen King's, Storm of the Century, "Give me what I want and I'll go away".

Casey Bisson contributes to the XMLOPAC Class

iii-xmlopac-1.5.tar.gz

I had a pleasant surprise this morning when I read that Casey had extended my XMLOPAC class. He's written a function that takes a search term, then returns an array of bib-nums for that search. He's hoping to create clustered search results, and his function may be a component of that. Yes, necessity is the mother of all invention.

Casey's comment sums up why we go through the trouble to squeeze out every last bit of functionality from our OPAC, "Because problems are meant to be overcome." I'd just like to see the odds stacked in our favor. Imagine what we could accomplish if our ILS actually enabled us to do this sort of work.

Thanks Casey!

I've incorporated his code into the class, with some minor changes. I also found another instance where III's XML is malformed and added a fix for that. The complete package can be found here.