Rev 116 | Rev 122 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 2 | jblyberg | 1 | <?php |
| 23 | jblyberg | 2 | /** |
| 3 | * Locum is a software library that abstracts ILS functionality into a |
||
| 4 | * catalog discovery layer for use with such things as bolt-on OPACs like |
||
| 5 | * SOPAC. |
||
| 101 | jblyberg | 6 | * |
| 7 | * This connector assumes that your Millennium webpac/webpac pro is set up |
||
| 8 | * to display in UTF-8. You may need to verify with III's helpdesk that |
||
| 9 | * it is. Additionally, you will need to verify that your III database |
||
| 10 | * has been converted to unicode storage. See: |
||
| 11 | * http://csdirect.iii.com/documentation/unicodestorage.shtml |
||
| 12 | * |
||
| 108 | jblyberg | 13 | * This connector has been developed against the plain-vanilla WebPAC |
| 14 | * Example Sets and Photoshop Files that can be downloaded for Release |
||
| 15 | * 2007 from here: |
||
| 16 | * http://csdirect.iii.com/downloads/webopac_custom_files.shtml |
||
| 17 | * The only wwwoption change you'll need to make, will be to enable |
||
| 18 | * (uncheck Inactive) FREEZE_HOLDS in the "Patron Record" section. |
||
| 19 | * |
||
| 23 | jblyberg | 20 | * @package Locum |
| 21 | * @category Locum Connector |
||
| 22 | * @author John Blyberg |
||
| 23 | */ |
||
| 2 | jblyberg | 24 | |
| 23 | jblyberg | 25 | /** |
| 26 | * The Locum connector class for III Mil. 2006. |
||
| 27 | * Note the naming convention that is required by Locum: locum _ vendor _ version |
||
| 28 | * Also, from a philisophical standpoint, I try to use only public-facing services here, |
||
| 29 | * with the exception of the III patron API, which is a product we bought, along with |
||
| 30 | * practically every other III customer. |
||
| 31 | */ |
||
| 80 | jblyberg | 32 | class locum_iii_2007 { |
| 2 | jblyberg | 33 | |
| 103 | jblyberg | 34 | public $locum_config; |
| 5 | jblyberg | 35 | |
| 103 | jblyberg | 36 | /** |
| 37 | * Prep this class |
||
| 38 | */ |
||
| 39 | public function __construct() { |
||
| 40 | require_once('patronapi.php'); |
||
| 41 | } |
||
| 21 | jblyberg | 42 | |
| 103 | jblyberg | 43 | /** |
| 44 | * Grabs bib info from XRECORD and returns it in a Locum-ready array. |
||
| 45 | * |
||
| 46 | * @param int $bnum Bib number to scrape |
||
| 47 | * @param boolean $skip_cover Forget about grabbing cover images. Default: FALSE |
||
| 48 | * @return boolean|array Will either return a Locum-ready array or FALSE |
||
| 49 | */ |
||
| 50 | public function scrape_bib($bnum, $skip_cover = FALSE) { |
||
| 2 | jblyberg | 51 | |
| 108 | jblyberg | 52 | $iii_server_info = self::iii_server_info(); |
| 6 | jblyberg | 53 | |
| 103 | jblyberg | 54 | $bnum = trim($bnum); |
| 17 | jblyberg | 55 | |
| 108 | jblyberg | 56 | $xrecord = @simplexml_load_file($iii_server_info['nosslurl'] . '/xrecord=b' . $bnum); |
| 18 | jblyberg | 57 | |
| 103 | jblyberg | 58 | // If there is no record, return false (weeded or non-existent) |
| 59 | if ($xrecord->NULLRECORD) { |
||
| 60 | return FALSE; |
||
| 61 | } |
||
| 62 | if ($xrecord->VARFLD) { |
||
| 63 | if (!$xrecord->VARFLD[0]->MARCINFO) { |
||
| 64 | return FALSE; |
||
| 65 | } |
||
| 66 | } else { |
||
| 67 | return 'skip'; |
||
| 68 | } |
||
| 2 | jblyberg | 69 | |
| 103 | jblyberg | 70 | $bib_info_record = $xrecord->RECORDINFO; |
| 71 | $bib_info_local = $xrecord->TYPEINFO->BIBLIOGRAPHIC->FIXFLD; |
||
| 72 | $bib_info_marc = self::parse_marc_subfields($xrecord->VARFLD); |
||
| 73 | unset($xrecord); |
||
| 19 | jblyberg | 74 | |
| 103 | jblyberg | 75 | // Process record information |
| 76 | $bib['bnum'] = $bnum; |
||
| 77 | $bib['bib_created'] = self::fixdate($bib_info_record->CREATEDATE); |
||
| 78 | $bib['bib_lastupdate'] = self::fixdate($bib_info_record->LASTUPDATEDATE); |
||
| 79 | $bib['bib_prevupdate'] = self::fixdate($bib_info_record->PREVUPDATEDATE); |
||
| 80 | $bib['bib_revs'] = (int) $bib_info_record->REVISIONS; |
||
| 2 | jblyberg | 81 | |
| 103 | jblyberg | 82 | // Process local record data |
| 83 | foreach ($bib_info_local as $bil_obj) { |
||
| 84 | switch (trim($bil_obj->FIXLABEL)) { |
||
| 85 | case 'LANG': |
||
| 86 | $bib['lang'] = trim($bil_obj->FIXVALUE); |
||
| 87 | break; |
||
| 88 | case 'LOCATION': |
||
| 89 | $bib['loc_code'] = trim($bil_obj->FIXVALUE); |
||
| 90 | break; |
||
| 91 | case 'MAT TYPE': |
||
| 92 | $bib['mat_code'] = trim($bil_obj->FIXVALUE); |
||
| 93 | break; |
||
| 94 | case 'BCODE3': |
||
| 95 | $bib['suppress'] = in_array(trim($bil_obj->FIXVALUE), locum::csv_parser($this->locum_config['ils_custom_config']['suppress_codes'])) ? 1 : 0; |
||
| 96 | break; |
||
| 2 | jblyberg | 97 | |
| 103 | jblyberg | 98 | } |
| 99 | } |
||
| 2 | jblyberg | 100 | |
| 103 | jblyberg | 101 | // Process MARC fields |
| 2 | jblyberg | 102 | |
| 103 | jblyberg | 103 | // Process Author information |
| 104 | $bib['author'] = ''; |
||
| 105 | $author_arr = self::prepare_marc_values($bib_info_marc['100'], array('a','b','c','d')); |
||
| 106 | $bib['author'] = $author_arr[0]; |
||
| 2 | jblyberg | 107 | |
| 103 | jblyberg | 108 | // In no author info, we'll go for the 110 field |
| 109 | if (!$bib['author']) { |
||
| 110 | $author_110 = self::prepare_marc_values($bib_info_marc['110'], array('a')); |
||
| 111 | $bib['author'] = $author_110[0]; |
||
| 112 | } |
||
| 2 | jblyberg | 113 | |
| 103 | jblyberg | 114 | // Additional author information |
| 115 | $bib['addl_author'] = ''; |
||
| 116 | $addl_author = self::prepare_marc_values($bib_info_marc['700'], array('a','b','c','d')); |
||
| 117 | if (is_array($addl_author)) { |
||
| 118 | $bib['addl_author'] = serialize($addl_author); |
||
| 119 | } |
||
| 2 | jblyberg | 120 | |
| 103 | jblyberg | 121 | // In no additional author info, we'll go for the 710 field |
| 122 | if (!$bib['addl_author']) { |
||
| 123 | $author_710 = self::prepare_marc_values($bib_info_marc['710'], array('a')); |
||
| 124 | if (is_array($author_710)) { |
||
| 125 | $bib['addl_author'] = serialize($author_710); |
||
| 126 | } |
||
| 127 | } |
||
| 2 | jblyberg | 128 | |
| 103 | jblyberg | 129 | // Title information |
| 130 | $bib['title'] = ''; |
||
| 131 | $title = self::prepare_marc_values($bib_info_marc['245'], array('a','b')); |
||
| 132 | if (substr($title[0], -1) == '/') { $title[0] = trim(substr($title[0], 0, -1)); } |
||
| 133 | $bib['title'] = trim($title[0]); |
||
| 2 | jblyberg | 134 | |
| 103 | jblyberg | 135 | // Title medium information |
| 136 | $bib['title_medium'] = ''; |
||
| 137 | $title_medium = self::prepare_marc_values($bib_info_marc['245'], array('h')); |
||
| 138 | if ($title_medium[0]) { |
||
| 139 | if (preg_match('/\[(.*?)\]/', $title_medium[0], $medium_match)) { |
||
| 140 | $bib['title_medium'] = $medium_match[1]; |
||
| 141 | } |
||
| 142 | } |
||
| 143 | |||
| 144 | // Edition information |
||
| 145 | $bib['edition'] = ''; |
||
| 146 | $edition = self::prepare_marc_values($bib_info_marc['250'], array('a')); |
||
| 147 | $bib['edition'] = trim($edition[0]); |
||
| 2 | jblyberg | 148 | |
| 103 | jblyberg | 149 | // Series information |
| 150 | $bib['series'] = ''; |
||
| 151 | $series = self::prepare_marc_values($bib_info_marc['490'], array('a','v')); |
||
| 152 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['440'], array('a','v')); } |
||
| 153 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['400'], array('a','v')); } |
||
| 154 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['410'], array('a','v')); } |
||
| 155 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['730'], array('a','v')); } |
||
| 156 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['800'], array('a','v')); } |
||
| 157 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['810'], array('a','v')); } |
||
| 158 | if (!$series[0]) { $series = self::prepare_marc_values($bib_info_marc['830'], array('a','v')); } |
||
| 159 | $bib['series'] = $series[0]; |
||
| 5 | jblyberg | 160 | |
| 103 | jblyberg | 161 | // Call number |
| 162 | $callnum = ''; |
||
| 163 | $callnum_arr = self::prepare_marc_values($bib_info_marc['099'], array('a')); |
||
| 164 | if (is_array($callnum_arr) && count($callnum_arr)) { |
||
| 165 | foreach ($callnum_arr as $cn_sub) { |
||
| 166 | $callnum .= $cn_sub . ' '; |
||
| 167 | } |
||
| 168 | } |
||
| 169 | $bib['callnum'] = trim($callnum); |
||
| 170 | |||
| 171 | // Publication information |
||
| 172 | $bib['pub_info'] = ''; |
||
| 173 | $pub_info = self::prepare_marc_values($bib_info_marc['260'], array('a','b','c')); |
||
| 174 | $bib['pub_info'] = $pub_info[0]; |
||
| 2 | jblyberg | 175 | |
| 103 | jblyberg | 176 | // Publication year |
| 177 | $bib['pub_year'] = ''; |
||
| 178 | $pub_year = self::prepare_marc_values($bib_info_marc['260'], array('c')); |
||
| 179 | $c_arr = explode(',', $pub_year[0]); |
||
| 180 | $c_key = count($c_arr) - 1; |
||
| 181 | $bib['pub_year'] = substr(ereg_replace("[^0-9]", '', $c_arr[$c_key]), -4); |
||
| 8 | jblyberg | 182 | |
| 103 | jblyberg | 183 | // ISBN / Std. number |
| 184 | $bib['stdnum'] = ''; |
||
| 185 | $stdnum = self::prepare_marc_values($bib_info_marc['020'], array('a')); |
||
| 186 | $bib['stdnum'] = $stdnum[0]; |
||
| 187 | |||
| 188 | // UPC |
||
| 189 | $bib['upc'] = ''; |
||
| 190 | $upc = self::prepare_marc_values($bib_info_marc['024'], array('a')); |
||
| 191 | $bib['upc'] = $upc[0]; |
||
| 192 | if($bib['upc'] == '') { $bib['upc'] = "000000000000"; } |
||
| 2 | jblyberg | 193 | |
| 103 | jblyberg | 194 | // Grab the cover image URL if we're doing that |
| 195 | $bib['cover_img'] = ''; |
||
| 196 | if ($skip_cover != TRUE) { |
||
| 197 | if ($bib['stdnum']) { $bib['cover_img'] = locum_server::get_cover_img($bib['stdnum']); } |
||
| 198 | } |
||
| 5 | jblyberg | 199 | |
| 103 | jblyberg | 200 | // LCCN |
| 201 | $bib['lccn'] = ''; |
||
| 202 | $lccn = self::prepare_marc_values($bib_info_marc['010'], array('a')); |
||
| 203 | $bib['lccn'] = $lccn[0]; |
||
| 116 | jblyberg | 204 | |
| 205 | // Download Link (if it's a downloadable) |
||
| 206 | $bib['download_link'] = ''; |
||
| 207 | $dl_link = self::prepare_marc_values($bib_info_marc['856'], array('u')); |
||
| 208 | $bib['download_link'] = $dl_link[0]; |
||
| 2 | jblyberg | 209 | |
| 103 | jblyberg | 210 | // Description |
| 211 | $bib['descr'] = ''; |
||
| 212 | $descr = self::prepare_marc_values($bib_info_marc['300'], array('a','b','c')); |
||
| 213 | $bib['descr'] = $descr[0]; |
||
| 2 | jblyberg | 214 | |
| 103 | jblyberg | 215 | // Notes |
| 216 | $notes = array(); |
||
| 217 | $bib['notes'] = ''; |
||
| 218 | $notes_tags = array('500','505','511','520'); |
||
| 219 | foreach ($notes_tags as $notes_tag) { |
||
| 220 | $notes_arr = self::prepare_marc_values($bib_info_marc[$notes_tag], array('a')); |
||
| 221 | if (is_array($notes_arr)) { |
||
| 222 | foreach ($notes_arr as $notes_arr_val) { |
||
| 223 | array_push($notes, $notes_arr_val); |
||
| 224 | } |
||
| 225 | } |
||
| 226 | } |
||
| 227 | if (count($notes)) { $bib['notes'] = serialize($notes); } |
||
| 2 | jblyberg | 228 | |
| 103 | jblyberg | 229 | // Subject headings |
| 230 | $subjects = array(); |
||
| 231 | $subj_tags = array( |
||
| 232 | '600', '610', '611', '630', '650', '651', |
||
| 233 | '653', '654', '655', '656', '657', '658', |
||
| 234 | '690', '691', '692', '693', '694', '695', |
||
| 235 | '696', '697', '698', '699' |
||
| 236 | ); |
||
| 237 | foreach ($subj_tags as $subj_tag) { |
||
| 238 | $subj_arr = self::prepare_marc_values($bib_info_marc[$subj_tag], array('a','b','c','d','e','v','x','y','z'), ' -- '); |
||
| 239 | if (is_array($subj_arr)) { |
||
| 240 | foreach ($subj_arr as $subj_arr_val) { |
||
| 241 | array_push($subjects, $subj_arr_val); |
||
| 242 | } |
||
| 243 | } |
||
| 244 | } |
||
| 245 | $bib['subjects'] = ''; |
||
| 246 | if (count($subjects)) { $bib['subjects'] = $subjects; } |
||
| 247 | |||
| 248 | unset($bib_info_marc); |
||
| 249 | return $bib; |
||
| 250 | } |
||
| 2 | jblyberg | 251 | |
| 103 | jblyberg | 252 | /** |
| 253 | * Parses item status for a particular bib item. |
||
| 254 | * |
||
| 255 | * @param string $bnum Bib number to query |
||
| 256 | * @return array Returns a Locum-ready availability array |
||
| 257 | */ |
||
| 258 | public function item_status($bnum) { |
||
| 259 | |||
| 108 | jblyberg | 260 | $iii_server_info = self::iii_server_info(); |
| 103 | jblyberg | 261 | $avail_token = locum::csv_parser($this->locum_config['ils_custom_config']['iii_available_token']); |
| 262 | $default_age = $this->locum_config['iii_custom_config']['default_age']; |
||
| 120 | jblyberg | 263 | $default_branch = $this->locum_config['iii_custom_config']['default_branch']; |
| 103 | jblyberg | 264 | $loc_codes_flipped = array_flip($this->locum_config['iii_location_codes']); |
| 265 | $bnum = trim($bnum); |
||
| 6 | jblyberg | 266 | |
| 103 | jblyberg | 267 | // Grab Hold Numbers |
| 108 | jblyberg | 268 | $url = $iii_server_info['nosslurl'] . '/search~24/.b' . $bnum . '/.b' . $bnum . '/1,1,1,B/marc~' . $bnum . '&FF=&1,0,'; |
| 103 | jblyberg | 269 | $hold_page_raw = utf8_encode(file_get_contents($url)); |
| 6 | jblyberg | 270 | |
| 103 | jblyberg | 271 | // Reserves Regex |
| 272 | $regex_r = '/(?<hold_num>\d+) hold/'; |
||
| 273 | preg_match($regex_r, $hold_page_raw, $match_r); |
||
| 274 | $avail_array['holds'] = $match_r['hold_num'] ? $match_r['hold_num'] : 0; |
||
| 88 | jblyberg | 275 | |
| 103 | jblyberg | 276 | // Order Entry Regex |
| 277 | $avail_array['on_order'] = 0; |
||
| 278 | $regex_o = '%bibOrderEntry(.*?)td(.*?)>(.*?)<%s'; |
||
| 279 | preg_match_all($regex_o, $hold_page_raw, $match_o); |
||
| 280 | foreach($match_o[3] as $order) { |
||
| 281 | $order_txt = trim($order); |
||
| 282 | preg_match('%^(.*?)cop%s', $order_txt, $order_count); |
||
| 283 | $avail_array['on_order'] = $avail_array['on_order'] + (int) trim($order_count[1]); |
||
| 284 | $avail_array['orders'][] = $order_txt; |
||
| 285 | } |
||
| 88 | jblyberg | 286 | |
| 108 | jblyberg | 287 | $url = $iii_server_info['nosslurl'] . '/search~24/.b' . $bnum . '/.b' . $bnum . '/1,1,1,B/holdings~' . $bnum . '&FF=&1,0,'; |
| 103 | jblyberg | 288 | $avail_page_raw = utf8_encode(file_get_contents($url)); |
| 98 | jblyberg | 289 | |
| 103 | jblyberg | 290 | // Holdings Regex |
| 291 | $regex_h = '%field 1 --> (.*?)</td>(.*?)browse">(.*?)</a>(.*?)field \% --> (.*?)</td>%s'; |
||
| 292 | preg_match_all($regex_h, $avail_page_raw, $matches); |
||
| 91 | smaskit | 293 | |
| 103 | jblyberg | 294 | foreach ($matches[1] as $i => $location) { |
| 295 | // put the item details in the array |
||
| 296 | $location = trim($location); |
||
| 297 | $loc_code = $loc_codes_flipped[$location]; |
||
| 298 | $call = str_replace("'", "'", trim($matches[3][$i])); |
||
| 299 | $status = trim($matches[5][$i]); |
||
| 300 | $age = $default_age; |
||
| 120 | jblyberg | 301 | $branch = $default_branch; |
| 103 | jblyberg | 302 | |
| 303 | if (in_array($status, $avail_token)) { |
||
| 304 | $avail = 1; |
||
| 305 | $due_date = 0; |
||
| 306 | } else { |
||
| 307 | $avail = 0; |
||
| 308 | if (preg_match('/DUE/i', $status)) { |
||
| 309 | $due_arr = explode(' ', trim($status)); |
||
| 310 | $due_date_arr = explode('-', $due_arr[1]); |
||
| 311 | $due_date = mktime(0, 0, 0, $due_date_arr[0], $due_date_arr[1], (2000 + (int) $due_date_arr[2])); |
||
| 312 | } else { |
||
| 313 | $due_date = 0; |
||
| 314 | } |
||
| 315 | } |
||
| 120 | jblyberg | 316 | |
| 317 | // Determine age from location |
||
| 318 | if (count($this->locum_config['iii_record_ages'])) { |
||
| 319 | foreach ($this->locum_config['iii_record_ages'] as $item_age => $match_crit) { |
||
| 320 | if (preg_match('/^\//', $match_crit)) { |
||
| 321 | if (preg_match($match_crit, $loc_code)) { $age = $item_age; } |
||
| 322 | } else { |
||
| 323 | if (in_array($loc_code, locum::csv_parser($match_crit))) { $age = $item_age; } |
||
| 324 | } |
||
| 103 | jblyberg | 325 | } |
| 326 | } |
||
| 120 | jblyberg | 327 | |
| 328 | // Determine branch from location |
||
| 329 | if (count($this->locum_config['branch_assignments'])) { |
||
| 330 | foreach ($this->locum_config['branch_assignments'] as $branch_code => $match_crit) { |
||
| 331 | if (preg_match('/^\//', $match_crit)) { |
||
| 332 | if (preg_match($match_crit, $loc_code)) { $branch = $branch_code; } |
||
| 333 | } else { |
||
| 334 | if (in_array($loc_code, locum::csv_parser($match_crit))) { $branch = $branch_code; } |
||
| 335 | } |
||
| 336 | } |
||
| 337 | } |
||
| 338 | |||
| 103 | jblyberg | 339 | $avail_array['items'][] = array( |
| 340 | 'location' => $location, |
||
| 341 | 'loc_code' => $loc_code, |
||
| 342 | 'callnum' => $call, |
||
| 343 | 'statusmsg' => $status, |
||
| 344 | 'due' => $due_date, |
||
| 345 | 'avail' => $avail, |
||
| 346 | 'age' => $age, |
||
| 120 | jblyberg | 347 | 'branch' => $branch, |
| 103 | jblyberg | 348 | ); |
| 349 | } |
||
| 350 | |||
| 351 | return $avail_array; |
||
| 11 | jblyberg | 352 | |
| 103 | jblyberg | 353 | } |
| 354 | |||
| 355 | /** |
||
| 356 | * Returns an array of patron information |
||
| 357 | * |
||
| 358 | * @param string $pid Patron barcode number or record number |
||
| 359 | * @return boolean|array Array of patron information or FALSE if login fails |
||
| 360 | */ |
||
| 361 | public function patron_info($pid) { |
||
| 362 | $papi = new iii_patronapi; |
||
| 112 | jblyberg | 363 | $iii_server_info = self::iii_server_info(); |
| 364 | $papi->iiiserver = $iii_server_info['server']; |
||
| 103 | jblyberg | 365 | $papi_data = $papi->get_patronapi_data($pid); |
| 6 | jblyberg | 366 | |
| 103 | jblyberg | 367 | if (!$papi_data) { return FALSE; } |
| 26 | jblyberg | 368 | |
| 103 | jblyberg | 369 | $pdata['pnum'] = $papi_data['RECORDNUM']; |
| 370 | $pdata['cardnum'] = $papi_data['PBARCODE']; |
||
| 371 | $pdata['checkouts'] = $papi_data['CURCHKOUT']; |
||
| 372 | $pdata['homelib'] = $papi_data['HOMELIBR']; |
||
| 373 | $pdata['balance'] = (float) preg_replace('%\$%s', '', $papi_data['MONEYOWED']); |
||
| 374 | $pdata['expires'] = $papi_data['EXPDATE'] ? self::date_to_timestamp($papi_data['EXPDATE'], 2000) : NULL; |
||
| 375 | $pdata['name'] = $papi_data['PATRNNAME']; |
||
| 376 | $pdata['address'] = preg_replace('%\$%s', "\n", $papi_data['ADDRESS']); |
||
| 377 | $pdata['tel1'] = $papi_data['TELEPHONE']; |
||
| 378 | if ($papi_data['TELEPHONE2']) { $pdata['tel2'] = $papi_data['TELEPHONE2']; } |
||
| 379 | $pdata['email'] = $papi_data['EMAILADDR']; |
||
| 26 | jblyberg | 380 | |
| 103 | jblyberg | 381 | return $pdata; |
| 382 | } |
||
| 26 | jblyberg | 383 | |
| 103 | jblyberg | 384 | /** |
| 385 | * Returns an array of patron checkouts |
||
| 386 | * |
||
| 387 | * @param string $cardnum Patron barcode/card number |
||
| 388 | * @param string $pin Patron pin/password |
||
| 389 | * @return boolean|array Array of patron checkouts or FALSE if login fails |
||
| 390 | */ |
||
| 391 | public function patron_checkouts($cardnum, $pin = NULL) { |
||
| 106 | jblyberg | 392 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 393 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 394 | return $iii->get_patron_items(); |
||
| 395 | } |
||
| 93 | smaskit | 396 | |
| 103 | jblyberg | 397 | /** |
| 398 | * Returns an array of patron checkouts for history |
||
| 399 | * |
||
| 400 | * @param string $cardnum Patron barcode/card number |
||
| 401 | * @param string $pin Patron pin/password |
||
| 402 | * @return boolean|array Array of patron checkouts or FALSE if login fails |
||
| 403 | */ |
||
| 404 | public function patron_checkout_history($cardnum, $pin = NULL) { |
||
| 405 | $iii = $this->get_tools($cardnum, $pin); |
||
| 406 | $result = $iii ? $iii->get_patron_history_items() : FALSE; |
||
| 407 | return $result; |
||
| 408 | } |
||
| 113 | jblyberg | 409 | |
| 103 | jblyberg | 410 | /** |
| 411 | * Opts patron in or out of checkout history |
||
| 412 | * |
||
| 413 | * @param string $cardnum Patron barcode/card number |
||
| 414 | * @param string $pin Patron pin/password |
||
| 415 | * @return boolean|array Array of patron checkouts or FALSE if login fails |
||
| 416 | */ |
||
| 417 | public function patron_checkout_history_toggle($cardnum, $pin = NULL, $action) { |
||
| 418 | $iii = $this->get_tools($cardnum, $pin); |
||
| 419 | $result = $iii ? $iii->toggle_patron_history($action) : FALSE; |
||
| 420 | return $result; |
||
| 421 | } |
||
| 422 | |||
| 423 | /** |
||
| 424 | * Returns an array of patron holds |
||
| 425 | * |
||
| 426 | * @param string $cardnum Patron barcode/card number |
||
| 427 | * @param string $pin Patron pin/password |
||
| 428 | * @return boolean|array Array of patron holds or FALSE if login fails |
||
| 429 | */ |
||
| 430 | public function patron_holds($cardnum, $pin = NULL) { |
||
| 106 | jblyberg | 431 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 432 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 433 | return $iii->get_patron_holds(); |
||
| 434 | } |
||
| 435 | |||
| 436 | /** |
||
| 437 | * Renews items and returns the renewal result |
||
| 438 | * |
||
| 439 | * @param string $cardnum Patron barcode/card number |
||
| 440 | * @param string $pin Patron pin/password |
||
| 441 | * @param array Array of varname => item numbers to be renewed, or NULL for everything. |
||
| 442 | * @return boolean|array Array of item renewal statuses or FALSE if it cannot renew for some reason |
||
| 443 | */ |
||
| 444 | public function renew_items($cardnum, $pin = NULL, $items = NULL) { |
||
| 106 | jblyberg | 445 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 446 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 447 | return $iii->renew_material($items); |
||
| 448 | } |
||
| 110 | jblyberg | 449 | |
| 103 | jblyberg | 450 | /** |
| 110 | jblyberg | 451 | * Updates holds/reserves |
| 103 | jblyberg | 452 | * |
| 453 | * @param string $cardnum Patron barcode/card number |
||
| 454 | * @param string $pin Patron pin/password |
||
| 110 | jblyberg | 455 | * @param array $cancelholds Array of varname => item/bib numbers to be cancelled, or NULL for everything. |
| 456 | * @param array $holdfreezes_to_update Array of updated holds freezes. |
||
| 457 | * @param array $pickup_locations Array of pickup location changes. |
||
| 103 | jblyberg | 458 | * @return boolean TRUE or FALSE if it cannot cancel for some reason |
| 459 | */ |
||
| 110 | jblyberg | 460 | public function update_holds($cardnum, $pin = NULL, $cancelholds = array(), $holdfreezes_to_update = array(), $pickup_locations = array()) { |
| 106 | jblyberg | 461 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 462 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 112 | jblyberg | 463 | $iii->update_holds($cancelholds, $holdfreezes_to_update, $pickup_locations); |
| 103 | jblyberg | 464 | return TRUE; |
| 465 | } |
||
| 27 | jblyberg | 466 | |
| 103 | jblyberg | 467 | /** |
| 468 | * Places holds |
||
| 469 | * |
||
| 470 | * @param string $cardnum Patron barcode/card number |
||
| 471 | * @param string $bnum Bib item record number to place a hold on |
||
| 472 | * @param string $inum Item number to place a hold on if required (presented as $varname in locum) |
||
| 473 | * @param string $pin Patron pin/password |
||
| 474 | * @param string $pickup_loc Pickup location value |
||
| 475 | * @return boolean TRUE or FALSE if it cannot place the hold for some reason |
||
| 476 | */ |
||
| 477 | public function place_hold($cardnum, $bnum, $inum = NULL, $pin = NULL, $pickup_loc = NULL) { |
||
| 106 | jblyberg | 478 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 479 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 480 | return $iii->place_hold($bnum, $inum, $pickup_loc); |
||
| 481 | } |
||
| 482 | |||
| 483 | /** |
||
| 484 | * Returns an array of patron fines |
||
| 485 | * |
||
| 486 | * @param string $cardnum Patron barcode/card number |
||
| 487 | * @param string $pin Patron pin/password |
||
| 488 | * @return boolean|array Array of patron fines or FALSE if login fails |
||
| 489 | */ |
||
| 490 | public function patron_fines($cardnum, $pin = NULL) { |
||
| 106 | jblyberg | 491 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 492 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 493 | $fines = $iii->get_patron_fines(); |
||
| 494 | return $fines['items']; |
||
| 495 | } |
||
| 496 | |||
| 497 | /** |
||
| 498 | * Pays patron fines. |
||
| 499 | * @param string $cardnum Patron barcode/card number |
||
| 500 | * @param string $pin Patron pin/password |
||
| 501 | * @param array payment_details |
||
| 502 | * @return array Payment result |
||
| 503 | */ |
||
| 504 | public function pay_patron_fines($cardnum, $pin = NULL, $payment_details) { |
||
| 106 | jblyberg | 505 | $iii = $this->get_tools($cardnum, $pin); |
| 103 | jblyberg | 506 | if ($iii->catalog_login() == FALSE) { return FALSE; } |
| 507 | $iii_payment_details['varnames'] = $payment_details['varnames']; |
||
| 508 | $iii_payment_details['amount'] = '$' . number_format($payment_details['total'], 2); |
||
| 509 | $iii_payment_details['name'] = $payment_details['name']; |
||
| 510 | $iii_payment_details['address1'] = $payment_details['address1']; |
||
| 511 | $iii_payment_details['city'] = $payment_details['city']; |
||
| 512 | $iii_payment_details['state'] = $payment_details['state']; |
||
| 513 | $iii_payment_details['zip'] = $payment_details['zip']; |
||
| 514 | $iii_payment_details['email'] = $payment_details['email']; |
||
| 515 | $iii_payment_details['ccnum'] = $payment_details['ccnum']; |
||
| 516 | $iii_payment_details['ccexp_month'] = $payment_details['ccexpmonth']; |
||
| 517 | $iii_payment_details['ccexp_year'] = $payment_details['ccexpyear']; |
||
| 518 | $iii_payment_details['cvv'] = $payment_details['ccseccode']; |
||
| 82 | jblyberg | 519 | |
| 103 | jblyberg | 520 | $payment_result = $iii->pay_fine($iii_payment_details); |
| 521 | return $payment_result; |
||
| 522 | } |
||
| 523 | |||
| 524 | /** |
||
| 525 | * This is an internal function used to parse MARC values. |
||
| 526 | * This function is called by scrape_bib() |
||
| 527 | * |
||
| 528 | * @param array $value_arr SimpleXML values from XRECORD for that MARC item |
||
| 529 | * @param array $subfields An array of MARC subfields to parse |
||
| 530 | * @param string $delimiter Delimiter to use for storage and indexing purposes. A space seems to work fine |
||
| 531 | * @return array An array of processed MARC values |
||
| 532 | */ |
||
| 533 | public function prepare_marc_values($value_arr, $subfields, $delimiter = ' ') { |
||
| 2 | jblyberg | 534 | |
| 103 | jblyberg | 535 | // Repeatable values can be returned as an array or a serialized value |
| 536 | foreach ($subfields as $subfield) { |
||
| 537 | if (is_array($value_arr[$subfield])) { |
||
| 2 | jblyberg | 538 | |
| 103 | jblyberg | 539 | foreach ($value_arr[$subfield] as $subkey => $subvalue) { |
| 2 | jblyberg | 540 | |
| 103 | jblyberg | 541 | if (is_array($subvalue)) { |
| 542 | foreach ($subvalue as $sub_subvalue) { |
||
| 543 | if ($i[$subkey]) { $pad[$subkey] = $delimiter; } |
||
| 544 | $sv_tmp = trim($sub_subvalue); |
||
| 545 | $matches = array(); |
||
| 546 | preg_match_all('/\{u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\}/', $sv_tmp, $matches); |
||
| 547 | foreach ($matches[0] as $match_string) { |
||
| 548 | $code = hexdec($match_string); |
||
| 549 | $character = html_entity_decode("&#$code;", ENT_NOQUOTES, 'UTF-8'); |
||
| 550 | $sv_tmp = str_replace($match_string, $character, $sv_tmp); |
||
| 551 | } |
||
| 552 | if (trim($sub_subvalue)) { $marc_values[$subkey] .= $pad[$subkey] . $sv_tmp; } |
||
| 553 | $i[$subkey] = 1; |
||
| 554 | } |
||
| 555 | } else { |
||
| 556 | if ($i[$subkey]) { $pad[$subkey] = $delimiter; } |
||
| 557 | |||
| 113 | jblyberg | 558 | // Process unicode for diacritics |
| 103 | jblyberg | 559 | $sv_tmp = trim($subvalue); |
| 560 | $matches = array(); |
||
| 561 | preg_match_all('/\{u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\}/', $sv_tmp, $matches); |
||
| 562 | foreach ($matches[0] as $match_string) { |
||
| 563 | $code = hexdec($match_string); |
||
| 564 | $character = html_entity_decode("&#$code;", ENT_NOQUOTES, 'UTF-8'); |
||
| 565 | $sv_tmp = str_replace($match_string, $character, $sv_tmp); |
||
| 566 | } |
||
| 10 | jblyberg | 567 | |
| 103 | jblyberg | 568 | if (trim($subvalue)) { $marc_values[$subkey] .= $pad[$subkey] . $sv_tmp; } |
| 569 | $i[$subkey] = 1; |
||
| 570 | } |
||
| 571 | } |
||
| 572 | } |
||
| 573 | } |
||
| 11 | jblyberg | 574 | |
| 103 | jblyberg | 575 | if (is_array($marc_values)) { |
| 576 | foreach ($marc_values as $mv) { |
||
| 577 | $result[] = $mv; |
||
| 578 | } |
||
| 579 | } |
||
| 580 | return $result; |
||
| 581 | } |
||
| 2 | jblyberg | 582 | |
| 103 | jblyberg | 583 | /** |
| 584 | * Does the initial job of creating an array out of the SimpleXML content from XRECORD. |
||
| 585 | * This function is called by scrape_bib() and the data is ultimately used by prepare_marc_values() |
||
| 586 | * |
||
| 587 | * @param array $bib_info_marc VARFLD value tree from XRECORD via SimpleXML |
||
| 588 | * @return array A normalized array of marc and subfield info |
||
| 589 | */ |
||
| 590 | public function parse_marc_subfields($bib_info_marc) { |
||
| 591 | $bim_item = 0; |
||
| 592 | foreach ($bib_info_marc as $bim_obj) { |
||
| 593 | // We need to treat MARC tag numbers as a string, or things would be a mess |
||
| 594 | $marc_num = (string) $bim_obj->MARCINFO->MARCTAG; |
||
| 595 | if (count($bim_obj->MARCSUBFLD) == 1) { |
||
| 596 | // Only one subfield value |
||
| 597 | $subfld = get_object_vars($bim_obj->MARCSUBFLD); |
||
| 598 | $marc_sub[$marc_num][trim($subfld['SUBFIELDINDICATOR'])][$bim_item] = trim($subfld['SUBFIELDDATA']); |
||
| 599 | } else if (count($bim_obj->MARCSUBFLD) > 1) { |
||
| 600 | // Multiple subfield values |
||
| 601 | for ($i = 0; $i < count($bim_obj->MARCSUBFLD); $i++) { |
||
| 602 | $subfld = get_object_vars($bim_obj->MARCSUBFLD[$i]); |
||
| 603 | $marc_sub[$marc_num][trim($subfld['SUBFIELDINDICATOR'])][$bim_item][] = trim($subfld['SUBFIELDDATA']); |
||
| 604 | } |
||
| 605 | } |
||
| 606 | $bim_item++; |
||
| 607 | } |
||
| 2 | jblyberg | 608 | |
| 103 | jblyberg | 609 | return $marc_sub; |
| 610 | } |
||
| 2 | jblyberg | 611 | |
| 103 | jblyberg | 612 | /** |
| 613 | * Fixes a non-standard date format. |
||
| 614 | * |
||
| 615 | * @param string $olddate Date string in MM-DD-YY format |
||
| 616 | * @param string Date string in YYYY-MM-DD format |
||
| 617 | */ |
||
| 618 | public function fixdate($olddate) { |
||
| 619 | return date('Y-m-d', self::date_to_timestamp($olddate)); |
||
| 620 | } |
||
| 621 | |||
| 622 | /** |
||
| 623 | * Converts MM-DD-YY to unix timestamp |
||
| 624 | * |
||
| 625 | * @param string $date_orig Original date in MM-DD-YY format |
||
| 626 | * @param int Optional century to use as a baseline. Fix for III's Y2K issues. |
||
| 627 | * @return timestamp |
||
| 628 | */ |
||
| 629 | public function date_to_timestamp($date_orig, $default_century = NULL) { |
||
| 630 | $date_arr = explode('-', trim($date_orig)); |
||
| 631 | if (strlen(trim($date_arr[2])) == 2) { |
||
| 632 | if ($default_century) { |
||
| 633 | $year = $default_century + (int) trim($date_arr[2]); |
||
| 634 | } else { |
||
| 635 | $year = $default_century + (int) trim($date_arr[2]); |
||
| 636 | if (date('Y') < $year) { $year = 1900 + (int) trim($date_arr[2]); } |
||
| 637 | } |
||
| 638 | } else { |
||
| 639 | $year = trim($date_arr[2]); |
||
| 640 | } |
||
| 641 | $time = mktime(0, 0, 0, $date_arr[0], $date_arr[1], $year); |
||
| 642 | return $time; |
||
| 643 | } |
||
| 2 | jblyberg | 644 | |
| 106 | jblyberg | 645 | /** |
| 646 | * Instantiates III tools class and returns a usable object. |
||
| 647 | */ |
||
| 648 | private function get_tools($cardnum, $pin) { |
||
| 649 | require_once('iiitools_2007.php'); |
||
| 650 | $iii = new iiitools; |
||
| 108 | jblyberg | 651 | $iii->set_iiiserver(self::iii_server_info()); |
| 106 | jblyberg | 652 | $iii->set_cardnum($cardnum); |
| 653 | $iii->set_pin($pin); |
||
| 654 | return $iii; |
||
| 655 | } |
||
| 11 | jblyberg | 656 | |
| 108 | jblyberg | 657 | private function iii_server_info() { |
| 658 | $server_select = strtolower(trim($this->locum_config['ils_config']['server_select'])); |
||
| 659 | $iii_server_info['server'] = $this->locum_config['ils_config']['ils_server']; |
||
| 660 | $iii_server_info['nosslport'] = $this->locum_config['ils_config']['ils_' . $server_select . '_port']; |
||
| 661 | $iii_server_info['nosslurl'] = 'http://' . $iii_server_info['server'] . ':' . $iii_server_info['nosslport']; |
||
| 662 | $iii_server_info['sslport'] = $this->locum_config['ils_config']['ils_' . $server_select . '_port_ssl']; |
||
| 663 | $iii_server_info['sslurl'] = 'https://' . $iii_server_info['server'] . ':' . $iii_server_info['sslport']; |
||
| 664 | return $iii_server_info; |
||
| 665 | } |
||
| 11 | jblyberg | 666 | |
| 21 | jblyberg | 667 | |
| 668 | |||
| 669 | |||
| 670 | |||
| 671 | |||
| 672 | |||
| 673 | |||
| 674 | |||
| 675 | |||
| 676 | |||
| 677 | |||
| 678 | |||
| 679 | |||
| 680 | |||
| 2 | jblyberg | 681 | } |