Welcome to the Locum Connector Developer's Guide. The purpose of this guide is to provide instruction on how to create a connector for your ILS as well as a reference for current connector developers.
This guide will tell you what a connector is, why you need one, how to go about creating one. It is intended for PHP developers who wish to have Locum (and therefore SOPAC) work with their particular ILS.
This is not an installation guide for SOPAC, which can be found here, though it contains information that will help you understand the underlying structure of the entire suite.
!! This documentation is incomplete !!
What is a connector?
The Locum connector segment is important because it is the initial abstraction layer in a dual abstraction model. In this model, the connector serves purely as a translation layer between the business logic of an Integrated Library System and the rest of the application stack.
The benefit to this model is that the connector will never have to manage any external databases or indexing engine. That is the job the Locum library.
Locum provides normalized application level access to both the database elements, Sphinx indexing engine, as well as the underlying business logic presented by the connector. Connectors, therefore, need only present data structures up to Locum and pass requests back to the ILS.
What does a connector consist of?
A connector is simply a PHP class that can be dropped into a locum installation. When properly implemented, connectors should require minimal configuration.
Connectors may also include ini files that contain ILS-specific configuration options.
Because different ILSes provide different levels of API access, connector development may range from very simple to somewhat complex.
Get to know your ILS
The first step in developing a Locum connector is to get to know your ILS. You will need to be familiar with any available APIs that will help in the process. Additionally, you will need to know which features are not going to be available via API. You'll need to have a strategy for dealing with those limitations, such as screen-scraping.
Take a look at the list of connector functions you will need to write and start thinking about how you might accomplish each.
Become familiar with the Locum architecture
Locum is written in such a way that you should not need to modify any of its scripts. In fact, it's always a bad idea to "hack the core". Locum 1.1 introduces the ability to hook in to the Locum methodology in order to override any existing Locum functionality. You can read more about that in the Locum Developer's Guide.
Also, it's a good idea to read through the Locum portion of the Getting Started with SOPAC guide, as you'll need a working installation of Locum in order to develop a connector.
The Locum directory and file structure
Understanding how files are arranged within the Locum directory tree is critical to the functionality of Locum. And Locum expects a connector bundle to be organized in a certain way.
Take a look at how a standard connector bundle should reside within the locum directory tree:
locum/
connectors/
{ILS-specific-connector}/
{ILS-specific-connector}.php
tools/
config/
{ILS-specific-connector}.ini{ILS-specific-connector} should use the following convention: locum_[ILS identifier]_[ILS version].init
Locum determines the ILS identified and ILS version from its main configuration file (config/locum.ini) in the ils_config section:
; Locum uses this section to determine which ILS connector to invoke, ; and where to look for the ILS server. [ils_config] ils = "iii"; ils_version = "2007"
In this example, locum would look for:
locum/
connectors/
locum_iii_2007/
locum_iii_2007.php
tools/
config/
locum_iii_2007.iniThe tools/ directory is optional and should include any additional scripts or programs that are required to make the connector work.
The config/ directory and configuration (ini) file are parsed by locum and merged into the $this->locum_config data array which should be made available within your connector.
The Locum connector class structure
When constructing your Locum PHP connector class, you will want to extend the same convention to your class name. A basic skeleton structure of a connector would look like this:
// {ILS-specific-connector}.php class locum_ILS_ILSVersion { public $locum_config; // Class methods & connector functions }
In the above example, using III's Millennium 2007, the basic skeleton would look like this:
// locum_iii_2007.php class locum_iii_2007 { public $locum_config; // Class methods & connector functions }
Connector functions are the functions that allow Locum to interface with your ILS. These functions must all be present in your connector class file as methods within your connector class definition.
Be sure to make yourself familiar with the Locum connector file, directory, and class structure so that you can develop these functions within the Locum framework.
!! This documentation is incomplete and subject to change !!
Though almost complete, this documentation does not include the patron checkout history functions yet. That functionality is still under development and subject to change.
Function:
item_status ($bnum)
Purpose:
item_status() needs to return item availability information to Locum. Locum's client class (locum_client) parses this information and formats it for Locum's calling application.
Arguments:
$bnum : (string) required An item's bibliographic number or unique identifier.
Expected Result:
Array
(
[holds] => (int) # of holds/reserves on the bib item (default: 0)
[on_order] => (int) Total # of items on order (default: 0)
[orders] => Array of item records (1 for each item in the system)
(
[] => (string) System on-order messages for each location awaiting an order
)
[items] => Array of item records (1 for each item in the system)
(
[] => Array
(
[location] => (string) Human-readable location name
[loc_code] => (string) Location code
[callnum] => (string) Call #
[statusmsg] => (string) Status of the item as reported by the system
[due] => (int) UNIX timestamp of the item's due date. (default: 0)
[avail] => (int) 1 = item is available, 0 = item is unavailable
[age] => (string) Age category as defined by you
[branch] => (string) Branch code/identifier
)
)
)Array
(
[holds] => 7
[on_order] => 5
[orders] => Array
(
[0] => 3 copies ordered for New Fiction Express on 07-21-2009.
[1] => 2 copies ordered for New Fiction on 07-22-2009.
)
[items] => Array
(
[0] => Array
(
[location] => New Fiction
[loc_code] => m1fgr
[callnum] => Fic BARBERY
[statusmsg] => DUE 10-07-09
[due] => 1254888000
[avail] => 0
[age] => adult
[branch] => dl
)
[1] => Array
(
[location] => New Fiction
[loc_code] => m1fgr
[callnum] => Fic BARBERY
[statusmsg] => DUE 09-13-09
[due] => 1252814400
[avail] => 0
[age] => adult
[branch] => nc
)
)
)Function:
patron_checkouts ($cardnum, $pin = NULL)
Purpose:
patron_checkouts() needs to return an array of items checked out to the cardholder. Locum's client class (locum_client) passes this information up to its calling application.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password.
Expected Result:
Array
(
[] => Array of checked-out items (1 for each item checked out)
(
[varname] => (string) Unique variable name used to refer to this item
[inum] => (string) Item number of checked-out item
[bnum] => (string) Bib number of checked-out item
[title] => (string) Title of checked-out item
[ill] => (int) 1 = item is an ILL, 0 = item is from the local collection
[numrenews] => (int) # of times this item has been renewed by the patron
[duedate] => (int) UNIX timestamp of item's due date
[callnum] => (string) Item's call #
)
)Function:
patron_fines ($cardnum, $pin = NULL)
Purpose:
patron_fines() needs to return an array of detailed charges to the patron's account.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password.
Expected Result:
Array
(
[] => Array of account charges/fines (1 for each charge)
(
[varname] => (string) Unique variable name used to refer to this charge
[desc] => (string) Description of the charge
[amount] => (float) Amount of charge
)
)Function:
patron_holds ($cardnum, $pin = NULL)
Purpose:
patron_holds() needs to return an array of items currently on hold to the cardholder. Locum's client class (locum_client) passes this information up to its calling application.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password.
Expected Result:
Array
(
[] => Array of on-hold items (1 for each item on-hold)
(
[bnum] => (string) Bib number of on-hold item
[title] => (string) Title of on-hold item
[ill] => (int) 1 = item is an ILL, 0 = item is from the local collection
[status] => (string) Where the hold is in the queue
[is_frozen] => (int) 1 = Hold is frozen, 0 = hold is not frozen
[can_freeze] => (int) 1 = Hold can be frozen, 0 = hold cannot be frozen
[pickuploc] => Array of possible pickup locations and current information
(
[selectid] => (string) A unique identifier that refers to the pickup location of this item
[options] => Array of values => labels of pickup locations
(
[{Value to pass back}] => (string) Pickup location label
)
[selected] => (string) Currently pickup location variable
)
)
)Function:
patron_info ($pid)
Purpose:
patron_info() needs to return patron specific information. Locum's client class (locum_client) passes this information up to its calling application.
Arguments:
$pid : (string) required $pid can be either a barcode number or a unique patron identifier. Your connector function must be able to accept either and tell the difference.
Expected Result:
Array
(
[pnum] => (string|int) Patron record number or unique identifier
[cardnum] => (string) Patron library card number
[checkouts] => (int) # of items currently checked out (default: 0)
[homelib] => (string) Identifier of patron's home library
[balance] => (float) Current fine/account balance (default: 0)
[expires] => (int) UNIX timestamp of patron's account expiration date (default: 0)
[name] => (string) Patron's full name
[address] => (string) Patron's address
[tel1] => (string) Patron's primary telephone #
[tel2] => (string) (optional) Patron's secondary telephone #
[email] => (string) Patron's email address
)Function:
pay_patron_fines ($cardnum, $pin = NULL, $payment_details)
Purpose:
pay_patron_fines() needs to accept an array of $payment_details and and pay off selected charges to a patron's account.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password. (must explicitly pass NULL for no pin)
$payment_details : (array) required A standard array of unique identifiers of items whose holds are to be canceled.
Array ($payment_details)
(
[varnames] => Array of variable references to specific charges
(
[{variable reference}] => (string) Variable value
)
[total] => (float) Total amount of charges to be paid
[name] => (string) Name on the credit card used
[address1] => (string) Billing address, line 1
[address2] => (string) (optional) Billing address, line 2
[city] => (string) Billing address city
[state] => (string) Billing address state
[zip] => (string) Billing address zip code
[email] => (string) Patron's email address
[ccnum] => Credit card number
[ccexpmonth] => Credit card expiration month
[ccexpyear] => Credit card expiration year
[ccseccode] => Credit card security code
)Expected Result:
Array
(
[approved] => (int) 1 = Payment was successful, 0 = Payment was unsuccessful
[error] => (string) Error message if payment could not be processed
[reason] => (string) Error message if the credit card was declined
)Function:
place_holds ($cardnum, $bnum, $inum = NULL, $pin = NULL, $pickup_loc = NULL)
Purpose:
place_holds() needs to place a hold on the item passed to the function. $bnum is the primary item identifier, as Locum assumes bib-levels holds, $inum can be considered a secondary identifier.
Arguments:
$cardnum : (string) required The patron's library card number.
$bnum : (string) required The bib number of the item to be reserved.
$inum : (string) optional The item number (or alternate identifier) of the item to be reserved.
$pin : (string) optional The patron's PIN number or password.
$pickup_loc : (string) optional A location identifier for the pickup location of this reserve.
Expected Result:
Array
(
[success] => (int) 1 = Hold was successfully placed, 0 = hold was not placed
[error] => (string) System error message or reason for failed reserve
[selection] => NULL or Array of item info if user interaction is required (usually if item-level holds are enabled)
(
[] => Array
(
[varname] => (string) Unique variable name for form reference
[location] => (string) Location code or identifier
[callnum] => (string) The call number for the item in that location
[status] => (string) The status of the item at that location
)
[varname] => (string) Unique variable name used to refer to this item
[bnum] => (string) Bib number of on-hold item
[title] => (string) Title of on-hold item
[ill] => (int) 1 = item is an ILL, 0 = item is from the local collection
[status] => (string) Where the hold is in the queue
[pickuploc] => (string) Where the hold will be available for pick-up
[is_frozen] => (int) 1 = Hold is frozen, 0 = hold is not frozen
[can_freeze] => (int) 1 = Hold can be frozen, 0 = hold cannot be frozen
)
[choose_location] => NULL or Array of location info if user interaction is required (if no default location is enabled or configured)
(
[options] => Array
(
[{Location code or identifier}] => (string) Location description
)
)
)Function:
renew_items ($cardnum, $pin = NULL, $items = NULL)
Purpose:
renew_items() needs to accept an array of $items and renew on those items. If no $items array is passed, all renewable items should be renewed.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password.
$items : (array) optional A keyed array of unique identifiers of items to be renewed. Each key should be a unique item identifier, or item number and the value should be a variable name used to refer to the item in question. Because different ILSs will handle renewal's differently, the connector can interpret this however it likes. This convention is so that Locum can round-trip the data.
Array ($items)
(
[{$inum}] => (string) Item identifier/variable name
)Expected Result:
Array of renewal result information
(
[{$inum}] => Array
(
[num_renews] => (int) # of times this item has been renewed sinced checked out
[error] => (string) Error message if this item cannot be renewed
[varname] => (string) This is the variable name as passed to the function
[new_duedate] => (int) UNIX timestamp of the item's new due date. Original due date if the item could not be renewed.
)
)Function:
scrape_bib ($bnum, $skip_cover = FALSE)
Purpose:
scrape_bib() needs to return an array of information about a particular bibliographic record. Locum's server class (locum_server) uses this function for harvesting and keeping the database up-to-date.
Arguments:
$bnum : (string) required An item's bibliographic number or unique identifier.
$skip_cover : (boolean) optional Tells the connector function to return a cover image URL in the result set.
Expected Result:
Array
(
[bnum] => (string) Bib number of record returned
[bib_created] => (date - YYYY-MM-DD) Date bib record was created
[bib_lastupdate] => (date) Date of last update to the record
[bib_prevupdate] => (date) (optional) Date of next-to-last update to the record
[bib_revs] => (int) (optional) Number of revisions to the record
[lang] => (string) Language code
[loc_code] => (string) Bib-level location or branch code
[mat_code] => (string) Material code
[suppress] => (int) 1 = Item should be suppressed, 0 = Not suppressed
[author] => (string) Author: lastname, firstname birth year-death year
[addl_author] => (string) Array of additional authors: lastname, firstname birth year-death year [serialized]
[title] => (string) Title of work
[title_medium] => (string) Media format description
[edition] => (string) Edition information (MARC 250a)
[series] => (string) Series name
[callnum] => (string) Call number (MARC 099a)
[pub_info] => (string) Publisher/publication information (MARC 260abc)
[pub_year] => (int) Year of publication (MARC 300c)
[stdnum] => (string) Standard number (ie ISBN) (MARC 020a)
[upc] => (int) UPC symbol number (MARC 024a)
[cover_img] => (string) URL of cover image
[lccn] => (string) Library of Congress Catalog number (MARC 010)
[descr] => (string) Physical Description (MARC 300abc)
[notes] => (string) Array of record notes [serialized] (MARC 500,505,511,520)
[subjects] => Array of subject headings
(
[] => (string) Subject heading
)
)Example:
Array
(
[bnum] => 1279429
[bib_created] => 2008-01-15
[bib_lastupdate] => 2008-02-11
[bib_prevupdate] => 2008-01-22
[bib_revs] => 3
[lang] => eng
[loc_code] => a
[mat_code] => b
[suppress] => 0
[author] => O'Brian, Patrick, 1914-2000
[addl_author] => a:1:{i:0;s:13:"Tull, Patrick";}
[title] => The thirteen gun salute
[title_medium] => sound recording
[edition] =>
[series] => Aubrey/Maturin series ; 13
[callnum] => ACD Fic OBRIAN
[pub_info] => Prince Frederick, Md. : Recorded Books, p1995, c1989
[pub_year] => 1989
[stdnum] => 1402588992
[upc] => 000000000000
[cover_img] =>
[lccn] =>
[descr] => 11 sound discs (13.25 hr.) : digital ; 4 3/4 in
[notes] => a:4:{i:0;s:13:"Compact discs";i:1;s:10:"Unabridged";i:2;s:24:"Narrated by Patrick Tull";i:3;s:206:"Captain Jack Aubrey and
Stephen Maturin set sail for the South China Sea. At the barbaric court of Pulo Prabang, the stage is set for a duel of intelligence age
nts, pitting Stephen against the French envoys";}
[subjects] => Array
(
[0] => Aubrey, Jack (Fictitious character) -- Fiction
[1] => Maturin, Stephen (Fictitious character) -- Fiction
[2] => Great Britain -- Fiction -- History, Naval -- 19th century
[3] => South China Sea -- Fiction -- History, Naval -- 19th century
[4] => Historical fiction.
[5] => Sea stories.
[6] => Audiobooks
)
)Function:
update_holds($cardnum, $pin = NULL, $cancelholds = array(), $holdfreezes_to_update = array(), $pickup_locations = array())
Purpose:
update_holds() needs to accept several arrays of information about the holds that need to be updated and perform the adjustments on the holds. The calling application must explicitly pass NULL for arrays that refer to hold properties that do not need to be changed.
Arguments:
$cardnum : (string) required The patron's library card number.
$pin : (string) optional The patron's PIN number or password. (must explicitly pass NULL for no pin)
$cancelholds : (array) optional A standard array of unique identifiers of items whose holds are to be canceled.
Array ($cancelholds)
(
[{bib number of item}] => (int) 1 = Cancel this hold, 0 (optional) = do not cancel
)Array ($holdfreezes_to_update)
(
[{bib number of item}] => (int) 1 = Freeze this item, 0 = unfreeze this item
)Array ($pickup_locations)
(
[{bib number of item}] => Array of new pickup location information
(
[selectid] => Unique variable name that refers to this item's pickup location
[selected] => New pickup location value
)
)Expected Result:
(boolean) TRUE = successfully processed, FALSE = unsuccessfully processed