Estos días he estado trasteando con vufind ([1] y [2]).
Mostrar el enlace hacia Holds
En algunas bibliotecas que también tienen vufind y su catálogo es Innovative Millenium había visto que mostraban la posibilidad de colocar un enlace para reservar ejemplares directamente. Sin embargo en mi instalación de vufind no parecía funcionar.
Investigando un poco en la wiki de vufind descubrí que el fichero que me estaba “fastidiando” era el view-holdings.tpl y más en concreto estas líneas:
{foreach from=$holding item=row} {if $row.barcode != ""} |
Mis registros no tenían un valor de barcode asignado, por lo cual esa parte del código no se ejecutaba.
¿Cómo lo averigué? Colocando un print_r de la variable $row en smarty (cómo hacer print_r de arrays en smarty templates). Mi código de view-holdings.tpl ha quedado ahora asi:
{foreach from=$holding item=row} <em> Edit view-holdings.tpl by MiguelMartin</em><br /> {$row|@print_r} <!-- comento esta linea y añado la siguiente --> <!--if $row.barcode != ""--> {if $row.id != ""} |
Como todos mis registros sí tienen ID, el código se ejecuta y se muestra el link.
Que viva el open source!
(Para saber cómo configurar la conexión entre vufind y tu software de catálogo puedes consultar éste link)
Hacer que funcione el enlace a Holds usando Innovative
El link que se genera con lo anterior es del tipo
http://yourvufindserver.com/vufind/Record/.b10002030/Hold
Si usamos el driver de Innovative que viene por defecto (la pareja de archivos Innovative.ini y Innovative.php) obtendremos un error de PEAR que dice algo asi:
Cannot Process Place Hold - ILS Not Supported |
Este error viene de $VUFIND_HOME/web/services/Record/Hold.php.
Para solucionarlo cambiad vuestro Innovative.ini por algo del tipo (ojo, cambiad la ‘url’ de la sección [Catalog] y de [PATRONAPI] para que apunte a la url de vuestro catálogo):
[Catalog] url = http://iii.server.org ; The following is a set of fields to look up for ; Change them to match your HTML [OPAC] location_column = "Location" call_no_column = "Call No" status_column = "Status" reserves_column = "Location" reserves_key_name = "res" status_avail = "AVAILABLE" status_due = "DUE " [CONFIG] ; "bib" or "item" level holds holdtype = "bib" [PATRONAPI] ; Enable III Patron API usage for patron authentication ; and profile information. enabled = "true" url = http://iii.server.org:4500/PATRONAPI/ |
Y vuestro Innovative.php por:
<?php /** * * Copyright (C) Villanova University 2007. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ require_once 'sys/Proxy_Request.php'; require_once 'Interface.php'; /** * VuFind Connector for Innovative * * This class uses screen scraping techniques to gather record holdings written * by Adam Bryn of the Tri-College consortium. * * @author Adam Brin <abrin@brynmawr.com> */ class Innovative implements DriverInterface { public $config; public function __construct() { // Load Configuration for this Module $this->config = parse_ini_file('conf/Innovative.ini', true); } public function getStatus($id) { // Strip ID $id_ = substr(str_replace('.b', '', $id), 0, -1); // Load Record Page if (substr($this->config['Catalog']['url'], -1) == '/') { $host = substr($this->config['Catalog']['url'], 0, -1); } else { $host = $this->config['Catalog']['url']; } //$req = new Proxy_Request($host . '/record=b' . $id_); //Grab the full item list view $req = new Proxy_Request($host . '/search/.b' . $id_ . '/.b' . $id_ .'/1%2C1%2C1%2CB/holdings~' . $id_ . '&FF=&1%2C0%2C'); if (PEAR::isError($req->sendRequest())) { return null; } $result = $req->getResponseBody(); //strip out html before the first occurance of 'bibItems', should be '<table class="bibItems" ' $r = substr($result, stripos($result, 'bibItems')); //strip out the rest of the first table tag. $r = substr($r,strpos($r,">")+1); //strip out the next table closing tag and everything after it. $r = substr($r,0,stripos($r,"</table")); //$r should only include the holdings table at this point //split up into strings that contain each table row, excluding the beginning tr tag. $rows = preg_split("/<tr([^>]*)>/",$r); $count = 0; $keys = array_pad(array(),10,""); $loc_col_name = $this->config['OPAC']['location_column']; $call_col_name = $this->config['OPAC']['call_no_column']; $status_col_name = $this->config['OPAC']['status_column']; $reserves_col_name = $this->config['OPAC']['location_column']; $reserves_key_name = $this->config['OPAC']['reserves_key_name']; $stat_avail = $this->config['OPAC']['status_avail']; $stat_due = $this->config['OPAC']['status_due']; $ret = array(); foreach ($rows as $row) { // Split up the contents of the row based on the th or td tag, excluding the tags themselves. $cols = preg_split("/<t(h|d)([^>]*)>/",$row); //for each th or td section, do the following. for ($i=0; $i < sizeof($cols); $i++) { //replace non blocking space encodings with a space. $cols[$i] = str_replace(" "," ",$cols[$i]); //remove html comment tags $cols[$i] = ereg_replace("<!--([^(-->)]*)-->","",$cols[$i]); //Remove closing th or td tag, trim whitespace and decode html entities $cols[$i] = html_entity_decode(trim(substr($cols[$i],0,stripos($cols[$i],"</t")))); //If this is the first row, it is the header row and has the column names if ($count == 1) { $keys[$i] = $cols[$i]; } else if ($count > 1) { //not the first row, has holding info //look for location column if (stripos($keys[$i],$loc_col_name) > -1) { $ret[$count-2]['location'] = strip_tags($cols[$i]); } // Does column hold reserves information? if (stripos($keys[$i],$reserves_col_name) > -1) { if (stripos($cols[$i],$reserves_key_name) > -1) { $ret[$count-2]['reserve'] = 'Y'; } else { $ret[$count-2]['reserve'] = 'N'; } } // Does column hold call numbers? if (stripos($keys[$i],$call_col_name) > -1) { $ret[$count-2]['callnumber'] = strip_tags($cols[$i]); } // Look for status information. if (stripos($keys[$i],$status_col_name) > -1) { if (stripos($cols[$i],$stat_avail) > -1) { $ret[$count-2]['status'] = "Available On Shelf"; $ret[$count-2]['availability'] = 1; } else { $ret[$count-2]['status'] = "Available to request"; $ret[$count-2]['availability'] = 0; } if (stripos($cols[$i],$stat_due) > -1) { $t = trim(substr($cols[$i],stripos($cols[$i],$stat_due)+strlen($stat_due))); $t = substr($t,0,stripos($t," ")); $ret[$count-2]['duedate'] = $t; } } //$ret[$count-2][$keys[$i]] = $cols[$i]; //$ret[$count-2]['id'] = $bibid; $ret[$count-2]['id'] = $id; $ret[$count-2]['number'] = ($count -1); //Return a fake barcode so hold link is enabled // Should be dependent on settings variable, If bib level holds. $ret[$count-2]['barcode'] = '1234567890123'; } } $count++; } return $ret; } public function getStatuses($ids) { $items = array(); $count = 0; foreach ($ids as $id) { $items[$count] = $this->getStatus($id); $count++; } return $items; } public function getHolding($id) { return $this->getStatus($id); } public function getPurchaseHistory($id) { return array(); } public function getHoldLink($id) { // Strip ID $id_ = substr(str_replace('.b', '', $id), 0, -1); //Build request link $link = $this->config['Catalog']['url'] . '/search?/.b' . $id_ . '/.b' . $id_ . '/1%2C1%2C1%2CB/request~b'. $id_; //$link = $this->config['Catalog']['url'] . '/record=b' . $id_; return $link; } public function getMyProfile($userinfo) { return $userinfo; } public function patronLogin($username,$password) { //Todo, if username is a barcode, test to make sure it fits proper format if($this->config['PATRONAPI']['enabled'] == 'true'){ //use patronAPI to authenticate customer $url = $this->config['PATRONAPI']['url']; //build patronapi pin test request $req = new Proxy_Request($url . urlencode($username) . '/' . urlencode($password) . '/pintest'); if (PEAR::isError($req->sendRequest())) { return null; } $result = $req->getResponseBody(); //search for sucessfull response of "RETCOD=0" if(stripos($result,"RETCOD=0") == -1){ //pin did not match, can look up specific error to return more usefull info. return null; } //Pin did match, get patron information $req = new Proxy_Request($url . urlencode($username) . '/dump'); if (PEAR::isError($req->sendRequest())) { return null; } $result = $req->getResponseBody(); //The following is taken and modified from patronapi.php by John Blyberg released under the GPL $api_contents = trim(strip_tags($result)); $api_array_lines = explode("\n", $api_contents); while (strlen($api_data[PBARCODE]) != 14 && !$api_data[ERRNUM]) { foreach ($api_array_lines as $api_line) { $api_line = str_replace("p=", "peq", $api_line); $api_line_arr = explode("=", $api_line); $regex_match = array("/\[(.*?)\]/","/\s/","/#/"); $regex_replace = array('','','NUM'); $key = trim(preg_replace($regex_match, $regex_replace, $api_line_arr[0])); $api_data[$key] = trim($api_line_arr[1]); } } if(!$api_data[PBARCODE]){ //no barcode found, can look up specific error to return more useful info. //this check needs to be modified to handle using III patron ids also. return null; } //return patron info $ret = array(); $ret['id'] = $api_data[PBARCODE]; //or should I return patron id num? $names = explode(',', $api_data[PATRNNAME]); $ret['firstname'] = $names[1]; $ret['lastname'] = $names[0]; $ret['cat_username'] = urlencode($username); $ret['cat_password'] = urlencode($password); $ret['email'] = $api_data[EMAILADDR]; $ret['major'] = null; $ret['college'] = $api_data[HOMELIBR]; $ret['homelib'] = $api_data[HOMELIBR]; //replace $ seperator in III addresses with newline $ret['address1'] = str_replace("$",", ",$api_data[ADDRESS]); $ret['address2'] = str_replace("$",", ",$api_data[ADDRESS2]); preg_match("/([0-9]{5}|[0-9]{5}-[0-9]{4})[ ]*$/",$api_data[ADDRESS],$zipmatch); $ret['zip'] = $zipmatch[1]; //retreive from address $ret['phone'] = $api_data[TELEPHONE]; $ret['phone2'] = $api_data[TELEPHONE2]; //Should probably have a translation table for patron type $ret['group'] = $api_data[PTYPE]; $ret['expiration'] = $api_data[EXPDATE]; //Only if agency module is enabled. $ret['region'] = $api_data[AGENCY]; return $ret; } else { //use screen scrape } } } ?> |
De esta forma al hacer click en “Reservar” os llevará a algo del tipo:
https://yourcatalog.com/patroninfo~S1/0/redirect=/search?/.b1000203/.b1000203/1%2C1%2C1%2CB/request~b1000203 |
Ver Más ayuda.

