Grima  2018-08
Whispering into Alma's ear
grima-lib.php
Go to the documentation of this file.
1 <?php
8 require_once("grima-util.php");
9 require_once("grima-xmlbag.php");
10 require_once "grima-splats.php";
11 
12 // {{{ class Grima
14 class Grima {
15  public $server;
16  public $apikey;
17 
18 // {{{ session management
19 
20  function session_init( $force = false ) {
21  if( !isset($_SESSION) ) {
22  $session_name = 'grima';
23  $session_dir = join_paths( sys_get_temp_dir(), 'grima' );
24  @mkdir($session_dir, 0777, true);
25  session_save_path($session_dir);
26  session_name( $session_name );
27  session_set_cookie_params(365*24*60*60); # one year
28  ini_set('session.gc_maxlifetime',525600*60); # of love
29  if( $force || isset($_COOKIE[$session_name]) ) {
30  session_start();
31  }
32  }
33  }
34 
35  function session_save($result) {
36  $this->session_init(true);
37  foreach( $result as $key => $value ) {
38  $_SESSION[$key] = $value;
39  }
40  session_write_close();
41  }
42 
43  function session_destroy() {
44  $this->session_init(true);
45  session_start();
46  if (ini_get("session.use_cookies")) {
47  $params = session_get_cookie_params();
48  setcookie(session_name(), '', time() - 42000,
49  $params["path"], $params["domain"],
50  $params["secure"], $params["httponly"]
51  );
52  }
54  $_SESSION=array();
55  }
56 
57 // }}}
58 
59 // {{{ config
60  function __construct() {
61  $this->get_config();
62  }
63 
64  function get_config() {
65  # Precedence:
66  # $_REQUEST, $_SESSION, $_SERVER, $_ENV, grima-config.php
67 
68  if (isset($_REQUEST['apikey']) and isset($_REQUEST['server']) and
69  ($_REQUEST['apikey']) and ($_REQUEST['server'])
70  ) {
71  $this->session_save( array(
72  'apikey' => $_REQUEST['apikey'],
73  'server' => $_REQUEST['server']
74  ) );
75  $this->apikey = $_REQUEST['apikey'];
76  $this->server = $_REQUEST['server'];
77  return true;
78  }
79 
80  $this->session_init();
81  if ( isset($_SESSION) ) {
82  session_write_close();
83  if(
84  isset($_SESSION['apikey']) and
85  isset($_SESSION['server']) and
86  ($_SESSION['apikey']) and
87  ($_SESSION['server'])
88  ) {
89  $this->apikey = $_SESSION['apikey'];
90  $this->server = $_SESSION['server'];
91  return true;
92  }
93  }
94 
95  if ( isset($_SERVER['apikey']) and isset($_SERVER['server']) and
96  ($_SERVER['apikey']) and ($_SERVER['server'])) {
97  $this->apikey = $_SERVER['apikey'];
98  $this->server = $_SERVER['server'];
99  return true;
100  }
101 
102  if ( isset($_ENV['apikey']) and isset($_ENV['server']) and
103  ($_ENV['apikey']) and ($_ENV['server'])) {
104  $this->apikey = $_ENV['apikey'];
105  $this->server = $_ENV['server'];
106  return true;
107  }
108 
109  if( file_exists("grima-config.php") ) {
110  require('grima-config.php'); # this should set those
111  return true;
112  }
113 
114  return false;
115  }
116 
117 // }}}
118 
119 // {{{ REST - get/post/put/delete
120 
121 // {{{ get - general function for GET (retrieve) API calls
130  function get($url,$URLparams,$QSparams) {
131  # returns a DOM document
132  foreach ($URLparams as $k => $v) {
133  $url = str_replace('{'.$k.'}',urlencode($v),$url);
134  }
135  $url = $this->server . $url . '?apikey=' . urlencode($this->apikey);
136  foreach ($QSparams as $k => $v) {
137  $url .= "&$k=$v";
138  }
139  $ch = curl_init();
140  curl_setopt($ch, CURLOPT_URL, $url);
141  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
142  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
143  curl_setopt($ch, CURLOPT_HEADER, FALSE);
144  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
145  $response = curl_exec($ch);
146  $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
147  if (curl_errno($ch)) {
148  throw new Exception("Network error: " . curl_error($ch));
149  }
150  curl_close($ch);
151  $xml = new DOMDocument();
152  try {
153  if (!preg_match('/^</',$response)) {
154  throw new Exception($url);
155  }
156  $xml->loadXML($response);
157  } catch (Exception $e) {
158  throw new Exception("Malformed XML from Alma: $e");
159  }
160  return $xml;
161  }
162 // }}}
163 
164 // {{{ post - general function for POST (create) API calls
174  function post($url,$URLparams,$QSparams,$body) {
175  foreach ($URLparams as $k => $v) {
176  $url = str_replace('{'.$k.'}',urlencode($v),$url);
177  }
178  $url = $this->server . $url . '?apikey=' . urlencode($this->apikey);
179  foreach ($QSparams as $k => $v) {
180  $url .= "&$k=$v";
181  }
182 
183  $bodyxml = $body->saveXML();
184 
185  $ch = curl_init();
186  curl_setopt($ch, CURLOPT_URL, $url);
187  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
188  curl_setopt($ch, CURLOPT_HEADER, FALSE);
189  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
190  curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyxml);
191  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/xml'));
192  $response = curl_exec($ch);
193  $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
194  if (curl_errno($ch)) {
195  throw new Exception("Network error: " . curl_error($ch));
196  }
197  curl_close($ch);
198  $xml = new DOMDocument();
199  try {
200  $xml->loadXML($response);
201  } catch (Exception $e) {
202  throw new Exception("Malformed XML from Alma: $e");
203  }
204  return $xml;
205  }
206 // }}}
207 
208 // {{{ put - general function for PUT (update) API calls
218  function put($url,$URLparams,$QSparams,$body) {
219  foreach ($URLparams as $k => $v) {
220  $url = str_replace('{'.$k.'}',urlencode($v),$url);
221  }
222  $url = $this->server . $url . '?apikey=' . urlencode($this->apikey);
223  foreach ($QSparams as $k => $v) {
224  $url .= "&$k=$v";
225  }
226 
227  $bodyxml = $body->saveXML();
228 
229  $ch = curl_init();
230  curl_setopt($ch, CURLOPT_URL, $url);
231  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
232  curl_setopt($ch, CURLOPT_HEADER, FALSE);
233  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
234  curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyxml);
235  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/xml'));
236  $response = curl_exec($ch);
237  $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
238  if (curl_errno($ch)) {
239  throw new Exception("Network error: " . curl_error($ch));
240  }
241  curl_close($ch);
242  $xml = new DOMDocument();
243  try {
244  $xml->loadXML($response);
245  } catch (Exception $e) {
246  throw new Exception("Malformed XML from Alma: $e");
247  }
248  return $xml;
249  }
250 // }}}
251 
252 // {{{ delete - general function for DELETE API calls
260  function delete($url,$URLparams,$QSparams) {
261  foreach ($URLparams as $k => $v) {
262  $url = str_replace('{'.$k.'}',urlencode($v),$url);
263  }
264  $url = $this->server . $url . '?apikey=' . urlencode($this->apikey);
265  foreach ($QSparams as $k => $v) {
266  $url .= "&$k=$v";
267  }
268  $ch = curl_init();
269  curl_setopt($ch, CURLOPT_URL, $url);
270  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
271  curl_setopt($ch, CURLOPT_HEADER, FALSE);
272  curl_setopt($ch, CURLOPT_HTTPHEADER,
273  array ("Accept: application/xml"));
274  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
275  $response = curl_exec($ch);
276  $code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
277  if (curl_errno($ch)) {
278  throw new Exception("Network error: " . curl_error($ch));
279  }
280  curl_close($ch);
281  if ($code != 204) {
282  $xml = new DOMDocument();
283  try {
284  $xml->loadXML($response);
285  } catch (Exception $e) {
286  throw new Exception("Malformed XML from Alma: $e");
287  }
288  return $xml;
289  }
290  }
291 // }}}
292 
293 // {{{ checkForErrorMessage - checks for errorMessage tag, throws exceptions
298  function checkForErrorMessage($xml) {
299  if ($xml instanceOf DomDocument) {
300  $xpath = new DomXpath($xml);
301  $xpath->registerNamespace("err","http://com/exlibris/urm/general/xmlbeans");
302  $error = $xpath->query('//err:errorMessage');
303  if ($error->length > 0) {
304  throw new Exception("Alma says: " . $error[0]->nodeValue);
305  }
306  }
307  }
308 // }}}
309 
310 // }}}
311 
312 //{{{Bib APIs
316 // {{{ getBib (Retrieve Bib)
330  function getBib($mms_id, $view = 'full', $expand = 'None') {
331  $ret = $this->get('/almaws/v1/bibs/{mms_id}',
332  array('mms_id' => $mms_id),
333  array('view' => $view, 'expand' => $expand)
334  );
335  $this->checkForErrorMessage($ret);
336  return $ret;
337  }
338 // }}}
339 
340 // {{{ postBib (Create Record)
352  function postBib($bib) {
353  $ret = $this->post('/almaws/v1/bibs',
354  array(),
355  array(),
356  $bib
357  );
358  $this->checkForErrorMessage($ret);
359  return $ret;
360  }
361 // }}}
362 
363 // {{{ putBib (Update Bib Record)
376  function putBib($mms_id,$bib) {
377  $ret = $this->put('/almaws/v1/bibs/{mms_id}',
378  array('mms_id' => $mms_id),
379  array(),
380  $bib
381  );
382  $this->checkForErrorMessage($ret);
383  return $ret;
384  }
385 // }}}
386 
387 // {{{ deleteBib (Delete Bib Record)
399  function deleteBib($mms_id,$override='false') {
400  $ret = $this->delete('/almaws/v1/bibs/{mms_id}',
401  array('mms_id' => $mms_id),
402  array('override' => $override)
403  );
404  $this->checkForErrorMessage($ret);
405  }
406 // }}}
407 
409 //}}}
410 
411 //{{{Holdings List APIs
415 // {{{ grima -> getHoldingsList (Retrieve Holdings list)
428  function getHoldingsList($mms_id) {
429  $ret = $this->get('/almaws/v1/bibs/{mms_id}/holdings',
430  array('mms_id' => $mms_id),
431  array()
432  );
433  $this->checkForErrorMessage($ret);
434  return $ret;
435  }
436 // }}}
437 
439 //}}}
440 
441 //{{{Holding APIs
445 // {{{ getHolding (Retrieve Holdings Record)
458  function getHolding($mms_id,$holding_id) {
459  $ret = $this->get('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}',
460  array(
461  'mms_id' => $mms_id,
462  'holding_id' => $holding_id
463  ),
464  array()
465  );
466  $this->checkForErrorMessage($ret);
467  return $ret;
468  }
469 // }}}
470 
471 // {{{ grima -> postHolding (Create holding record)
484  function postHolding($mms_id,$holding) {
485  $ret = $this->post('/almaws/v1/bibs/{mms_id}/holdings',
486  array('mms_id' => $mms_id),
487  array(),
488  $holding
489  );
490  $this->checkForErrorMessage($ret);
491  return $ret;
492  }
493 // }}}
494 
495 // {{{ putHolding (Update Holdings Record)
509  function putHolding($mms_id,$holding_id,$holding) {
510  $ret = $this->put('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}',
511  array('mms_id' => $mms_id, 'holding_id' => $holding_id),
512  array(),
513  $holding
514  );
515  }
516 // }}}
517 
518 // {{{ grima -> deleteHolding (Delete Holdings Record)
531  function deleteHolding($mms_id,$holding_id,$override='false') {
532  $ret = $this->delete('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}',
533  array(
534  'mms_id' => $mms_id,
535  'holding_id' => $holding_id
536  ),
537  array('override' => $override)
538  );
539  $this->checkForErrorMessage($ret);
540  }
541 // }}}
542 
544 //}}}
545 
546 //{{{Item List APIs
550 // {{{ getItemList (Retrieve Items list)
565  function getItemList($mms_id,$holding_id,$limit,$offset) {
566  $ret = $this->get('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}/items', array('mms_id' => $mms_id, 'holding_id' => $holding_id),
567  array('limit' => $limit, 'offset' => $offset)
568  );
569  $this->checkForErrorMessage($ret);
570  return $ret;
571  }
572 // }}}
573 
575 //}}}
576 
577 //{{{Item APIs
581 // {{{ getItem (Retrieve Item and print label information)
594  function getItem($mms_id,$holding_id,$item_pid) {
595  $ret = $this->get('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}', array(
596  'mms_id' => $mms_id,
597  'holding_id' => $holding_id,
598  'item_pid' => $item_pid
599  ),
600  array()
601  );
602  $this->checkForErrorMessage($ret);
603  return $ret;
604  }
605 // }}}
606 
607 // {{{ getItemBC (Retrieve Item and print label information (by barcode))
618  function getItemBC($barcode) {
619  $ret = $this->get('/almaws/v1/items',
620  array(),
621  array(
622  'item_barcode' => $barcode,
623  )
624  );
625  $this->checkForErrorMessage($ret);
626  return $ret;
627  }
628 // }}}
629 
630 // {{{ postItem (Create Item)
644  function postItem($mms_id,$holding_id,$item) {
645  $ret = $this->post('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}/items',
646  array('mms_id' => $mms_id, 'holding_id' => $holding_id),
647  array(),
648  $item
649  );
650  $this->checkForErrorMessage($ret);
651  return $ret;
652  }
653 // }}}
654 
655 // {{{ putItem (Update Item information)
670  function putItem($mms_id,$holding_id,$item_pid,$item) {
671  $ret = $this->put('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}',
672  array('mms_id' => $mms_id, 'holding_id' => $holding_id, 'item_pid' => $item_pid),
673  array(),
674  $item
675  );
676  return $ret;
677  }
678 // }}}
679 
680 // {{{ deleteItem (Withdraw Item)
695  function deleteItem($mms_id,$holding_id,$item_pid,$override = "false",
696  $holdings = "retain") {
697  $ret = $this->delete('/almaws/v1/bibs/{mms_id}/holdings/{holding_id}/items/{item_pid}', array(
698  'mms_id' => $mms_id,
699  'holding_id' => $holding_id,
700  'item_pid' => $item_pid
701  ), array(
702  'override' => $override,
703  'holdings' => $holdings
704  )
705  );
706  $this->checkForErrorMessage($ret);
707  }
708 // }}}
709 
711 //}}}
712 
713 //{{{Electronic APIs
717 // {{{ getElectronicPortfolio (Retrieve Portfolio)
731  function getElectronicPortfolio($collection_id,$service_id,$portfolio_id) {
732  $ret = $this->get('/almaws/v1/electronic/e-collections/{collection_id}/e-services/{service_id}/portfolios/{portfolio_id}',
733  array('collection_id' => $collection_id, 'service_id' => $service_id, 'portfolio_id' => $portfolio_id),
734  array()
735  );
736  $this->checkForErrorMessage($ret);
737  return $ret;
738  }
739 // }}}
740 
741 // {{{ getElectronicPortfolioFromBib (Retrieve Portfolio)
754  function getElectronicPortfolioFromBib($mms_id, $portfolio_id) {
755  $ret = $this->get('/almaws/v1/bibs/{mms_id}/portfolios/{portfolio_id}',
756  array('mms_id' => $mms_id, 'portfolio_id' => $portfolio_id),
757  array()
758  );
759  $this->checkForErrorMessage($ret);
760  return $ret;
761  }
762 // }}}
763 
764 // {{{ postElectronicPortfolio (Create Electronic Portfolio) #XXX
778  function postElectronicPortfolio($collection_id,$service_id,$portfolio) {
779  $ret = $this->post('/almaws/v1/electronic/e-collections/{collection_id}/e-services/{service_id}/portfolios',
780  array('collection_id' => $collection_id, 'service_id' => $service_id),
781  array(),
782  $portfolio
783  );
784  $this->checkForErrorMessage($ret);
785  return $ret;
786  }
787 // }}}
788 
789 // {{{ postElectronicPortfolioOnBib (Create Electronic Portfolio on Bib)
801  function postElectronicPortfolioOnBib($mms_id,$portfolio) {
802  $ret = $this->post('/almaws/v1/bibs/{mms_id}/portfolios/',
803  array('mms_id' => $mms_id),
804  array(),
805  $portfolio
806  );
807  $this->checkForErrorMessage($ret);
808  return $ret;
809  }
810 // }}}
811 
812 // {{{ putElectronicPortfolioOnBib (Update Portfolio for a Bib)
825  function putElectronicPortfolioOnBib($mms_id,$portfolio_id,$portfolio) {
826  $ret = $this->put('/almaws/v1/bibs/{mms_id}/portfolios/{portfolio_id}',
827  array('mms_id' => $mms_id, 'portfolio_id' => $portfolio_id),
828  array(),
829  $portfolio
830  );
831  $this->checkForErrorMessage($ret);
832  return $ret;
833  }
834 // }}}
835 
836 // {{{ deleteElectronicPortfolio (Delete Electronic Portfolio)
849  function deleteElectronicPortfolio($collection_id,$service_id,$portfolio_id) {
850  $ret = $this->delete('/almaws/v1/electronic/e-collections/{collection_id}/e-services/{service_id}/portfolios/{portfolio_id}',
851  array('collection_id' => $collection_id, 'service_id' => $service_id, 'portfolio_id' => $portfolio_id),
852  array()
853  );
854  $this->checkForErrorMessage($ret);
855  }
856 // }}}
857 
858 // {{{ getElectronicPortfoliosForService (Retrieve Portfolios)
873  function getElectronicPortfoliosForService($collection_id, $service_id, $limit, $offset) {
874  $ret = $this->get('/almaws/v1/electronic/e-collections/{collection_id}/e-services/{service_id}/portfolios',
875  array('collection_id' => $collection_id, 'service_id' => $service_id),
876  array('limit' => $limit, $offset = $offset)
877  );
878  $this->checkForErrorMessage($ret);
879  return $ret;
880  }
881 // }}}
882 
883 // {{{ grima -> getElectronicPortfoliosForBib (Retrieve Portfolios)
897  function getElectronicPortfoliosForBib($mms_id, $limit, $offset) {
898  $ret = $this->get('/almaws/v1/bibs/{mms_id}/portfolios',
899  array('mms_id' => $mms_id),
900  array('limit' => $limit, $offset = $offset)
901  );
902  $this->checkForErrorMessage($ret);
903  return $ret;
904  }
905 // }}}
906 
907 // {{{ getElectronicCollection (Retrieve Electronic Collection)
919  function getElectronicCollection($collection_id) {
920  $ret = $this->get('/almaws/v1/electronic/e-collections/{collection_id}',
921  array('collection_id' => $collection_id),
922  array()
923  );
924  $this->checkForErrorMessage($ret);
925  return $ret;
926  }
927 // }}}
928 
929 // {{{ getElectronicServices (Retrieve Electronic Services)
942  function getElectronicServices($collection_id) {
943  $ret = $this->get('/almaws/v1/electronic/e-collections/{collection_id}/e-services',
944  array('collection_id' => $collection_id),
945  array()
946  );
947  $this->checkForErrorMessage($ret);
948  return $ret;
949  }
950 // }}}
951 
953 //}}}
954 
955 //{{{Library APIs
959 // {{{ getLibrary (Retrieve a Library)
971  function getLibrary($libraryCode) {
972  $ret = $this->get('/almaws/v1/conf/libraries/{libraryCode}',
973  array('libraryCode' => $libraryCode),
974  array()
975  );
976  $this->checkForErrorMessage($ret);
977  return $ret;
978  }
979 // }}}
980 
982 //}}}
983 
984 //{{{Location APIs
988 // {{{ getLocation (Retrieve Location)
1000  function getLocation($libraryCode,$locationCode) {
1001  $ret = $this->get('/almaws/v1/conf/libraries/{libraryCode}/locations/{locationCode}',
1002  array(
1003  'libraryCode' => $libraryCode,
1004  'locationCode' => $locationCode,
1005  ),
1006  array()
1007  );
1008  $this->checkForErrorMessage($ret);
1009  return $ret;
1010  }
1011 // }}}
1012 
1014 //}}}
1015 
1016 //{{{Set APIs
1020 // {{{ Set -> getSet (Retrieve a Set)
1032  function getSet($set_id) {
1033  $ret = $this->get('/almaws/v1/conf/sets/{set_id}',
1034  array('set_id' => $set_id),
1035  array()
1036  );
1037  $this->checkForErrorMessage($ret);
1038  return $ret;
1039  }
1040 // }}}
1041 
1042 /*
1043  function postSetManageMembers($set_id,$id_type,$op) {
1044  }
1045 */
1046 
1047 // {{{ Set -> createSetFromImport (Create a Set)
1060  function createSetFromImport($job_instance_id, $population) {
1061  # create blank set
1062 
1063  $body = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>
1064 <set>
1065  <name>Grima set from ' . $job_instance_id . '</name>
1066  <description>members of ' . $job_instance_id . '</description>
1067  <type desc="Itemized">ITEMIZED</type>
1068  <content desc="All Titles">BIB_MMS</content>
1069  <private desc="No">false</private>
1070 </set>';
1071 
1072 /*
1073  Content:
1074  BIB_MMS -- all titles
1075  ITEM
1076  PORTFOLIO
1077  IEPA
1078  FILE
1079  AUTHORITY_MMS
1080  IEP
1081  IEE
1082  IED
1083  IEC
1084 */
1085 
1086 /*
1087  Population:
1088 */
1089 
1090  $bodyxml = new DomDocument();
1091  $bodyxml->loadXML($body);
1092 
1093  $ret = $this->post('/almaws/v1/conf/sets', array(), array('job_instance_id' => $job_instance_id, 'population' => $population),$bodyxml);
1094  $this->checkForErrorMessage($ret);
1095  return $ret;
1096 
1097  }
1098 // }}}
1099 
1100 // {{{ grima -> deleteSet (Delete a Set)
1111  function deleteSet($set_id) {
1112  $ret = $this->delete('/almaws/v1/conf/sets/{set_id}',
1113  array(
1114  'set_id' => $set_id,
1115  ),
1116  array()
1117  );
1118  $this->checkForErrorMessage($ret);
1119  }
1120 // }}}
1121 
1122 // {{{ grima -> getSetMembers (Does it work????)
1135  function getSetMembers($set_id,$limit = 10,$offset = 0) {
1136  $ret = $this->get('/almaws/v1/conf/sets/{set_id}/members',
1137  array('set_id' => $set_id),
1138  array('limit' => $limit, 'offset' => $offset)
1139  );
1140  $this->checkForErrorMessage($ret);
1141  return $ret;
1142  }
1143 // }}}
1144 
1146 //}}}
1147 
1148 //{{{Analytics APIs
1152  # XXX check if blank filter is ok
1153  function getAnalytics($path,$filter,$limit=25,$token=null) {
1154  return $this->get('/almaws/v1/analytics/reports',
1155  array(),
1156  array('path' => urlencode($path), 'filter' => urlencode($filter),
1157  'limit' => $limit, 'token' => $token)
1158  );
1159  }
1160 
1162 //}}}
1163 
1164 }
1165 
1166 $grima = new Grima();
1167 
1168 // }}}
1169 
1170 // {{{ class GrimaTask
1174 abstract class GrimaTask implements ArrayAccess {
1175 
1176  public $error = false;
1177  public $args = array();
1178  public $el_override = array();
1179 
1180  public $auto_args = array();
1181 
1182  public $messages = array();
1183 
1184  function offsetExists($offset) {
1185  return isset($this->args[$offset]);
1186  }
1187 
1188  function offsetGet($offset) {
1189  return $this->args[$offset];
1190  }
1191 
1192  function offsetSet($offset,$value) {
1193  $this->args[$offset] = $value;
1194  }
1195 
1196  function offsetUnset($offset) {
1197  unset($this->args[$offset]);
1198  }
1199 
1200  function __construct() {
1201  $webroot = __DIR__;
1202  $base = get_class($this); //basename($_SERVER['PHP_SELF'],'.php');
1203  if (file_exists(join_paths($webroot,$base,"$base.xml")) and (!isset($this->formxml))) {
1204  $this->formxml = file_get_contents(join_paths($webroot,$base,"$base.xml"));
1205  }
1206  if (isset($this->formxml)) {
1207  $this->form = new GrimaForm();
1208  $this->form->fromXML($this->formxml);
1209  }
1210  }
1211 
1212  function setup_splat() {
1213  $webroot = __DIR__;
1214  $basename = get_class($this); //basename($_SERVER['PHP_SELF'],'.php');
1215 
1216  $this->splat = new zemowsplat\Splat();
1217 
1218  $this->splat->addBases(array(
1219  "$webroot/$basename/splats", // per-task overrides
1220  "$webroot/splats", // default
1221  ));
1222 
1223  $this->splatVars = array(
1224  'title' => $this->form->title,
1225  'basename' => $basename,
1226  'webroot' => $webroot,
1227  'local_stylesheets' => array('Grima.css'),
1228  'form' => &$this->form,
1229  'messages' => &$this->messages,
1230  'width' => 9,
1231  );
1232  if (isset($this['redirect_url'])) {
1233  $this->splatVars['redirect_url'] = $this['redirect_url'];
1234  }
1235  }
1236 
1237  function print_form() {
1238  $this->form->loadValues($this);
1239  $this->splat->splat('print_form', $this->splatVars );
1240  }
1241 
1242  function print_success() {
1243  $this->form->loadPersistentValues($this);
1244  $this->splat->splat('print_success', $this->splatVars );
1245  }
1246 
1247  function print_failure() {
1248  $this->form->loadValues($this);
1249  $this->splat->splat('print_failure', $this->splatVars );
1250  }
1251 
1252  function check_login() {
1253  global $grima;
1254  if (isset($grima->apikey) and isset($grima->server) and
1255  ($grima->apikey) and ($grima->server)) {
1256  return true;
1257  } else {
1258  do_redirect('../Login/Login.php?redirect_url=' . urlencode($_SERVER['PHP_SELF']));
1259  exit;
1260  return false;
1261  }
1262  }
1263 
1264  public function addMessage($type,$message) {
1265  $this->messages[] = new GrimaTaskMessage($type,$message);
1266  }
1267 
1268  public function run() {
1269  $this->check_login(); # if not logged in, print login form
1270  $this->error = false;
1271  $this->get_input();
1272  $this->setup_splat(); # should happen after form xml read in get_input
1273  if ($this->check_input()) {
1274  try {
1275  $this->do_task();
1276  } catch (Exception $e) {
1277  $this->addMessage('error',$e->getMessage());
1278  $this->error = true;
1279  }
1280  } else {
1281  $this->print_form();
1282  exit;
1283  }
1284  if ($this->error) {
1285  $this->print_failure();
1286  } else {
1287  $this->print_success();
1288  }
1289  }
1290 
1291  public static function RunIt() {
1292  $task = new static();
1293  $task->run();
1294  }
1295 
1296  function get_input() {
1297  if (isset($this->form)) {
1298  if (php_sapi_name() == "cli") { # command line
1299  /*
1300  if ($options = getopt(implode(array_keys($param)))) {
1301  foreach ($param as $k => $v) {
1302  $this->args[$v] = $options[$k[0]];
1303  }
1304  if (!$this->check_input()) {
1305  $this->usage(); exit;
1306  }
1307  } else {
1308  $this->usage(); exit;
1309  }
1310  */
1311  } else { # web
1312  foreach ($this->form->fields as $field) {
1313  if (isset($_REQUEST[$field->name])) {
1314  $this[$field->name] = $_REQUEST[$field->name];
1315  /* sanitize */
1316  }
1317  }
1318  }
1319 
1320  } else {
1321  $this->get_input_param($this->auto_args);
1322  }
1323  }
1324 
1325  function check_input() {
1326  if (isset($this->form)) {
1327  $input_good = true;
1328  foreach ($this->form->fields as $field) {
1329  if ($field->required) {
1330  if (!isset($this[$field->name]) or
1331  !($this[$field->name])) {
1332  $field->error_condition = "error";
1333  $field->error_message = "Field is required\n";
1334  $input_good = false;
1335  }
1336  }
1337  }
1338  return $input_good;
1339  } else {
1340 
1341  foreach ($this->auto_args as $k => $v) {
1342  if (preg_match('/[^:]:$/',$k)) {
1343  if (!isset($this->args[$v]) or !($this->args[$v])) {
1344  return false;
1345  }
1346  }
1347  }
1348  return true;
1349  }
1350  }
1351 
1352  function get_input_param($param) {
1353  if (php_sapi_name() == "cli") { # command line
1354  if ($options = getopt(implode(array_keys($param)))) {
1355  foreach ($param as $k => $v) {
1356  $this->args[$v] = $options[$k[0]];
1357  }
1358  if (!$this->check_input()) {
1359  $this->usage(); exit;
1360  }
1361  } else {
1362  $this->usage(); exit;
1363  }
1364  } else { # web
1365  foreach ($param as $k => $v) {
1366  if (isset($_REQUEST[$v])) {
1367  $this->args[$v] = $_REQUEST[$v];
1368  }
1369  }
1370  if (!$this->check_input()) {
1371  $this->print_form(); exit;
1372  }
1373  }
1374  }
1375 
1376  abstract function do_task();
1377 
1378  function usage() { # XXX rewrite for grima form
1379  global $argv;
1380  print "Usage: php ${argv[0]} ";
1381  foreach ($this->auto_args as $k => $v) {
1382  if (preg_match('/^(.):$/',$k,$m)) {
1383  print "-${m[1]} <$v> ";
1384  } else {
1385  if (preg_match('/^(.)::$/',$k,$m)) {
1386  print "[ -${m[1]} <$v> ] ";
1387  } else {
1388  if (preg_match('/^.$/',$k)) {
1389  print "[ -$k ] ";
1390  }
1391  }
1392  }
1393  }
1394  print "\n";
1395  exit;
1396  }
1397 
1398  public static function call($grimaname,$args = array()) {
1399  $url = rtrim("../$grimaname/$grimaname.php?" . http_build_query($args),"?");
1400  do_redirect($url);
1401  }
1402 
1403 }
1404 
1405 // }}}
1406 
1407 // {{{ class GrimaTaskMessage
1412  public $type;
1413  /* bootstrap type: debug, info, success, warning, error */
1414  public $message;
1415 
1417  $this->type = $type;
1418  $this->message = $message;
1419  }
1420 }
1421 
1422 // }}}
1423 
1424 //{{{ class GrimaForm
1428 class GrimaForm {
1429  public $fields = array();
1430  public $title;
1431  protected $action;
1432 
1433 // {{{ loadValues
1439  function loadValues($obj) {
1440  foreach ($this->fields as $field) {
1441  if (isset($obj[$field->name])) {
1442  $field->value = $obj[$field->name];
1443  }
1444  }
1445  }
1446 // }}}
1447 
1448 // {{{ loadPersistentValues
1454  function loadPersistentValues($obj) {
1455  foreach ($this->fields as $field) {
1456  if (($field->persistent) and isset($obj[$field->name])) {
1457  $field->value = $obj[$field->name];
1458  }
1459  }
1460  }
1461 // }}}
1462 
1463 
1464 
1465 // {{{ fromXML
1470  function fromXML($xml) {
1471  $doc = new DomDocument();
1472  $doc->loadXML($xml);
1473  $xpath = new DomXpath($doc);
1474  $this->title = $xpath->query('//Title')[0]->nodeValue;
1475  $this->action = basename($_SERVER['PHP_SELF']); # allow set?
1476 
1477  $nodes = $xpath->query('//Field');
1478  foreach ($nodes as $node) {
1479  $this->fields[$node->getAttribute('name')] = new GrimaFormField($node);
1480  }
1481  }
1482 // }}}
1483 
1484 }
1485 
1486 // }}}
1487 
1488 //{{{ class GrimaFormField
1489 
1494 
1495  public $value;
1496 
1497  public $name;
1498  public $label;
1500  public $required;
1501  public $persistent;
1502  public $visible;
1503  public $rows;
1504  protected $autocomplete;
1505  protected $highlight;
1506  public $error_condition = ""; /* can be warning or error */
1507  public $error_message = "";
1508 
1509 // {{{ booly - is it true or false
1517  function booly($str, $default = 'undefined') {
1518  switch(strtolower($str)) {
1519  case 'true':
1520  case 't':
1521  case 'on':
1522  case 'yes':
1523  case '1':
1524  return true;
1525  case 'false':
1526  case 'f':
1527  case 'off':
1528  case 'no':
1529  case '0':
1530  return false;
1531  default:
1532  return $default;
1533  }
1534  }
1535 // }}}
1536 
1537 // {{{ __construct
1543  function __construct($field) {
1544  $this->name = $field->getAttribute('name');
1545  $this->label = $field->getAttribute('label');
1546  $this->placeholder = $field->getAttribute('placeholder');
1547  $this->rows = $field->getAttribute('rows');
1548  $this->type = $field->getAttribute('type');
1549  if (!$this->type) {
1550  $this->type = 'input';
1551  }
1552  $this->required = $this->booly($field->getAttribute('required'),true);
1553  $this->persistent = $this->booly($field->getAttribute('persistent'),false);
1554  $this->autocomplete = $this->booly($field->getAttribute('autocomplete'),false);
1555  $this->visible = $this->booly($field->getAttribute('visible'),true);
1556  $this->options = array();
1557  foreach ($field->getElementsByTagName("option") as $option) {
1558  $this->options[] = $option->ownerDocument->saveXML( $option );
1559  }
1560  }
1561 // }}}
1562 
1563 }
1564 
1565 // }}}
1566 
1567 //{{{ class AlmaObject
1571 class AlmaObject implements ArrayAccess {
1572  public $el_access = array();
1573  public $xml;
1574  public $templateDir = __DIR__ . "/templates";
1575 
1576 // {{{ __construct
1580  function __construct() {
1581  $this->xml = new DomDocument();
1582  $blankRecord = get_class($this);
1583  $this->xml->loadXML(file_get_contents("{$this->templateDir}/{$blankRecord}.xml"));
1584  }
1585 // }}}
1586 
1587  function offsetExists($offset) {
1588  if (isset($this->el_override)) {
1589  return array_key_exists($offset, $this->el_override);
1590  }
1591  return array_key_exists($offset, $this->el_access);
1592  }
1593 
1594  function offsetGet($offset) {
1595  if ((isset($this->el_override)) and
1596  (isset($this->el_override[$offset]))) {
1597  return $this->el_override[$offset];
1598  }
1599  $xpath = new DomXpath($this->xml);
1600  $node = $xpath->query($this->el_address[$offset]);
1601  if (count($node) >= 1) {
1602  return $node[0]->nodeValue;
1603  }
1604  return null;
1605  }
1606 
1607  function offsetSet($offset, $value) {
1608  $xpath = new DomXpath($this->xml);
1609  $node = $xpath->query($this->el_address[$offset]);
1610  $node[0]->nodeValue = $value;
1611  }
1612 
1613  function offsetUnset($offset) {
1614  $xpath = new DomXpath($this->xml);
1615  $node = $xpath->query($this->el_address[$offset]);
1616  $node[0]->nodeValue = null;
1617  }
1618 
1619 }
1620 
1621 // }}}
1622 
1623 // {{{ class AlmaObjectWithMARC
1628 
1629 // {{{ AlmaObjectWithMARC -> appendField
1638  function appendField($tag,$ind1,$ind2,$subfields) {
1639  $frag = "<datafield ind1=\"$ind1\" ind2=\"$ind2\" tag=\"$tag\">";
1640  foreach ($subfields as $k => $v) {
1641  $frag .= "<subfield code=\"$k\">$v</subfield>";
1642  }
1643  $frag .= "</datafield>";
1644  $xpath = new DomXpath($this->xml);
1645  $record = $xpath->query("//record");
1646  appendInnerXML($record[0],$frag);
1647  }
1648 // }}}
1649 
1650 // {{{ AlmaObjectWithMARC -> getFields # XXX IN PROGRESS
1657  function getFields($tag) {
1658  $xpath = new DomXpath($this->xml);
1659  $tag = preg_replace('/X*$/','',$tag);
1660  $tag = preg_replace('/\.*$/','',$tag);
1661  $fields = $xpath->query("//record/datafield[starts-with(@tag,'$tag')]");
1662  $fieldarr = array();
1663  foreach ($fields as $field) {
1664  $subfieldarr = array();
1665  foreach ($field->childNodes as $child) {
1666  $subfieldarr[] = array(
1667  $child->attributes[0]->value,
1668  $child->nodeValue
1669  );
1670  }
1671  $fieldarr[] = $subfieldarr;
1672  }
1673  return $fieldarr;
1674  }
1675 // }}}
1676 
1677 // {{{ AlmaObjectWithMARC -> getSubfieldValues
1685  function getSubfieldValues($tag,$code) {
1686  $xpath = new DomXpath($this->xml);
1687  $subfields = $xpath->query("//record/datafield[@tag='$tag']/subfield[@code='$code']");
1688  $arr = array();
1689  foreach ($subfields as $subfield) {
1690  $arr[] = $subfield->nodeValue;
1691  }
1692  return $arr;
1693  }
1694 // }}}
1695 
1696 // {{{ AlmaObjectWithMARC -> deleteField
1702  function deleteField($tag) {
1703  $xpath = new DomXpath($this->xml);
1704  $fields = $xpath->query("//record/datafield[@tag='$tag']");
1705  foreach( $fields as $field ) {
1706  $field->parentNode->removeChild( $field );
1707  }
1708  }
1709 // }}}
1710 
1711 // {{{ AlmaObjectWithMARC -> deleteSubfieldMatching
1717  function deleteSubfieldMatching($tag,$code,$regex) {
1718  $xpath = new DomXPath($this->xml);
1719  $subfs = $xpath->query("//datafield[@tag='$tag']/subfield[@code='$code']");
1720  foreach ($subfs as $subf) {
1721  if (preg_match($regex,$subf->nodeValue)) {
1722  $subf->parentNode->removeChild($subf);
1723  }
1724  }
1725  }
1726 // }}}
1727 
1728 // {{{ AlmaObjectWithMARC -> replaceOrAddSubfield
1736  function replaceOrAddSubfield($tag,$code,$value) {
1737  # very shady but sometimes needed
1738  $xpath = new DomXpath($this->xml);
1739  $fields = $xpath->query("//record/datafield[@tag='$tag']");
1740  if (sizeof($fields) == 0) {
1741  $this->appendField($tag,' ',' ',array($code => $value));
1742  } else {
1743  $done = false;
1744  foreach ($fields[0]->childNodes as $subfield) {
1745  if($subfield->nodeType !== 1) {
1746  continue;
1747  }
1748  if ($subfield->getAttribute("code") == $code) {
1749  $subfield->nodeValue = $value;
1750  $done = true;
1751  break;
1752  }
1753  }
1754  if (!$done) {
1755  $subfield = $this->xml->createElement("subfield");
1756  $subfield->setAttribute("code",$code);
1757  $subfield->appendChild($this->xml->createTextNode($value));
1758  $fields[0]->appendChild($subfield);
1759  }
1760  }
1761  }
1762 // }}}
1763 
1764 }
1765 // }}}
1766 
1767 // {{{ class MARCField -- # XXX in progress
1772 class MARCField {
1773  public $tag;
1774  public $subfields = array();
1775 }
1776 
1778  public $code;
1779  public $value;
1780 }
1781 
1782 // }}}
1783 
1784 // {{{ class bib
1788 class Bib extends AlmaObjectWithMARC {
1789  public $holdingsList; # HoldingsList object
1790  public $holdings = array();
1791 
1792  public $portfolioList = array(); # just an array for now
1793 
1794  /* public $networknums = array(); */
1795 
1796  protected $el_address = array(
1797  'mms_id' => '//mms_id',
1798  'leader' => '//leader',
1799  'record_format' => '//record_format',
1800  'title' => '//title',
1801  'author' => '//author',
1802  'place_of_publication' => '//place_of_publication',
1803  'publisher_const' => '//publisher_const',
1804  'publisher' => '//publisher_const'
1805  );
1806 
1807  function offsetGet($offset) {
1808  if ($offset == 'Type') {
1809  $leader = $this['leader'];
1810  return $leader[6];
1811  }
1812  if ($offset == 'BLvl') {
1813  $leader = $this['leader'];
1814  return $leader[7];
1815  }
1816  if ($offset == 'ELvl') {
1817  $leader = $this['leader'];
1818  return $leader[17];
1819  }
1820  if ($offset == 'Desc') {
1821  $leader = $this['leader'];
1822  return $leader[18];
1823  }
1824  return parent::offsetGet($offset);
1825  }
1826 
1827  # override because these go multiple places
1828  function offsetSet($offset,$value) {
1829  parent::offsetSet($offset,$value);
1830  if ($offset == 'author') {
1831  $this->replaceOrAddSubfield('100','a',$value);
1832  }
1833  if ($offset == 'title') {
1834  $this->replaceOrAddSubfield('245','a',$value);
1835  }
1836  if (($offset == 'publisher_const') or ($offset == 'publisher')) {
1837  $this->replaceOrAddSubfield('264','b',$value);
1838  }
1839  if ($offset == 'place_of_publication') {
1840  $this->replaceOrAddSubfield('264','a',$value);
1841  }
1842  }
1843 
1844 // {{{ Bib -> loadFromAlma (get) - gets Bib from Alma
1850  function loadFromAlma($mms_id) {
1851  global $grima;
1852  $this->xml = $grima->getBib($mms_id);
1853  }
1854 // }}}
1855 
1856 // {{{ Bib -> addToAlma (post) - adds the Bib to Alma
1861  function addToAlma() {
1862  global $grima;
1863  $this->xml = $grima->postBib($this->xml);
1864  }
1865 // }}}
1866 
1867 // {{{ Bib -> updateAlma (put) - replaces the Bib in Alma
1871  function updateAlma() {
1872  global $grima;
1873  $this->xml = $grima->putBib($this['mms_id'],$this->xml);
1874  }
1875 // }}}
1876 
1877 // {{{ Bib -> deleteFromAlma (delete) - deletes the Bib from Alma
1881  function deleteFromAlma() {
1882  global $grima;
1883  $grima->deleteBib($this['mms_id']);
1884  }
1885 // }}}
1886 
1887 // {{{ Bib -> deleteTreeFromAlma (delete) - deletes Bib and inventory from Alma
1891  function deleteTreeFromAlma() {
1892  global $grima;
1893  $this->getHoldings();
1894  foreach ($this->holdings as $holding) {
1895  $holding->deleteTreeFromAlma(); #XXX
1896  }
1897  $this->deleteAllPortfolios($this['mms_id']); #XXX
1898  $grima->deleteBib($this['mms_id']);
1899  }
1900 // }}}
1901 
1902 // {{{ Bib -> hasInventory - does the bib have holdings or portfolios in Alma?
1906  function hasInventory() {
1907  $this->getHoldingsList();
1908  if (count($this->holdingsList->entries) > 0) {
1909  return true;
1910  }
1911  $this->getPortfolioList();
1912  if (count($this->portfolioList) > 0) {
1913  print_r($this->portfolioList);
1914  return true;
1915  } else {
1916  return false;
1917  }
1918  }
1919 // }}}
1920 
1921 // {{{ Bib -> linkedToCZ - is the bib linked to community zone?
1925  function linkedToCZ() {
1926  $xpath = new DomXPath($this->xml);
1927  $nodes = $xpath->query("//linked_record_id[@type='CZ']");
1928  return (count($nodes) > 0);
1929  }
1930 // }}}
1931 
1932 // {{{ Bib -> unlinkFromCZ - does this work
1937  function unlinkFromCZ() {
1938  $xpath = new DomXPath($this->xml);
1939  $nodes = $xpath->query("//linked_record_id[@type='CZ']");
1940  foreach ($nodes as $node) {
1941  $node->parentNode->removeChild($node);
1942  }
1943  $this->updateAlma();
1944  }
1945 // }}}
1946 
1947 // {{{ Bib -> getHoldings - get holdings objects
1951  function getHoldings() {
1952  $this->getHoldingsList();
1953  foreach ($this->holdingsList->entries as $entry) {
1954  $holding = new Holding();
1955  $holding->loadFromAlma($this['mms_id'],$entry['holding_id']);
1956  $holding['mms_id'] = $this['mms_id'];
1957  $this->holdings[] = $holding;
1958  }
1959  }
1960 // }}}
1961 
1962 // {{{ Bib -> deleteAllPortfolios - delete all portfolios from the bib
1966  function deleteAllPortfolios() {
1967  global $grima;
1968  while ($this->getPortfolioList()) {
1969  foreach($this->portfolioList as $portfolio) {
1970  $portfolio->deleteFromAlma();
1971  }
1972  $this->portfolioList = array();
1973  sleep(2);
1974  }
1975  }
1976 // }}}
1977 
1978 // {{{ Bib -> getHoldingsList
1982  function getHoldingsList() {
1983  $this->holdingsList = new HoldingsList($this['mms_id']);
1984  }
1985 // }}}
1986 
1987 // {{{ Bib -> getPortfolioList
1991  function getPortfolioList() { # maybe rename
1992  global $grima;
1993  $limit = 10; $offset = 0; # where to allow passing
1994  $ret = $grima->getElectronicPortfoliosForBib($this['mms_id'],$limit,$offset);
1995  $xpath = new DOMXpath($ret);
1996  $ports = $xpath->query('//portfolio');
1997  foreach ($ports as $portnode) {
1998  $newport = new ElectronicPortfolio();
1999  $newport->loadFromPortfolioListNode($portnode);
2000  $this->portfolioList[] = $newport;
2001  }
2002  return count($ports);
2003  }
2004 // }}}
2005 
2006 /*
2007  function recycle() { # XXX
2008  global $grima;
2009  $recycle_bin = new Set();
2010  $recycle_bin->loadFromAlma("9543638640002636");
2011  $recycle_bin->addMember($this['mms_id']);
2012  # add to recycle bin
2013  }
2014 */
2015 
2016 // {{{ Bib -> get_title_proper
2020  function get_title_proper() {
2021  $xpath = new DomXpath($this->xml);
2022  $title = $xpath->query("//record/datafield[@tag='245']/subfield[@code='a']");
2023  return preg_replace("/[ \/=:,;\.]*$/","",$title[0]->nodeValue);
2024  }
2025 // }}}
2026 
2027  /*
2028  function get_networkNumbers() {
2029  $xpath = new DomXpath($this->xml);
2030  $netNums = $xpath->query("//bib/network_numbers/network_number");
2031  $ret = array();
2032  for ($j=0;$j<$netNums->length;$j++) {
2033  $ret[] = $netNums[$j]->nodeValue;
2034  }
2035  return $ret;
2036  }
2037  */
2038 
2039 // {{{ Bib -> getLCCallNumber #XXX
2045  function getLCCallNumber() {
2046  $xpath = new DomXPath($this->xml);
2047  $calls = array();
2048  foreach (array('050','090') as $tag) {
2049  foreach ($xpath->query("//datafield[@tag='$tag']") as $call) {
2050  $calls[] = $call;
2051  }
2052  }
2053  $ret = array();
2054 
2055  foreach ($calls as $node) {
2056  $classs = $xpath->query("subfield[@code='a']",$node);
2057  $items = $xpath->query("subfield[@code='b']",$node);
2058  if ((count($classs) > 0) and (count($items) > 0)) {
2059  $ret = array($classs[0]->nodeValue,$items[0]->nodeValue);
2060  }
2061  }
2062  return $ret;
2063  }
2064 // }}}
2065 
2066 }
2067 
2068 // }}}
2069 
2070 // {{{ class HoldingsList
2072 class HoldingsList extends AlmaObject {
2073  public $el_address = array(
2074  'mms_id' => '//mms_id',
2075  'title' => '//title',
2076  'author' => '//author',
2077  );
2078  public $xml;
2079  #public $holdings = array(); # should this go in BIB?
2080  public $entries = array(); # array of HoldingsListEntry
2081 
2082  function __construct($mms_id = null) {
2083  if (!is_null($mms_id)) {
2084  $this->loadFromAlma($mms_id);
2085  }
2086  }
2087 
2088  function loadFromAlma($mms_id) {
2089  global $grima;
2090  $this->xml = $grima->getHoldingsList($mms_id);
2091  $xpath = new DomXpath($this->xml);
2092  $hs = $xpath->query('//holding');
2093  $this->entries = array(); # clear
2094  #$this->holdings = array(); # clear
2095  foreach ($hs as $h) {
2096  #$this->holdings[] = new HoldingsListEntry($h,$mms_id);
2097  $this->entries[] = new HoldingsListEntry($h,$mms_id);
2098  }
2099  }
2100 }
2101 
2102 // }}}
2103 
2104 // {{{ class HoldingsListEntry
2107  protected $el_address = array(
2108  'holding_id' => '//holding_id',
2109  'call_number' => '//holding/call_number',
2110  'library_code' => '//holding/library',
2111  'library' => '//holding/library/@desc',
2112  'location_code' => '//holding/location',
2113  'location' => '//holding/location/@desc'
2114  );
2115  public $xml;
2116 
2117  function __construct($node,$mms_id) {
2118  $this->xml = new DomDocument();
2119  $this->xml->appendChild($this->xml->importNode($node,true));
2120  $this->el_override['mms_id'] = $mms_id;
2121  }
2122 
2123  function getItemList($limit = -1) {
2124  global $grima;
2125  $this->getMmsIfNeeded();
2126  $this->itemList = new ItemList($this['mms_id'], $this['holding_id'], $limit);
2127  }
2128 }
2129 
2130 // }}}
2131 
2132 // {{{ class ItemList
2134 class ItemList extends AlmaObject {
2135  public $items = array(); #maybe ok as is
2136 
2137  function __construct($mms_id,$holding_id,$limit =-1) {
2138 
2139  global $grima;
2140  $curr_offset = 0;
2141  $req_limit = ($limit == -1)?100:$limit;
2142 
2143  do {
2144  if ($curr_offset > 0) {
2145  if (($curr_offset+1)*100 > $limit) {
2146  $req_limit = $limit - $curr_offset*100;
2147  } else {
2148  $req_limit = 100;
2149  }
2150  }
2151  $xml = $grima->getItemList($mms_id,$holding_id,$req_limit,$curr_offset*100);
2152  $xpath = new DomXpath($xml);
2153  $is = $xpath->query('//item');
2154  foreach ($is as $i) {
2155  $new_item = new Item();
2156  $new_item->loadFromItemListNode($i);
2157  $this->items[] = $new_item;
2158  }
2159  $xpath = new DomXPath($xml);
2160  if (!$curr_offset) {
2161  $length = $xpath->query('//items/@total_record_count')[0]->nodeValue;
2162  if ($limit == -1) { $limit = $length; }
2163  }
2164  $curr_offset++;
2165 
2166  } while (($curr_offset*100 < $length) and ($curr_offset*100 < $limit));
2167 
2168  }
2169 
2170 }
2171 
2172 // }}}
2173 
2174 // {{{ class Holding
2177  public $itemList; # object
2178  public $items = array();
2179  public $xml;
2180 
2181  function offsetSet($offset,$value) {
2182  if ($offset == "mms_id") {
2183  $this->el_override['mms_id'] = $value;
2184  } else {
2185  parent::offsetSet($offset,$value);
2186  }
2187  }
2188 
2189  function offsetGet($offset) { #XXX TEST
2190  if ($offset == "library") {
2191  $lib = new Library();
2192  $lib->loadFromAlma($this['library_code']);
2193  return $lib['name'];
2194  }
2195  if ($offset == "location") {
2196  $loc = new Location();
2197  $loc->loadFromAlma($this['library_code'],$this['location_code']);
2198  return $loc['name'];
2199  }
2200  if ($offset == "call_number") {
2201  $Hs = $this->getSubfieldValues("852","h");
2202  $Is = $this->getSubfieldValues("852","i");
2203  $acc = "";
2204  foreach ($Hs as $h) {
2205  $acc .= "$h ";
2206  }
2207  foreach ($Is as $i) {
2208  $acc .= "$i ";
2209  }
2210  return rtrim($acc);
2211  }
2212  return parent::offsetGet($offset);
2213  }
2214 
2215 // {{{ $el_address
2216  public $el_address = array(
2217  'holding_id' => '//holding_id',
2218  'inst_code' => "/holding/record/datafield[@tag='852']/subfield[@code='a']",
2219  'library_code' => "/holding/record/datafield[@tag='852']/subfield[@code='b']",
2220  'location_code' => "/holding/record/datafield[@tag='852']/subfield[@code='c']",
2221  );
2222 // }}}
2223 
2224 // {{{ loadFromAlma (get) - populates record from Alma
2231  function loadFromAlma($mms_id,$holding_id) {
2232  global $grima;
2233  $this->xml = $grima->getHolding($mms_id,$holding_id);
2234  $this['mms_id'] = $mms_id;
2235  }
2236 // }}}
2237 
2238 // {{{ getMmsFromHoldingID (get) - gets the MMS for a holding ID
2243  public static function getMmsFromHoldingID($holding_id) {
2244  global $grima;
2245 
2246  $report = new AnalyticsReport();
2247  $report->path = "/shared/UK Libraries- University of Kentucky (UKY)/Reports/Kathryn/HoldingToMMS";
2248  $report->filter = '
2249 <sawx:expr xsi:type="sawx:comparison" op="equal" xmlns:saw="com.siebel.analytics.web/report/v1.1"
2250 xmlns:sawx="com.siebel.analytics.web/expression/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2251 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
2252  <sawx:expr xsi:type="sawx:sqlExpression">"Holding Details"."Holding Id"</sawx:expr><sawx:expr xsi:type="xsd:string">{holding_id}</sawx:expr>
2253 </sawx:expr>';
2254 
2255  $report->runReport(array('holding_id' => $holding_id), 1);
2256  if (count($report->rows) == 1) {
2257  return $report->rows[0][1];
2258  } else {
2259  return null;
2260  }
2261  }
2262 // }}}
2263 
2264 // {{{ getMmsIfNeeded (get) - populates MMS if needed
2269  function getMmsIfNeeded() {
2270  global $grima;
2271 
2272  if (!isset($this['mms_id']) or (!$this['mms_id'])) {
2273  $this['mms_id'] = Holding::getMmsFromHoldingID($this['holding_id']);
2274  }
2275  }
2276 // }}}
2277 
2278 // {{{ loadFromAlmaX (get) - populates record from Alma using holding_id
2284  function loadFromAlmaX($holding_id) {
2285  global $grima;
2286 
2287  $mms_id = Holding::getMmsFromHoldingID($holding_id);
2288  $this->xml = $grima->getHolding($mms_id,$holding_id);
2289  $this['mms_id'] = $mms_id;
2290  }
2291 // }}}
2292 
2293 // {{{ Holding -> addToAlmaBib (post) - adds new holding record to specified bib
2299  function addToAlmaBib($mms_id) {
2300  global $grima;
2301  $this->xml = $grima->postHolding($mms_id,$this->xml);
2302  $this['mms_id'] = $mms_id;
2303  }
2304 // }}}
2305 
2306 // {{{ updateAlma (put) - update record in Alma
2310  function updateAlma() {
2311  global $grima;
2312  $grima->putHolding($this['mms_id'],$this['holding_id'],$this->xml);
2313  }
2314 // }}}
2315 
2316 // {{{ deleteFromAlma (delete) - delete record in Alma
2320  function deleteFromAlma() {
2321  global $grima;
2322  $grima->deleteHolding($this['mms_id'],$this['holding_id']);
2323  }
2324 // }}}
2325 
2326 /*
2327  function appendField($tag,$ind1,$ind2,$subfields) {
2328  $frag = "<datafield ind1=\"$ind1\" ind2=\"$ind2\" tag=\"$tag\">";
2329  foreach ($subfields as $k => $v) {
2330  $frag .= "<subfield code=\"$k\">$v</subfield>";
2331  }
2332  $frag .= "</datafield>";
2333  $xpath = new DomXpath($this->xml);
2334  $record = $xpath->query("//record");
2335  appendInnerXML($record[0],$frag);
2336  }
2337 */
2338 
2339  # call number object?
2340 
2341  function setCallNumber($h,$i,$ind1) {
2342  $xpath = new DomXpath($this->xml);
2343  $xpath->query("//record/datafield[@tag='852']")->item(0)->setAttribute("ind1",$ind1);
2344 
2345  $field852 = $xpath->query("//record/datafield[@tag='852']")->item(0);
2346  $subfieldHs = $xpath->query("subfield[@code='h']",$field852);
2347  foreach ($subfieldHs as $subfieldH) {
2348  $subfieldH->parentNode->removeChild($subfieldH);
2349  }
2350  $subfieldIs = $xpath->query("subfield[@code='i']",$field852);
2351  foreach ($subfieldIs as $subfieldI) {
2352  $subfieldI->parentNode->removeChild($subfieldI);
2353  }
2354 
2355  appendInnerXML($field852,"<subfield code=\"h\">$h</subfield>");
2356  if ($i) {
2357  appendInnerXML($field852,"<subfield code=\"i\">$i</subfield>");
2358  }
2359  }
2360 
2361 // {{{ moveToBib - moves a holding from one bib to another
2365  function moveToBib($mms_id) {
2366  $this->deleteFromAlma();
2367  $this->addToAlmaBib($mms_id);
2368  }
2369 // }}}
2370 
2371 // {{{ Holding -> getItems - get items objects
2375  function getItems() {
2376  $this->getItemList();
2377  $this->items =& $this->itemList->items;
2378  }
2379 // }}}
2380 
2381 // {{{ getItemList - populates itemList property from Alma
2385  function getItemList() {
2386  global $grima;
2387  $this->getMmsIfNeeded();
2388  $this->itemList = new ItemList($this['mms_id'],$this['holding_id']);
2389  }
2390 // }}}
2391 
2392 // {{{ Holding -> deleteTreeFromAlma - delete the holding and all items
2396  function deleteTreeFromAlma() {
2397  global $grima;
2398  $this->getItemList();
2399  foreach ($this->itemList->items as $item) {
2400  $item->deleteFromAlma("true");
2401  }
2402  $this->deleteFromAlma();
2403  }
2404 // }}}
2405 
2406 // {{{ Holding -> deleteSubfieldMatching # XXX TEST. UM. MARC INTERFACE? OMG
2415 /*
2416  function deleteSubfieldMatching($tag,$code,$regex) {
2417  $xpath = new DomXPath($this->xml);
2418  $subfs = $xpath->query("datafield[@tag='$tag']/subfield[@code='$code']");
2419  foreach ($subfs as $subf) {
2420  print "HERE";
2421  if (preg_match($regex,$subf->nodeValue)) {
2422  $subf->parentNode->removeChild($subf);
2423  }
2424  }
2425  }
2426 */
2427 // }}}
2428 
2429 }
2430 
2431 // }}}
2432 
2433 // {{{ class Item
2435 class Item extends AlmaObject {
2436 
2437  public $el_address = array(
2438  'item_pid' => '//pid',
2439  'barcode' => '//barcode',
2440  'creation_date' => '//creation_date',
2441  'modification_date' => '//modification_date',
2442  'base_status' => '//base_status',
2443  'physical_material_type_code' => '//physical_material_type',
2444  'physical_material_type' => '//physical_material_type/@desc',
2445  'location' => '//location/@desc',
2446  'location_code' => '//location',
2447  'library' => '//location/@desc',
2448  'library_code' => '//location',
2449  'policy' => '//policy',
2450  'item_policy' => '//policy',
2451  'provenance' => '//provenance',
2452  'po_line' => '//po_line',
2453  'is_magnetic' => '//is_magnetic',
2454  'arrival_date' => '//arrival_date',
2455  'year_of_issue' => '//year_of_issue',
2456  'enumeration_a' => '//enumeration_a',
2457  'enumeration_b' => '//enumeration_b',
2458  'enumeration_c' => '//enumeration_c',
2459  'enumeration_d' => '//enumeration_d',
2460  'enumeration_e' => '//enumeration_e',
2461  'enumeration_f' => '//enumeration_f',
2462  'enumeration_g' => '//enumeration_g',
2463  'enumeration_h' => '//enumeration_h',
2464  'chronology_i' => '//chronology_i',
2465  'chronology_j' => '//chronology_j',
2466  'chronology_k' => '//chronology_k',
2467  'chronology_l' => '//chronology_l',
2468  'chronology_m' => '//chronology_m',
2469  'description' => '//description',
2470  'alternative_call_number' => '//alternative_call_number',
2471  'alternative_call_number_type' => '//alternative_call_number_type',
2472  'storage_location_id' => '//storage_location_id',
2473  'receiving_operator' => '//receiving_operator',
2474  'process_type' => '//process_type',
2475  'in_temp_location' => '//in_temp_location',
2476  'mms_id' => '//mms_id',
2477  'holding_id' => '//holding_id',
2478  'title' => '//title',
2479  'call_number' => '//call_number',
2480  'pages' => '//pages',
2481  'pieces' => '//pieces',
2482  'public_note' => '//public_note',
2483  'fulfillment_note' => '//fulfillment_note',
2484  'internal_note_1' => '//internal_note_1',
2485  'internal_note_2' => '//internal_note_2',
2486  'internal_note_3' => '//internal_note_3',
2487  'statistics_note_1' => '//statistics_note_1',
2488  'statistics_note_2' => '//statistics_note_2',
2489  'statistics_note_3' => '//statistics_note_3',
2490  'requested' => '//requested',
2491  'physical_condition' => '//physical_condition',
2492  'temp_library' => '//temp_library',
2493  'temp_location' => '//temp_location',
2494  );
2495 
2496 // {{{ loadFromAlma (get)
2504  function loadFromAlma($mms_id,$holding_id,$item_pid) {
2505  global $grima;
2506  $this->xml = $grima->getItem($mms_id,$holding_id,$item_pid);
2507  }
2508 // }}}
2509 
2510 // {{{ loadFromAlmaX (get)
2515  function loadFromAlmaX($item_pid) {
2516  global $grima;
2517  $this->xml = $grima->getItem('X','X',$item_pid);
2518  }
2519 // }}}
2520 
2521 // {{{ loadFromAlmaBarcode (get)
2526  function loadFromAlmaBarcode($barcode) {
2527  global $grima;
2528  $this->xml = $grima->getItemBC($barcode);
2529  }
2530 // }}}
2531 
2532 // {{{ loadFromAlmaBCorX (get)
2539  function loadFromAlmaBCorX($id) {
2540  global $grima;
2541  if (preg_match("/^23.*/",$id)) { # item_pid
2542  # probably should know about suffix too
2543  $this->loadFromAlmaX($id);
2544  } else {
2545  $this->loadFromAlmaBarcode($id);
2546  }
2547  }
2548 // }}}
2549 
2550 // {{{ loadFromItemListNode
2556  function loadFromItemListNode($node) {
2557  $this->xml = new DomDocument();
2558  $this->xml->appendChild($this->xml->importNode($node,true));
2559  }
2560 // }}}
2561 
2562 // {{{ Item -> addToAlmaHolding (post)
2569  function addToAlmaHolding($mms_id,$holding_id) {
2570  global $grima;
2571  $this->mms_id = $mms_id;
2572  $this->holding_id = $holding_id;
2573  $this->xml = $grima->postItem($mms_id,$holding_id,$this->xml);
2574  return $this->xml;
2575  }
2576 // }}}
2577 
2578 // {{{ updateAlma (put)
2583  function updateAlma() {
2584  global $grima;
2585  return $grima->putItem(
2586  $this['mms_id'],
2587  $this['holding_id'],
2588  $this['item_pid'],
2589  $this->xml
2590  );
2591  }
2592 // }}}
2593 
2594 // {{{ Item -> deleteFromAlma (delete)
2601  function deleteFromAlma($override = "false", $holdings = "retain") {
2602  global $grima;
2603  $grima->deleteItem($this['mms_id'],$this['holding_id'],$this['item_pid'],$override,$holdings);
2604  }
2605 // }}}
2606 
2607 }
2608 
2609 // }}}
2610 
2611 // {{{ class ElectronicCollection
2614 
2615  public $xml;
2616  public $services = array();
2617 
2618 
2619 // {{{ ElectronicCollection -> el_address
2620  public $el_address = array(
2621  'collection_id' => '//id',
2622  'id' => '//id',
2623  );
2624 // }}}
2625 
2626 // {{{ ElectronicCollection -> loadFromAlma (get)
2631  function loadFromAlma($collection_id) {
2632  global $grima;
2633  $this->xml = $grima->getElectronicCollection($collection_id);
2634  #$this['collection_id'] = $collection_id;
2635  }
2636 // }}}
2637 
2638 // {{{ ElectronicCollection ->
2643  function getServices() {
2644  global $grima;
2645  $ret = $grima->getElectronicServices($this['collection_id']);
2646  $xpath = new DomXpath($ret);
2647  $eservices = $xpath->query('//electronic_services/electronic_service');
2648  foreach ($eservices as $service) {
2649  $service_id = $service->firstChild->nodeValue; # XXX really?
2650  $ser = new ElectronicService();
2651  $ser->loadFromServiceListNode($service);
2652  $this->services[] = $ser;
2653  }
2654  }
2655 // }}}
2656 
2657 }
2658 
2659 // }}}
2660 
2661 // {{{ class ElectronicService
2665 
2666  public $portfolios = array();
2667 
2668  public $el_address = array(
2669  'id' => '//id',
2670  'service_id' => '//id',
2671  );
2672 
2673  public $el_override = array();
2674 
2675  function __construct() {
2676  # load from template
2677  }
2678 
2679  function offsetSet($offset,$value) {
2680  if ($offset == "collection_id") {
2681  $this->el_override['collection_id'] = $value;
2682  } else {
2683  parent::offsetSet($offset,$value);
2684  }
2685  }
2686 
2687 // {{{ ElectronicService -> loadFromAlma (get)
2692  function loadFromAlma($collection_id,$service_id) {
2693  global $grima;
2694  $this->xml = $grima->getElectronicService($collection_id,$service_id);
2695  $this['collection_id'] = $collection_id;
2696  }
2697 // }}}
2698 
2699 // {{{ ElectronicService -> loadFromServiceListNode
2705  function loadFromServiceListNode($node) {
2706  $this->xml = new DomDocument();
2707  $this->xml->appendChild($this->xml->importNode($node,true));
2708  $xpath = new DomXPath($this->xml);
2709  $service_link = $xpath->query('//electronic_service')->item(0)->attributes['link']->nodeValue;
2710  preg_match('!/e-collections/(.*)/e-services/!',$service_link,$m);
2711  $this['collection_id'] = $m[1];
2712  }
2713 
2715  $curr_offset = 0;
2716  do {
2717  $retrieved = $this->getPortfolios(100, $curr_offset);
2718  $curr_offset += 100;
2719  } while ($retrieved == 100);
2720  }
2721 
2722 // {{{ ElectronicService -> getPortfolios
2730  /* mark full or brief? */
2731  #function retrievePortfolios($limit = 10, $offset = 0) { # RENAME
2732  function getPortfolios($limit = 10, $offset = 0) {
2733  global $grima;
2734  $ret = $grima->getElectronicPortfoliosForService($this['collection_id'],$this['service_id'],$limit,$offset);
2735  $xpath = new DOMXpath($ret);
2736  $ports = $xpath->query('//portfolio');
2737  foreach ($ports as $portnode) {
2738  $newport = new ElectronicPortfolio();
2739  $newport->loadFromPortfolioListNode($portnode);
2740  $this->portfolios[] = $newport;
2741  }
2742  return count($ports);
2743  }
2744 
2745 // }}}
2746 
2747 // {{{ ElectronicService -> deleteAllPortfolios - delete all portfolios from the bib
2753  function deleteAllPortfolios($bib_treat) {
2754  global $grima;
2755  while ($this->getPortfolios(100,0)) {
2756  foreach($this->portfolios as $portfolio) {
2757  $portfolio->deleteFromAlma($bib_treat);
2758  }
2759  $this->portfolios = array();
2760  sleep(2);
2761  }
2762  }
2763 // }}}
2764 
2765 /*
2766  function deleteAllPortfolios() { #XXX
2767  global $grima;
2768  # get portfolio list? or just ten at a time?
2769  $this->retrievePortfolios();
2770  while (sizeof($this->portfolios) > 0) {
2771  foreach ($this->portfolios as $portfolio) {
2772  print $portfolio['mms_id']->nodeValue; exit;
2773  #$portfolio->delete();
2774  }
2775  }
2776  }
2777 */
2778 
2779 }
2780 
2781 //}}}
2783 //}}}
2784 
2785 //{{{ class ElectronicPortfolio
2789  public $xml;
2790 
2791 // {{{ ElectronicPortfolio -> el_address
2792  public $el_address = array(
2793  'portfolio_id' => '//portfolio/id',
2794  'is_local' => '//is_local',
2795  'is_standalone' => '//is_standalone',
2796  'mms_id' => '//mms_id',
2797  'title' => '//title',
2798  'service' => '//service',
2799  'url' => '//url',
2800  'static_url' => '//static_url',
2801  'availability' => '//availability',
2802  'collection_id' => '//electronic_collection/id',
2803  'service_id' => '//electronic_collection/service',
2804  'material_type' => '//material_type',
2805  'url_type' => '//url_type',
2806  'public_note' => '//public_note'
2807  );
2808 // }}}
2809 
2810 // {{{ ElectronicPortfolio -> addToAlmaService
2817  function addToAlmaService($collection_id,$service_id) {
2818  global $grima;
2819  $ret = $grima->postElectronicPortfolio($collection_id, $service_id, $this->xml);
2820  return $ret;
2821  }
2822 // }}}
2823 
2824 // {{{ ElectronicPortfolio -> addToAlmaBib
2832  function addToAlmaBib($mms_id) {
2833  global $grima;
2834  $ret = $grima->postElectronicPortfolioOnBib($mms_id, $this->xml);
2835  return $ret;
2836  }
2837 // }}}
2838 
2839 // {{{ ElectronicPortfolio -> loadFromAlma
2845  function loadFromAlma($portfolio_id) {
2846  global $grima;
2847  $this->xml = $grima->getElectronicPortfolio('X','X',$portfolio_id);
2848  }
2849 
2850  function loadFromAlmaX($portfolio_id) {
2851  global $grima;
2852  $this->xml = $grima->getElectronicPortfolio('X','X',$portfolio_id);
2853  }
2854 // }}}
2855 
2856 // {{{ ElectronicPortfolio -> loadFromPortfolioListNode
2862  function loadFromPortfolioListNode($node) {
2863  $this->xml = new DomDocument();
2864  $this->xml->appendChild($this->xml->importNode($node,true));
2865  }
2866 // }}}
2867 
2868 // {{{ ElectronicPortfolio -> updateAlma
2872  function updateAlma() {
2873  global $grima;
2874  $this->xml = $grima->putElectronicPortfolioOnBib($this['mms_id'],$this['portfolio_id'],$this->xml);
2875  }
2876 // }}}
2877 
2878 // {{{ ElectronicPortfolio -> deleteFromAlma
2884  function deleteFromAlma($bib_treat = "retain") { # accept a variable?
2885  global $grima;
2886  $mms_id = $this['mms_id'];
2887  $grima->deleteElectronicPortfolio('X','X',
2888  $this['portfolio_id']);
2889  if ($bib_treat == "delete") {
2890  $bib = new Bib();
2891  $bib->loadFromAlma($mms_id);
2892  sleep(2);
2893  if (! $bib->hasInventory()) {
2894  if ($bib->linkedToCZ()) {
2895  print "LINKED TO CZ";
2896  $bib->unlinkFromCZ();
2897  exit;
2898  } else {
2899  $bib->deleteFromAlma();
2900  }
2901  }
2902  }
2903  }
2904 // }}}
2905 
2906 }
2907 
2908 // }}}
2909 
2910 // {{{ class Set
2912 class Set extends AlmaObject {
2913  public $xml;
2914  public $members = array();
2915 
2916  /*
2917  public $id;
2918  public $type; # itemized or logical
2919  public $name;
2920  public $private;
2921  public $active;
2922  public $size; # number of members
2923  */
2924 
2925 // {{{ Set -> el_address
2926  public $el_address = array(
2927  'set_id' => '//set/id',
2928  'id' => '//set/id',
2929  );
2930 // }}}
2931 
2932  function createFromImport($job_id,$population) {
2933  global $grima;
2934  $this->xml = $grima->createSetFromImport($job_id,$population);
2935  }
2936 
2937 // {{{ Set -> loadFromAlma
2943  function loadFromAlma($set_id) {
2944  global $grima;
2945  $this->xml = $grima->getSet($set_id);
2946  }
2947 // }}}
2948 
2949  function getMembers($limit = -1) { # put in $members
2950  # limit -1 means all
2951  global $grima;
2952  if ($limit == -1) { # get them all
2953  $xml = $grima->getSetMembers($this['set_id'],0);
2954  $xpath = new DomXpath($xml);
2955  $this->size = $xpath->query("//members")->item(0)->getAttribute("total_record_count");
2956  $limit = $this->size;
2957  }
2958 
2959  for ($j = 0; $j < ceil($limit/100); $j++) { # how many queries
2960  $xml = $grima->getSetMembers($this['id'],100,$j*100);
2961  $xpath = new DomXpath($xml);
2962  foreach ($xpath->query("//member") as $member) {
2963  $this->members[] = new SetMember(
2964  $member->childNodes[0]->nodeValue,
2965  $member->childNodes[1]->nodeValue
2966  );
2967  }
2968  }
2969  }
2970 
2971 // {{{ Set -> deleteFromAlma (delete)
2976  function deleteFromAlma() {
2977  global $grima;
2978  $grima->deleteSet($this['set_id']);
2979  }
2980 // }}}
2981 
2982  function addMember($mms_id) {
2983  global $grima;
2984  }
2985 
2986  function deleteAllMembers() {
2987  global $grima;
2988  }
2989 
2990 }
2991 
2992 // }}}
2993 
2994 // {{{ class SetMember
2996 class SetMember {
2997  public $id;
2999 
3001  $this->id = $id;
3002  $this->description = $description;
3003  }
3004 }
3005 
3006 // }}}
3007 
3008 // {{{ class Library
3010 class Library extends AlmaObject {
3011  public $el_address = array(
3012  'code' => '//code',
3013  'path' => '//path',
3014  'name' => '//name',
3015  'resource_sharing' => '//resource_sharing',
3016  );
3017 
3018 // {{{ Library -> loadFromAlma
3024  function loadFromAlma($code) {
3025  global $grima;
3026  $this->xml = $grima->getLibrary($code);
3027  }
3028 // }}}
3029 
3030 }
3031 
3032 // }}}
3033 
3034 // {{{ class Location
3036 class Location extends AlmaObject {
3037  public $el_address = array(
3038  'code' => '//code',
3039  'name' => '//name',
3040  );
3041 
3042 // {{{ Location -> loadFromAlma
3048  function loadFromAlma($libraryCode,$locationCode) {
3049  global $grima;
3050  $this->xml = $grima->getLocation($libraryCode, $locationCode);
3051  }
3052 // }}}
3053 
3054 }
3055 
3056 // }}}
3057 
3058 // {{{ class AnalyticsReport
3061 
3062 public $path;
3063 public $filter;
3064 public $reportXml;
3065 public $rows = array();
3066 
3067 // {{{ AnalyticsReport -> runReport
3073  function runReport($filter_params=array(), $limit = -1, $token = "") {
3074  global $grima;
3075  if (isset($this->filter)) {
3076  $passfilter = $this->filter;
3077  foreach ($filter_params as $k => $v) {
3078  $passfilter = str_replace('{'.$k.'}',urlencode($v),$passfilter);
3079  }
3080  } else {
3081  $passfilter = null;
3082  }
3083 
3084  if ($limit == -1) { $limit = 1000; } # no limit
3085  if ($limit < 25) { $limit = 25; } # must be in chunks of 25
3086  $this->reportXml = $grima->getAnalytics($this->path, $passfilter, $limit, $token);
3087 
3088  $xpath = new DomXpath($this->reportXml);
3089  $xpath->registerNamespace("x", "urn:schemas-microsoft-com:xml-analysis:rowset");
3090 
3091  $rows = $xpath->query('//x:Row');
3092  foreach ($rows as $row) {
3093  $newrow = array();
3094  $cols = $xpath->query("./*[contains(name(),'Column')]", $row);
3095  foreach ($cols as $col) {
3096  $newrow[] = $col->nodeValue;
3097  }
3098  $this->rows[] = $newrow;
3099  }
3100 
3101  }
3102 
3103 // }}}
3104 
3105 
3106 }
3107 
3108 // }}}
3109 
3110 // {{{ class GrimaDB
3111 
3112 // {{{ shared
3113 function tableExists($pdo, $table) {
3114  $table_esc = "\"" . preg_replace( "/\"/", "\"\"", $table ) . "\"";
3115  try {
3116  $result = $pdo->query("SELECT 1 FROM $table_esc LIMIT 1");
3117  } catch (Exception $e) {
3118  // We got an exception == table not found
3119  return FALSE;
3120  }
3121  // Result is either boolean FALSE (no table found) or PDOStatement Object (table found)
3122  return $result !== FALSE;
3123 }
3124 
3125 // }}}
3126 
3127 // {{{ class GrimaDB
3132 class GrimaDB implements ArrayAccess, IteratorAggregate {
3133  static function init() {
3134  try {
3135  $db = self::getDb();
3136  if (!tableExists($db,"institutions")) {
3137  $db->exec("CREATE TABLE institutions ( institution VARCHAR(100) PRIMARY KEY, apikey VARCHAR(100), server VARCHAR(100) )");
3138  }
3139  if (!tableExists($db,"users")) {
3140  $db->exec("CREATE TABLE users ( institution VARCHAR(100), username VARCHAR(100), password VARCHAR(255), isAdmin BOOLEAN )");
3141  }
3142  return true;
3143  } catch(Exception $x) {
3144  # create the database
3145  return false;
3146  }
3147  }
3148  static function isEmpty() {
3149  self::init();
3150  $db = self::getDb();
3151  $result = $db->query( 'SELECT COUNT(*) as c FROM institutions' );
3152  foreach( $result as $row ) {
3153  if ($row['c']>0) return false;
3154  }
3155  return true;
3156  }
3157 
3158  protected static function getDb() {
3159  if (!self::$db) {
3160  $db_url = getenv('DATABASE_URL');
3161  if (!$db_url) $db_url = "sqlite:" . join_paths( sys_get_temp_dir(), "grima/grima.sql");
3162  self::$db = new PDO($db_url);
3163  }
3164  return self::$db;
3165  }
3166  protected function getPasswordAlgorithm() {
3167  return defined("PASSWORD_ARGON2I") ? constant("PASSWORD_ARGON2I") : PASSWORD_DEFAULT;
3168  }
3169 
3170  private static $db = FALSE;
3171  private $info; // array
3172 
3173  function offsetExists($offset) {
3174  return isset($this->info[$offset]);
3175  }
3176 
3177  function offsetGet($offset) {
3178  return isset($this->info[$offset]) ? $this->info[$offset] : '';
3179  }
3180 
3181  function offsetSet($offset,$value) {
3182  $this->info[$offset] = $value;
3183  }
3184 
3185  function offsetUnset($offset) {
3186  unset($this->info[$offset]);
3187  }
3188 
3189  function getIterator() {
3190  return new ArrayIterator($this->info);
3191  }
3192 
3193 }
3194 
3195 // }}}
3196 
3197 // {{{ class GrimaInstitution
3201 class GrimaInstitution extends GrimaDB {
3202  public function addToDB() {
3203  $db = $this->getDb();
3204  $query = $db->prepare( 'INSERT INTO institutions(institution,apikey,server) VALUES (:institution,:apikey,:server)' );
3205  if (!$query) {
3206  $errorCode = $db->errorCode();
3207  $errorInfo = $db->errorInfo();
3208  throw new Exception(
3209  "Could not even prepare to insert into institution database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3210  );
3211  }
3212  $success = $query->execute( array(
3213  'institution' => $this['institution'],
3214  'apikey' => $this['apikey'],
3215  'server' => $this['server'],
3216  ) );
3217  if (!$success) {
3218  $errorCode = $query->errorCode();
3219  $errorInfo = $query->errorInfo();
3220  throw new Exception(
3221  "Could not insert into user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3222  );
3223  }
3224  }
3225 }
3226 
3227 // }}}
3228 
3229 // {{{ class GrimaUser
3233 class GrimaUser extends GrimaDB {
3234  public static function FromArray( $data ) {
3235  $user = new GrimaUser();
3236  foreach ( $data as $key => $val ) {
3237  $user[$key] = $val;
3238  }
3239  return $user;
3240  }
3241 
3242  public static function LookupUser($username, $institution = '', $password = FALSE) {
3243  $db = self::getDb();
3244  $query = $db->prepare(
3245  'SELECT * ' .
3246  'FROM institutions NATURAL JOIN users '.
3247  'WHERE institution=:institution '.
3248  'AND username=:username'
3249  );
3250  $success = $query->execute( array(
3251  'institution' => $institution,
3252  'username' => $username,
3253  ) );
3254  if ($success) {
3255  $row = $query->fetch(PDO::FETCH_ASSOC);
3256  if ($row===false) return false;
3257  $user = GrimaUser::FromArray( $row );
3258  if ( ($password !== FALSE) && ($user['password']!='') ) {
3259  if ( !password_verify( $password, $user['password'] ) ) return false;
3260  if ( password_needs_rehash( $user['password'], $user->getPasswordAlgorithm() ) ) {
3261  $user['password'] = $password;
3262  $user->updateDB();
3263  }
3264  }
3265  unset( $user['password'] );
3266  return $user;
3267  } else {
3268  $errorCode = $query->errorCode();
3269  $errorInfo = $query->errorInfo();
3270  throw new Exception(
3271  "Could not select from user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3272  );
3273  }
3274  }
3275 
3276  public static function RenameUser( $username, $institution, $newusername ) {
3277  $db = self::getDb();
3278  $query = $db->prepare(
3279  'UPDATE users ' .
3280  'SET username=:newusername ' .
3281  'WHERE institution=:institution '.
3282  'AND username=:username'
3283  );
3284  $success = $query->execute( array(
3285  'institution' => $institution,
3286  'username' => $username,
3287  'newusername' => $newusername,
3288  ) );
3289  if ($success) {
3290  return true;
3291  } else {
3292  $errorCode = $query->errorCode();
3293  $errorInfo = $query->errorInfo();
3294  throw new Exception(
3295  "Could not update user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3296  );
3297  }
3298  }
3299 
3300  public static function ResetPassword( $username, $institution, $password ) {
3301  $db = self::getDb();
3302  $query = $db->prepare(
3303  'UPDATE users ' .
3304  'SET password=:password ' .
3305  'WHERE institution=:institution '.
3306  'AND username=:username'
3307  );
3308  $passwordHash = password_hash( $password, self::getPasswordAlgorithm() );
3309  $success = $query->execute( array(
3310  'institution' => $institution,
3311  'username' => $username,
3312  'password' => $passwordHash,
3313  ) );
3314  if ($success) {
3315  return true;
3316  } else {
3317  $errorCode = $query->errorCode();
3318  $errorInfo = $query->errorInfo();
3319  throw new Exception(
3320  "Could not update user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3321  );
3322  }
3323  }
3324 
3325  public static function GetCurrentUser() {
3326  global $grima;
3327  $grima->session_init();
3328  session_write_close();
3329  if (!isset($_SESSION)) return false;
3330  return GrimaUser::FromArray( $_SESSION );
3331  }
3332 
3333  public static function SetCurrentUser( $username, $password, $institution = '' ) {
3334  global $grima;
3335  $user = GrimaUser::LookupUser( $username, $institution, $password );
3336  if ( $user !== false ) {
3337  if (isset($_SESSION)) {
3338  session_write_close();
3339  session_start();
3340  }
3341  $grima->session_save($user);
3342  } else {
3343  return false;
3344  }
3345  }
3346 
3347  function addToDB() {
3348  $db = $this->getDb();
3349  $query = $db->prepare( 'INSERT INTO users( username, password, institution, isAdmin ) VALUES (:username, :password, :institution, :isAdmin)' );
3350  if (!$query) {
3351  $errorCode = $db->errorCode();
3352  $errorInfo = $db->errorInfo();
3353  throw new Exception(
3354  "Could not even prepare to insert into user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3355  );
3356  }
3357  $success = $query->execute( array(
3358  'username' => $this['username'],
3359  'password' => password_hash( $this['password'], $this->getPasswordAlgorithm() ),
3360  'institution' => $this['institution'],
3361  'isAdmin' => $this['isAdmin'],
3362  ) );
3363  if (!$success) {
3364  $errorCode = $query->errorCode();
3365  $errorInfo = $query->errorInfo();
3366  throw new Exception(
3367  "Could not insert into user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3368  );
3369  }
3370  }
3371 
3372  function updateDB() {
3373  $db = $this->getDb();
3374  $query = $db->prepare( 'UPDATE users SET isAdmin=:isAdmin, password=:password WHERE username=:username AND institution=:institution' );
3375  if (!$query) {
3376  $errorCode = $db->errorCode();
3377  $errorInfo = $db->errorInfo();
3378  throw new Exception(
3379  "Could not even prepare to update user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3380  );
3381  }
3382  $success = $query->execute( array(
3383  'username' => $this['username'],
3384  'password' => password_hash( $this['password'], $this->getPasswordAlgorithm() ),
3385  'institution' => $this['institution'],
3386  'isAdmin' => $this['isAdmin'],
3387  ) );
3388  if (!$success) {
3389  $errorCode = $query->errorCode();
3390  $errorInfo = $query->errorInfo();
3391  throw new Exception(
3392  "Could not update user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3393  );
3394  }
3395  }
3396 
3397  function deleteFromDB() {
3398  $db = $this->getDb();
3399  $query = $db->prepare( 'DELETE FROM users WHERE username=:username AND institution=:institution' );
3400  if (!$query) {
3401  $errorCode = $db->errorCode();
3402  $errorInfo = $db->errorInfo();
3403  throw new Exception(
3404  "Could not even prepare to delete from user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3405  );
3406  }
3407  $success = $query->execute( array(
3408  'username' => $this['username'],
3409  'institution' => $this['institution'],
3410  ) );
3411  if (!$success) {
3412  $errorCode = $query->errorCode();
3413  $errorInfo = $query->errorInfo();
3414  throw new Exception(
3415  "Could not delete from user database: [$errorCode] {$errorInfo[0]} {$errorInfo[2]}"
3416  );
3417  }
3418  }
3419 }
3420 
3421 // }}}
3422 
3423 // }}}
3424 
3425 /* vim: set foldmethod=marker noexpandtab shiftwidth=4 tabstop=4: */
putBib($mms_id, $bib)
Update Bib Record - updates the copy of the bib in Alma.
Definition: grima-lib.php:376
getPortfolios($limit=10, $offset=0)
get list of portfolios from Alma
Definition: grima-lib.php:2732
offsetExists($offset)
Definition: grima-lib.php:1184
runReport($filter_params=array(), $limit=-1, $token="")
pull Analytics report from Alma
Definition: grima-lib.php:3073
unlinkFromCZ()
does this work : Not supported for CZ
Definition: grima-lib.php:1937
deleteAllPortfolios()
delete all portfolios from the bib
Definition: grima-lib.php:1966
offsetSet($offset, $value)
Definition: grima-lib.php:2181
loadFromAlma($mms_id, $holding_id, $item_pid)
populates item record from Alma
Definition: grima-lib.php:2504
getBib($mms_id, $view='full', $expand='None')
Retrieve Bib - retrieve a bib record from Alma.
Definition: grima-lib.php:330
deleteTreeFromAlma()
deletes the Bib and its inventory #XXX
Definition: grima-lib.php:1891
addToAlmaHolding($mms_id, $holding_id)
add new item record to holding in Alma
Definition: grima-lib.php:2569
offsetUnset($offset)
Definition: grima-lib.php:3185
class Library
Definition: grima-lib.php:3010
deleteHolding($mms_id, $holding_id, $override='false')
Delete Holdings Record - delete the holdings record from Alma.
Definition: grima-lib.php:531
deleteBib($mms_id, $override='false')
Delete Bib Record - deletes the bib record from Alma.
Definition: grima-lib.php:399
putItem($mms_id, $holding_id, $item_pid, $item)
Update Item information - replace item record in Alma.
Definition: grima-lib.php:670
static ResetPassword( $username, $institution, $password)
Definition: grima-lib.php:3300
A holder for the user inputs to a grima, base on the XML file.
Definition: grima-lib.php:1428
getHolding($mms_id, $holding_id)
Retrieve Holdings Record - retrieve holdings record from Alma.
Definition: grima-lib.php:458
getPasswordAlgorithm()
Definition: grima-lib.php:3166
loadFromAlma($mms_id, $holding_id)
populates the record from Alma
Definition: grima-lib.php:2231
loadFromAlma($set_id)
populate set with info from Alma
Definition: grima-lib.php:2943
offsetUnset($offset)
Definition: grima-lib.php:1196
static RenameUser( $username, $institution, $newusername)
Definition: grima-lib.php:3276
deleteFromAlma($override="false", $holdings="retain")
delete record from Alma
Definition: grima-lib.php:2601
loadFromServiceListNode($node)
populate item record from the information in an ServiceList node
Definition: grima-lib.php:2705
session_save($result)
Definition: grima-lib.php:35
deleteAllPortfolios($bib_treat)
delete all portfolios from the service
Definition: grima-lib.php:2753
putHolding($mms_id, $holding_id, $holding)
Update Holdings Record - replace the holdings record in Alma.
Definition: grima-lib.php:509
updateAlma()
update holding record in Alma
Definition: grima-lib.php:2310
getSetMembers($set_id, $limit=10, $offset=0)
get the members of a set, IF IT WORKS?!?!
Definition: grima-lib.php:1135
getElectronicCollection($collection_id)
Retrieve Electronic Collection - retrieve a collection record from Alma.
Definition: grima-lib.php:919
postElectronicPortfolioOnBib($mms_id, $portfolio)
Create Electronic Portfolio - add a new portfolio to Alma Bib.
Definition: grima-lib.php:801
loadPersistentValues($obj)
load persistent values into the form
Definition: grima-lib.php:1454
updateAlma()
replaces the Portfolio in Alma
Definition: grima-lib.php:2872
getLCCallNumber()
get LC call number, giving pref to 090 and later fields
Definition: grima-lib.php:2045
addToAlmaBib($mms_id)
adds a new holding record to the specified bib
Definition: grima-lib.php:2299
$holdings
Definition: grima-lib.php:1790
loadFromAlmaX($portfolio_id)
Definition: grima-lib.php:2850
MARC fields for use in bibs and holdings.
Definition: grima-lib.php:1772
offsetSet($offset, $value)
Definition: grima-lib.php:1192
class ElectronicPortfolio
Definition: grima-lib.php:2788
getElectronicPortfoliosForService($collection_id, $service_id, $limit, $offset)
Retrieve Portfolios - retrieve a list of portfolios from Alma.
Definition: grima-lib.php:873
loadFromAlma($code)
populate library with info from Alma
Definition: grima-lib.php:3024
static SetCurrentUser( $username, $password, $institution='')
Definition: grima-lib.php:3333
loadFromItemListNode($node)
populate item record from the information in an ItemList node
Definition: grima-lib.php:2556
class Holding
Definition: grima-lib.php:2176
offsetExists($offset)
Definition: grima-lib.php:1587
getItem($mms_id, $holding_id, $item_pid)
Retrieve Item and print label information.
Definition: grima-lib.php:594
getElectronicPortfolio($collection_id, $service_id, $portfolio_id)
Retrieve Portfolio - retrieve a portfolio record from Alma.
Definition: grima-lib.php:731
updateAlma()
replace item record in Alma
Definition: grima-lib.php:2583
setCallNumber($h, $i, $ind1)
Definition: grima-lib.php:2341
getHoldings()
populate holdings property with Holdings items
Definition: grima-lib.php:1951
getIterator()
Definition: grima-lib.php:3189
getHoldingsList($mms_id)
Retrieve Holdings list - download brief descriptions of holdings for the bib.
Definition: grima-lib.php:428
deleteElectronicPortfolio($collection_id, $service_id, $portfolio_id)
Delete Electronic Portfolio - delete portfolio from Alma.
Definition: grima-lib.php:849
offsetSet($offset, $value)
Definition: grima-lib.php:2679
static isEmpty()
Definition: grima-lib.php:3148
offsetGet($offset)
Definition: grima-lib.php:1807
__construct()
Definition: grima-lib.php:60
getFields($tag)
get fields for the given MARC tag
Definition: grima-lib.php:1657
loadFromAlmaBCorX($id)
populates item record from Alma using either identifier
Definition: grima-lib.php:2539
deleteFromAlma($bib_treat="retain")
delete portfolio from Alma
Definition: grima-lib.php:2884
session_init( $force=false)
Definition: grima-lib.php:20
tableExists($pdo, $table)
Definition: grima-lib.php:3113
hasInventory()
populate holdings property with Holdings items
Definition: grima-lib.php:1906
fromXML($xml)
interpret XML to determine form fields and behavior
Definition: grima-lib.php:1470
appendInnerXML( $elt, $xmlString)
Definition: grima-util.php:20
loadFromPortfolioListNode($node)
populate item record from the information in an PortfolioList node
Definition: grima-lib.php:2862
deleteFromAlma()
delete set from Alma
Definition: grima-lib.php:2976
getItemList()
populates itemList property from Alma
Definition: grima-lib.php:2385
deleteFromAlma()
delete the holding record from Alma
Definition: grima-lib.php:2320
loadFromAlmaBarcode($barcode)
populates item record from Alma, using barcode
Definition: grima-lib.php:2526
session_destroy()
Definition: grima-lib.php:43
$members
Definition: grima-lib.php:2914
putElectronicPortfolioOnBib($mms_id, $portfolio_id, $portfolio)
Update Electronic Portfolio - update portfolio in Alma.
Definition: grima-lib.php:825
offsetGet($offset)
Definition: grima-lib.php:3177
get_input_param($param)
Definition: grima-lib.php:1352
Shared access to the database for GrimaUser and GrimaInstitution.
Definition: grima-lib.php:3132
offsetSet($offset, $value)
Definition: grima-lib.php:1607
grima-lib.php - a library for running API calls in Alma
Definition: grima-lib.php:14
$el_address
Definition: grima-lib.php:2437
__construct($type, $message)
Definition: grima-lib.php:1416
do_redirect($url)
Definition: grima-util.php:45
getElectronicPortfoliosForBib($mms_id, $limit, $offset)
Retrieve Portfolios list (Bib) - retrieve a list of portfolios from Alma.
Definition: grima-lib.php:897
loadFromAlma($portfolio_id)
populate portfolio with info from Alma
Definition: grima-lib.php:2845
The base class for most "grimas".
Definition: grima-lib.php:1174
$grima
Definition: grima-lib.php:1166
deleteAllMembers()
Definition: grima-lib.php:2986
static FromArray( $data)
Definition: grima-lib.php:3234
Interface to the GrimaDB database to check password and get institution&#39;s apikey. ...
Definition: grima-lib.php:3233
offsetSet($offset, $value)
Definition: grima-lib.php:1828
static GetCurrentUser()
Definition: grima-lib.php:3325
$el_address
Definition: grima-lib.php:1796
postElectronicPortfolio($collection_id, $service_id, $portfolio)
Create Electronic Portfolio - add a new portfolio to Alma.
Definition: grima-lib.php:778
getAnalytics($path, $filter, $limit=25, $token=null)
Definition: grima-lib.php:1153
get_config()
Definition: grima-lib.php:64
class ElectronicService
Definition: grima-lib.php:2663
class Item
Definition: grima-lib.php:2435
offsetGet($offset)
Definition: grima-lib.php:1594
__construct($field)
create a new GrimaFormField
Definition: grima-lib.php:1543
getHoldingsList()
populate holdingsList property with info from Alma
Definition: grima-lib.php:1982
offsetSet($offset, $value)
Definition: grima-lib.php:3181
deleteFromAlma()
deletes the Bib from Alma
Definition: grima-lib.php:1881
Simple template engine.
__construct()
create new blank Alma Object
Definition: grima-lib.php:1580
offsetExists($offset)
Definition: grima-lib.php:3173
postHolding($mms_id, $holding)
Create holding record - add a new holdings record to a bib.
Definition: grima-lib.php:484
__construct($id, $description)
Definition: grima-lib.php:3000
loadFromAlma($mms_id)
Definition: grima-lib.php:2088
Methods for fields and subfields in Alma&#39;s MARCXML.
Definition: grima-lib.php:1627
getMmsIfNeeded()
populates the MMS ID if not already known
Definition: grima-lib.php:2269
addToAlmaService($collection_id, $service_id)
populate item record from the information in an PortfolioList node : Insufficient permission ...
Definition: grima-lib.php:2817
getLibrary($libraryCode)
Retrieve a Library - retrieve a Library from Alma.
Definition: grima-lib.php:971
Interface to the GrimaDB database to retrieve API keys.
Definition: grima-lib.php:3201
getSubfieldValues($tag, $code)
get subfield value
Definition: grima-lib.php:1685
booly($str, $default='undefined')
return boolean meaning of common terms ("true","on","1","yes")
Definition: grima-lib.php:1517
postBib($bib)
Create Record - adds a new bib record to Alma.
Definition: grima-lib.php:352
getSet($set_id)
Retrieve a Set - retrieve a Set from Alma.
Definition: grima-lib.php:1032
Base class for objects returned from alma APIs (mostly just array access)
Definition: grima-lib.php:1571
loadFromAlma($mms_id)
populates the bib with a record from Alma
Definition: grima-lib.php:1850
static call($grimaname, $args=array())
Definition: grima-lib.php:1398
$holdingsList
Definition: grima-lib.php:1789
checkForErrorMessage($xml)
checks for errorMessage tag, throws exceptions
Definition: grima-lib.php:298
loadFromAlmaX($item_pid)
populates item record from Alma, only needs item_pid
Definition: grima-lib.php:2515
put($url, $URLparams, $QSparams, $body)
general function for PUT (update) API calls
Definition: grima-lib.php:218
class HoldingsListEntry
Definition: grima-lib.php:2106
__construct($node, $mms_id)
Definition: grima-lib.php:2117
addMessage($type, $message)
Definition: grima-lib.php:1264
getElectronicPortfolioFromBib($mms_id, $portfolio_id)
Retrieve Portfolio - retrieve a portfolio record from Alma.
Definition: grima-lib.php:754
linkedToCZ()
is the bib linked to the community zone?
Definition: grima-lib.php:1925
static RunIt()
Definition: grima-lib.php:1291
loadFromAlma($collection_id)
load record from Alma
Definition: grima-lib.php:2631
A thin wrapper around a message and urgency level.
Definition: grima-lib.php:1411
getPortfolioList()
populate portfolioList property with info from Alma
Definition: grima-lib.php:1991
deleteField($tag)
delete all $tag fields from the MARC record
Definition: grima-lib.php:1702
join_paths(... $paths)
Definition: grima-util.php:114
class SetMember
Definition: grima-lib.php:2996
createFromImport($job_id, $population)
Definition: grima-lib.php:2932
class ElectronicCollection
Definition: grima-lib.php:2613
replaceOrAddSubfield($tag, $code, $value)
replace or add subfield value in marc
Definition: grima-lib.php:1736
$portfolioList
Definition: grima-lib.php:1792
addToAlmaBib($mms_id)
add portfolio to Bib in Alma : Insufficient permission
Definition: grima-lib.php:2832
static getDb()
Definition: grima-lib.php:3158
__construct($mms_id, $holding_id, $limit=-1)
Definition: grima-lib.php:2137
loadFromAlma($libraryCode, $locationCode)
populate location with info from Alma
Definition: grima-lib.php:3048
getItemBC($barcode)
Retrieve Item and print label information (by barcode))
Definition: grima-lib.php:618
get_title_proper()
a tidy title proper
Definition: grima-lib.php:2020
getMembers($limit=-1)
Definition: grima-lib.php:2949
getItems()
populate items property with Items objects ## XXX TEST
Definition: grima-lib.php:2375
class ItemList
Definition: grima-lib.php:2134
class AnalyticsReport
Definition: grima-lib.php:3060
offsetUnset($offset)
Definition: grima-lib.php:1613
static getMmsFromHoldingID($holding_id)
populates the MMS ID
Definition: grima-lib.php:2243
$el_address
Definition: grima-lib.php:2926
class Location
Definition: grima-lib.php:3036
class HoldingsList
Definition: grima-lib.php:2072
addToAlma()
adds record as a new record to Alma, updates Bib with current Alma version
Definition: grima-lib.php:1861
getLocation($libraryCode, $locationCode)
Retrieve Location - retrieve a Library Location from Alma.
Definition: grima-lib.php:1000
updateAlma()
replaces the Bib in Alma
Definition: grima-lib.php:1871
deleteItem($mms_id, $holding_id, $item_pid, $override="false", $holdings="retain")
Withdraw Item - delete an item record from Alma.
Definition: grima-lib.php:695
addMember($mms_id)
Definition: grima-lib.php:2982
getItemList($mms_id, $holding_id, $limit, $offset)
Retrieve Items list - retrieve the items list from a holding or bib from Alma.
Definition: grima-lib.php:565
getItemList($limit=-1)
Definition: grima-lib.php:2123
loadFromAlma($collection_id, $service_id)
load record from Alma
Definition: grima-lib.php:2692
deleteSet($set_id)
Delete a Set - delete a set (not its items) from Alma.
Definition: grima-lib.php:1111
deleteSubfieldMatching($tag, $code, $regex)
delete subfields matching a regex
Definition: grima-lib.php:1717
__construct($mms_id=null)
Definition: grima-lib.php:2082
static $db
Definition: grima-lib.php:3170
loadFromAlmaX($holding_id)
populates the record from Alma - only requires holding_id
Definition: grima-lib.php:2284
loadValues($obj)
load values into the form
Definition: grima-lib.php:1439
static LookupUser($username, $institution='', $password=FALSE)
Definition: grima-lib.php:3242
offsetGet($offset)
Definition: grima-lib.php:1188
moveToBib($mms_id)
moves the holding from one bib to another – only for empty holdings!
Definition: grima-lib.php:2365
offsetGet($offset)
Definition: grima-lib.php:2189
createSetFromImport($job_instance_id, $population)
Create a Set from an import job.
Definition: grima-lib.php:1060
class Set IN PROGRESS
Definition: grima-lib.php:2912
deleteTreeFromAlma()
delete the holding and all of its items
Definition: grima-lib.php:2396
appendField($tag, $ind1, $ind2, $subfields)
add a field to the MARC record
Definition: grima-lib.php:1638
getElectronicServices($collection_id)
Retrieve Electronic Services - retrieve a list of services from a collection in Alma.
Definition: grima-lib.php:942
getServices()
load record from Alma
Definition: grima-lib.php:2643
Wrapper for each field in a form, keeping track of its properties.
Definition: grima-lib.php:1493
post($url, $URLparams, $QSparams, $body)
general function for POST (create) API calls
Definition: grima-lib.php:174
postItem($mms_id, $holding_id, $item)
Create Item - add a new item to a holding in Alma.
Definition: grima-lib.php:644
static init()
Definition: grima-lib.php:3133