Subversion Repositories connectors

Rev

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 -->&nbsp;(.*?)</td>(.*?)browse">(.*?)</a>(.*?)field \% -->&nbsp;(.*?)</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("'", "&apos;", 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
}