Passed
Push — master ( 04f8fa...a076a5 )
by Dan Michael O.
02:23
created

Bib::getNzMmsId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 0
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
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);
0 ignored issues
show
Bug introduced by
The property id does not seem to exist in Scriptotek\Marc\Collection.

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.

Loading history...
Documentation introduced by
$marcRecord is of type object<Scriptotek\Marc\Collection>, but the function expects a null|object<Scriptotek\Marc\Record>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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());
0 ignored issues
show
Documentation Bug introduced by
It seems like \Scriptotek\Marc\Record:...bNode->record->asXML()) can also be of type object<Scriptotek\Marc\Collection>. However, the property $marc_data is declared as type object<Scriptotek\Marc\Record>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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