BibliographicRecord::parseMaterial()   F
last analyzed

Complexity

Conditions 37
Paths 1516

Size

Total Lines 250

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 250
rs 0
c 0
b 0
f 0
cc 37
nc 1516
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Scriptotek\SimpleMarcParser;
4
5
use Carbon\Carbon;
6
use Danmichaelo\QuiteSimpleXmlElement\QuiteSimpleXmlElement;
7
8
/**
9
 * @property int       $id                 Local record identifier
10
 * @property string    $material
11
 * @property boolean   $electronic
12
 * @property boolean   $is_series
13
 * @property boolean   $is_multivolume
14
 * @property boolean
15
 * @property string    $agency
16
 * @property string    $lccn
17
 * @property string    $catalogingRules
18
 * @property string    $title
19
 * @property string    $alternativeTitles
20
 * @property string    $part_no
21
 * @property string    $part_name
22
 * @property string    $part_of
23
 * @property string    $medium
24
 * @property string    $edition
25
 * @property string    $placeOfPublication
26
 * @property string    $publisher
27
 * @property string    $extent
28
 * @property string    $contents
29
 * @property string    $summary
30
 * @property string    $cover_image
31
 * @property string    $description
32
 * @property string    $preceding
33
 * @property string    $succeeding
34
 * @property string[]  $isbns
35
 * @property string[]  $issns
36
 * @property string[]  $notes
37
 * @property array     $series
38
 * @property array     $other_form
39
 * @property array     $creators
40
 * @property array     $meetings
41
 * @property array     $subjects
42
 * @property array     $genres
43
 * @property array     $classifications
44
 * @property array     $debug
45
 * @property int       $pages
46
 * @property int       $year
47
 * @property Carbon    $modified
48
 * @property Carbon    $created
49
 */
50
class BibliographicRecord extends Record
51
{
52
    /**
53
     * @param string $x1
54
     * @param string $x2
55
     * @param string $default
56
     *
57
     * @return string
58
     */
59
    public function getMaterialSubtypeFrom007($x1, $x2, $default = 'Unknown')
60
    {
61
        $f007values = array(
62
            'a' => array(
63
                'd' => 'Atlas',
64
                'g' => 'Diagram',
65
                'j' => 'Map',
66
                'k' => 'Profile',
67
                'q' => 'Model',
68
                'r' => 'Remote-sensing image',
69
                '_' => 'Map',
70
            ),
71
            'c' => array(
72
                'a' => 'Tape cartridge',
73
                'b' => 'Chip cartridge',
74
                'c' => 'Computer optical disc cartridge',
75
                'd' => 'Computer disc, type unspecified',
76
                'e' => 'Computer disc cartridge, type unspecified',
77
                'f' => 'Tape cassette',
78
                'h' => 'Tape reel',
79
                'j' => 'Magnetic disk',
80
                'k' => 'Computer card',
81
                'm' => 'Magneto-optical disc',
82
                'o' => 'CD-ROM',                // Optical disc
83
                'r' => 'Remote resource',    // n Nettdokumenter
84
            ),
85
            'f' => array(
86
                'a' => 'Moon',         // in the Moon writing system
87
                'b' => 'Braille',      // in the Braille writing system
88
                'c' => 'Combination ', // in a combination of two or more of the other defined types
89
                'd' => 'No writing system',
90
            ),
91
            'h' => array(
92
                'a' => 'Aperture card',
93
                'b' => 'Microfilm cartridge',
94
                'c' => 'Microfilm cassette',
95
                'd' => 'Microfilm reel',
96
                'e' => 'Microfiche',
97
                'f' => 'Microfiche cassette',
98
                'g' => 'Microopaque',
99
                'h' => 'Microfilm slip',
100
                'j' => 'Microfilm roll',
101
                'u' => 'Microform', // Unspecified
102
                'z' => 'Microform', // Other
103
                '|' => 'Microform', // No attempt to code
104
            ),
105
            'o' => array(
106
                'u' => 'Kit',
107
                '|' => 'Kit',
108
            ),
109
            's' => array(
110
                'd' => 'Music CD',             // v CD-er
111
                'e' => 'Cylinder',
112
                'g' => 'Sound cartridge',
113
                'i' => 'Sound-track film',
114
                'q' => 'Roll',
115
                's' => 'Sound cassette',
116
                't' => 'Sound-tape reel',
117
                'u' => 'Unspecified',
118
                'w' => 'Wire recording',
119
            ),
120
            'v' => array(
121
                'c' => 'Videocartridge',
122
                'd' => 'Videodisc',           // w DVD-er
123
                'f' => 'Videocassette',
124
                'r' => 'Videoreel',
125
            ),
126
        );
127
        if (isset($f007values[$x1]) && isset($f007values[$x1][$x2])) {
128
            return $f007values[$x1][$x2];
129
        }
130
        // TODO: LOG IT!
131
        return $default;
132
    }
133
134
    /**
135
     * @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $data
136
     */
137
    protected function parseMaterial(QuiteSimpleXmlElement $data)
138
    {
139
        // See http://www.loc.gov/marc/ldr06guide.html
140
141
        // The Leader/06 (Type of record) character position contains a one-character
142
        // alphabetic code that differentiates MARC records created for various types of
143
        // content and materials.
144
145
        // The 008 field contains character positions that provide coded information about
146
        // the record as a whole and about special bibliographic aspects of the item cataloged.
147
148
        // Field 006 (Fixed-length data elements - Additional material characteristics)
149
        // permits coding for additional aspects of an electronic resource (including any
150
        // computer file aspects) if the 007 and 008 fields do not adequately describe it.
151
152
        // leader[6] : Type of record
153
        // leader[7] : Bibliographic level
154
        // Field 008/18-34 Configuration
155
156
        // LDR/06
157
        $recordTypes = array(
0 ignored issues
show
Unused Code introduced by
$recordTypes is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
158
            'a' => 'Language material',
159
            'c' => 'Notated music',
160
            'd' => 'Manuscript notated music',
161
            'e' => 'Cartographic material',
162
            'f' => 'Manuscript cartographic material',
163
            'g' => 'Projected medium',
164
            'i' => 'Nonmusical sound recording',
165
            'j' => 'Musical sound recording',
166
            'k' => 'Two-dimensional nonprojectable graphic',
167
            'm' => 'Computer file',
168
            'o' => 'Kit',
169
            'p' => 'Mixed materials',
170
            'r' => 'Three-dimensional artifact or naturally occurring object',
171
            't' => 'Manuscript language material',
172
        );
173
174
        // LDR/07
175
        $bibliographicLevels = array(
0 ignored issues
show
Unused Code introduced by
$bibliographicLevels is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
176
            'a' => 'Monographic component part',
177
            'b' => 'Serial component part',
178
            'c' => 'Collection',
179
            'd' => 'Subunit',
180
            'i' => 'Integrating resource',
181
            'm' => 'Monograph/Item',
182
            's' => 'Serial',
183
        );
184
185
        // 007/00 (Category of material)
186
        $materialCategories = array(
0 ignored issues
show
Unused Code introduced by
$materialCategories is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
187
            'a' => 'Map',
188
            'c' => 'Electronic resource',
189
            'd' => 'Globe',
190
            'f' => 'Tactile material',
191
            'g' => 'Projected graphic',
192
            'h' => 'Microform',
193
            'k' => 'Nonprojected graphic',
194
            'm' => 'Motion picture',
195
            'o' => 'Kit',
196
            'q' => 'Notated music',
197
            'r' => 'Remote-sensing image',
198
            's' => 'Sound recording',
199
            't' => 'Text',                 // p Trykt materiale
200
            'v' => 'Videorecording',
201
            'z' => 'Unspecified',
202
        );
203
204
        // 008/24-27 - Nature of contents (006/07-10)
205
        $natureOfContents = array(
206
            'a' => 'Abstract',
207
            'b' => 'Bibliography',
208
            'c' => 'Catalog',
209
            'd' => 'Dictionary',
210
            'e' => 'Encyclopedia',
211
            'f' => 'Handbook',
212
            'g' => 'Legal article',
213
            'i' => 'Index',
214
            'j' => 'Patent document',
215
            'k' => 'Discography',
216
            'l' => 'Legislation',
217
            'm' => 'Thesis',
218
            'n' => 'Surveys of literature in a subject area',
219
            'o' => 'Review',
220
            'p' => 'Programmed text',
221
            'q' => 'Filmography',
222
            'r' => 'Directory',
223
            's' => 'Statistics',
224
            't' => 'Technical report',
225
            'u' => 'Standards/specification',
226
            'v' => 'Legal cases and case notes',
227
            'w' => 'Law reports and digests',
228
            'y' => 'Yearbook',
229
            'z' => 'Treaty',
230
            '2' => 'Offprint',
231
            '5' => 'Calendar',
232
            '6' => 'Comics/graphic novel',
233
        );
234
235
        $videoFormats = array(
236
            'a' => 'Beta (1/2 in., videocassette)',
237
            'b' => 'VHS (1/2 in., videocassette)',
238
            'c' => 'U-matic (3/4 in., videocasstte)',
239
            'd' => 'EIAJ (1/2 in., reel)',
240
            'e' => 'Type C (1 in., reel)',
241
            'f' => 'Quadruplex (1 in. or 2 in., reel)',
242
            'g' => 'Laserdisc',
243
            'h' => 'CED (Capacitance Electronic Disc) videodisc',
244
            'i' => 'Betacam (1/2 in., videocassette)',
245
            'j' => 'Betacam SP (1/2 in., videocassette)',
246
            'k' => 'Super-VHS (1/2 in., videocassette)',
247
            'm' => 'M-II (1/2 in., videocassette)',
248
            'o' => 'D-2 (3/4 in., videocassette)',
249
            'p' => '8 mm.',
250
            'q' => 'Hi-8 mm.',
251
            's' => 'Blu-ray',
252
            'u' => 'Unknown',
253
            'v' => 'DVD',
254
        );
255
256
        // If Leader/06 = a and Leader/07 = a, c, d, or m: Books
257
        // If Leader/06 = a and Leader/07 = b, i, or s: Continuing Resources
258
        // If Leader/06 = t: Books
259
        // If Leader/06 = c, d, i, or j: Music
260
        // If Leader/06 = e, or f: Maps
261
        // If Leader/06 = g, k, o, or r: Visual Materials
262
        // If Leader/06 = m: Computer Files
263
        // If Leader/06 = p: Mixed Materials
264
265
        $ldr = str_split($data->text('marc:leader'));
266
        $f007 = str_split($data->text('marc:controlfield[@tag="007"]'));
267
        $f008 = str_split($data->text('marc:controlfield[@tag="008"]'));
268
269
        $material = 'Unknown';
270
        $this->material = $material;
271
        $this->electronic = false;
272
273
        $this->debug = array(
274
            'ldr06' => array_get($ldr, 6),
275
            'ldr07' => array_get($ldr, 7),
276
            'f7_01' => array_get($f007, 0) ?: null,
277
            'f7_02' => array_get($f007, 1),
278
        );
279
280
        if (count($ldr) < 8) {
281
            return;
282
        }
283
        if (count($f007) < 2) {
284
            return;
285
        }
286
287
        switch ($ldr[6]) {
288
289
            case 'a':
290
                if (in_array($ldr[7], array('a', 'c', 'd', 'm'))) {
291
                    $material = 'Book';
292
                }
293
                if (in_array($ldr[7], array('b', 'i', 's'))) {
294
                    $material = 'Series';
295
                }
296
                break;
297
298
            case 't':
299
                $material = 'Book';
300
                break;
301
302
            case 'c':
303
            case 'd':
304
            case 'i':
305
            case 'j':
306
                $material = 'Music';
307
                break;
308
309
            case 'e':
310
            case 'f':
311
                $material = 'Map';
312
                break;
313
314
            case 'g':
315
            case 'k':
316
            case 'o':
317
            case 'r':
318
                $material = 'Visual';
319
                break;
320
321
            case 'm':
322
                $material = 'File';
323
                // used for computer software, numeric data, not for e-books or e-journals!
324
                break;
325
326
            case 'p':
327
                $material = 'Mixed';
328
                break;
329
330
        }
331
332
        $online = ($f007[0] == 'c' && $f007[1] == 'r');
333
334
        if ($material == 'File') {
335
            $material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material);
336
        } elseif ($material == 'Visual') {
337
            $material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material);
338
339
            if (isset($f007[4]) && isset($videoFormats[$f007[4]])) {
340
                $material = $videoFormats[$f007[4]]; // DVD, Blu-ray
341
            }
342
        } elseif ($material == 'Music') {
343
            if ($f007[0] == 't') {
344
                $material = 'Sheet music';
345
            } else {
346
                $material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material);
347
                if (array_get($ldr, 7) == 'a') {
348
                    $material .= ' track';
349
                }
350
            }
351
        } elseif ($material == 'Series') {
352
            switch ($f008[21]) {
353
354
                case 'm':
355
                    $material = 'Series';  // Monographic series (merk: skiller ikke mellom 'flerbindsverk' og 'serieinnførsel')
356
                    break;
357
358
                case 'n':
359
                    $material = 'Newspaper';
360
                    if ($f007[0] == 'h') {
361
                        $material .= ' on microform';
362
                    }
363
                    break;
364
365
                case 'p':
366
                    $material = 'Periodical';
367
                    break;
368
369
            }
370
            if (array_get($ldr, 7) == 'a') {
371
                $material = 'Article';
372
            }
373
        } elseif ($material == 'Book') {
374
            if (isset($natureOfContents[$f008[24]])) {
375
                // Slight simplification
376
                $material = $natureOfContents[$f008[24]];
377
            }
378
            if (array_get($ldr, 7) == 'a') {
379
                $material = 'Article';
380
                // or Article/Chapter ?
381
            }
382
        }
383
384
        $this->material = $material;
385
        $this->electronic = $online;
386
    }
387
388
    public function addClassification($node, &$classifications, $fields, $system = null, $edition = null, $assigner = null)
389
    {
390
        $cl = array('system' => $system, 'edition' => $edition, 'number' => null, 'assigner' => $assigner);
391
        foreach ($fields as $key => $val) {
392
            $t = $node->text('marc:subfield[@code="' . $key . '"]');
393
            if (!is_array($val)) {
394
                $val = array($val);
395
            }
396
            if (count($val) > 2) {
397
                $t = preg_replace('/' . $val[1] . '/', $val[2], $t);
398
            }
399
            if (!empty($t)) {
400
                $cl[$val[0]] = $t;
401
            }
402
        }
403
404
        if (is_null($cl['system'])) {
405
            return;
406
            // Invalid value in $a, should we trigger some event to allow logging?
407
        }
408
409
        if (is_null($cl['number'])) {
410
            return;
411
            // Invalid value in $a, should we trigger some event to allow logging?
412
        }
413
414
        $classifications[] = $cl;
415
    }
416
417
    /**
418
     * Parses common elements in subject added entry fields 600-655.
419
     *
420
     * @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $node
421
     *
422
     * @return array
423
     */
424
    public function parseSubjectAddedEntry(QuiteSimpleXmlElement &$node)
425
    {
426
        $out = array('term' => '', 'vocabulary' => null);
427
        $vocabularies = array(
428
            '0' => 'lcsh',
429
            '1' => 'lccsh', // LC subject headings for children's literature
430
            '2' => 'mesh', // Medical Subject Headings
431
            '3' => 'atg', // National Agricultural Library subject authority file (?)
432
            // 4 : unknown
433
            '5' => 'cash', // Canadian Subject Headings
434
            '6' => 'rvm', // Répertoire de vedettes-matière
435
            // 7: Source specified in subfield $2
436
        );
437
        $ind2 = $node->attr('ind2');
438
439
        $id = $node->text('marc:subfield[@code="0"]');
440
        $out['id'] = empty($id) ? null : $id;
441
442
        if (isset($vocabularies[$ind2])) {
443
            $out['vocabulary'] = $vocabularies[$ind2];
444
        } elseif ($ind2 == '7') {
445
            $vocab = $node->text('marc:subfield[@code="2"]');
446
            if (!empty($vocab)) {
447
                $out['vocabulary'] = $vocab;
448
            }
449
        } elseif ($ind2 == '4') {
450
            $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $out);
451
        }
452
453
        $out['parts'] = array();
454
        $subdivtypes = array(
455
            'v' => 'form',
456
            'x' => 'general',
457
            'y' => 'chronologic',
458
            'z' => 'geographic',
459
        );
460
        foreach ($node->all('marc:subfield') as $subdiv) {
461
            $code = $subdiv->attr('code');
462
            if (in_array($code, array_keys($subdivtypes))) {
463
                $subdiv = trim($subdiv, '.');
464
                $out['parts'][] = array('value' => $subdiv, 'type' => $subdivtypes[$code]);
465
                $out['term'] .= self::$subfieldSeparator . $subdiv;
466
            }
467
        }
468
469
        return $out;
470
    }
471
472
    /**
473
     * @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $data
474
     */
475
    public function __construct(QuiteSimpleXmlElement $data = null)
476
    {
477
        if (is_null($data)) {
478
            return;
479
        }
480
481
        $this->parseMaterial($data);
482
483
        // Control fields
484
        $this->id = $data->text('marc:controlfield[@tag="001"]');
485
486
        // 003: MARC code for the agency whose system control number is
487
        // contained in field 001 (Control Number)
488
        // See http://www.loc.gov/marc/authority/ecadorg.html
489
        $this->agency = $data->text('marc:controlfield[@tag="003"]');
490
491
        // 005: Modified
492
        $this->modified = $this->parseDateTime($data->text('marc:controlfield[@tag="005"]'));
493
494
        // 008: Extract *some* information
495
        $f008 = $data->text('marc:controlfield[@tag="008"]');
496
        $this->created = $this->parseDateTime(substr($f008, 0, 6));
497
        $this->language = substr($f008, 35, 3);
0 ignored issues
show
Documentation introduced by
The property language does not exist on object<Scriptotek\Simple...er\BibliographicRecord>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
498
499
        $creators = array();
500
        $meetings = array();
501
        $subjects = array();
502
        $genres = array();
503
        $classifications = array();
504
        $series = array();
505
        $notes = array();
506
        $isbns = array();
507
        $issns = array();
508
        $alternativeTitles = array();
509
510
        // Relationships
511
        $preceding = array();
512
        $succeeding = array();
513
        $part_of = array();
514
        $other_form = array();
515
516
        $this->is_series = false;
517
        $this->is_multivolume = false;
518
519
        foreach ($data->all('marc:datafield') as $node) {
520
            $marcfield = intval($node->attributes()->tag);
521
            switch ($marcfield) {
522
523
                // 010 - Library of Congress Control Number (NR)
524
                case 10:
525
                    $this->lccn = $node->text('marc:subfield[@code="a"]');
526
                    break;
527
528
                // 020 - International Standard Book Number (R)
529 View Code Duplication
                case 20:                                                            // Test added
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
530
                    $isbn = $node->text('marc:subfield[@code="a"]');
531
                    $isbn = preg_replace('/^([0-9\-xX]+).*$/', '\1', $isbn);
532
                    if (empty($isbn)) {
533
                        break;
534
                    }
535
                    array_push($isbns, $isbn);
536
                    break;
537
538
                // 022 - International Standard Serial Number (R)
539 View Code Duplication
                case 22:                                                            // Test added
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
540
                    $issn = $node->text('marc:subfield[@code="a"]');
541
                    $issn = preg_replace('/^([0-9\-xX]+).*$/', '\1', $issn);
542
                    if (empty($issn)) {
543
                        break;
544
                    }
545
                    array_push($issns, $issn);
546
                    break;
547
548
                // 040 - Cataloging Source (NR)
549
                case 40:                                                            // Test added
550
                    $x = $node->text('marc:subfield[@code="e"]');
551
                    if ($x) {
552
                        $this->catalogingRules = $x;
553
                    }
554
                    // Value from http://www.loc.gov/standards/sourcelist/descriptive-conventions.html
555
                    break;
556
557
                // 060 - National Library of Medicine Call Number (R)
558
                case 60:
559
                    $this->addClassification(
560
                        $node,
561
                        $classifications,
562
                        array(
563
                            'a' => 'number',
564
                        ),
565
                        $system = 'nlm',
566
                        $assigner = ($node->attr('ind2') == '0') ? 'DNLM' : null
567
                    );
568
                    break;
569
570
                // 080 - Universal Decimal Classification Number (R)
571 View Code Duplication
                case 80:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
572
                    $this->addClassification(
573
                        $node,
574
                        $classifications,
575
                        array(
576
                            'a' => array('number', '^.*?([0-9.\/:()]+).*$', '\1'),
577
                            '2' => 'edition',
578
                        ),
579
                        $system = 'udc'
580
                    );
581
                    break;
582
583
                // 082 - Dewey Decimal Classification Number (R)
584 View Code Duplication
                case 82:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
585
                    $this->addClassification(
586
                        $node,
587
                        $classifications,
588
                        array(
589
                            'a' => array('number', '^.*?([0-9.]+)\/?([0-9.]*).*$', '\1\2'),
590
                            '2' => 'edition',
591
                            'q' => 'assigner',
592
                        ),
593
                        $system = 'ddc'
594
                    );
595
                    break;
596
597
                // 084 - Other Classification Number (R)
598
                case 84:
599
                    $this->addClassification(
600
                        $node,
601
                        $classifications,
602
                        array(
603
                            'a' => 'number',
604
                            '2' => 'system',
605
                            'q' => 'assigner',
606
                        )
607
                    );
608
                    break;
609
610
                /*
611
                case 89:
612
                    if (!isset($this->klass)) $this->klass = array();
613
                    $klass = $node->text('marc:subfield[@code="a"]');
614
                    $klass = preg_replace('/[^0-9.]/', '', $klass);
615
                    foreach ($this->klass as $kitem) {
616
                        if (($kitem['kode'] == $klass) && ($kitem['system'] == 'dewey')) {
617
                            continue 3;
618
                        }
619
                    }
620
                    array_push($this->klass, array('kode' => $klass, 'system' => 'dewey'));
621
                    break;
622
                */
623
624
                case 100:
625
                    $author = array(
626
                        'name' => $node->text('marc:subfield[@code="a"]'),
627
                    );
628
                    $author['normalizedName'] = $author['name'];
629
                    $spl = explode(', ', $author['name']);
630 View Code Duplication
                    if (count($spl) == 2) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
                        $author['name'] = $spl[1] . ' ' . $spl[0];
632
                    }
633
                    $this->parseRelator($node, $author, 'main');
634
                    $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author);
635
636
                    $creators[] = $author;
637
                    break;
638
639
                case 110:
640
                    $author = array(
641
                        'name' => $node->text('marc:subfield[@code="a"]'),
642
                    );
643
                    $author['normalizedName'] = $author['name'];
644
                    foreach ($node->all('marc:subfield[@code="b"]') as $subunit) {
645
                        $author['name'] .= self::$subfieldSeparator . trim($subunit, ',');
646
                    }
647
                    $this->parseRelator($node, $author, 'corporate');
648
                    $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author);
649
650
                    $creators[] = $author;
651
                    break;
652
653 View Code Duplication
                case 111:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
654
                    $meeting = array(
655
                        'name' => $node->text('marc:subfield[@code="a"]'),
656
                    );
657
                    $meeting['normalizedName'] = $meeting['name'];
658
                    $this->parseRelator($node, $meeting, 'meeting');
659
                    $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $meeting);
660
661
                    $meetings[] = $meeting;
662
                    break;
663
664
                case 130:
665
                    // Uniform title
666
667
                    // TODO: Need a more robust way to prefer 130 over 245
668
                    //       Currently we depend on 130 coming before 245.
669
                    $this->title = $node->text('marc:subfield[@code="a"]');
670
                    break;
671
672
                // 245 : Title Statement (NR)
673
                case 245:
674
                    $title = $node->text('marc:subfield[@code="a"]') . ' ' . $node->text('marc:subfield[@code="b"]');
675
                    $title = rtrim($title, ' /');
676
677
                    $titleParts = preg_split('/(:|=)/', $title, -1, PREG_SPLIT_DELIM_CAPTURE);
678
                    $isbdCode = ':';
679
                    $title = '';
680
                    foreach ($titleParts as $titlePart) {
681
                        $titlePart = trim($titlePart);
682
                        if (is_null($isbdCode)) {
683
                            $isbdCode = $titlePart;
684
                        } else {
685
                            if ($isbdCode == '=') {
686
                                $alternativeTitles[] = $titlePart;
687
                            } else { // isbdCode == ':' or ';'
688
                                // TODO: Cover more cases explicitly?
689
                                //  http://www.loc.gov/marc/bibliographic/bd245.html
690
                                $title = empty($title) ? $titlePart : "$title $isbdCode $titlePart";
691
                            }
692
                            $isbdCode = null;
693
                        }
694
                    }
695
696
                    if (isset($this->title)) { // If not already set by 130
697
                        $alternativeTitles[] = $title;
698
                    } else {
699
                        $this->title = $title;
700
                    }
701
702
                    // $n : Number of part/section of a work (R)
703
                    $part_no = $node->text('marc:subfield[@code="n"]');
704
                    if ($part_no !== '') {
705
                        $this->part_no = $part_no;
706
                    }
707
708
                    // $p : Name of part/section of a work (R)
709
                    $part_name = $node->text('marc:subfield[@code="p"]');
710
                    if ($part_name !== '') {
711
                        $this->part_name = $part_name;
712
                    }
713
714
                    // $h : Medium (NR)
715
                    $medium = $node->text('marc:subfield[@code="h"]');
716
                    if ($medium !== '') {
717
                        $this->medium = $medium;
718
                    }
719
720
                    break;
721
722
                // 246 : Varying Form of Title (R)
723
                case 246:
724
                    // Note: The second indicator gives the type of title:
725
                    // 0 - Portion of title
726
                    // 1 - Parallel title
727
                    // 2 - Distinctive title
728
                    // 3 - Other title
729
                    // 4 - Cover title
730
                    // 5 - Added title page title
731
                    // 6 - Caption title
732
                    // 7 - Running title
733
                    // 8 - Spine title
734
                    $title = rtrim($node->text('marc:subfield[@code="a"]'), ' :-');
735
                    $subtitle = $node->text('marc:subfield[@code="b"]');
736
                    // TODO: Cover more of the cases on
737
                    //  http://www.loc.gov/marc/bibliographic/bd246.html
738
                    if (!empty($subtitle)) {
739
                        $title .= ' : ' . $subtitle;
740
                    }
741
                    $alternativeTitles[] = $title;
742
                    break;
743
744
                case 250:
745
                    $this->edition = $node->text('marc:subfield[@code="a"]');
746
                    break;
747
748
                case 260:
749
                    $this->placeOfPublication = $node->text('marc:subfield[@code="a"]');
750
                    $this->publisher = $node->text('marc:subfield[@code="b"]');
751
                    $y = preg_replace('/^.*?([0-9]{4}).*$/', '\1', $node->first('marc:subfield[@code="c"]'));
752
                    $this->year = $y ? intval($y) : null;
753
                    break;
754
755
                case 300:
756
                    $this->extent = $node->text('marc:subfield[@code="a"]');
757
758
                    # 2.5B2 "327 s.", 2.5B4 "48 [i.e. 96] s.", 2.5B7 "[93] s."
759
                    preg_match(
760
                        '/\[?([0-9]+)\]? (s.|p.|pp.)/',
761
                        $node->text('marc:subfield[@code="a"]'),
762
                        $matches
763
                    );
764
                    if ($matches) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matches of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
765
                        $this->pages = intval($matches[1]);
766
                    }
767
768
                    # 2.5B6 Eks: "s. 327-698" (flerbindsverk)
769
                    preg_match(
770
                        '/(s.|p.|pp.) ([0-9]+)-([0-9]+)/',
771
                        $node->text('marc:subfield[@code="a"]'),
772
                        $matches
773
                    );
774
                    if ($matches) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matches of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
775
                        $this->pages = intval($matches[3]) - intval($matches[2]) + 1;
776
                    }
777
                    break;
778
779
                /*
780
                case 490:
781
                    $serie = array(
782
                        'title' => $node->text('marc:subfield[@code="a"]'),
783
                        'volume' => $node->text('marc:subfield[@code="v"]')
784
                    );
785
                    $this->series[] = $serie;
786
                    break;
787
                */
788
789
                // 500 : General Note (R)
790
                case 500:
791
792
                    // $a - General note (NR)
793
                    $notes[] = $node->text('marc:subfield[@code="a"]');
794
                    break;
795
796
                // 502 : Dissertation Note (R)
797
                case 502:
798
799
                    // $a - Dissertation note (NR)
800
                    $notes[] = $node->text('marc:subfield[@code="a"]');
801
                    break;
802
803
                case 505:
804
805
                    // <datafield tag="520" ind1=" " ind2=" ">
806
                    //     <subfield code="a">"The conceptual changes brought by modern physics are important, radical and fascinating, yet they are only vaguely understood by people working outside the field. Exploring the four pillars of modern physics - relativity, quantum mechanics, elementary particles and cosmology - this clear and lively account will interest anyone who has wondered what Einstein, Bohr, Schro&#x308;dinger and Heisenberg were really talking about. The book discusses quarks and leptons, antiparticles and Feynman diagrams, curved space-time, the Big Bang and the expanding Universe. Suitable for undergraduate students in non-science as well as science subjects, it uses problems and worked examples to help readers develop an understanding of what recent advances in physics actually mean"--</subfield>
807
                    //     <subfield code="c">Provided by publisher.</subfield>
808
                    // </datafield>
809
                    $this->contents = $node->text('marc:subfield[@code="a"]');
810
                    break;
811
812
                case 520:
813
814
                    // <datafield tag="520" ind1=" " ind2=" ">
815
                    //     <subfield code="a">"The conceptual changes brought by modern physics are important, radical and fascinating, yet they are only vaguely understood by people working outside the field. Exploring the four pillars of modern physics - relativity, quantum mechanics, elementary particles and cosmology - this clear and lively account will interest anyone who has wondered what Einstein, Bohr, Schro&#x308;dinger and Heisenberg were really talking about. The book discusses quarks and leptons, antiparticles and Feynman diagrams, curved space-time, the Big Bang and the expanding Universe. Suitable for undergraduate students in non-science as well as science subjects, it uses problems and worked examples to help readers develop an understanding of what recent advances in physics actually mean"--</subfield>
816
                    //     <subfield code="c">Provided by publisher.</subfield>
817
                    // </datafield>
818
                    $this->summary = array(
819
                        'assigning_source' => $node->text('marc:subfield[@code="c"]'),
820
                        'text' => $node->text('marc:subfield[@code="a"]'),
821
                    );
822
                    break;
823
824
                // 580 : Complex Linking Note (R)
825
                case 580:
826
827
                    if ($data->has('marc:datafield[@tag="780"]')) {
828
                        $preceding['note'] = $node->text('marc:subfield[@code="a"]');
829
                    } elseif ($data->has('marc:datafield[@tag="785"]')) {
830
                        $succeeding['note'] = $node->text('marc:subfield[@code="a"]');
831
                    } elseif ($data->has('marc:datafield[@tag="773"]')) {
832
                        $part_of['note'] = $node->text('marc:subfield[@code="a"]');
833
                    }
834
                    break;
835
836
                case 600:
837
                    $tmp = $this->parseSubjectAddedEntry($node);
838
839
                    $name = $node->text('marc:subfield[@code="a"]');
840
                    $qualifiers = array();
841
                    $titles = $node->text('marc:subfield[@code="c"]');
842
                    if (!empty($titles)) {
843
                        $qualifiers[] = trim($titles, '(),.');
844
                    }
845
                    $dates = $node->text('marc:subfield[@code="d"]');
846
                    if (!empty($dates)) {
847
                        $qualifiers[] = trim($dates, '(),.');
848
                    }
849
850
                    // - To concat or not concat… not sure, but in principle
851
                    // the $a $c $d $q values should be the same on all
852
                    // records, so for filtering purposes it doesn't seem
853
                    // necessary to have them separated. For display
854
                    // purposes, it can be useful of course. But then again,
855
                    // the parts should be available from the authority
856
                    // register..
857
                    // - Another question is whether we should do some
858
                    // normalizing to try aligning records with different
859
                    // punctuation standards (US vs UK)
860
                    if (count($qualifiers) != 0) {
861
                        $name = "$name (" . implode(', ', $qualifiers) . ')';
862
                    }
863
                    $tmp['term'] = $name . $tmp['term'];
864
                    $tmp['type'] = 'person';
865
866
                    array_push($subjects, $tmp);
867
                    break;
868
869
                case 610:
870
                    $tmp = $this->parseSubjectAddedEntry($node);
871
872
                    $name = trim($node->text('marc:subfield[@code="a"]'), ',');
873
                    foreach ($node->all('marc:subfield[@code="b"]') as $subunit) {
874
                        $name .= self::$subfieldSeparator . trim($subunit, ',');
875
                    }
876
                    $tmp['type'] = 'corporation';
877
                    $tmp['term'] = $name . $tmp['term'];
878
                    array_push($subjects, $tmp);
879
                    break;
880
881
                case 611:
882
                    $tmp = $this->parseSubjectAddedEntry($node);
883
                    $dates = $node->text('marc:subfield[@code="d"]');
884
                    if (!empty($dates)) {
885
                        $tmp['time'] = trim($dates, ' :,.()');
886
                    }
887
                    $location = $node->text('marc:subfield[@code="c"]');
888
                    if (!empty($location)) {
889
                        $tmp['place'] = trim($location, ' :,.()');
890
                    }
891
                    $misc = $node->text('marc:subfield[@code="g"]');
892
                    if (!empty($misc)) {
893
                        $tmp['misc'] = trim($misc, ' :,.()');
894
                    }
895
                    $number = $node->text('marc:subfield[@code="n"]');
896
                    if (!empty($number)) {
897
                        $tmp['number'] = trim($number, ' :,.()');
898
                    }
899
900
                    $name = trim($node->text('marc:subfield[@code="a"]'), ',');
901
                    $tmp['type'] = 'meeting';
902
                    $tmp['term'] = $name . $tmp['term'];
903
                    array_push($subjects, $tmp);
904
                    break;
905
906 View Code Duplication
                case 648:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
907
                    $tmp = $this->parseSubjectAddedEntry($node);
908
909
                    $emne = $node->text('marc:subfield[@code="a"]');
910
                    $tmp['type'] = 'chronologic';
911
                    $tmp['term'] = trim($emne, '.') . $tmp['term'];
912
913
                    array_push($subjects, $tmp);
914
                    break;
915
916 View Code Duplication
                case 650:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
917
                    $tmp = $this->parseSubjectAddedEntry($node);
918
919
                    $emne = $node->text('marc:subfield[@code="a"]');
920
                    $tmp['term'] = trim($emne, '.') . $tmp['term'];
921
                    $tmp['type'] = 'topic';
922
923
                    array_push($subjects, $tmp);
924
                    break;
925
926 View Code Duplication
                case 651:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
927
                    $tmp = $this->parseSubjectAddedEntry($node);
928
929
                    $emne = $node->text('marc:subfield[@code="a"]');
930
                    $tmp['type'] = 'geographic';
931
                    $tmp['term'] = trim($emne, '.') . $tmp['term'];
932
933
                    array_push($subjects, $tmp);
934
                    break;
935
936
                case 653:
937
                    $tmp = array('type' => null, 'vocabulary' => null);
938
939
                    $ind2 = $node->attr('ind2');
940
                    $types = array(
941
                        '0' => 'topic',
942
                        '1' => 'person',
943
                        '2' => 'corporate',
944
                        '3' => 'meeting',
945
                        '4' => 'chronologic',
946
                        '5' => 'geographic',
947
                        '6' => 'genre',
948
                    );
949
                    if (isset($types[$ind2])) {
950
                        $tmp['type'] = $types[$ind2];
951
                    }
952
953
                    foreach ($node->all('marc:subfield[@code="a"]') as $emne) {
954
                        $tmp['term'] = trim($emne, '.');
955
                        if ($tmp['type'] == 'genre') {
956
                            unset($tmp['type']);
957
                            array_push($genres, $tmp);
958
                        } else {
959
                            array_push($subjects, $tmp);
960
                        }
961
                    }
962
963
                    break;
964
965
                case 655:
966
967
                    $tmp = $this->parseSubjectAddedEntry($node);
968
                    $tmp['term'] = trim($node->text('marc:subfield[@code="a"]'), '.') . $tmp['term'];
969
970
                    array_push($genres, $tmp);
971
                    break;
972
973
                case 700:
974
                    $author = array(
975
                        'name' => $node->text('marc:subfield[@code="a"]'),
976
                    );
977
                    $author['normalizedName'] = $author['name'];
978
                    $spl = explode(', ', $author['name']);
979 View Code Duplication
                    if (count($spl) == 2) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
980
                        $author['name'] = $spl[1] . ' ' . $spl[0];
981
                    }
982
983
                    $this->parseRelator($node, $author, 'added');
984
                    $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author);
985
986
                    $dates = $node->text('marc:subfield[@code="d"]');
987
                    if (!empty($dates)) {
988
                        $author['dates'] = $dates;
989
                    }
990
991
                    $creators[] = $author;
992
                    break;
993
994 View Code Duplication
                case 710:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
995
                    $author = array(
996
                        'name' => $node->text('marc:subfield[@code="a"]'),
997
                    );
998
                    $author['normalizedName'] = $author['name'];
999
1000
                    $this->parseRelator($node, $author, 'added_corporate');
1001
                    $this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author);
1002
1003
                    $creators[] = $author;
1004
                    break;
1005
1006
                // 773 : Host Item Entry (R)
1007
                // See also: 580
1008
                case 773:
1009
                    $part_of = isset($part_of) ? $part_of : array();
1010
                    $part_of['relationship'] = $node->text('marc:subfield[@code="i"]');
1011
                    $part_of['title'] = $node->text('marc:subfield[@code="t"]');
1012
                    $part_of['issn'] = $node->text('marc:subfield[@code="x"]') ?: null;
1013
                    $part_of['isbn'] = $node->text('marc:subfield[@code="z"]') ?: null;
1014
                    $part_of['volume'] = $node->text('marc:subfield[@code="v"]') ?: null;
1015
                    $this->parseAuthority($node->text('marc:subfield[@code="w"]'), $part_of);
1016
1017
                    break;
1018
1019
                // 776 : Additional Physical Form Entry (R)
1020
                case 776:
1021
                        // <marc:datafield tag="776" ind1="0" ind2=" ">
1022
                        //     <marc:subfield code="z">9781107602175</marc:subfield>
1023
                        //     <marc:subfield code="w">(NO-TrBIB)132191512</marc:subfield>
1024
                        // </marc:datafield>
1025
                    $other_form = $this->parseRelationship($node);
1026
                    break;
1027
1028
                // 780 : Preceding Entry (R)
1029
                // Information concerning the immediate predecessor of the target item
1030
                case 780:
1031
                    // <marc:datafield tag="780" ind1="0" ind2="0">
1032
                    //     <marc:subfield code="w">(NO-TrBIB)920713874</marc:subfield>
1033
                    //     <marc:subfield code="g">nr 80(1961)</marc:subfield>
1034
                    // </marc:datafield>
1035
1036
                    if (!isset($preceding['items'])) {
1037
                        $preceding['items'] = array();
1038
                    }
1039
                    $preceding['items'][] = $this->parseRelationship($node);
1040
1041
                    $ind2 = $node->attr('ind2');
1042
                    $relationship_types = array(
1043
                        '0' => 'Continues',
1044
                        '1' => 'Continues in part',
1045
                        '2' => 'Supersedes',
1046
                        '3' => 'Supersedes in part',
1047
                        '4' => 'Formed by the union of',  // ... and ...',
1048
                        '5' => 'Absorbed',
1049
                        '6' => 'Absorbed in part',
1050
                        '7' => 'Separated from',
1051
                    );
1052
                    if (isset($relationship_types[$ind2])) {
1053
                        $preceding['relationship_type'] = $relationship_types[$ind2];
1054
                    }
1055
1056
                    break;
1057
1058
                // 785 : Succeeding Entry (R)
1059
                // Information concerning the immediate successor to the target item
1060
                case 785:
1061
                    // <marc:datafield tag="785" ind1="0" ind2="0">
1062
                    //     <marc:subfield code="w">(NO-TrBIB)920713874</marc:subfield>
1063
                    //     <marc:subfield code="g">nr 80(1961)</marc:subfield>
1064
                    // </marc:datafield>
1065
1066
                    if (!isset($succeeding['items'])) {
1067
                        $succeeding['items'] = array();
1068
                    }
1069
                    $succeeding['items'][] = $this->parseRelationship($node);
1070
1071
                    $ind2 = $node->attr('ind2');
1072
                    $relationship_types = array(
1073
                        '0' => 'Continued by',
1074
                        '1' => 'Continued in part by',
1075
                        '2' => 'Superseded by',
1076
                        '3' => 'Superseded in part by',
1077
                        '4' => 'Absorbed by',
1078
                        '5' => 'Absorbed in part by',
1079
                        '6' => 'Split into',  // ... and ...',
1080
                        '7' => 'Continued by', // more precisely 'Merged with ... to form ...', but we simplify slightly
1081
                        '8' => 'Changed back to',
1082
                    );
1083
1084
                    if ($ind2 == '7') {
1085
                        // The first elements are the documents that go into the merge,
1086
                        // we are not interested in those due to our slight simplification.
1087
                        $succeeding['items'] = array(array_pop($succeeding['items']));
1088
                    }
1089
1090
                    if (isset($relationship_types[$ind2])) {
1091
                        $succeeding['relationship_type'] = $relationship_types[$ind2];
1092
                    }
1093
                    break;
1094
1095
                // 830 : Series Added Entry – Uniform Title (R)
1096
                case 830:
1097
                    $serie = array(
1098
                        'title' => $node->text('marc:subfield[@code="a"]'),
1099
                        'id' => preg_replace('/\(NO-TrBIB\)/', '', $node->text('marc:subfield[@code="w"]')) ?: null,
1100
                        'volume' => $node->text('marc:subfield[@code="v"]') ?: null,
1101
                    );
1102
                    $series[] = $serie;
1103
                    break;
1104
1105
                case 856:
1106
                case 956:
1107
                    # MARC 21 uses field 856 for electronic "links", where you can have URLs for example covers images and/or blurbs.
1108
                    # 956 ?
1109
1110
                        // <marc:datafield tag="856" ind1="4" ind2="2">
1111
                        //     <marc:subfield code="3">Beskrivelse fra forlaget (kort)</marc:subfield>
1112
                        //     <marc:subfield code="u">http://content.bibsys.no/content/?type=descr_publ_brief&amp;isbn=0521176832</marc:subfield>
1113
                        // </marc:datafield>
1114
                        // <marc:datafield tag="956" ind1="4" ind2="2">
1115
                        //     <marc:subfield code="3">Omslagsbilde</marc:subfield>
1116
                        //     <marc:subfield code="u">http://innhold.bibsys.no/bilde/forside/?size=mini&amp;id=9780521176835.jpg</marc:subfield>
1117
                        //     <marc:subfield code="q">image/jpeg</marc:subfield>
1118
                        // </marc:datafield>
1119
                    $description = $node->text('marc:subfield[@code="3"]');
1120
                    if (in_array($description, array('Cover image', 'Omslagsbilde'))) {
1121
                        $this->cover_image = $node->text('marc:subfield[@code="u"]');
1122
1123
                        // Silly hack to get larger images from Bibsys:
1124
                        $this->cover_image = str_replace('mini', 'stor', $this->cover_image);
1125
                        $this->cover_image = str_replace('LITE', 'STOR', $this->cover_image);
1126
                    }
1127
                    if (in_array($description, array('Beskrivelse fra forlaget (kort)', 'Beskrivelse fra forlaget (lang)'))) {
1128
                        $this->description = $node->text('marc:subfield[@code="u"]');
1129
                    }
1130
                    break;
1131
1132
                // 991 Kriterium für Sekundärsortierung (R) ???
1133
                // Ref: http://ead.nb.admin.ch/web/marc21/dmarcb991.pdf
1134
                // Hvor i BIBSYSMARC kommer dette fra?
1135
                case 991:
1136
1137
                    // Multi-volume work (flerbindsverk), parts linked through 773 w
1138
                    if ($node->text('marc:subfield[@code="a"]') == 'volumes') {
1139
                        $this->is_multivolume = true;
1140
                    }
1141
1142
                    // Series (serier), parts linked through 830 w
1143
                    if ($node->text('marc:subfield[@code="a"]') == 'parts') {
1144
                        $this->is_series = true;
1145
                    }
1146
1147
                    break;
1148
1149
            }
1150
        }
1151
1152
        if (!empty($preceding)) {
1153
            $this->preceding = $preceding;
1154
        }
1155
        if (!empty($succeeding)) {
1156
            $this->succeeding = $succeeding;
1157
        }
1158
        if (count($part_of)) {
1159
            $this->part_of = $part_of;
1160
        }
1161
        if (!empty($other_form)) {
1162
            $this->other_form = $other_form;
1163
        }
1164
1165
        $this->alternativeTitles = array_unique($alternativeTitles);
1166
        $this->isbns = $isbns;
1167
        $this->issns = $issns;
1168
        $this->series = $series;
1169
        $this->creators = $creators;
1170
        $this->meetings = $meetings;
1171
        $this->subjects = $subjects;
1172
        $this->genres = $genres;
1173
        $this->classifications = $classifications;
1174
        $this->notes = $notes;
1175
    }
1176
}
1177