PHP port of ISBN-10/13 tool

OSS4Lib and David Bigwood (Catalogablog) wrote the other day about an ISBN tool from ManaSystems that converts ISBN-10 to ISBN-13. ManaSystem’s version is written in Perl, so I went ahead and ported it to PHP5 for the rest of us.

Feel free to download it here, or from my files section.

Basically, all the function names are the same, so the original instructions apply. From the ISBN.pl page:

convert($isbn)
Takes a 10 digit ISBN and returns the 13 digit equivalent. Does not perform any error checking or validation.

gettype($isbn)
Takes a string value and will make a guess as to whether or not it fits the criteria of an ISBN. Returns 10 for a possible ISBN-10 and 13 for ISBN-13. Does not validate further.

validateten($isbn)
Takes a 10 digit numeric value and checks to determine if it is a valid ISBN-10.

validatettn($isbn)
Takes a 13 digit digit numeric value and checks to determine if it is a valid ISBN-13.

genchksum13($isbn)
Takes a 12 digit numeric value and generates an ISBN-13 checksum digit.

genchksum10($isbn)
Takes a 9 digit numeric value and generates an ISBN-10 checksum digit.

printinvalid() Returns a message informing the user the ISBN is invalid.

Of course, you’ll instantiate it a little differently:

<?php
require_once('ISBN.php');
 
$isbn_no = "012345678";
$ISBN = new ISBN;
$isbntype = $ISBN->gettype($isbn_no);
 
if ($isbntype < 1) { $ISBN->printinvalid(); }
else if ($isbntype == 10) { $isvalidten = $ISBN->validateten($isbn_no); }
else if ($isbntype == 13) { $isvalidttn = $ISBN->validatettn($isbn_no); }
 
if ($isvalidten) { print "That is a valid ISBN-10\n"; } 
else if ($isvalidttn) { print "That is a valid ISBN-13\n"; } 
else { $ISBN->printinvalid(); }
?>

Enjoy!

Stick ‘em up! Easing the holds process

Starting today, patrons who have items on hold at select branches will notice something new about the material they receive: a sticky note.

The whole point of these new stickers is to ease the work created by an ever-increasing volume of holds being placed on AADL material. Our processors have been bearing the brunt of increased loads, partly due to general growth, but also because it is so easy to place a hold online now that the number of holds we get has shot up. Now, as far as the processors are concerned, when they scan material that has been routed to the correct pickup location, a custom label, replete with patron information and barcode will spit right out of a networked label printer. This removes a step or two from the process and has led to some very happy circulation staff. Though I'm quite pleased with the way the labels turned out, what pleases me the most (besides the happy processors) is what happens behind the scenes. What's fun about this are the relatively simple back-end components that make this work.

The III circulation client can be configured to send a print job to an email address instead of a standard receipt or line printer. In this case, I've set up an instance of Exim running on a Linux box with an address alias that pipes the email through a very simple PHP script. The PHP script parses the email, creates a PNG on the fly, then sends it to the label printer via cupsys lp. I've been having a lot of fun with PHP's GD module lately and this little project really underscores how slick it can be. In addition to GD, I also made use of PEAR's Image::Barcode class so that the item's barcode could be included on the tag. Because PEAR's barcode class doesn't allow you to return the image as an object, I had to instantiate it as a separate script. That's fine because you can just point imagecreatefrompng to the URL. The barcode script couldn't be simpler. Not only that, it's so generic, you can really use it for all your barcoding needs:

<?php
// bcode.php
if (!$_GET[input]) { return; }
require_once('Image/Barcode.php');
$bcode = new Image_Barcode;
$bcode->draw($_GET[input], 'int25', 'png');
?>

'Eh? What a great class! Here's the guts of the label code--messy, I know, but it works. As you can see, it's utilizing PHP's CLI or CGI build. Yes, PHP makes a great shell scripting language too!

#!/usr/bin/php5 -q
<?php
 
putenv('GDFONTPATH=' . realpath('/usr/local/php/fpdf/ttf/'));  // Where my TTF fonts are
 
$fd = fopen("php://stdin", "r");
$email = "";
while (!feof($fd)) {
        $email .= fread($fd, 1024);
}
fclose($fd);
 
$item = hold_item_info($email);
 
$x = 350;
$y = 350;
$daysonshelf = 8;
$unique = time() . rand(2000000, 6000000);
$font = 'arialbd';
$logourl = "http://www.aadl.org/staticimages/aadllogo.gif";
$bcodeurl = "http://bcodeserver.aadl.org/bcode.php?input=$item[barcode]";
 
// Create the image
$im = imagecreatetruecolor($x, $y);
$im2 = imagecreatefrompng($bcodeurl);
$im3 = imagecreatefromgif($logourl);
 
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
 
imagefill($im, 0, 0, $$white);
imagefilledrectangle($im, 0, 0, $x, $y, $white);
 
$spine_name = $item[plname];
if ($item[pfname]) { $spine_name .= ', ' . strtoupper($item[pfname]{1}) . '.'; }
 
$holdtil = (time() + ($daysonshelf * 86400));
$holdtilfmt = date("n/j", $holdtil);
$canceldate = date("m-d-Y", $holdtil);
 
$details = 'Title: ' . $item[title] . "\n" .
        'Author: ' . $item[author] . "\n" .
        'Callnum: ' . $item[callnum] . "\n" .
        'Barcode: ' . $item[barcode] . "\n" .
        'Held for: ' . $item[plname] . ', ' . $item[pfname] . "\n" .
        'Pickup location: ' . $item[pickuploc] . "\n" .
        'Hold until: ' . $canceldate;
 
imagettftext($im, 28, 270, 40, 20, $black, $font, $spine_name);
imagefilledrectangle($im, 72, 20, 74, 345, $black);
imagefilledrectangle($im, 15, 300, 70, 335, $white);
imagettftext($im, 12, 0, 32, 320, $black, $font, $holdtilfmt);
ImageCopyMerge($im , $im2, 85, 40, 0, 0, ImageSX($im2), ImageSY($im2), 100);
ImageCopyMerge($im , $im3, 85, 275, 0, 0, ImageSX($im3), ImageSY($im3), 100);
imagettftext($im, 12, 0, 85, 120, $black, $font, $details);
 
imagepng($im,"/tmp/pic$unique.png");
imagedestroy($im);
 
if ($item[printer]) {
        $printer = $item[printer];
        exec("/usr/bin/lp -d $printer /tmp/pic$unique.png");
}
 
unlink("/tmp/pic$unique.png");
 
// Functions Below
 
function hold_item_info($email) {
    // This function returns the $item array -- customize it for your environment.
}
?>

The script creates a PNG that looks something like this:

The PNG is sent to the Zebra S4M and printed on a label that has Post-It-like adhesive. Processors then peel off the backing and fold the sticker over the spine of the book and put it on the hold shelf.

The hardest part of this whole project was getting the printer to work with CUPS. I wound up bastardizing some existing postscript drivers through trial and error. As you can see from the photos, I still don't have it right. I'd like the image to take up the entire sticker area. All in good time. If anyone out there wants the driver I'll be glad to email it--maybe you can get it working better! Just ask.

[update]
This is how the labels are affixed to material:

You can overlook the fact that the label info doesn't match the book info--it's just for show!
[/update]

[tags]library, libraries, PHP, coding[/tags]

Source code for virtual card catalog images

iii-vcards-0.1.tar.gz

I can't tell you how many people have emailed me about getting the source code to the virtual card catalog images I announced a few weeks ago. Anyway, I've finally gotten around to stripping out all the garbage from the script that generates the images, and I'm releasing it here (and as always, it'll be available in the files section). There are a few things you need to keep in mind about it, however.

First, this code is written for use with III's XMLOPAC and requires my PHP XMLOPAC class. That said, an astute PHP coder could easily port this app and make it usable on another system (I heartily encourage that). Someday, I plan to make it completely generic so that all you need to do is pass it the data itself. I'm a little busy at the moment, however.

I am not releasing the card stock images that AADL uses. There was no license info associated with the original images. Until I can contact the folks at UPenn and find out what the deal is, I'm not going to make them available. It'd be very easy to create your own stock, however.

Same deal with the fonts. I was able to freely download them--so should you.

At present, this code is really meant for developers, it is not a "package" that will work out of the box. You must know what you're doing in order to get this going.

I'm releasing it under GPL for all the world to use freely, forever and ever.

Included in the tarball is a README file with some basic instructions. Be sure to read that before emailing me your questions.

Enjoy. I'm looking forward to some possible creative uses. Please email me if you get it working as I'd love to see what you're doing with it. If you come up with a particularly interesting use, I'll be sure to showcase it here.

[tags]PHP, Programming, Virtual Card Catalog, AADL, Web 2.0, Library 2.0, Open Source[/tags]

III XMLOPAC Class update

iii-xmlopac-1.10.tar.gz

After a fair amount of work, I'm releasing an update to the iii-xmlopac class. I've been sitting on this update for awhile because it's a fairly big update and I wanted to make sure it was performing like it should. I highly recommend that anyone using this class update because a number of fairly critical bugs have been fixed, including a messy tangle of UTF8 encoding issues.

In addition, I've included an XSLT file written by David Walker which I've modified slightly. It allows me to easily extract subject headings from the XML, so yes, this class now will return an array of subject headings!!

So, be sure to download the latest version. As always, you can grab it anytime from the files section.

[tags]PHP, XML, Programming, XMLOPAC, OPAC, AADL, Open Source, III[/tags]

III-XMLOPAC Class 1.9 update

iii-xmlopac-1.9.tar.gz

While working on the virtual card catalog, I ran into some serious issues with the way my xmlopac class was dealing with III's malformed XML (sound familiar?). Again, it all comes back to the fact that III's XML output claims to be UTF-8, but in reality, it is no such thing. These problems have also been plaguing our users who would often complain of missing titles, authors, etc.

Every time this crops up, I've fixed the problem, but it's sort of like putting your finger in the dike--another leak springs up somewhere else. Anyway, the 1.9 update goes a long way toward applying a broader fix to those problems. I'd recommend that anyone who is currently using this class to update because it'll greatly improve your results.