1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Scriptotek\Alma\Bibs; |
4
|
|
|
|
5
|
|
|
use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement; |
6
|
|
|
use Scriptotek\Alma\Client; |
7
|
|
|
use Scriptotek\Alma\Exception\NoLinkedNetworkZoneRecordException; |
8
|
|
|
use Scriptotek\Marc\Record as MarcRecord; |
9
|
|
|
use Scriptotek\Sru\Record as SruRecord; |
10
|
|
|
|
11
|
|
|
class Bib |
12
|
|
|
{ |
13
|
|
|
public $mms_id; |
14
|
|
|
|
15
|
|
|
/** @var Client */ |
16
|
|
|
protected $client; |
17
|
|
|
|
18
|
|
|
/** @var QuiteSimpleXMLElement */ |
19
|
|
|
protected $bib_data = null; |
20
|
|
|
|
21
|
|
|
/* @var MarcRecord */ |
22
|
|
|
protected $marc_data = null; |
23
|
|
|
|
24
|
|
|
protected $_holdings = null; |
25
|
|
|
|
26
|
|
|
public function __construct(Client $client = null, $mms_id = null, MarcRecord $marc_data = null, QuiteSimpleXMLElement $bib_data = null) |
27
|
|
|
{ |
28
|
|
|
$this->mms_id = $mms_id; |
29
|
|
|
$this->client = $client; |
30
|
|
|
$this->marc_data = $marc_data; |
31
|
|
|
$this->bib_data = $bib_data; |
32
|
|
|
$this->extractMarcDataFromBibData(); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Initialize from SRU record without having to fetch the Bib record. |
37
|
|
|
*/ |
38
|
|
|
public static function fromSruRecord(SruRecord $record, Client $client = null) |
39
|
|
|
{ |
40
|
|
|
$record->data->registerXPathNamespace('marc', 'http://www.loc.gov/MARC21/slim'); |
41
|
|
|
$marcRecord = MarcRecord::fromString($record->data->asXML()); |
42
|
|
|
|
43
|
|
|
return new self($client, strval($marcRecord->id), $marcRecord); |
|
|
|
|
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/* Lazy load */ |
47
|
|
|
protected function load() |
48
|
|
|
{ |
49
|
|
|
if (!is_null($this->bib_data)) { |
50
|
|
|
return; // we already have the data and won't re-fetch |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
$options = []; |
54
|
|
|
$this->bib_data = $this->client->getXML('/bibs/' . $this->mms_id, $options); |
55
|
|
|
|
56
|
|
|
$mms_id = $this->bib_data->text('mms_id'); |
57
|
|
|
if ($mms_id != $this->mms_id) { |
58
|
|
|
throw new \ErrorException('Record mms_id ' . $mms_id . ' does not match requested mms_id ' . $this->mms_id . '.'); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$this->extractMarcDataFromBibData(); |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Extract and parse the MARC data in the <record> tag |
66
|
|
|
* as a MarcRecord object. |
67
|
|
|
*/ |
68
|
|
|
protected function extractMarcDataFromBibData() |
69
|
|
|
{ |
70
|
|
|
if (is_null($this->bib_data)) { |
71
|
|
|
return; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
$bibNode = $this->bib_data->el; |
75
|
|
|
|
76
|
|
|
// If we already have the MARC record (from SRU), we should not |
77
|
|
|
// overwrite it in case the user has made edits to it. |
78
|
|
|
if (is_null($this->marc_data)) { |
79
|
|
|
$this->marc_data = MarcRecord::fromString($bibNode->record->asXML()); |
|
|
|
|
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$bibNode->record = null; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
public function getHolding($holding_id) |
86
|
|
|
{ |
87
|
|
|
return new Holding($this->client, $this->mms_id, $holding_id); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
public function getHoldings() |
91
|
|
|
{ |
92
|
|
|
if (is_null($this->_holdings)) { |
93
|
|
|
$this->_holdings = new Holdings($this->client, $this->mms_id); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
return $this->_holdings; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
public function save() |
100
|
|
|
{ |
101
|
|
|
// If initialized from an SRU record, we need to fetch the |
102
|
|
|
// remaining parts of the Bib record. |
103
|
|
|
$this->load(); |
104
|
|
|
|
105
|
|
|
// Inject the MARC record |
106
|
|
|
$marcXml = new QuiteSimpleXMLElement($this->marc_data->toXML('UTF-8', false, false)); |
107
|
|
|
$this->bib_data->first('record')->replace($marcXml); |
108
|
|
|
|
109
|
|
|
// Serialize |
110
|
|
|
$newData = $this->bib_data->asXML(); |
111
|
|
|
|
112
|
|
|
// Alma doesn't like namespaces |
113
|
|
|
$newData = str_replace(' xmlns="http://www.loc.gov/MARC21/slim"', '', $newData); |
114
|
|
|
|
115
|
|
|
return $this->client->putXML('/bibs/' . $this->mms_id, $newData); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
public function getXml() |
119
|
|
|
{ |
120
|
|
|
if (is_null($this->bib_data)) { |
121
|
|
|
$this->load(); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
return $this->bib_data->asXML(); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* Get the MMS ID of the linked record in network zone. |
129
|
|
|
*/ |
130
|
|
|
public function getNzMmsId() |
131
|
|
|
{ |
132
|
|
|
// If initialized from an SRU record, we need to fetch the |
133
|
|
|
// remaining parts of the Bib record. |
134
|
|
|
$this->load(); |
135
|
|
|
|
136
|
|
|
$nz_mms_id = $this->bib_data->text('linked_record_id[@type="NZ"]'); |
137
|
|
|
if (!$nz_mms_id) { |
138
|
|
|
throw new NoLinkedNetworkZoneRecordException("Record $this->mms_id is not linked to a network zone record."); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
return $nz_mms_id; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* Get the Bib of the linked record in network zone. |
146
|
|
|
*/ |
147
|
|
|
public function getNzRecord() |
148
|
|
|
{ |
149
|
|
|
return $this->client->nz->bibs->get($this->getNzMmsId()); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Returns the MARC record. |
154
|
|
|
*/ |
155
|
|
|
public function getRecord() |
156
|
|
|
{ |
157
|
|
|
if (is_null($this->marc_data)) { |
158
|
|
|
$this->load(); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
return $this->marc_data; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
public function __get($key) |
165
|
|
|
{ |
166
|
|
|
if ($key == 'record') { |
167
|
|
|
return $this->getRecord(); |
168
|
|
|
} |
169
|
|
|
if ($key == 'holdings') { |
170
|
|
|
return $this->getHoldings(); |
171
|
|
|
} |
172
|
|
|
$this->load(); |
173
|
|
|
|
174
|
|
|
return $this->bib_data->text($key); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.