Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( b811c3...b34a1c )
by Sebastian
19s
created

tx_dlf_document::getPhysicalPage()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 28
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 4
nop 1
dl 0
loc 28
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
4
 *
5
 * This file is part of the Kitodo and TYPO3 projects.
6
 *
7
 * @license GNU General Public License version 3 or later.
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
/**
13
 * Document class 'tx_dlf_document' for the 'dlf' extension.
14
 *
15
 * @author	Sebastian Meyer <[email protected]>
16
 * @author	Henrik Lochmann <[email protected]>
17
 * @package	TYPO3
18
 * @subpackage	tx_dlf
19
 * @access	public
20
 */
21
final class tx_dlf_document {
22
23
	/**
24
	 * This holds the whole XML file as string for serialization purposes
25
	 * @see __sleep() / __wakeup()
26
	 *
27
	 * @var	string
28
	 * @access protected
29
	 */
30
	protected $asXML = '';
31
32
	/**
33
	 * This holds the PID for the configuration
34
	 *
35
	 * @var	integer
36
	 * @access protected
37
	 */
38
	protected $cPid = 0;
39
40
	/**
41
	 * This holds the XML file's dmdSec parts with their IDs as array key
42
	 *
43
	 * @var	array
44
	 * @access protected
45
	 */
46
	protected $dmdSec = array ();
47
48
	/**
49
	 * Are the METS file's dmdSecs loaded?
50
	 * @see $dmdSec
51
	 *
52
	 * @var	boolean
53
	 * @access protected
54
	 */
55
	protected $dmdSecLoaded = FALSE;
56
57
	/**
58
	 * The extension key
59
	 *
60
	 * @var	string
61
	 * @access public
62
	 */
63
	public static $extKey = 'dlf';
64
65
	/**
66
	 * This holds the file ID -> USE concordance
67
	 * @see _getFileGrps()
68
	 *
69
	 * @var	array
70
	 * @access protected
71
	 */
72
	protected $fileGrps = array ();
73
74
	/**
75
	 * Are the file groups loaded?
76
	 * @see $fileGrps
77
	 *
78
	 * @var	boolean
79
	 * @access protected
80
	 */
81
	protected $fileGrpsLoaded = FALSE;
82
83
	/**
84
	 * This holds the configuration for all supported metadata encodings
85
	 * @see loadFormats()
86
	 *
87
	 * @var	array
88
	 * @access protected
89
	 */
90
	protected $formats = array (
91
		'METS' => array (
92
			'rootElement' => 'mets',
93
			'namespaceURI' => 'http://www.loc.gov/METS/',
94
		),
95
		'XLINK' => array (
96
			'rootElement' => 'xlink',
97
			'namespaceURI' => 'http://www.w3.org/1999/xlink',
98
		)
99
	);
100
101
	/**
102
	 * Are the available metadata formats loaded?
103
	 * @see $formats
104
	 *
105
	 * @var	boolean
106
	 * @access protected
107
	 */
108
	protected $formatsLoaded = FALSE;
109
110
	/**
111
	 * Are there any fulltext files available?
112
	 *
113
	 * @var boolean
114
	 * @access protected
115
	 */
116
	protected $hasFulltext = FALSE;
117
118
	/**
119
	 * Last searched logical and physical page
120
	 *
121
	 * @var	array
122
	 * @access protected
123
	 */
124
	protected $lastSearchedPhysicalPage = array ('logicalPage' => NULL, 'physicalPage' => NULL);
125
126
	/**
127
	 * This holds the documents location
128
	 *
129
	 * @var	string
130
	 * @access protected
131
	 */
132
	protected $location = '';
133
134
	/**
135
	 * This holds the logical units
136
	 *
137
	 * @var	array
138
	 * @access protected
139
	 */
140
	protected $logicalUnits = array ();
141
142
	/**
143
	 * This holds the documents' parsed metadata array with their corresponding structMap//div's ID as array key
144
	 *
145
	 * @var	array
146
	 * @access protected
147
	 */
148
	protected $metadataArray = array ();
149
150
	/**
151
	 * Is the metadata array loaded?
152
	 * @see $metadataArray
153
	 *
154
	 * @var	boolean
155
	 * @access protected
156
	 */
157
	protected $metadataArrayLoaded = FALSE;
158
159
	/**
160
	 * This holds the XML file's METS part as SimpleXMLElement object
161
	 *
162
	 * @var	SimpleXMLElement
163
	 * @access protected
164
	 */
165
	protected $mets;
166
167
	/**
168
	 * The holds the total number of pages
169
	 *
170
	 * @var	integer
171
	 * @access protected
172
	 */
173
	protected $numPages = 0;
174
175
	/**
176
	 * This holds the UID of the parent document or zero if not multi-volumed
177
	 *
178
	 * @var	integer
179
	 * @access protected
180
	 */
181
	protected $parentId = 0;
182
183
	/**
184
	 * This holds the physical structure
185
	 *
186
	 * @var	array
187
	 * @access protected
188
	 */
189
	protected $physicalStructure = array ();
190
191
	/**
192
	 * This holds the physical structure metadata
193
	 *
194
	 * @var	array
195
	 * @access protected
196
	 */
197
	protected $physicalStructureInfo = array ();
198
199
	/**
200
	 * Is the physical structure loaded?
201
	 * @see $physicalStructure
202
	 *
203
	 * @var	boolean
204
	 * @access protected
205
	 */
206
	protected $physicalStructureLoaded = FALSE;
207
208
	/**
209
	 * This holds the PID of the document or zero if not in database
210
	 *
211
	 * @var	integer
212
	 * @access protected
213
	 */
214
	protected $pid = 0;
215
216
	/**
217
	 * Is the document instantiated successfully?
218
	 *
219
	 * @var	boolean
220
	 * @access protected
221
	 */
222
	protected $ready = FALSE;
223
224
	/**
225
	 * The METS file's record identifier
226
	 *
227
	 * @var	string
228
	 * @access protected
229
	 */
230
	protected $recordId;
231
232
	/**
233
	 * This holds the singleton object of the document
234
	 *
235
	 * @var	array (tx_dlf_document)
236
	 * @access protected
237
	 */
238
	protected static $registry = array ();
239
240
	/**
241
	 * This holds the UID of the root document or zero if not multi-volumed
242
	 *
243
	 * @var	integer
244
	 * @access protected
245
	 */
246
	protected $rootId = 0;
247
248
	/**
249
	 * Is the root id loaded?
250
	 * @see $rootId
251
	 *
252
	 * @var	boolean
253
	 * @access protected
254
	 */
255
	protected $rootIdLoaded = FALSE;
256
257
	/**
258
	 * This holds the smLinks between logical and physical structMap
259
	 *
260
	 * @var	array
261
	 * @access protected
262
	 */
263
	protected $smLinks = array ('l2p' => array (), 'p2l' => array ());
264
265
	/**
266
	 * Are the smLinks loaded?
267
	 * @see $smLinks
268
	 *
269
	 * @var	boolean
270
	 * @access protected
271
	 */
272
	protected $smLinksLoaded = FALSE;
273
274
	/**
275
	 * This holds the logical structure
276
	 *
277
	 * @var	array
278
	 * @access protected
279
	 */
280
	protected $tableOfContents = array ();
281
282
	/**
283
	 * Is the table of contents loaded?
284
	 * @see $tableOfContents
285
	 *
286
	 * @var	boolean
287
	 * @access protected
288
	 */
289
	protected $tableOfContentsLoaded = FALSE;
290
291
	/**
292
	 * This holds the document's thumbnail location.
293
	 *
294
	 * @var	string
295
	 * @access protected
296
	 */
297
	protected $thumbnail = '';
298
299
	/**
300
	 * Is the document's thumbnail location loaded?
301
	 * @see $thumbnail
302
	 *
303
	 * @var	boolean
304
	 * @access protected
305
	 */
306
	protected $thumbnailLoaded = FALSE;
307
308
	/**
309
	 * This holds the toplevel structure's @ID
310
	 *
311
	 * @var	string
312
	 * @access protected
313
	 */
314
	protected $toplevelId = '';
315
316
	/**
317
	 * This holds the UID or the URL of the document
318
	 *
319
	 * @var	mixed
320
	 * @access protected
321
	 */
322
	protected $uid = 0;
323
324
	/**
325
	 * This holds the whole XML file as SimpleXMLElement object
326
	 *
327
	 * @var	SimpleXMLElement
328
	 * @access protected
329
	 */
330
	protected $xml;
331
332
	/**
333
	 * This clears the static registry to prevent memory exhaustion
334
	 *
335
	 * @access	public
336
	 *
337
	 * @return	void
338
	 */
339
	public static function clearRegistry() {
340
341
		// Reset registry array.
342
		self::$registry = array ();
343
344
	}
345
346
	/**
347
	 * This gets the location of a file representing a physical page or track
348
	 *
349
	 * @access	public
350
	 *
351
	 * @param	string		$id: The @ID attribute of the file node
352
	 *
353
	 * @return	string		The file's location as URL
354
	 */
355 View Code Duplication
	public function getFileLocation($id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
356
357
		if (!empty($id) && ($location = $this->mets->xpath('./mets:fileSec/mets:fileGrp/mets:file[@ID="'.$id.'"]/mets:FLocat[@LOCTYPE="URL"]'))) {
358
359
			return (string) $location[0]->attributes('http://www.w3.org/1999/xlink')->href;
360
361
		} else {
362
363
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
364
365
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getFileLocation('.$id.')] There is no file node with @ID "'.$id.'"', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\GeneralUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
366
367
			}
368
369
			return '';
370
371
		}
372
373
	}
374
375
	/**
376
	 * This gets the MIME type of a file representing a physical page or track
377
	 *
378
	 * @access	public
379
	 *
380
	 * @param	string		$id: The @ID attribute of the file node
381
	 *
382
	 * @return	string		The file's MIME type
383
	 */
384 View Code Duplication
	public function getFileMimeType($id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
385
386
		if (!empty($id) && ($mimetype = $this->mets->xpath('./mets:fileSec/mets:fileGrp/mets:file[@ID="'.$id.'"]/@MIMETYPE'))) {
387
388
			return (string) $mimetype[0];
389
390
		} else {
391
392
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
393
394
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getFileMimeType('.$id.')] There is no file node with @ID "'.$id.'" or no MIME type specified', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
395
396
			}
397
398
			return '';
399
400
		}
401
402
	}
403
404
	/**
405
	 * This is a singleton class, thus an instance must be created by this method
406
	 *
407
	 * @access	public
408
	 *
409
	 * @param	mixed		$uid: The unique identifier of the document to parse or URL of XML file
410
	 * @param	integer		$pid: If > 0, then only document with this PID gets loaded
411
	 * @param	boolean		$forceReload: Force reloading the document instead of returning the cached instance
412
	 *
413
	 * @return	&tx_dlf_document		Instance of this class
414
	 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment &tx_dlf_document at position 0 could not be parsed: Unknown type name '&' at position 0 in &tx_dlf_document.
Loading history...
415
	public static function &getInstance($uid, $pid = 0, $forceReload = FALSE) {
416
417
		// Sanitize input.
418
		$pid = max(intval($pid), 0);
419
420
		if (!$forceReload) {
421
422
			$regObj = md5($uid);
423
424
			if (is_object(self::$registry[$regObj]) && self::$registry[$regObj] instanceof self) {
425
426
				// Check if instance has given PID.
427
				if (!$pid || !self::$registry[$regObj]->pid || $pid == self::$registry[$regObj]->pid) {
428
429
					// Return singleton instance if available.
430
					return self::$registry[$regObj];
431
432
				}
433
434
			} else {
435
436
				// Check the user's session...
437
				$sessionData = tx_dlf_helper::loadFromSession(get_called_class());
438
439
				if (is_object($sessionData[$regObj]) && $sessionData[$regObj] instanceof self) {
440
441
					// Check if instance has given PID.
442
					if (!$pid || !$sessionData[$regObj]->pid || $pid == $sessionData[$regObj]->pid) {
443
444
						// ...and restore registry.
445
						self::$registry[$regObj] = $sessionData[$regObj];
446
447
						return self::$registry[$regObj];
448
449
					}
450
451
				}
452
453
			}
454
455
		}
456
457
		// Create new instance...
458
		$instance = new self($uid, $pid);
459
460
		// ...and save it to registry.
461
		if ($instance->ready) {
462
463
			self::$registry[md5($instance->uid)] = $instance;
464
465
			if ($instance->uid != $instance->location) {
466
467
				self::$registry[md5($instance->location)] = $instance;
468
469
			}
470
471
			// Load extension configuration
472
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
473
474
			// Save registry to session if caching is enabled.
475
			if (!empty($extConf['caching'])) {
476
477
				tx_dlf_helper::saveToSession(self::$registry, get_class($instance));
478
479
			}
480
481
		}
482
483
		// Return new instance.
484
		return $instance;
485
486
	}
487
488
	/**
489
	 * This gets details about a logical structure element
490
	 *
491
	 * @access	public
492
	 *
493
	 * @param	string		$id: The @ID attribute of the logical structure node
494
	 * @param	boolean		$recursive: Whether to include the child elements
495
	 *
496
	 * @return	array		Array of the element's id, label, type and physical page indexes/mptr link
497
	 */
498
	public function getLogicalStructure($id, $recursive = FALSE) {
499
500
		$details = array ();
501
502
		// Is the requested logical unit already loaded?
503
		if (!$recursive && !empty($this->logicalUnits[$id])) {
504
505
			// Yes. Return it.
506
			return $this->logicalUnits[$id];
507
508
		} elseif (!empty($id)) {
509
510
			// Get specified logical unit.
511
			$divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]');
512
513
		} else {
514
515
			// Get all logical units at top level.
516
			$divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]/mets:div');
517
518
		}
519
520
		if (!empty($divs)) {
521
522
			if (!$recursive) {
523
524
				// Get the details for the first xpath hit.
525
				$details = $this->getLogicalStructureInfo($divs[0]);
526
527
			} else {
528
529
				// Walk the logical structure recursively and fill the whole table of contents.
530
				foreach ($divs as $div) {
531
532
					$this->tableOfContents[] = $this->getLogicalStructureInfo($div, TRUE);
533
534
				}
535
536
			}
537
538
		}
539
540
		return $details;
541
542
	}
543
544
	/**
545
	 * This gets details about a logical structure element
546
	 *
547
	 * @access	protected
548
	 *
549
	 * @param	SimpleXMLElement		$structure: The logical structure node
550
	 * @param	boolean		$recursive: Whether to include the child elements
551
	 *
552
	 * @return	array		Array of the element's id, label, type and physical page indexes/mptr link
553
	 */
554
	protected function getLogicalStructureInfo(SimpleXMLElement $structure, $recursive = FALSE) {
555
556
		// Get attributes.
557
		foreach ($structure->attributes() as $attribute => $value) {
558
559
			$attributes[$attribute] = (string) $value;
560
561
		}
562
563
		// Load plugin configuration.
564
		$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
565
566
		// Extract identity information.
567
		$details = array ();
568
569
		$details['id'] = $attributes['ID'];
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $attributes seems to be defined by a foreach iteration on line 557. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
570
571
		$details['dmdId'] = (isset($attributes['DMDID']) ?  $attributes['DMDID'] : '');
572
573
		$details['label'] = (isset($attributes['LABEL']) ? $attributes['LABEL'] : '');
574
575
		$details['orderlabel'] = (isset($attributes['ORDERLABEL']) ? $attributes['ORDERLABEL'] : '');
576
577
		$details['contentIds'] = (isset($attributes['CONTENTIDS']) ? $attributes['CONTENTIDS'] : '');
578
579
		$details['volume'] = '';
580
581
		// Set volume information only if no label is set and this is the toplevel structure element.
582
		if (empty($details['label']) && $details['id'] == $this->_getToplevelId()) {
583
584
			$metadata = $this->getMetadata($details['id']);
585
586 View Code Duplication
			if (!empty($metadata['volume'][0])) {
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...
587
588
				$details['volume'] = $metadata['volume'][0];
589
590
			}
591
592
		}
593
594
		$details['pagination'] = '';
595
596
		$details['type'] = $attributes['TYPE'];
597
598
		$details['thumbnailId'] = '';
599
600
		// Load smLinks.
601
		$this->_getSmLinks();
602
603
		// Load physical structure.
604
		$this->_getPhysicalStructure();
605
606
		// Get the physical page or external file this structure element is pointing at.
607
		$details['points'] = '';
608
609
		// Is there a mptr node?
610
		if (count($structure->children('http://www.loc.gov/METS/')->mptr)) {
611
612
			// Yes. Get the file reference.
613
			$details['points'] = (string) $structure->children('http://www.loc.gov/METS/')->mptr[0]->attributes('http://www.w3.org/1999/xlink')->href;
614
615
		// Are there any physical elements and is this logical unit linked to at least one of them?
616
		} elseif (!empty($this->physicalStructure) && array_key_exists($details['id'], $this->smLinks['l2p'])) {
617
618
			$details['points'] = max(intval(array_search($this->smLinks['l2p'][$details['id']][0], $this->physicalStructure, TRUE)), 1);
619
620
			if (!empty($this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['files'][$extConf['fileGrpThumbs']])) {
621
622
				$details['thumbnailId'] = $this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['files'][$extConf['fileGrpThumbs']];
623
624
			}
625
626
			// Get page/track number of the first page/track related to this structure element.
627
			$details['pagination'] = $this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['orderlabel'];
628
629
		// Is this the toplevel structure element?
630
		} elseif ($details['id'] == $this->_getToplevelId()) {
631
632
			// Yes. Point to itself.
633
			$details['points'] = 1;
634
635
			if (!empty($this->physicalStructure) && !empty($this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']])) {
636
637
				$details['thumbnailId'] = $this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']];
638
639
			}
640
641
		}
642
643
		// Get the files this structure element is pointing at.
644
		$details['files'] = array ();
645
646
		$fileUse = $this->_getFileGrps();
647
648
		// Get the file representations from fileSec node.
649
		foreach ($structure->children('http://www.loc.gov/METS/')->fptr as $fptr) {
650
651
			// Check if file has valid @USE attribute.
652
			if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
653
654
				$details['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
655
656
			}
657
658
		}
659
660
		// Keep for later usage.
661
		$this->logicalUnits[$details['id']] = $details;
662
663
		// Walk the structure recursively? And are there any children of the current element?
664
		if ($recursive && count($structure->children('http://www.loc.gov/METS/')->div)) {
665
666
			$details['children'] = array ();
667
668
			foreach ($structure->children('http://www.loc.gov/METS/')->div as $child) {
669
670
				// Repeat for all children.
671
				$details['children'][] = $this->getLogicalStructureInfo($child, TRUE);
672
673
			}
674
675
		}
676
677
		return $details;
678
679
	}
680
681
	/**
682
	 * This extracts all the metadata for a logical structure node
683
	 *
684
	 * @access	public
685
	 *
686
	 * @param	string		$id: The @ID attribute of the logical structure node
687
	 * @param	integer		$cPid: The PID for the metadata definitions
688
	 * 						(defaults to $this->cPid or $this->pid)
689
	 *
690
	 * @return	array		The logical structure node's parsed metadata array
691
	 */
692
	public function getMetadata($id, $cPid = 0) {
693
694
		// Save parameter for logging purposes.
695
		$_cPid = $cPid;
696
697
		// Make sure $cPid is a non-negative integer.
698
		$cPid = max(intval($cPid), 0);
699
700
		// If $cPid is not given, try to get it elsewhere.
701
		if (!$cPid && ($this->cPid || $this->pid)) {
702
703
			// Retain current PID.
704
			$cPid = ($this->cPid ? $this->cPid : $this->pid);
705
706
		} elseif (!$cPid) {
707
708
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
709
710
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getMetadata('.$id.', '.$_cPid.')] Invalid PID "'.$cPid.'" for metadata definitions', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
711
712
			}
713
714
			return array ();
715
716
		}
717
718
		// Get metadata from parsed metadata array if available.
719
		if (!empty($this->metadataArray[$id]) && $this->metadataArray[0] == $cPid) {
720
721
			return $this->metadataArray[$id];
722
723
		}
724
725
		// Initialize metadata array with empty values.
726
		$metadata = array (
727
			'title' => array (),
728
			'title_sorting' => array (),
729
			'author' => array (),
730
			'place' => array (),
731
			'year' => array (),
732
			'prod_id' => array (),
733
			'record_id' => array (),
734
			'opac_id' => array (),
735
			'union_id' => array (),
736
			'urn' => array (),
737
			'purl' => array (),
738
			'type' => array (),
739
			'volume' => array (),
740
			'volume_sorting' => array (),
741
			'collection' => array (),
742
			'owner' => array (),
743
		);
744
745
		// Get the logical structure node's DMDID.
746
		if (!empty($this->logicalUnits[$id])) {
747
748
			$dmdId = $this->logicalUnits[$id]['dmdId'];
749
750
		} else {
751
752
			$dmdId = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]/@DMDID');
753
754
			$dmdId = (string) $dmdId[0];
755
756
		}
757
758
		if (!empty($dmdId)) {
759
760
			// Load available metadata formats and dmdSecs.
761
			$this->loadFormats();
762
763
			$this->_getDmdSec();
764
765
			// Is this metadata format supported?
766
			if (!empty($this->formats[$this->dmdSec[$dmdId]['type']])) {
767
768
				if (!empty($this->formats[$this->dmdSec[$dmdId]['type']]['class'])) {
769
770
					$class = $this->formats[$this->dmdSec[$dmdId]['type']]['class'];
771
772
					// Get the metadata from class.
773
					if (class_exists($class) && ($obj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($class)) instanceof tx_dlf_format) {
774
775
						$obj->extractMetadata($this->dmdSec[$dmdId]['xml'], $metadata);
776
777 View Code Duplication
					} else {
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...
778
779
						if (TYPO3_DLOG) {
780
781
							\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getMetadata('.$id.', '.$_cPid.')] Invalid class/method "'.$class.'->extractMetadata()" for metadata format "'.$this->dmdSec[$dmdId]['type'].'"', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
782
783
						}
784
785
					}
786
787
				}
788
789 View Code Duplication
			} else {
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...
790
791
				if (TYPO3_DLOG) {
792
793
					\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getMetadata('.$id.', '.$_cPid.')] Unsupported metadata format "'.$this->dmdSec[$dmdId]['type'].'" in dmdSec with @ID "'.$dmdId.'"', self::$extKey, SYSLOG_SEVERITY_WARNING);
794
795
				}
796
797
				return array ();
798
799
			}
800
801
			// Get the structure's type.
802
			if (!empty($this->logicalUnits[$id])) {
803
804
				$metadata['type'] = array ($this->logicalUnits[$id]['type']);
805
806
			} else {
807
808
				$struct = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]/@TYPE');
809
810
				$metadata['type'] = array ((string) $struct[0]);
811
812
			}
813
814
			// Get the additional metadata from database.
815
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
816
				'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadataformat.xpath AS xpath,tx_dlf_metadataformat.xpath_sorting AS xpath_sorting,tx_dlf_metadata.is_sortable AS is_sortable,tx_dlf_metadata.default_value AS default_value,tx_dlf_metadata.format AS format',
817
				'tx_dlf_metadata,tx_dlf_metadataformat,tx_dlf_formats',
818
				'tx_dlf_metadata.pid='.$cPid.' AND tx_dlf_metadataformat.pid='.$cPid.' AND ((tx_dlf_metadata.uid=tx_dlf_metadataformat.parent_id AND tx_dlf_metadataformat.encoded=tx_dlf_formats.uid AND tx_dlf_formats.type='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->dmdSec[$dmdId]['type'], 'tx_dlf_formats').') OR tx_dlf_metadata.format=0)'.tx_dlf_helper::whereClause('tx_dlf_metadata', TRUE).tx_dlf_helper::whereClause('tx_dlf_metadataformat').tx_dlf_helper::whereClause('tx_dlf_formats'),
819
				'',
820
				'',
821
				''
822
			);
823
824
			// We need a DOMDocument here, because SimpleXML doesn't support XPath functions properly.
825
			$domNode = dom_import_simplexml($this->dmdSec[$dmdId]['xml']);
826
827
			$domXPath = new DOMXPath($domNode->ownerDocument);
828
829
			$this->registerNamespaces($domXPath);
830
831
			// OK, now make the XPath queries.
832
			while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
833
834
				// Set metadata field's value(s).
835
				if ($resArray['format'] > 0 && !empty($resArray['xpath']) && ($values = $domXPath->evaluate($resArray['xpath'], $domNode))) {
836
837
					if ($values instanceof DOMNodeList && $values->length > 0) {
838
839
						$metadata[$resArray['index_name']] = array ();
840
841
						foreach ($values as $value) {
842
843
							$metadata[$resArray['index_name']][] = trim((string) $value->nodeValue);
844
845
						}
846
847 View Code Duplication
					} elseif (!($values instanceof DOMNodeList)) {
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...
848
849
						$metadata[$resArray['index_name']] = array (trim((string) $values));
850
851
					}
852
853
				}
854
855
				// Set default value if applicable.
856
				if (empty($metadata[$resArray['index_name']][0]) && $resArray['default_value']) {
857
858
					$metadata[$resArray['index_name']] = array ($resArray['default_value']);
859
860
				}
861
862
				// Set sorting value if applicable.
863
				if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) {
864
865
					if ($resArray['format'] > 0 && !empty($resArray['xpath_sorting']) && ($values = $domXPath->evaluate($resArray['xpath_sorting'], $domNode))) {
866
867
						if ($values instanceof DOMNodeList && $values->length > 0) {
868
869
							$metadata[$resArray['index_name'].'_sorting'][0] = trim((string) $values->item(0)->nodeValue);
870
871 View Code Duplication
						} elseif (!($values instanceof DOMNodeList)) {
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...
872
873
							$metadata[$resArray['index_name'].'_sorting'][0] = trim((string) $values);
874
875
						}
876
877
					}
878
879
					if (empty($metadata[$resArray['index_name'].'_sorting'][0])) {
880
881
						$metadata[$resArray['index_name'].'_sorting'][0] = $metadata[$resArray['index_name']][0];
882
883
					}
884
885
				}
886
887
			}
888
889
			// Set title to empty string if not present.
890 View Code Duplication
			if (empty($metadata['title'][0])) {
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...
891
892
				$metadata['title'][0] = '';
893
894
				$metadata['title_sorting'][0] = '';
895
896
			}
897
898
		} else {
899
900
			// There is no dmdSec for this structure node.
901
			return array ();
902
903
		}
904
905
		return $metadata;
906
907
	}
908
909
	/**
910
	 * This returns the first corresponding physical page number of a given logical page label
911
	 *
912
	 * @access	public
913
	 *
914
	 * @param	string		$logicalPage: The label (or a part of the label) of the logical page
915
	 *
916
	 * @return	integer		The physical page number
917
	 */
918
	public function getPhysicalPage($logicalPage) {
919
920
		if(!empty( $this->lastSearchedPhysicalPage['logicalPage']) &&  $this->lastPhysicalPageSearch['logicalPage'] == $logicalPage) {
0 ignored issues
show
Bug Best Practice introduced by
The property lastPhysicalPageSearch does not exist on tx_dlf_document. Since you implemented __get, consider adding a @property annotation.
Loading history...
921
922
			return $this->lastSearchedPhysicalPage['physicalPage'];
923
924
		} else {
925
926
			$physicalPage = 0;
927
928
			foreach($this->physicalStructureInfo as $page) {
929
930
				if(strpos($page['orderlabel'], $logicalPage) !== false){
931
932
					$this->lastSearchedPhysicalPage['logicalPage'] = $logicalPage;
933
					$this->lastSearchedPhysicalPage['physicalPage'] = $physicalPage;
934
935
					return $physicalPage;
936
937
				}
938
939
				$physicalPage++;
940
941
			}
942
943
		}
944
945
		return 1;
946
947
	}
948
	
949
	/**
950
	 * This determines a title for the given document
951
	 *
952
	 * @access	public
953
	 *
954
	 * @param	integer		$uid: The UID of the document
955
	 * @param	boolean		$recursive: Search superior documents for a title, too?
956
	 *
957
	 * @return	string		The title of the document itself or a parent document
958
	 */
959
	public static function getTitle($uid, $recursive = FALSE) {
960
961
		// Save parameter for logging purposes.
962
		$_uid = $uid;
963
964
		$title = '';
965
966
		// Sanitize input.
967
		$uid = max(intval($uid), 0);
968
969
		if ($uid) {
970
971
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
972
				'tx_dlf_documents.title,tx_dlf_documents.partof',
973
				'tx_dlf_documents',
974
				'tx_dlf_documents.uid='.$uid.tx_dlf_helper::whereClause('tx_dlf_documents'),
975
				'',
976
				'',
977
				'1'
978
			);
979
980
			if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
981
982
				// Get title information.
983
				list ($title, $partof) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
984
985
				// Search parent documents recursively for a title?
986
				if ($recursive && empty($title) && intval($partof) && $partof != $uid) {
987
988
					$title = self::getTitle($partof, TRUE);
989
990
				}
991
992
			} else {
993
994
				if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
995
996
					\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getTitle('.$_uid.', ['.($recursive ? 'TRUE' : 'FALSE').'])] No document with UID "'.$uid.'" found or document not accessible', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
997
998
				}
999
1000
			}
1001
1002
		} else {
1003
1004
			if (TYPO3_DLOG) {
1005
1006
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getTitle('.$_uid.', ['.($recursive ? 'TRUE' : 'FALSE').'])] Invalid UID "'.$uid.'" for document', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1007
1008
			}
1009
1010
		}
1011
1012
		return $title;
1013
1014
	}
1015
1016
	/**
1017
	 * This extracts all the metadata for the toplevel logical structure node
1018
	 *
1019
	 * @access	public
1020
	 *
1021
	 * @param	integer		$cPid: The PID for the metadata definitions
1022
	 *
1023
	 * @return	array		The logical structure node's parsed metadata array
1024
	 */
1025
	public function getTitledata($cPid = 0) {
1026
1027
		$titledata = $this->getMetadata($this->_getToplevelId(), $cPid);
1028
1029
		// Set record identifier for METS file if not present.
1030
		if (is_array($titledata) && array_key_exists('record_id', $titledata)) {
1031
1032
			if (!in_array($this->recordId, $titledata['record_id'])) {
1033
1034
				array_unshift($titledata['record_id'], $this->recordId);
1035
1036
			}
1037
1038
		};
1039
1040
		return $titledata;
1041
1042
	}
1043
1044
	/**
1045
	 * This sets some basic class properties
1046
	 *
1047
	 * @access	protected
1048
	 *
1049
	 * @return	void
1050
	 */
1051
	protected function init() {
1052
1053
		// Get METS node from XML file.
1054
		$this->registerNamespaces($this->xml);
1055
1056
		$mets = $this->xml->xpath('//mets:mets');
1057
1058
		if ($mets) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $mets of type SimpleXMLElement[] 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...
1059
1060
			$this->mets = $mets[0];
1061
1062
			// Register namespaces.
1063
			$this->registerNamespaces($this->mets);
1064
1065
		} else {
1066
1067
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1068
1069
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->init()] No METS part found in document with UID "'.$this->uid.'"', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1070
1071
			}
1072
1073
		}
1074
1075
	}
1076
1077
	/**
1078
	 * Load XML file from URL
1079
	 *
1080
	 * @access	protected
1081
	 *
1082
	 * @param	string		$location: The URL of the file to load
1083
	 *
1084
	 * @return	boolean		TRUE on success or FALSE on failure
1085
	 */
1086
	protected function load($location) {
1087
1088
		// Load XML file.
1089
		if (\TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($location)) {
1090
1091
			// Load extension configuration
1092
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
1093
1094
			// Set user-agent to identify self when fetching XML data.
1095
			if (!empty($extConf['useragent'])) {
1096
1097
				@ini_set('user_agent', $extConf['useragent']);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1097
				/** @scrutinizer ignore-unhandled */ @ini_set('user_agent', $extConf['useragent']);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1098
1099
			}
1100
1101
			// Turn off libxml's error logging.
1102
			$libxmlErrors = libxml_use_internal_errors(TRUE);
1103
1104
			// Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1105
			$previousValueOfEntityLoader = libxml_disable_entity_loader(TRUE);
1106
1107
			// Load XML from file.
1108
			$xml = simplexml_load_string(\TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($location));
1109
1110
			// reset entity loader setting
1111
			libxml_disable_entity_loader($previousValueOfEntityLoader);
1112
1113
			// Reset libxml's error logging.
1114
			libxml_use_internal_errors($libxmlErrors);
1115
1116
			// Set some basic properties.
1117
			if ($xml !== FALSE) {
1118
1119
				$this->xml = $xml;
1120
1121
				return TRUE;
1122
1123
			} else {
1124
1125
				if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1126
1127
					\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->load('.$location.')] Could not load XML file from "'.$location.'"', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1128
1129
				}
1130
1131
			}
1132
1133
		} else {
1134
1135
			if (TYPO3_DLOG) {
1136
1137
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->load('.$location.')] Invalid file location "'.$location.'" for document loading', self::$extKey, SYSLOG_SEVERITY_ERROR);
1138
1139
			}
1140
1141
		}
1142
1143
		return FALSE;
1144
1145
	}
1146
1147
	/**
1148
	 * Register all available data formats
1149
	 *
1150
	 * @access	protected
1151
	 *
1152
	 * @return	void
1153
	 */
1154
	protected function loadFormats() {
1155
1156
		if (!$this->formatsLoaded) {
1157
1158
			// Get available data formats from database.
1159
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1160
				'tx_dlf_formats.type AS type,tx_dlf_formats.root AS root,tx_dlf_formats.namespace AS namespace,tx_dlf_formats.class AS class',
1161
				'tx_dlf_formats',
1162
				'tx_dlf_formats.pid=0'.tx_dlf_helper::whereClause('tx_dlf_formats'),
1163
				'',
1164
				'',
1165
				''
1166
			);
1167
1168
			while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
1169
1170
				// Update format registry.
1171
				$this->formats[$resArray['type']] = array (
1172
					'rootElement' => $resArray['root'],
1173
					'namespaceURI' => $resArray['namespace'],
1174
					'class' => $resArray['class']
1175
				);
1176
1177
			}
1178
1179
			$this->formatsLoaded = TRUE;
1180
1181
		}
1182
1183
	}
1184
1185
	/**
1186
	 * Register all available namespaces for a SimpleXMLElement object
1187
	 *
1188
	 * @access	public
1189
	 *
1190
	 * @param	SimpleXMLElement|DOMXPath		&$obj: SimpleXMLElement or DOMXPath object
1191
	 *
1192
	 * @return	void
1193
	 */
1194
	public function registerNamespaces(&$obj) {
1195
1196
		$this->loadFormats();
1197
1198
		// Do we have a SimpleXMLElement or DOMXPath object?
1199
		if ($obj instanceof SimpleXMLElement) {
1200
1201
			$method = 'registerXPathNamespace';
1202
1203
		} elseif ($obj instanceof DOMXPath) {
1204
1205
			$method = 'registerNamespace';
1206
1207
		} else {
1208
1209
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1210
1211
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->registerNamespaces(['.get_class($obj).'])] Given object is neither a SimpleXMLElement nor a DOMXPath instance', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1212
1213
			}
1214
1215
			return;
1216
1217
		}
1218
1219
		// Register metadata format's namespaces.
1220
		foreach ($this->formats as $enc => $conf) {
1221
1222
			$obj->$method(strtolower($enc), $conf['namespaceURI']);
1223
1224
		}
1225
1226
	}
1227
1228
	/**
1229
	 * This saves the document to the database and index
1230
	 *
1231
	 * @access	public
1232
	 *
1233
	 * @param	integer		$pid: The PID of the saved record
1234
	 * @param	integer		$core: The UID of the Solr core for indexing
1235
	 *
1236
	 * @return	boolean		TRUE on success or FALSE on failure
1237
	 */
1238
	public function save($pid = 0, $core = 0) {
1239
1240
		// Save parameters for logging purposes.
1241
		$_pid = $pid;
1242
1243
		$_core = $core;
1244
1245
		if (TYPO3_MODE !== 'BE') {
0 ignored issues
show
Bug introduced by
The constant TYPO3_MODE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1246
1247
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1248
1249
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Saving a document is only allowed in the backend', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1250
1251
			}
1252
1253
			return FALSE;
1254
1255
		}
1256
1257
		// Make sure $pid is a non-negative integer.
1258
		$pid = max(intval($pid), 0);
1259
1260
		// Make sure $core is a non-negative integer.
1261
		$core = max(intval($core), 0);
1262
1263
		// If $pid is not given, try to get it elsewhere.
1264
		if (!$pid && $this->pid) {
1265
1266
			// Retain current PID.
1267
			$pid = $this->pid;
1268
1269
		} elseif (!$pid) {
1270
1271
			if (TYPO3_DLOG) {
1272
1273
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Invalid PID "'.$pid.'" for document saving', self::$extKey, SYSLOG_SEVERITY_ERROR);
1274
1275
			}
1276
1277
			return FALSE;
1278
1279
		}
1280
1281
		// Set PID for metadata definitions.
1282
		$this->cPid = $pid;
1283
1284
		// Set UID placeholder if not updating existing record.
1285
		if ($pid != $this->pid) {
1286
1287
			$this->uid = uniqid('NEW');
1288
1289
		}
1290
1291
		// Get metadata array.
1292
		$metadata = $this->getTitledata($pid);
1293
1294
		// Check for record identifier.
1295
		if (empty($metadata['record_id'][0])) {
1296
1297
			if (TYPO3_DLOG) {
1298
1299
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] No record identifier found to avoid duplication', self::$extKey, SYSLOG_SEVERITY_ERROR);
1300
1301
			}
1302
1303
			return FALSE;
1304
1305
		}
1306
1307
		// Load plugin configuration.
1308
		$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
1309
1310
		// Get UID for user "_cli_dlf".
1311
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1312
			'be_users.uid AS uid',
1313
			'be_users',
1314
			'username='.$GLOBALS['TYPO3_DB']->fullQuoteStr('_cli_dlf', 'be_users').\TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields('be_users').\TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause('be_users'),
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Utility\BackendUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1315
			'',
1316
			'',
1317
			'1'
1318
		);
1319
1320
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1321
1322
			list ($be_user) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1323
1324
		} else {
1325
1326
			if (TYPO3_DLOG) {
1327
1328
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Backend user "_cli_dlf" not found or disabled', self::$extKey, SYSLOG_SEVERITY_ERROR);
1329
1330
			}
1331
1332
			return FALSE;
1333
1334
		}
1335
1336
		// Get UID for structure type.
1337
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1338
			'tx_dlf_structures.uid AS uid',
1339
			'tx_dlf_structures',
1340
			'tx_dlf_structures.pid='.intval($pid).' AND tx_dlf_structures.index_name='.$GLOBALS['TYPO3_DB']->fullQuoteStr($metadata['type'][0], 'tx_dlf_structures').tx_dlf_helper::whereClause('tx_dlf_structures'),
1341
			'',
1342
			'',
1343
			'1'
1344
		);
1345
1346
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1347
1348
			list ($structure) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1349
1350 View Code Duplication
		} else {
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...
1351
1352
			if (TYPO3_DLOG) {
1353
1354
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Could not identify document/structure type ' . $GLOBALS['TYPO3_DB']->fullQuoteStr($metadata['type'][0], 'tx_dlf_structures'),
1355
									       self::$extKey, SYSLOG_SEVERITY_ERROR);
1356
1357
			}
1358
1359
			return FALSE;
1360
1361
		}
1362
1363
		$metadata['type'][0] = $structure;
1364
1365
		// Get UIDs for collections.
1366
		$collections = array ();
1367
1368
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1369
			'tx_dlf_collections.index_name AS index_name,tx_dlf_collections.uid AS uid',
1370
			'tx_dlf_collections',
1371
			'tx_dlf_collections.pid='.intval($pid).' AND tx_dlf_collections.cruser_id='.intval($be_user).' AND tx_dlf_collections.fe_cruser_id=0'.tx_dlf_helper::whereClause('tx_dlf_collections'),
1372
			'',
1373
			'',
1374
			''
1375
		);
1376
1377
		for ($i = 0, $j = $GLOBALS['TYPO3_DB']->sql_num_rows($result); $i < $j; $i++) {
1378
1379
			$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
1380
1381
			$collUid[$resArray['index_name']] = $resArray['uid'];
1382
1383
		}
1384
1385
		foreach ($metadata['collection'] as $collection) {
1386
1387
			if (!empty($collUid[$collection])) {
1388
1389
				// Add existing collection's UID.
1390
				$collections[] = $collUid[$collection];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $collUid does not seem to be defined for all execution paths leading up to this point.
Loading history...
1391
1392
			} else {
1393
1394
				// Insert new collection.
1395
				$collNewUid = uniqid('NEW');
1396
1397
				$collData['tx_dlf_collections'][$collNewUid] = array (
1398
					'pid' => $pid,
1399
					'label' => $collection,
1400
					'index_name' => $collection,
1401
					'oai_name' => (!empty($conf['publishNewCollections']) ? $collection : ''),
1402
					'description' => '',
1403
					'documents' => 0,
1404
					'owner' => 0,
1405
					'status' => 0,
1406
				);
1407
1408
				$substUid = tx_dlf_helper::processDB($collData);
1409
1410
				// Prevent double insertion.
1411
				unset ($collData);
1412
1413
				// Add new collection's UID.
1414
				$collections[] = $substUid[$collNewUid];
1415
1416
				if (!defined('TYPO3_cliMode')) {
1417
1418
					$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1419
						'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1420
						htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.newCollection'), $collection, $substUid[$collNewUid])),
1421
						tx_dlf_helper::getLL('flash.attention', TRUE),
1422
						\TYPO3\CMS\Core\Messaging\FlashMessage::INFO,
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Messaging\FlashMessage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1423
						TRUE
1424
					);
1425
1426
					tx_dlf_helper::addMessage($message);
1427
1428
				}
1429
1430
			}
1431
1432
		}
1433
1434
		// Preserve user-defined collections.
1435
		$result = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
1436
			'tx_dlf_collections.uid AS uid',
1437
			'tx_dlf_documents',
1438
			'tx_dlf_relations',
1439
			'tx_dlf_collections',
1440
			'AND tx_dlf_documents.pid='.intval($pid).' AND tx_dlf_collections.pid='.intval($pid).' AND tx_dlf_documents.uid='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->uid, 'tx_dlf_documents').' AND NOT (tx_dlf_collections.cruser_id='.intval($be_user).' AND tx_dlf_collections.fe_cruser_id=0) AND tx_dlf_relations.ident='.$GLOBALS['TYPO3_DB']->fullQuoteStr('docs_colls', 'tx_dlf_relations'),
1441
			'',
1442
			'',
1443
			''
1444
		);
1445
1446
		for ($i = 0, $j = $GLOBALS['TYPO3_DB']->sql_num_rows($result); $i < $j; $i++) {
1447
1448
			list ($collections[]) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1449
1450
		}
1451
1452
		$metadata['collection'] = $collections;
1453
1454
		// Get UID for owner.
1455
		$owner = !empty($metadata['owner'][0]) ? $metadata['owner'][0] : 'default';
1456
1457
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1458
			'tx_dlf_libraries.uid AS uid',
1459
			'tx_dlf_libraries',
1460
			'tx_dlf_libraries.pid='.intval($pid).' AND tx_dlf_libraries.index_name='.$GLOBALS['TYPO3_DB']->fullQuoteStr($owner, 'tx_dlf_libraries').tx_dlf_helper::whereClause('tx_dlf_libraries'),
1461
			'',
1462
			'',
1463
			'1'
1464
		);
1465
1466
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1467
1468
			list ($ownerUid) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1469
1470
		} else {
1471
1472
			// Insert new library.
1473
			$libNewUid = uniqid('NEW');
1474
1475
			$libData['tx_dlf_libraries'][$libNewUid] = array (
1 ignored issue
show
Comprehensibility Best Practice introduced by
$libData was never initialized. Although not strictly required by PHP, it is generally a good practice to add $libData = array(); before regardless.
Loading history...
1476
				'pid' => $pid,
1477
				'label' => $owner,
1478
				'index_name' => $owner,
1479
				'website' => '',
1480
				'contact' => '',
1481
				'image' => '',
1482
				'oai_label' => '',
1483
				'oai_base' => '',
1484
				'opac_label' => '',
1485
				'opac_base' => '',
1486
				'union_label' => '',
1487
				'union_base' => '',
1488
			);
1489
1490
			$substUid = tx_dlf_helper::processDB($libData);
1491
1492
			// Add new library's UID.
1493
			$ownerUid = $substUid[$libNewUid];
1494
1495
			if (!defined('TYPO3_cliMode')) {
1496
1497
				$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1498
					'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1499
					htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.newLibrary'), $owner, $ownerUid)),
1500
					tx_dlf_helper::getLL('flash.attention', TRUE),
1501
					\TYPO3\CMS\Core\Messaging\FlashMessage::INFO,
1502
					TRUE
1503
				);
1504
1505
				tx_dlf_helper::addMessage($message);
1506
1507
			}
1508
1509
		}
1510
1511
		$metadata['owner'][0] = $ownerUid;
1512
1513
		// Get UID of parent document.
1514
		$partof = 0;
1515
1516
		// Get the closest ancestor of the current document which has a MPTR child.
1517
		$parentMptr = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$this->_getToplevelId().'"]/ancestor::mets:div[./mets:mptr][1]/mets:mptr');
1518
1519
		if (!empty($parentMptr[0])) {
1520
1521
			$parentLocation = (string) $parentMptr[0]->attributes('http://www.w3.org/1999/xlink')->href;
1522
1523
			if ($parentLocation != $this->location) {
1524
1525
				$parentDoc =& tx_dlf_document::getInstance($parentLocation, $pid);
1526
1527
				if ($parentDoc->ready) {
1528
1529
					if ($parentDoc->pid != $pid) {
1530
1531
						$parentDoc->save($pid, $core);
1532
1533
					}
1534
1535
					$partof = $parentDoc->uid;
1536
1537
				}
1538
1539
			}
1540
1541
		}
1542
1543
		// Use the date of publication or title as alternative sorting metric for parts of multi-part works.
1544
		if (!empty($partof)) {
1545
1546 View Code Duplication
			if (empty($metadata['volume'][0]) && !empty($metadata['year'][0])) {
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...
1547
1548
				$metadata['volume'] = $metadata['year'];
1549
1550
			}
1551
1552
			if (empty($metadata['volume_sorting'][0])) {
1553
1554
				if (!empty($metadata['year_sorting'][0])) {
1555
1556
					$metadata['volume_sorting'][0] = $metadata['year_sorting'][0];
1557
1558
				} elseif (!empty($metadata['year'][0])) {
1559
1560
					$metadata['volume_sorting'][0] = $metadata['year'][0];
1561
1562
				}
1563
1564
			}
1565
1566
			// If volume_sorting is still empty, try to use title_sorting finally (workaround for newspapers)
1567 View Code Duplication
			if (empty($metadata['volume_sorting'][0])) {
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...
1568
1569
				if (!empty($metadata['title_sorting'][0])) {
1570
1571
					$metadata['volume_sorting'][0] = $metadata['title_sorting'][0];
1572
1573
				}
1574
			}
1575
1576
		}
1577
1578
		// Get metadata for lists and sorting.
1579
		$listed = array ();
1580
1581
		$sortable = array ();
1582
1583
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1584
			'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadata.is_listed AS is_listed,tx_dlf_metadata.is_sortable AS is_sortable',
1585
			'tx_dlf_metadata',
1586
			'(tx_dlf_metadata.is_listed=1 OR tx_dlf_metadata.is_sortable=1) AND tx_dlf_metadata.pid='.intval($pid).tx_dlf_helper::whereClause('tx_dlf_metadata'),
1587
			'',
1588
			'',
1589
			''
1590
		);
1591
1592
		while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
1593
1594
			if (!empty($metadata[$resArray['index_name']])) {
1595
1596
				if ($resArray['is_listed']) {
1597
1598
					$listed[$resArray['index_name']] = $metadata[$resArray['index_name']];
1599
1600
				}
1601
1602
				if ($resArray['is_sortable']) {
1603
1604
					$sortable[$resArray['index_name']] = $metadata[$resArray['index_name']][0];
1605
1606
				}
1607
1608
			}
1609
1610
		}
1611
1612
		// Fill data array.
1613
		$data['tx_dlf_documents'][$this->uid] = array (
1 ignored issue
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
1614
			'pid' => $pid,
1615
			$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['starttime'] => 0,
1616
			$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['endtime'] => 0,
1617
			'prod_id' => $metadata['prod_id'][0],
1618
			'location' => $this->location,
1619
			'record_id' => $metadata['record_id'][0],
1620
			'opac_id' => $metadata['opac_id'][0],
1621
			'union_id' => $metadata['union_id'][0],
1622
			'urn' => $metadata['urn'][0],
1623
			'purl' => $metadata['purl'][0],
1624
			'title' => $metadata['title'][0],
1625
			'title_sorting' => $metadata['title_sorting'][0],
1626
			'author' => implode('; ', $metadata['author']),
1627
			'year' => implode('; ', $metadata['year']),
1628
			'place' => implode('; ', $metadata['place']),
1629
			'thumbnail' => $this->_getThumbnail(TRUE),
1630
			'metadata' => serialize($listed),
1631
			'metadata_sorting' => serialize($sortable),
1632
			'structure' => $metadata['type'][0],
1633
			'partof' => $partof,
1634
			'volume' => $metadata['volume'][0],
1635
			'volume_sorting' => $metadata['volume_sorting'][0],
1636
			'collections' => $metadata['collection'],
1637
			'owner' => $metadata['owner'][0],
1638
			'solrcore' => $core,
1639
			'status' => 0,
1640
		);
1641
1642
		// Unhide hidden documents.
1643
		if (!empty($conf['unhideOnIndex'])) {
1644
1645
			$data['tx_dlf_documents'][$this->uid][$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['disabled']] = 0;
1646
1647
		}
1648
1649
		// Process data.
1650
		$newIds = tx_dlf_helper::processDB($data);
1651
1652
		// Replace placeholder with actual UID.
1653
		if (strpos($this->uid, 'NEW') === 0) {
1654
1655
			$this->uid = $newIds[$this->uid];
1656
1657
			$this->pid = $pid;
1658
1659
			$this->parentId = $partof;
1660
1661
		}
1662
1663
		if (!defined('TYPO3_cliMode')) {
1664
1665
			$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1666
				'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1667
				htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.documentSaved'), $metadata['title'][0], $this->uid)),
1668
				tx_dlf_helper::getLL('flash.done', TRUE),
1669
				\TYPO3\CMS\Core\Messaging\FlashMessage::OK,
1670
				TRUE
1671
			);
1672
1673
			tx_dlf_helper::addMessage($message);
1674
1675
		}
1676
1677
		// Add document to index.
1678
		if ($core) {
1679
1680
			tx_dlf_indexing::add($this, $core);
1681
1682
		} else {
1683
1684
			if (TYPO3_DLOG) {
1685
1686
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Invalid UID "'.$core.'" for Solr core', self::$extKey, SYSLOG_SEVERITY_NOTICE);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_NOTICE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1687
1688
			}
1689
1690
		}
1691
1692
		return TRUE;
1693
1694
	}
1695
1696
	/**
1697
	 * This returns $this->cPid via __get()
1698
	 *
1699
	 * @access	protected
1700
	 *
1701
	 * @return	integer		The PID of the metadata definitions
1702
	 */
1703
	protected function _getCPid() {
1704
1705
		return $this->cPid;
1706
1707
	}
1708
1709
	/**
1710
	 * This builds an array of the document's dmdSecs
1711
	 *
1712
	 * @access	protected
1713
	 *
1714
	 * @return	array		Array of dmdSecs with their IDs as array key
1715
	 */
1716
	protected function _getDmdSec() {
1717
1718
		if (!$this->dmdSecLoaded) {
1719
1720
			// Get available data formats.
1721
			$this->loadFormats();
1722
1723
			// Get dmdSec nodes from METS.
1724
			$dmdIds = $this->mets->xpath('./mets:dmdSec/@ID');
1725
1726
			foreach ($dmdIds as $dmdId) {
1727
1728
				if ($type = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[not(@MDTYPE="OTHER")]/@MDTYPE')) {
1729
1730 View Code Duplication
					if (!empty($this->formats[(string) $type[0]])) {
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...
1731
1732
						$type = (string) $type[0];
1733
1734
						$xml = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="'.$type.'"]/mets:xmlData/'.strtolower($type).':'.$this->formats[$type]['rootElement']);
1735
1736
					}
1737
1738
				} elseif ($type = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="OTHER"]/@OTHERMDTYPE')) {
1739
1740 View Code Duplication
					if (!empty($this->formats[(string) $type[0]])) {
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...
1741
1742
						$type = (string) $type[0];
1743
1744
						$xml = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="OTHER"][@OTHERMDTYPE="'.$type.'"]/mets:xmlData/'.strtolower($type).':'.$this->formats[$type]['rootElement']);
1745
1746
					}
1747
1748
				}
1749
1750
				if ($xml) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $xml of type SimpleXMLElement[] 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...
Comprehensibility Best Practice introduced by
The variable $xml does not seem to be defined for all execution paths leading up to this point.
Loading history...
1751
1752
					$this->dmdSec[(string) $dmdId]['type'] = $type;
1753
1754
					$this->dmdSec[(string) $dmdId]['xml'] = $xml[0];
1755
1756
					$this->registerNamespaces($this->dmdSec[(string) $dmdId]['xml']);
1757
1758
				}
1759
1760
			}
1761
1762
			$this->dmdSecLoaded = TRUE;
1763
1764
		}
1765
1766
		return $this->dmdSec;
1767
1768
	}
1769
1770
	/**
1771
	 * This builds the file ID -> USE concordance
1772
	 *
1773
	 * @access	protected
1774
	 *
1775
	 * @return	array		Array of file use groups with file IDs
1776
	 */
1777
	protected function _getFileGrps() {
1778
1779
		if (!$this->fileGrpsLoaded) {
1780
1781
			// Get configured USE attributes.
1782
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
1783
1784
			$useGrps = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $extConf['fileGrps']);
1785
1786
			if (!empty($extConf['fileGrpThumbs'])) {
1787
1788
				$useGrps[] = $extConf['fileGrpThumbs'];
1789
1790
			}
1791
1792
			if (!empty($extConf['fileGrpDownload'])) {
1793
1794
				$useGrps[] = $extConf['fileGrpDownload'];
1795
1796
			}
1797
1798
			if (!empty($extConf['fileGrpFulltext'])) {
1799
1800
				$useGrps[] = $extConf['fileGrpFulltext'];
1801
1802
			}
1803
1804
			if (!empty($extConf['fileGrpAudio'])) {
1805
1806
				$useGrps[] = $extConf['fileGrpAudio'];
1807
1808
			}
1809
1810
			// Get all file groups.
1811
			$fileGrps = $this->mets->xpath('./mets:fileSec/mets:fileGrp');
1812
1813
			// Build concordance for configured USE attributes.
1814
			foreach ($fileGrps as $fileGrp) {
1815
1816
				if (in_array((string) $fileGrp['USE'], $useGrps)) {
1817
1818
					foreach ($fileGrp->children('http://www.loc.gov/METS/')->file as $file) {
1819
1820
						$this->fileGrps[(string) $file->attributes()->ID] = (string) $fileGrp['USE'];
1821
1822
					}
1823
1824
				}
1825
1826
			}
1827
1828
			// Are there any fulltext files available?
1829
			if (!empty($extConf['fileGrpFulltext']) && in_array($extConf['fileGrpFulltext'], $this->fileGrps)) {
1830
1831
				$this->hasFulltext = TRUE;
1832
1833
			}
1834
1835
			$this->fileGrpsLoaded = TRUE;
1836
1837
		}
1838
1839
		return $this->fileGrps;
1840
1841
	}
1842
1843
	/**
1844
	 * This returns $this->hasFulltext via __get()
1845
	 *
1846
	 * @access	protected
1847
	 *
1848
	 * @return	boolean		Are there any fulltext files available?
1849
	 */
1850
	protected function _getHasFulltext() {
1851
1852
		// Are the fileGrps already loaded?
1853
		if (!$this->fileGrpsLoaded) {
1854
1855
			$this->_getFileGrps();
1856
1857
		}
1858
1859
		return $this->hasFulltext;
1860
1861
	}
1862
1863
	/**
1864
	 * This returns $this->location via __get()
1865
	 *
1866
	 * @access	protected
1867
	 *
1868
	 * @return	string		The location of the document
1869
	 */
1870
	protected function _getLocation() {
1871
1872
		return $this->location;
1873
1874
	}
1875
1876
	/**
1877
	 * This builds an array of the document's metadata
1878
	 *
1879
	 * @access	protected
1880
	 *
1881
	 * @return	array		Array of metadata with their corresponding logical structure node ID as key
1882
	 */
1883
	protected function _getMetadataArray() {
1884
1885
		// Set metadata definitions' PID.
1886
		$cPid = ($this->cPid ? $this->cPid : $this->pid);
1887
1888
		if (!$cPid) {
1889
1890
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1891
1892
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getMetadataArray()] Invalid PID "'.$cPid.'" for metadata definitions', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1893
1894
			}
1895
1896
			return array ();
1897
1898
		}
1899
1900
		if (!$this->metadataArrayLoaded || $this->metadataArray[0] != $cPid) {
1901
1902
			// Get all logical structure nodes with metadata.
1903
			if (($ids = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@DMDID]/@ID'))) {
1904
1905
				foreach ($ids as $id) {
1906
1907
					$this->metadataArray[(string) $id] = $this->getMetadata((string) $id, $cPid);
1908
1909
				}
1910
1911
			}
1912
1913
			// Set current PID for metadata definitions.
1914
			$this->metadataArray[0] = $cPid;
1915
1916
			$this->metadataArrayLoaded = TRUE;
1917
1918
		}
1919
1920
		return $this->metadataArray;
1921
1922
	}
1923
1924
	/**
1925
	 * This returns $this->mets via __get()
1926
	 *
1927
	 * @access	protected
1928
	 *
1929
	 * @return	SimpleXMLElement		The XML's METS part as SimpleXMLElement object
1930
	 */
1931
	protected function _getMets() {
1932
1933
		return $this->mets;
1934
1935
	}
1936
1937
	/**
1938
	 * This returns $this->numPages via __get()
1939
	 *
1940
	 * @access	protected
1941
	 *
1942
	 * @return	integer		The total number of pages and/or tracks
1943
	 */
1944
	protected function _getNumPages() {
1945
1946
		$this->_getPhysicalStructure();
1947
1948
		return $this->numPages;
1949
1950
	}
1951
1952
	/**
1953
	 * This returns $this->parentId via __get()
1954
	 *
1955
	 * @access	protected
1956
	 *
1957
	 * @return	integer		The UID of the parent document or zero if not applicable
1958
	 */
1959
	protected function _getParentId() {
1960
1961
		return $this->parentId;
1962
1963
	}
1964
1965
	/**
1966
	 * This builds an array of the document's physical structure
1967
	 *
1968
	 * @access	protected
1969
	 *
1970
	 * @return	array		Array of physical elements' id, type, label and file representations ordered by @ORDER attribute
1971
	 */
1972
	protected function _getPhysicalStructure() {
1973
1974
		// Is there no physical structure array yet?
1975
		if (!$this->physicalStructureLoaded) {
1976
1977
			// Does the document have a structMap node of type "PHYSICAL"?
1978
			$elementNodes = $this->mets->xpath('./mets:structMap[@TYPE="PHYSICAL"]/mets:div[@TYPE="physSequence"]/mets:div');
1979
1980
			if ($elementNodes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $elementNodes of type SimpleXMLElement[] 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...
1981
1982
				// Get file groups.
1983
				$fileUse = $this->_getFileGrps();
1984
1985
				// Get the physical sequence's metadata.
1986
				$physNode = $this->mets->xpath('./mets:structMap[@TYPE="PHYSICAL"]/mets:div[@TYPE="physSequence"]');
1987
1988
				$physSeq[0] = (string) $physNode[0]['ID'];
1 ignored issue
show
Comprehensibility Best Practice introduced by
$physSeq was never initialized. Although not strictly required by PHP, it is generally a good practice to add $physSeq = array(); before regardless.
Loading history...
1989
1990
				$this->physicalStructureInfo[$physSeq[0]]['id'] = $physNode[0]['ID'];
1991
1992
				$this->physicalStructureInfo[$physSeq[0]]['dmdId'] = (isset($physNode[0]['DMDID']) ? (string) $physNode[0]['DMDID'] : '');
1993
1994
				$this->physicalStructureInfo[$physSeq[0]]['label'] = (isset($physNode[0]['LABEL']) ? (string) $physNode[0]['LABEL'] : '');
1995
1996
				$this->physicalStructureInfo[$physSeq[0]]['orderlabel'] = (isset($physNode[0]['ORDERLABEL']) ? (string) $physNode[0]['ORDERLABEL'] : '');
1997
1998
				$this->physicalStructureInfo[$physSeq[0]]['type'] = (string) $physNode[0]['TYPE'];
1999
2000
				$this->physicalStructureInfo[$physSeq[0]]['contentIds'] = (isset($physNode[0]['CONTENTIDS']) ? (string) $physNode[0]['CONTENTIDS'] : '');
2001
2002
				// Get the file representations from fileSec node.
2003 View Code Duplication
				foreach ($physNode[0]->children('http://www.loc.gov/METS/')->fptr as $fptr) {
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...
2004
2005
					// Check if file has valid @USE attribute.
2006
					if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
2007
2008
						$this->physicalStructureInfo[$physSeq[0]]['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
2009
2010
					}
2011
2012
				}
2013
2014
				// Build the physical elements' array from the physical structMap node.
2015
				foreach ($elementNodes as $elementNode) {
2016
2017
					$elements[(int) $elementNode['ORDER']] = (string) $elementNode['ID'];
2018
2019
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['id'] = $elementNode['ID'];
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $elements seems to be defined later in this foreach loop on line 2017. Are you sure it is defined here?
Loading history...
2020
2021
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['dmdId'] = (isset($elementNode['DMDID']) ? (string) $elementNode['DMDID'] : '');
2022
2023
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['label'] = (isset($elementNode['LABEL']) ? (string) $elementNode['LABEL'] : '');
2024
2025
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['orderlabel'] = (isset($elementNode['ORDERLABEL']) ? (string) $elementNode['ORDERLABEL'] : '');
2026
2027
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['type'] = (string) $elementNode['TYPE'];
2028
2029
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['contentIds'] = (isset($elementNode['CONTENTIDS']) ? (string) $elementNode['CONTENTIDS'] : '');
2030
2031
					// Get the file representations from fileSec node.
2032 View Code Duplication
					foreach ($elementNode->children('http://www.loc.gov/METS/')->fptr as $fptr) {
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...
2033
2034
						// Check if file has valid @USE attribute.
2035
						if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
2036
2037
							$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
2038
2039
						}
2040
2041
					}
2042
2043
				}
2044
2045
				// Sort array by keys (= @ORDER).
2046
				if (ksort($elements)) {
2047
2048
					// Set total number of pages/tracks.
2049
					$this->numPages = count($elements);
2050
2051
					// Merge and re-index the array to get nice numeric indexes.
2052
					$this->physicalStructure = array_merge($physSeq, $elements);
2053
2054
				}
2055
2056
			}
2057
2058
			$this->physicalStructureLoaded = TRUE;
2059
2060
		}
2061
2062
		return $this->physicalStructure;
2063
2064
	}
2065
2066
	/**
2067
	 * This gives an array of the document's physical structure metadata
2068
	 *
2069
	 * @access	protected
2070
	 *
2071
	 * @return	array		Array of elements' type, label and file representations ordered by @ID attribute
2072
	 */
2073
	protected function _getPhysicalStructureInfo() {
2074
2075
		// Is there no physical structure array yet?
2076
		if (!$this->physicalStructureLoaded) {
2077
2078
			// Build physical structure array.
2079
			$this->_getPhysicalStructure();
2080
2081
		}
2082
2083
		return $this->physicalStructureInfo;
2084
2085
	}
2086
2087
	/**
2088
	 * This returns $this->pid via __get()
2089
	 *
2090
	 * @access	protected
2091
	 *
2092
	 * @return	integer		The PID of the document or zero if not in database
2093
	 */
2094
	protected function _getPid() {
2095
2096
		return $this->pid;
2097
2098
	}
2099
2100
	/**
2101
	 * This returns $this->ready via __get()
2102
	 *
2103
	 * @access	protected
2104
	 *
2105
	 * @return	boolean		Is the document instantiated successfully?
2106
	 */
2107
	protected function _getReady() {
2108
2109
		return $this->ready;
2110
2111
	}
2112
2113
	/**
2114
	 * This returns $this->recordId via __get()
2115
	 *
2116
	 * @access	protected
2117
	 *
2118
	 * @return	mixed		The METS file's record identifier
2119
	 */
2120
	protected function _getRecordId() {
2121
2122
		return $this->recordId;
2123
2124
	}
2125
2126
	/**
2127
	 * This returns $this->rootId via __get()
2128
	 *
2129
	 * @access	protected
2130
	 *
2131
	 * @return	integer		The UID of the root document or zero if not applicable
2132
	 */
2133
	protected function _getRootId() {
2134
2135
		if (!$this->rootIdLoaded) {
2136
2137
			if ($this->parentId) {
2138
2139
				$parent = self::getInstance($this->parentId, $this->pid);
2140
2141
				$this->rootId = $parent->rootId;
2142
2143
			}
2144
2145
			$this->rootIdLoaded = TRUE;
2146
2147
		}
2148
2149
		return $this->rootId;
2150
2151
	}
2152
2153
	/**
2154
	 * This returns the smLinks between logical and physical structMap
2155
	 *
2156
	 * @access	protected
2157
	 *
2158
	 * @return	array		The links between logical and physical nodes
2159
	 */
2160
	protected function _getSmLinks() {
2161
2162
		if (!$this->smLinksLoaded) {
2163
2164
			$smLinks = $this->mets->xpath('./mets:structLink/mets:smLink');
2165
2166
			foreach ($smLinks as $smLink) {
2167
2168
				$this->smLinks['l2p'][(string) $smLink->attributes('http://www.w3.org/1999/xlink')->from][] = (string) $smLink->attributes('http://www.w3.org/1999/xlink')->to;
2169
2170
				$this->smLinks['p2l'][(string) $smLink->attributes('http://www.w3.org/1999/xlink')->to][] = (string) $smLink->attributes('http://www.w3.org/1999/xlink')->from;
2171
2172
			}
2173
2174
			$this->smLinksLoaded = TRUE;
2175
2176
		}
2177
2178
		return $this->smLinks;
2179
2180
	}
2181
2182
	/**
2183
	 * This builds an array of the document's logical structure
2184
	 *
2185
	 * @access	protected
2186
	 *
2187
	 * @return	array		Array of structure nodes' id, label, type and physical page indexes/mptr link with original hierarchy preserved
2188
	 */
2189
	protected function _getTableOfContents() {
2190
2191
		// Is there no logical structure array yet?
2192
		if (!$this->tableOfContentsLoaded) {
2193
2194
			// Get all logical structures.
2195
			$this->getLogicalStructure('', TRUE);
2196
2197
			$this->tableOfContentsLoaded = TRUE;
2198
2199
		}
2200
2201
		return $this->tableOfContents;
2202
2203
	}
2204
2205
	/**
2206
	 * This returns the document's thumbnail location
2207
	 *
2208
	 * @access	protected
2209
	 *
2210
	 * @param	boolean		$forceReload: Force reloading the thumbnail instead of returning the cached value
2211
	 *
2212
	 * @return	string		The document's thumbnail location
2213
	 */
2214
	protected function _getThumbnail($forceReload = FALSE) {
2215
2216
		if (!$this->thumbnailLoaded || $forceReload) {
2217
2218
			// Retain current PID.
2219
			$cPid = ($this->cPid ? $this->cPid : $this->pid);
2220
2221 View Code Duplication
			if (!$cPid) {
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...
2222
2223
				if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2224
2225
					\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->_getThumbnail()] Invalid PID "'.$cPid.'" for structure definitions', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2226
2227
				}
2228
2229
				$this->thumbnailLoaded = TRUE;
2230
2231
				return $this->thumbnail;
2232
2233
			}
2234
2235
			// Load extension configuration.
2236
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
2237
2238 View Code Duplication
			if (empty($extConf['fileGrpThumbs'])) {
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...
2239
2240
				if (TYPO3_DLOG) {
2241
2242
					\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->_getThumbnail()] No fileGrp for thumbnails specified', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2243
2244
				}
2245
2246
				$this->thumbnailLoaded = TRUE;
2247
2248
				return $this->thumbnail;
2249
2250
			}
2251
2252
			$strctId = $this->_getToplevelId();
2253
2254
			$metadata = $this->getTitledata($cPid);
2255
2256
			// Get structure element to get thumbnail from.
2257
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2258
				'tx_dlf_structures.thumbnail AS thumbnail',
2259
				'tx_dlf_structures',
2260
				'tx_dlf_structures.pid='.intval($cPid).' AND tx_dlf_structures.index_name='.$GLOBALS['TYPO3_DB']->fullQuoteStr($metadata['type'][0], 'tx_dlf_structures').tx_dlf_helper::whereClause('tx_dlf_structures'),
2261
				'',
2262
				'',
2263
				'1'
2264
			);
2265
2266
			if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
2267
2268
				$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
2269
2270
				// Get desired thumbnail structure if not the toplevel structure itself.
2271
				if (!empty($resArray['thumbnail'])) {
2272
2273
					$strctType = tx_dlf_helper::getIndexName($resArray['thumbnail'], 'tx_dlf_structures', $cPid);
2274
2275
					// Check if this document has a structure element of the desired type.
2276
					$strctIds = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@TYPE="'.$strctType.'"]/@ID');
2277
2278
					if (!empty($strctIds)) {
2279
2280
						$strctId = (string) $strctIds[0];
2281
2282
					}
2283
2284
				}
2285
2286
				// Load smLinks.
2287
				$this->_getSmLinks();
2288
2289
				// Get thumbnail location.
2290
				if ($this->_getPhysicalStructure() && !empty($this->smLinks['l2p'][$strctId])) {
2291
2292
					$this->thumbnail = $this->getFileLocation($this->physicalStructureInfo[$this->smLinks['l2p'][$strctId][0]]['files'][$extConf['fileGrpThumbs']]);
2293
2294
				} else {
2295
2296
					$this->thumbnail = $this->getFileLocation($this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']]);
2297
2298
				}
2299
2300
			} elseif (TYPO3_DLOG) {
2301
2302
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->_getThumbnail()] No structure of type "'.$metadata['type'][0].'" found in database', self::$extKey, SYSLOG_SEVERITY_ERROR);
2303
2304
			}
2305
2306
			$this->thumbnailLoaded = TRUE;
2307
2308
		}
2309
2310
		return $this->thumbnail;
2311
2312
	}
2313
2314
	/**
2315
	 * This returns the ID of the toplevel logical structure node
2316
	 *
2317
	 * @access	protected
2318
	 *
2319
	 * @return	string		The logical structure node's ID
2320
	 */
2321
	protected function _getToplevelId() {
2322
2323
		if (empty($this->toplevelId)) {
2324
2325
			// Get all logical structure nodes with metadata, but without associated METS-Pointers.
2326
			if (($divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@DMDID and not(./mets:mptr)]'))) {
2327
2328
				// Load smLinks.
2329
				$this->_getSmLinks();
2330
2331
				foreach ($divs as $div) {
2332
2333
					$id = (string) $div['ID'];
2334
2335
					// Are there physical structure nodes for this logical structure?
2336
					if (array_key_exists($id, $this->smLinks['l2p'])) {
2337
2338
						// Yes. That's what we're looking for.
2339
						$this->toplevelId = $id;
2340
2341
						break;
2342
2343
					} elseif (empty($this->toplevelId)) {
2344
2345
						// No. Remember this anyway, but keep looking for a better one.
2346
						$this->toplevelId = $id;
2347
2348
					}
2349
2350
				}
2351
2352
			}
2353
2354
		}
2355
2356
		return $this->toplevelId;
2357
2358
	}
2359
2360
	/**
2361
	 * This returns $this->uid via __get()
2362
	 *
2363
	 * @access	protected
2364
	 *
2365
	 * @return	mixed		The UID or the URL of the document
2366
	 */
2367
	protected function _getUid() {
2368
2369
		return $this->uid;
2370
2371
	}
2372
2373
	/**
2374
	 * This sets $this->cPid via __set()
2375
	 *
2376
	 * @access	protected
2377
	 *
2378
	 * @param	integer		$value: The new PID for the metadata definitions
2379
	 *
2380
	 * @return	void
2381
	 */
2382
	protected function _setCPid($value) {
2383
2384
		$this->cPid = max(intval($value), 0);
2385
2386
	}
2387
2388
	/**
2389
	 * This magic method is invoked each time a clone is called on the object variable
2390
	 * (This method is defined as private/protected because singleton objects should not be cloned)
2391
	 *
2392
	 * @access	protected
2393
	 *
2394
	 * @return	void
2395
	 */
2396
	protected function __clone() {}
2397
2398
	/**
2399
	 * This is a singleton class, thus the constructor should be private/protected
2400
	 *
2401
	 * @access	protected
2402
	 *
2403
	 * @param	integer		$uid: The UID of the document to parse or URL to XML file
2404
	 * @param	integer		$pid: If > 0, then only document with this PID gets loaded
2405
	 *
2406
	 * @return	void
2407
	 */
2408
	protected function __construct($uid, $pid) {
2409
2410
		// Prepare to check database for the requested document.
2411
		if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($uid)) {
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Core\Utility\MathUtility was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2412
2413
			$whereClause = 'tx_dlf_documents.uid='.intval($uid).tx_dlf_helper::whereClause('tx_dlf_documents');
2414
2415
		} else {
2416
2417
			// Cast to string for safety reasons.
2418
			$location = (string) $uid;
2419
2420
			// Try to load METS file.
2421
			if ($this->load($location)) {
2422
2423
				// Initialize core METS object.
2424
				$this->init();
2425
2426
				if ($this->mets !== NULL) {
2427
2428
					// Check for METS object @ID.
2429
					if (!empty($this->mets['OBJID'])) {
2430
2431
						$this->recordId = (string) $this->mets['OBJID'];
2432
2433
					}
2434
2435
					// Get hook objects.
2436
					$hookObjects = tx_dlf_helper::getHookObjects('common/class.tx_dlf_document.php');
2437
2438
					// Apply hooks.
2439
					foreach($hookObjects as $hookObj) {
2440
2441
						if (method_exists($hookObj, 'construct_postProcessRecordId')) {
2442
2443
							$hookObj->construct_postProcessRecordId($this->xml, $this->recordId);
2444
2445
						}
2446
2447
					}
2448
2449
				} else {
2450
2451
					// No METS part found.
2452
					return;
2453
2454
				}
2455
2456
			} else {
2457
2458
				// Loading failed.
2459
				return;
2460
2461
			}
2462
2463
			if (!empty($this->recordId)) {
2464
2465
				$whereClause = 'tx_dlf_documents.record_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->recordId, 'tx_dlf_documents').tx_dlf_helper::whereClause('tx_dlf_documents');
2466
2467
			} else {
2468
2469
				// There is no record identifier and there should be no hit in the database.
2470
				$whereClause = '1=-1';
2471
2472
			}
2473
2474
		}
2475
2476
		// Check for PID if needed.
2477
		if ($pid) {
2478
2479
			$whereClause .= ' AND tx_dlf_documents.pid='.intval($pid);
2480
2481
		}
2482
2483
		// Get document PID and location from database.
2484
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2485
			'tx_dlf_documents.uid AS uid,tx_dlf_documents.pid AS pid,tx_dlf_documents.record_id AS record_id,tx_dlf_documents.partof AS partof,tx_dlf_documents.thumbnail AS thumbnail,tx_dlf_documents.location AS location',
2486
			'tx_dlf_documents',
2487
			$whereClause,
2488
			'',
2489
			'',
2490
			'1'
2491
		);
2492
2493
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
2494
2495
			list ($this->uid, $this->pid, $this->recordId, $this->parentId, $this->thumbnail, $this->location) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
2496
2497
			$this->thumbnailLoaded = TRUE;
2498
2499
			// Load XML file if necessary...
2500
			if ($this->mets === NULL && $this->load($this->location)) {
2501
2502
				// ...and set some basic properties.
2503
				$this->init();
2504
2505
			}
2506
2507
			// Do we have a METS object now?
2508
			if ($this->mets !== NULL) {
2509
2510
				// Set new location if necessary.
2511
				if (!empty($location)) {
2512
2513
					$this->location = $location;
2514
2515
				}
2516
2517
				// Document ready!
2518
				$this->ready = TRUE;
2519
2520
			}
2521
2522
		} elseif ($this->mets !== NULL) {
2523
2524
			// Set location as UID for documents not in database.
2525
			$this->uid = $location;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $location does not seem to be defined for all execution paths leading up to this point.
Loading history...
2526
2527
			$this->location = $location;
2528
2529
			// Document ready!
2530
			$this->ready = TRUE;
2531
2532
		} else {
2533
2534
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2535
2536
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->__construct('.$uid.', '.$pid.')] No document with UID "'.$uid.'" found or document not accessible', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2537
2538
			}
2539
2540
		}
2541
2542
	}
2543
2544
	/**
2545
	 * This magic method is called each time an invisible property is referenced from the object
2546
	 *
2547
	 * @access	public
2548
	 *
2549
	 * @param	string		$var: Name of variable to get
2550
	 *
2551
	 * @return	mixed		Value of $this->$var
2552
	 */
2553
	public function __get($var) {
2554
2555
		$method = '_get'.ucfirst($var);
2556
2557
		if (!property_exists($this, $var) || !method_exists($this, $method)) {
2558
2559
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2560
2561
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->__get('.$var.')] There is no getter function for property "'.$var.'"', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2562
2563
			}
2564
2565
			return;
2566
2567
		} else {
2568
2569
			return $this->$method();
2570
2571
		}
2572
2573
	}
2574
2575
	/**
2576
	 * This magic method is called each time an invisible property is referenced from the object
2577
	 *
2578
	 * @access	public
2579
	 *
2580
	 * @param	string		$var: Name of variable to set
2581
	 * @param	mixed		$value: New value of variable
2582
	 *
2583
	 * @return	void
2584
	 */
2585 View Code Duplication
	public function __set($var, $value) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
2586
2587
		$method = '_set'.ucfirst($var);
2588
2589
		if (!property_exists($this, $var) || !method_exists($this, $method)) {
2590
2591
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2592
2593
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->__set('.$var.', '.$value.')] There is no setter function for property "'.$var.'"', self::$extKey, SYSLOG_SEVERITY_WARNING);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_WARNING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2594
2595
			}
2596
2597
		} else {
2598
2599
			$this->$method($value);
2600
2601
		}
2602
2603
	}
2604
2605
	/**
2606
	 * This magic method is executed prior to any serialization of the object
2607
	 * @see __wakeup()
2608
	 *
2609
	 * @access	public
2610
	 *
2611
	 * @return	array		Properties to be serialized
2612
	 */
2613
	public function __sleep() {
2614
2615
		// SimpleXMLElement objects can't be serialized, thus save the XML as string for serialization
2616
		$this->asXML = $this->xml->asXML();
2617
2618
		return array ('uid', 'pid', 'recordId', 'parentId', 'asXML');
2619
2620
	}
2621
2622
	/**
2623
	 * This magic method is used for setting a string value for the object
2624
	 *
2625
	 * @access	public
2626
	 *
2627
	 * @return	string		String representing the METS object
2628
	 */
2629
	public function __toString() {
2630
2631
		$xml = new DOMDocument('1.0', 'utf-8');
2632
2633
		$xml->appendChild($xml->importNode(dom_import_simplexml($this->mets), TRUE));
2634
2635
		$xml->formatOutput = TRUE;
2636
2637
		return $xml->saveXML();
2638
2639
	}
2640
2641
	/**
2642
	 * This magic method is executed after the object is deserialized
2643
	 * @see __sleep()
2644
	 *
2645
	 * @access	public
2646
	 *
2647
	 * @return	void
2648
	 */
2649
	public function __wakeup() {
2650
2651
		// Turn off libxml's error logging.
2652
		$libxmlErrors = libxml_use_internal_errors(TRUE);
2653
2654
		// Reload XML from string.
2655
		$xml = @simplexml_load_string($this->asXML);
2656
2657
		// Reset libxml's error logging.
2658
		libxml_use_internal_errors($libxmlErrors);
2659
2660
		if ($xml !== FALSE) {
2661
2662
			$this->asXML = '';
2663
2664
			$this->xml = $xml;
2665
2666
			// Rebuild the unserializable properties.
2667
			$this->init();
2668
2669
		} else {
2670
2671
			if (TYPO3_DLOG) {
0 ignored issues
show
Bug introduced by
The constant TYPO3_DLOG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2672
2673
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->__wakeup()] Could not load XML after deserialization', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
2674
2675
			}
2676
2677
		}
2678
2679
	}
2680
2681
}
2682