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.
Passed
Push — master ( 06de54...39ad46 )
by Sebastian
03:12
created

tx_dlf_document::getTitledata()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 5
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 16
rs 8.8571
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
		'OAI' => array (
92
			'rootElement' => 'OAI-PMH',
93
			'namespaceURI' => 'http://www.openarchives.org/OAI/2.0/',
94
		),
95
		'METS' => array (
96
			'rootElement' => 'mets',
97
			'namespaceURI' => 'http://www.loc.gov/METS/',
98
		),
99
		'XLINK' => array (
100
			'rootElement' => 'xlink',
101
			'namespaceURI' => 'http://www.w3.org/1999/xlink',
102
		)
103
	);
104
105
	/**
106
	 * Are the available metadata formats loaded?
107
	 * @see $formats
108
	 *
109
	 * @var	boolean
110
	 * @access protected
111
	 */
112
	protected $formatsLoaded = FALSE;
113
114
	/**
115
	 * Are there any fulltext files available?
116
	 *
117
	 * @var boolean
118
	 * @access protected
119
	 */
120
	protected $hasFulltext = FALSE;
121
122
	/**
123
	 * Last searched logical and physical page
124
	 *
125
	 * @var	array
126
	 * @access protected
127
	 */
128
	protected $lastSearchedPhysicalPage = array ('logicalPage' => NULL, 'physicalPage' => NULL);
129
130
	/**
131
	 * This holds the documents location
132
	 *
133
	 * @var	string
134
	 * @access protected
135
	 */
136
	protected $location = '';
137
138
	/**
139
	 * This holds the logical units
140
	 *
141
	 * @var	array
142
	 * @access protected
143
	 */
144
	protected $logicalUnits = array ();
145
146
	/**
147
	 * This holds the documents' parsed metadata array with their corresponding structMap//div's ID as array key
148
	 *
149
	 * @var	array
150
	 * @access protected
151
	 */
152
	protected $metadataArray = array ();
153
154
	/**
155
	 * Is the metadata array loaded?
156
	 * @see $metadataArray
157
	 *
158
	 * @var	boolean
159
	 * @access protected
160
	 */
161
	protected $metadataArrayLoaded = FALSE;
162
163
	/**
164
	 * This holds the XML file's METS part as SimpleXMLElement object
165
	 *
166
	 * @var	SimpleXMLElement
167
	 * @access protected
168
	 */
169
	protected $mets;
170
171
	/**
172
	 * The holds the total number of pages
173
	 *
174
	 * @var	integer
175
	 * @access protected
176
	 */
177
	protected $numPages = 0;
178
179
	/**
180
	 * This holds the UID of the parent document or zero if not multi-volumed
181
	 *
182
	 * @var	integer
183
	 * @access protected
184
	 */
185
	protected $parentId = 0;
186
187
	/**
188
	 * This holds the physical structure
189
	 *
190
	 * @var	array
191
	 * @access protected
192
	 */
193
	protected $physicalStructure = array ();
194
195
	/**
196
	 * This holds the physical structure metadata
197
	 *
198
	 * @var	array
199
	 * @access protected
200
	 */
201
	protected $physicalStructureInfo = array ();
202
203
	/**
204
	 * Is the physical structure loaded?
205
	 * @see $physicalStructure
206
	 *
207
	 * @var	boolean
208
	 * @access protected
209
	 */
210
	protected $physicalStructureLoaded = FALSE;
211
212
	/**
213
	 * This holds the PID of the document or zero if not in database
214
	 *
215
	 * @var	integer
216
	 * @access protected
217
	 */
218
	protected $pid = 0;
219
220
	/**
221
	 * Is the document instantiated successfully?
222
	 *
223
	 * @var	boolean
224
	 * @access protected
225
	 */
226
	protected $ready = FALSE;
227
228
	/**
229
	 * The METS file's record identifier
230
	 *
231
	 * @var	string
232
	 * @access protected
233
	 */
234
	protected $recordId;
235
236
	/**
237
	 * This holds the singleton object of the document
238
	 *
239
	 * @var	array (tx_dlf_document)
240
	 * @access protected
241
	 */
242
	protected static $registry = array ();
243
244
	/**
245
	 * This holds the UID of the root document or zero if not multi-volumed
246
	 *
247
	 * @var	integer
248
	 * @access protected
249
	 */
250
	protected $rootId = 0;
251
252
	/**
253
	 * Is the root id loaded?
254
	 * @see $rootId
255
	 *
256
	 * @var	boolean
257
	 * @access protected
258
	 */
259
	protected $rootIdLoaded = FALSE;
260
261
	/**
262
	 * This holds the smLinks between logical and physical structMap
263
	 *
264
	 * @var	array
265
	 * @access protected
266
	 */
267
	protected $smLinks = array ('l2p' => array (), 'p2l' => array ());
268
269
	/**
270
	 * Are the smLinks loaded?
271
	 * @see $smLinks
272
	 *
273
	 * @var	boolean
274
	 * @access protected
275
	 */
276
	protected $smLinksLoaded = FALSE;
277
278
	/**
279
	 * This holds the logical structure
280
	 *
281
	 * @var	array
282
	 * @access protected
283
	 */
284
	protected $tableOfContents = array ();
285
286
	/**
287
	 * Is the table of contents loaded?
288
	 * @see $tableOfContents
289
	 *
290
	 * @var	boolean
291
	 * @access protected
292
	 */
293
	protected $tableOfContentsLoaded = FALSE;
294
295
	/**
296
	 * This holds the document's thumbnail location.
297
	 *
298
	 * @var	string
299
	 * @access protected
300
	 */
301
	protected $thumbnail = '';
302
303
	/**
304
	 * Is the document's thumbnail location loaded?
305
	 * @see $thumbnail
306
	 *
307
	 * @var	boolean
308
	 * @access protected
309
	 */
310
	protected $thumbnailLoaded = FALSE;
311
312
	/**
313
	 * This holds the toplevel structure's @ID
314
	 *
315
	 * @var	string
316
	 * @access protected
317
	 */
318
	protected $toplevelId = '';
319
320
	/**
321
	 * This holds the UID or the URL of the document
322
	 *
323
	 * @var	mixed
324
	 * @access protected
325
	 */
326
	protected $uid = 0;
327
328
	/**
329
	 * This holds the whole XML file as SimpleXMLElement object
330
	 *
331
	 * @var	SimpleXMLElement
332
	 * @access protected
333
	 */
334
	protected $xml;
335
336
	/**
337
	 * This clears the static registry to prevent memory exhaustion
338
	 *
339
	 * @access	public
340
	 *
341
	 * @return	void
342
	 */
343
	public static function clearRegistry() {
344
345
		// Reset registry array.
346
		self::$registry = array ();
347
348
	}
349
350
	/**
351
	 * This gets the location of a file representing a physical page or track
352
	 *
353
	 * @access	public
354
	 *
355
	 * @param	string		$id: The @ID attribute of the file node
356
	 *
357
	 * @return	string		The file's location as URL
358
	 */
359 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...
360
361
		if (!empty($id) && ($location = $this->mets->xpath('./mets:fileSec/mets:fileGrp/mets:file[@ID="'.$id.'"]/mets:FLocat[@LOCTYPE="URL"]'))) {
362
363
			return (string) $location[0]->attributes('http://www.w3.org/1999/xlink')->href;
364
365
		} else {
366
367
			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...
368
369
				\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...
370
371
			}
372
373
			return '';
374
375
		}
376
377
	}
378
379
	/**
380
	 * This gets the MIME type of a file representing a physical page or track
381
	 *
382
	 * @access	public
383
	 *
384
	 * @param	string		$id: The @ID attribute of the file node
385
	 *
386
	 * @return	string		The file's MIME type
387
	 */
388 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...
389
390
		if (!empty($id) && ($mimetype = $this->mets->xpath('./mets:fileSec/mets:fileGrp/mets:file[@ID="'.$id.'"]/@MIMETYPE'))) {
391
392
			return (string) $mimetype[0];
393
394
		} else {
395
396
			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...
397
398
				\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...
399
400
			}
401
402
			return '';
403
404
		}
405
406
	}
407
408
	/**
409
	 * This is a singleton class, thus an instance must be created by this method
410
	 *
411
	 * @access	public
412
	 *
413
	 * @param	mixed		$uid: The unique identifier of the document to parse or URL of XML file
414
	 * @param	integer		$pid: If > 0, then only document with this PID gets loaded
415
	 * @param	boolean		$forceReload: Force reloading the document instead of returning the cached instance
416
	 *
417
	 * @return	&tx_dlf_document		Instance of this class
418
	 */
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...
419
	public static function &getInstance($uid, $pid = 0, $forceReload = FALSE) {
420
421
		// Sanitize input.
422
		$pid = max(intval($pid), 0);
423
424
		if (!$forceReload) {
425
426
			$regObj = md5($uid);
427
428
			if (is_object(self::$registry[$regObj]) && self::$registry[$regObj] instanceof self) {
429
430
				// Check if instance has given PID.
431
				if (!$pid || !self::$registry[$regObj]->pid || $pid == self::$registry[$regObj]->pid) {
432
433
					// Return singleton instance if available.
434
					return self::$registry[$regObj];
435
436
				}
437
438
			} else {
439
440
				// Check the user's session...
441
				$sessionData = tx_dlf_helper::loadFromSession(get_called_class());
442
443
				if (is_object($sessionData[$regObj]) && $sessionData[$regObj] instanceof self) {
444
445
					// Check if instance has given PID.
446
					if (!$pid || !$sessionData[$regObj]->pid || $pid == $sessionData[$regObj]->pid) {
447
448
						// ...and restore registry.
449
						self::$registry[$regObj] = $sessionData[$regObj];
450
451
						return self::$registry[$regObj];
452
453
					}
454
455
				}
456
457
			}
458
459
		}
460
461
		// Create new instance...
462
		$instance = new self($uid, $pid);
463
464
		// ...and save it to registry.
465
		if ($instance->ready) {
466
467
			self::$registry[md5($instance->uid)] = $instance;
468
469
			if ($instance->uid != $instance->location) {
470
471
				self::$registry[md5($instance->location)] = $instance;
472
473
			}
474
475
			// Load extension configuration
476
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
477
478
			// Save registry to session if caching is enabled.
479
			if (!empty($extConf['caching'])) {
480
481
				tx_dlf_helper::saveToSession(self::$registry, get_class($instance));
482
483
			}
484
485
		}
486
487
		// Return new instance.
488
		return $instance;
489
490
	}
491
492
	/**
493
	 * This gets details about a logical structure element
494
	 *
495
	 * @access	public
496
	 *
497
	 * @param	string		$id: The @ID attribute of the logical structure node
498
	 * @param	boolean		$recursive: Whether to include the child elements
499
	 *
500
	 * @return	array		Array of the element's id, label, type and physical page indexes/mptr link
501
	 */
502
	public function getLogicalStructure($id, $recursive = FALSE) {
503
504
		$details = array ();
505
506
		// Is the requested logical unit already loaded?
507
		if (!$recursive && !empty($this->logicalUnits[$id])) {
508
509
			// Yes. Return it.
510
			return $this->logicalUnits[$id];
511
512
		} elseif (!empty($id)) {
513
514
			// Get specified logical unit.
515
			$divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]');
516
517
		} else {
518
519
			// Get all logical units at top level.
520
			$divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]/mets:div');
521
522
		}
523
524
		if (!empty($divs)) {
525
526
			if (!$recursive) {
527
528
				// Get the details for the first xpath hit.
529
				$details = $this->getLogicalStructureInfo($divs[0]);
530
531
			} else {
532
533
				// Walk the logical structure recursively and fill the whole table of contents.
534
				foreach ($divs as $div) {
535
536
					$this->tableOfContents[] = $this->getLogicalStructureInfo($div, TRUE);
537
538
				}
539
540
			}
541
542
		}
543
544
		return $details;
545
546
	}
547
548
	/**
549
	 * This gets details about a logical structure element
550
	 *
551
	 * @access	protected
552
	 *
553
	 * @param	SimpleXMLElement		$structure: The logical structure node
554
	 * @param	boolean		$recursive: Whether to include the child elements
555
	 *
556
	 * @return	array		Array of the element's id, label, type and physical page indexes/mptr link
557
	 */
558
	protected function getLogicalStructureInfo(SimpleXMLElement $structure, $recursive = FALSE) {
559
560
		// Get attributes.
561
		foreach ($structure->attributes() as $attribute => $value) {
562
563
			$attributes[$attribute] = (string) $value;
564
565
		}
566
567
		// Load plugin configuration.
568
		$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
569
570
		// Extract identity information.
571
		$details = array ();
572
573
		$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 561. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
574
575
		$details['dmdId'] = (isset($attributes['DMDID']) ?  $attributes['DMDID'] : '');
576
577
		$details['label'] = (isset($attributes['LABEL']) ? $attributes['LABEL'] : '');
578
579
		$details['orderlabel'] = (isset($attributes['ORDERLABEL']) ? $attributes['ORDERLABEL'] : '');
580
581
		$details['contentIds'] = (isset($attributes['CONTENTIDS']) ? $attributes['CONTENTIDS'] : '');
582
583
		$details['volume'] = '';
584
585
		// Set volume information only if no label is set and this is the toplevel structure element.
586
		if (empty($details['label']) && $details['id'] == $this->_getToplevelId()) {
587
588
			$metadata = $this->getMetadata($details['id']);
589
590 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...
591
592
				$details['volume'] = $metadata['volume'][0];
593
594
			}
595
596
		}
597
598
		$details['pagination'] = '';
599
600
		$details['type'] = $attributes['TYPE'];
601
602
		$details['thumbnailId'] = '';
603
604
		// Load smLinks.
605
		$this->_getSmLinks();
606
607
		// Load physical structure.
608
		$this->_getPhysicalStructure();
609
610
		// Get the physical page or external file this structure element is pointing at.
611
		$details['points'] = '';
612
613
		// Is there a mptr node?
614
		if (count($structure->children('http://www.loc.gov/METS/')->mptr)) {
615
616
			// Yes. Get the file reference.
617
			$details['points'] = (string) $structure->children('http://www.loc.gov/METS/')->mptr[0]->attributes('http://www.w3.org/1999/xlink')->href;
618
619
		// Are there any physical elements and is this logical unit linked to at least one of them?
620
		} elseif (!empty($this->physicalStructure) && array_key_exists($details['id'], $this->smLinks['l2p'])) {
621
622
			$details['points'] = max(intval(array_search($this->smLinks['l2p'][$details['id']][0], $this->physicalStructure, TRUE)), 1);
623
624
			if (!empty($this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['files'][$extConf['fileGrpThumbs']])) {
625
626
				$details['thumbnailId'] = $this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['files'][$extConf['fileGrpThumbs']];
627
628
			}
629
630
			// Get page/track number of the first page/track related to this structure element.
631
			$details['pagination'] = $this->physicalStructureInfo[$this->smLinks['l2p'][$details['id']][0]]['orderlabel'];
632
633
		// Is this the toplevel structure element?
634
		} elseif ($details['id'] == $this->_getToplevelId()) {
635
636
			// Yes. Point to itself.
637
			$details['points'] = 1;
638
639
			if (!empty($this->physicalStructure) && !empty($this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']])) {
640
641
				$details['thumbnailId'] = $this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']];
642
643
			}
644
645
		}
646
647
		// Get the files this structure element is pointing at.
648
		$details['files'] = array ();
649
650
		$fileUse = $this->_getFileGrps();
651
652
		// Get the file representations from fileSec node.
653
		foreach ($structure->children('http://www.loc.gov/METS/')->fptr as $fptr) {
654
655
			// Check if file has valid @USE attribute.
656
			if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
657
658
				$details['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
659
660
			}
661
662
		}
663
664
		// Keep for later usage.
665
		$this->logicalUnits[$details['id']] = $details;
666
667
		// Walk the structure recursively? And are there any children of the current element?
668
		if ($recursive && count($structure->children('http://www.loc.gov/METS/')->div)) {
669
670
			$details['children'] = array ();
671
672
			foreach ($structure->children('http://www.loc.gov/METS/')->div as $child) {
673
674
				// Repeat for all children.
675
				$details['children'][] = $this->getLogicalStructureInfo($child, TRUE);
676
677
			}
678
679
		}
680
681
		return $details;
682
683
	}
684
685
	/**
686
	 * This extracts all the metadata for a logical structure node
687
	 *
688
	 * @access	public
689
	 *
690
	 * @param	string		$id: The @ID attribute of the logical structure node
691
	 * @param	integer		$cPid: The PID for the metadata definitions
692
	 * 						(defaults to $this->cPid or $this->pid)
693
	 *
694
	 * @return	array		The logical structure node's parsed metadata array
695
	 */
696
	public function getMetadata($id, $cPid = 0) {
697
698
		// Save parameter for logging purposes.
699
		$_cPid = $cPid;
700
701
		// Make sure $cPid is a non-negative integer.
702
		$cPid = max(intval($cPid), 0);
703
704
		// If $cPid is not given, try to get it elsewhere.
705
		if (!$cPid && ($this->cPid || $this->pid)) {
706
707
			// Retain current PID.
708
			$cPid = ($this->cPid ? $this->cPid : $this->pid);
709
710
		} elseif (!$cPid) {
711
712
			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...
713
714
				\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...
715
716
			}
717
718
			return array ();
719
720
		}
721
722
		// Get metadata from parsed metadata array if available.
723
		if (!empty($this->metadataArray[$id]) && $this->metadataArray[0] == $cPid) {
724
725
			return $this->metadataArray[$id];
726
727
		}
728
729
		// Initialize metadata array with empty values.
730
		$metadata = array (
731
			'title' => array (),
732
			'title_sorting' => array (),
733
			'author' => array (),
734
			'place' => array (),
735
			'year' => array (),
736
			'prod_id' => array (),
737
			'record_id' => array (),
738
			'opac_id' => array (),
739
			'union_id' => array (),
740
			'urn' => array (),
741
			'purl' => array (),
742
			'type' => array (),
743
			'volume' => array (),
744
			'volume_sorting' => array (),
745
			'collection' => array (),
746
			'owner' => array (),
747
		);
748
749
		// Get the logical structure node's DMDID.
750
		if (!empty($this->logicalUnits[$id])) {
751
752
			$dmdId = $this->logicalUnits[$id]['dmdId'];
753
754
		} else {
755
756
			$dmdId = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]/@DMDID');
757
758
			$dmdId = (string) $dmdId[0];
759
760
		}
761
762
		if (!empty($dmdId)) {
763
764
			// Load available metadata formats and dmdSecs.
765
			$this->loadFormats();
766
767
			$this->_getDmdSec();
768
769
			// Is this metadata format supported?
770
			if (!empty($this->formats[$this->dmdSec[$dmdId]['type']])) {
771
772
				if (!empty($this->formats[$this->dmdSec[$dmdId]['type']]['class'])) {
773
774
					$class = $this->formats[$this->dmdSec[$dmdId]['type']]['class'];
775
776
					// Get the metadata from class.
777
					if (class_exists($class) && ($obj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($class)) instanceof tx_dlf_format) {
778
779
						$obj->extractMetadata($this->dmdSec[$dmdId]['xml'], $metadata);
780
781 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...
782
783
						if (TYPO3_DLOG) {
784
785
							\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...
786
787
						}
788
789
					}
790
791
				}
792
793 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...
794
795
				if (TYPO3_DLOG) {
796
797
					\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);
798
799
				}
800
801
				return array ();
802
803
			}
804
805
			// Get the structure's type.
806
			if (!empty($this->logicalUnits[$id])) {
807
808
				$metadata['type'] = array ($this->logicalUnits[$id]['type']);
809
810
			} else {
811
812
				$struct = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$id.'"]/@TYPE');
813
814
				$metadata['type'] = array ((string) $struct[0]);
815
816
			}
817
818
			// Get the additional metadata from database.
819
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
820
				'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',
821
				'tx_dlf_metadata,tx_dlf_metadataformat,tx_dlf_formats',
822
				'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'),
823
				'',
824
				'',
825
				''
826
			);
827
828
			// We need a DOMDocument here, because SimpleXML doesn't support XPath functions properly.
829
			$domNode = dom_import_simplexml($this->dmdSec[$dmdId]['xml']);
830
831
			$domXPath = new DOMXPath($domNode->ownerDocument);
832
833
			$this->registerNamespaces($domXPath);
834
835
			// OK, now make the XPath queries.
836
			while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
837
838
				// Set metadata field's value(s).
839
				if ($resArray['format'] > 0 && !empty($resArray['xpath']) && ($values = $domXPath->evaluate($resArray['xpath'], $domNode))) {
840
841
					if ($values instanceof DOMNodeList && $values->length > 0) {
842
843
						$metadata[$resArray['index_name']] = array ();
844
845
						foreach ($values as $value) {
846
847
							$metadata[$resArray['index_name']][] = trim((string) $value->nodeValue);
848
849
						}
850
851 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...
852
853
						$metadata[$resArray['index_name']] = array (trim((string) $values));
854
855
					}
856
857
				}
858
859
				// Set default value if applicable.
860
				if (empty($metadata[$resArray['index_name']][0])) {
861
862
					$metadata[$resArray['index_name']] = array ($resArray['default_value']);
863
864
				}
865
866
				// Set sorting value if applicable.
867
				if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) {
868
869
					if ($resArray['format'] > 0 && !empty($resArray['xpath_sorting']) && ($values = $domXPath->evaluate($resArray['xpath_sorting'], $domNode))) {
870
871
						if ($values instanceof DOMNodeList && $values->length > 0) {
872
873
							$metadata[$resArray['index_name'].'_sorting'][0] = trim((string) $values->item(0)->nodeValue);
874
875 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...
876
877
							$metadata[$resArray['index_name'].'_sorting'][0] = trim((string) $values);
878
879
						}
880
881
					}
882
883
					if (empty($metadata[$resArray['index_name'].'_sorting'][0])) {
884
885
						$metadata[$resArray['index_name'].'_sorting'][0] = $metadata[$resArray['index_name']][0];
886
887
					}
888
889
				}
890
891
			}
892
893
			// Set title to empty string if not present.
894 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...
895
896
				$metadata['title'][0] = '';
897
898
				$metadata['title_sorting'][0] = '';
899
900
			}
901
902
		} else {
903
904
			// There is no dmdSec for this structure node.
905
			return array ();
906
907
		}
908
909
		return $metadata;
910
911
	}
912
913
	/**
914
	 * This returns the first corresponding physical page number of a given logical page label
915
	 *
916
	 * @access	public
917
	 *
918
	 * @param	string		$logicalPage: The label (or a part of the label) of the logical page
919
	 *
920
	 * @return	integer		The physical page number
921
	 */
922
	public function getPhysicalPage($logicalPage) {
923
924
		if(!empty( $this->lastSearchedPhysicalPage['logicalPage']) &&  $this->lastSearchedPhysicalPage['logicalPage'] == $logicalPage) {
925
926
			return $this->lastSearchedPhysicalPage['physicalPage'];
927
928
		} else {
929
930
			$physicalPage = 0;
931
932
			foreach($this->physicalStructureInfo as $page) {
933
934
				if(strpos($page['orderlabel'], $logicalPage) !== false){
935
936
					$this->lastSearchedPhysicalPage['logicalPage'] = $logicalPage;
937
					$this->lastSearchedPhysicalPage['physicalPage'] = $physicalPage;
938
939
					return $physicalPage;
940
941
				}
942
943
				$physicalPage++;
944
945
			}
946
947
		}
948
949
		return 1;
950
951
	}
952
953
	/**
954
	 * This determines a title for the given document
955
	 *
956
	 * @access	public
957
	 *
958
	 * @param	integer		$uid: The UID of the document
959
	 * @param	boolean		$recursive: Search superior documents for a title, too?
960
	 *
961
	 * @return	string		The title of the document itself or a parent document
962
	 */
963
	public static function getTitle($uid, $recursive = FALSE) {
964
965
		// Save parameter for logging purposes.
966
		$_uid = $uid;
967
968
		$title = '';
969
970
		// Sanitize input.
971
		$uid = max(intval($uid), 0);
972
973
		if ($uid) {
974
975
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
976
				'tx_dlf_documents.title,tx_dlf_documents.partof',
977
				'tx_dlf_documents',
978
				'tx_dlf_documents.uid='.$uid.tx_dlf_helper::whereClause('tx_dlf_documents'),
979
				'',
980
				'',
981
				'1'
982
			);
983
984
			if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
985
986
				// Get title information.
987
				list ($title, $partof) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
988
989
				// Search parent documents recursively for a title?
990
				if ($recursive && empty($title) && intval($partof) && $partof != $uid) {
991
992
					$title = self::getTitle($partof, TRUE);
993
994
				}
995
996
			} else {
997
998
				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...
999
1000
					\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...
1001
1002
				}
1003
1004
			}
1005
1006
		} else {
1007
1008
			if (TYPO3_DLOG) {
1009
1010
				\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...
1011
1012
			}
1013
1014
		}
1015
1016
		return $title;
1017
1018
	}
1019
1020
	/**
1021
	 * This extracts all the metadata for the toplevel logical structure node
1022
	 *
1023
	 * @access	public
1024
	 *
1025
	 * @param	integer		$cPid: The PID for the metadata definitions
1026
	 *
1027
	 * @return	array		The logical structure node's parsed metadata array
1028
	 */
1029
	public function getTitledata($cPid = 0) {
1030
1031
		$titledata = $this->getMetadata($this->_getToplevelId(), $cPid);
1032
1033
		// Set record identifier for METS file if not present.
1034
		if (is_array($titledata) && array_key_exists('record_id', $titledata)) {
1035
1036
			if (!empty($this->recordId) && !in_array($this->recordId, $titledata['record_id'])) {
1037
1038
				array_unshift($titledata['record_id'], $this->recordId);
1039
1040
			}
1041
1042
		};
1043
1044
		return $titledata;
1045
1046
	}
1047
1048
	/**
1049
	 * This sets some basic class properties
1050
	 *
1051
	 * @access	protected
1052
	 *
1053
	 * @return	void
1054
	 */
1055
	protected function init() {
1056
1057
		// Get METS node from XML file.
1058
		$this->registerNamespaces($this->xml);
1059
1060
		$mets = $this->xml->xpath('//mets:mets');
1061
1062
		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...
1063
1064
			$this->mets = $mets[0];
1065
1066
			// Register namespaces.
1067
			$this->registerNamespaces($this->mets);
1068
1069
		} else {
1070
1071
			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...
1072
1073
				\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...
1074
1075
			}
1076
1077
		}
1078
1079
	}
1080
1081
	/**
1082
	 * Load XML file from URL
1083
	 *
1084
	 * @access	protected
1085
	 *
1086
	 * @param	string		$location: The URL of the file to load
1087
	 *
1088
	 * @return	boolean		TRUE on success or FALSE on failure
1089
	 */
1090
	protected function load($location) {
1091
1092
		// Load XML file.
1093
		if (\TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($location)) {
1094
1095
			// Load extension configuration
1096
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['dlf']);
1097
1098
			// Set user-agent to identify self when fetching XML data.
1099
			if (!empty($extConf['useragent'])) {
1100
1101
				@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

1101
				/** @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...
1102
1103
			}
1104
1105
			// Turn off libxml's error logging.
1106
			$libxmlErrors = libxml_use_internal_errors(TRUE);
1107
1108
			// Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
1109
			$previousValueOfEntityLoader = libxml_disable_entity_loader(TRUE);
1110
1111
			// Load XML from file.
1112
			$xml = simplexml_load_string(\TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($location));
1113
1114
			// reset entity loader setting
1115
			libxml_disable_entity_loader($previousValueOfEntityLoader);
1116
1117
			// Reset libxml's error logging.
1118
			libxml_use_internal_errors($libxmlErrors);
1119
1120
			// Set some basic properties.
1121
			if ($xml !== FALSE) {
1122
1123
				$this->xml = $xml;
1124
1125
				return TRUE;
1126
1127
			} else {
1128
1129
				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...
1130
1131
					\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...
1132
1133
				}
1134
1135
			}
1136
1137
		} else {
1138
1139
			if (TYPO3_DLOG) {
1140
1141
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->load('.$location.')] Invalid file location "'.$location.'" for document loading', self::$extKey, SYSLOG_SEVERITY_ERROR);
1142
1143
			}
1144
1145
		}
1146
1147
		return FALSE;
1148
1149
	}
1150
1151
	/**
1152
	 * Register all available data formats
1153
	 *
1154
	 * @access	protected
1155
	 *
1156
	 * @return	void
1157
	 */
1158
	protected function loadFormats() {
1159
1160
		if (!$this->formatsLoaded) {
1161
1162
			// Get available data formats from database.
1163
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1164
				'tx_dlf_formats.type AS type,tx_dlf_formats.root AS root,tx_dlf_formats.namespace AS namespace,tx_dlf_formats.class AS class',
1165
				'tx_dlf_formats',
1166
				'tx_dlf_formats.pid=0'.tx_dlf_helper::whereClause('tx_dlf_formats'),
1167
				'',
1168
				'',
1169
				''
1170
			);
1171
1172
			while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
1173
1174
				// Update format registry.
1175
				$this->formats[$resArray['type']] = array (
1176
					'rootElement' => $resArray['root'],
1177
					'namespaceURI' => $resArray['namespace'],
1178
					'class' => $resArray['class']
1179
				);
1180
1181
			}
1182
1183
			$this->formatsLoaded = TRUE;
1184
1185
		}
1186
1187
	}
1188
1189
	/**
1190
	 * Register all available namespaces for a SimpleXMLElement object
1191
	 *
1192
	 * @access	public
1193
	 *
1194
	 * @param	SimpleXMLElement|DOMXPath		&$obj: SimpleXMLElement or DOMXPath object
1195
	 *
1196
	 * @return	void
1197
	 */
1198
	public function registerNamespaces(&$obj) {
1199
1200
		$this->loadFormats();
1201
1202
		// Do we have a SimpleXMLElement or DOMXPath object?
1203
		if ($obj instanceof SimpleXMLElement) {
1204
1205
			$method = 'registerXPathNamespace';
1206
1207
		} elseif ($obj instanceof DOMXPath) {
1208
1209
			$method = 'registerNamespace';
1210
1211
		} else {
1212
1213
			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...
1214
1215
				\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...
1216
1217
			}
1218
1219
			return;
1220
1221
		}
1222
1223
		// Register metadata format's namespaces.
1224
		foreach ($this->formats as $enc => $conf) {
1225
1226
			$obj->$method(strtolower($enc), $conf['namespaceURI']);
1227
1228
		}
1229
1230
	}
1231
1232
	/**
1233
	 * This saves the document to the database and index
1234
	 *
1235
	 * @access	public
1236
	 *
1237
	 * @param	integer		$pid: The PID of the saved record
1238
	 * @param	integer		$core: The UID of the Solr core for indexing
1239
	 *
1240
	 * @return	boolean		TRUE on success or FALSE on failure
1241
	 */
1242
	public function save($pid = 0, $core = 0) {
1243
1244
		// Save parameters for logging purposes.
1245
		$_pid = $pid;
1246
1247
		$_core = $core;
1248
1249
		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...
1250
1251
			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...
1252
1253
				\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...
1254
1255
			}
1256
1257
			return FALSE;
1258
1259
		}
1260
1261
		// Make sure $pid is a non-negative integer.
1262
		$pid = max(intval($pid), 0);
1263
1264
		// Make sure $core is a non-negative integer.
1265
		$core = max(intval($core), 0);
1266
1267
		// If $pid is not given, try to get it elsewhere.
1268
		if (!$pid && $this->pid) {
1269
1270
			// Retain current PID.
1271
			$pid = $this->pid;
1272
1273
		} elseif (!$pid) {
1274
1275
			if (TYPO3_DLOG) {
1276
1277
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] Invalid PID "'.$pid.'" for document saving', self::$extKey, SYSLOG_SEVERITY_ERROR);
1278
1279
			}
1280
1281
			return FALSE;
1282
1283
		}
1284
1285
		// Set PID for metadata definitions.
1286
		$this->cPid = $pid;
1287
1288
		// Set UID placeholder if not updating existing record.
1289
		if ($pid != $this->pid) {
1290
1291
			$this->uid = uniqid('NEW');
1292
1293
		}
1294
1295
		// Get metadata array.
1296
		$metadata = $this->getTitledata($pid);
1297
1298
		// Check for record identifier.
1299
		if (empty($metadata['record_id'][0])) {
1300
1301
			if (TYPO3_DLOG) {
1302
1303
				\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->save('.$_pid.', '.$_core.')] No record identifier found to avoid duplication', self::$extKey, SYSLOG_SEVERITY_ERROR);
1304
1305
			}
1306
1307
			return FALSE;
1308
1309
		}
1310
1311
		// Load plugin configuration.
1312
		$conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
1313
1314
		// Get UID for user "_cli_dlf".
1315
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1316
			'be_users.uid AS uid',
1317
			'be_users',
1318
			'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...
1319
			'',
1320
			'',
1321
			'1'
1322
		);
1323
1324
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1325
1326
			list ($be_user) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1327
1328
		} else {
1329
1330
			if (TYPO3_DLOG) {
1331
1332
				\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);
1333
1334
			}
1335
1336
			return FALSE;
1337
1338
		}
1339
1340
		// Get UID for structure type.
1341
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1342
			'tx_dlf_structures.uid AS uid',
1343
			'tx_dlf_structures',
1344
			'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'),
1345
			'',
1346
			'',
1347
			'1'
1348
		);
1349
1350
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1351
1352
			list ($structure) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1353
1354 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...
1355
1356
			if (TYPO3_DLOG) {
1357
1358
				\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'),
1359
									       self::$extKey, SYSLOG_SEVERITY_ERROR);
1360
1361
			}
1362
1363
			return FALSE;
1364
1365
		}
1366
1367
		$metadata['type'][0] = $structure;
1368
1369
		// Get UIDs for collections.
1370
		$collections = array ();
1371
1372
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1373
			'tx_dlf_collections.index_name AS index_name,tx_dlf_collections.uid AS uid',
1374
			'tx_dlf_collections',
1375
			'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'),
1376
			'',
1377
			'',
1378
			''
1379
		);
1380
1381
		for ($i = 0, $j = $GLOBALS['TYPO3_DB']->sql_num_rows($result); $i < $j; $i++) {
1382
1383
			$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
1384
1385
			$collUid[$resArray['index_name']] = $resArray['uid'];
1386
1387
		}
1388
1389
		foreach ($metadata['collection'] as $collection) {
1390
1391
			if (!empty($collUid[$collection])) {
1392
1393
				// Add existing collection's UID.
1394
				$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...
1395
1396
			} else {
1397
1398
				// Insert new collection.
1399
				$collNewUid = uniqid('NEW');
1400
1401
				$collData['tx_dlf_collections'][$collNewUid] = array (
1402
					'pid' => $pid,
1403
					'label' => $collection,
1404
					'index_name' => $collection,
1405
					'oai_name' => (!empty($conf['publishNewCollections']) ? $collection : ''),
1406
					'description' => '',
1407
					'documents' => 0,
1408
					'owner' => 0,
1409
					'status' => 0,
1410
				);
1411
1412
				$substUid = tx_dlf_helper::processDB($collData);
1413
1414
				// Prevent double insertion.
1415
				unset ($collData);
1416
1417
				// Add new collection's UID.
1418
				$collections[] = $substUid[$collNewUid];
1419
1420
				if (!defined('TYPO3_cliMode')) {
1421
1422
					$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1423
						'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1424
						htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.newCollection'), $collection, $substUid[$collNewUid])),
1425
						tx_dlf_helper::getLL('flash.attention', TRUE),
1426
						\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...
1427
						TRUE
1428
					);
1429
1430
					tx_dlf_helper::addMessage($message);
1431
1432
				}
1433
1434
			}
1435
1436
		}
1437
1438
		// Preserve user-defined collections.
1439
		$result = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query(
1440
			'tx_dlf_collections.uid AS uid',
1441
			'tx_dlf_documents',
1442
			'tx_dlf_relations',
1443
			'tx_dlf_collections',
1444
			'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'),
1445
			'',
1446
			'',
1447
			''
1448
		);
1449
1450
		for ($i = 0, $j = $GLOBALS['TYPO3_DB']->sql_num_rows($result); $i < $j; $i++) {
1451
1452
			list ($collections[]) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1453
1454
		}
1455
1456
		$metadata['collection'] = $collections;
1457
1458
		// Get UID for owner.
1459
		$owner = !empty($metadata['owner'][0]) ? $metadata['owner'][0] : 'default';
1460
1461
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1462
			'tx_dlf_libraries.uid AS uid',
1463
			'tx_dlf_libraries',
1464
			'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'),
1465
			'',
1466
			'',
1467
			'1'
1468
		);
1469
1470
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result)) {
1471
1472
			list ($ownerUid) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
1473
1474
		} else {
1475
1476
			// Insert new library.
1477
			$libNewUid = uniqid('NEW');
1478
1479
			$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...
1480
				'pid' => $pid,
1481
				'label' => $owner,
1482
				'index_name' => $owner,
1483
				'website' => '',
1484
				'contact' => '',
1485
				'image' => '',
1486
				'oai_label' => '',
1487
				'oai_base' => '',
1488
				'opac_label' => '',
1489
				'opac_base' => '',
1490
				'union_label' => '',
1491
				'union_base' => '',
1492
			);
1493
1494
			$substUid = tx_dlf_helper::processDB($libData);
1495
1496
			// Add new library's UID.
1497
			$ownerUid = $substUid[$libNewUid];
1498
1499
			if (!defined('TYPO3_cliMode')) {
1500
1501
				$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1502
					'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1503
					htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.newLibrary'), $owner, $ownerUid)),
1504
					tx_dlf_helper::getLL('flash.attention', TRUE),
1505
					\TYPO3\CMS\Core\Messaging\FlashMessage::INFO,
1506
					TRUE
1507
				);
1508
1509
				tx_dlf_helper::addMessage($message);
1510
1511
			}
1512
1513
		}
1514
1515
		$metadata['owner'][0] = $ownerUid;
1516
1517
		// Get UID of parent document.
1518
		$partof = 0;
1519
1520
		// Get the closest ancestor of the current document which has a MPTR child.
1521
		$parentMptr = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="'.$this->_getToplevelId().'"]/ancestor::mets:div[./mets:mptr][1]/mets:mptr');
1522
1523
		if (!empty($parentMptr[0])) {
1524
1525
			$parentLocation = (string) $parentMptr[0]->attributes('http://www.w3.org/1999/xlink')->href;
1526
1527
			if ($parentLocation != $this->location) {
1528
1529
				$parentDoc =& tx_dlf_document::getInstance($parentLocation, $pid);
1530
1531
				if ($parentDoc->ready) {
1532
1533
					if ($parentDoc->pid != $pid) {
1534
1535
						$parentDoc->save($pid, $core);
1536
1537
					}
1538
1539
					$partof = $parentDoc->uid;
1540
1541
				}
1542
1543
			}
1544
1545
		}
1546
1547
		// Use the date of publication or title as alternative sorting metric for parts of multi-part works.
1548
		if (!empty($partof)) {
1549
1550 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...
1551
1552
				$metadata['volume'] = $metadata['year'];
1553
1554
			}
1555
1556
			if (empty($metadata['volume_sorting'][0])) {
1557
1558
				if (!empty($metadata['year_sorting'][0])) {
1559
1560
					$metadata['volume_sorting'][0] = $metadata['year_sorting'][0];
1561
1562
				} elseif (!empty($metadata['year'][0])) {
1563
1564
					$metadata['volume_sorting'][0] = $metadata['year'][0];
1565
1566
				}
1567
1568
			}
1569
1570
			// If volume_sorting is still empty, try to use title_sorting finally (workaround for newspapers)
1571 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...
1572
1573
				if (!empty($metadata['title_sorting'][0])) {
1574
1575
					$metadata['volume_sorting'][0] = $metadata['title_sorting'][0];
1576
1577
				}
1578
			}
1579
1580
		}
1581
1582
		// Get metadata for lists and sorting.
1583
		$listed = array ();
1584
1585
		$sortable = array ();
1586
1587
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
1588
			'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadata.is_listed AS is_listed,tx_dlf_metadata.is_sortable AS is_sortable',
1589
			'tx_dlf_metadata',
1590
			'(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'),
1591
			'',
1592
			'',
1593
			''
1594
		);
1595
1596
		while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
1597
1598
			if (!empty($metadata[$resArray['index_name']])) {
1599
1600
				if ($resArray['is_listed']) {
1601
1602
					$listed[$resArray['index_name']] = $metadata[$resArray['index_name']];
1603
1604
				}
1605
1606
				if ($resArray['is_sortable']) {
1607
1608
					$sortable[$resArray['index_name']] = $metadata[$resArray['index_name']][0];
1609
1610
				}
1611
1612
			}
1613
1614
		}
1615
1616
		// Fill data array.
1617
		$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...
1618
			'pid' => $pid,
1619
			$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['starttime'] => 0,
1620
			$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['endtime'] => 0,
1621
			'prod_id' => $metadata['prod_id'][0],
1622
			'location' => $this->location,
1623
			'record_id' => $metadata['record_id'][0],
1624
			'opac_id' => $metadata['opac_id'][0],
1625
			'union_id' => $metadata['union_id'][0],
1626
			'urn' => $metadata['urn'][0],
1627
			'purl' => $metadata['purl'][0],
1628
			'title' => $metadata['title'][0],
1629
			'title_sorting' => $metadata['title_sorting'][0],
1630
			'author' => implode('; ', $metadata['author']),
1631
			'year' => implode('; ', $metadata['year']),
1632
			'place' => implode('; ', $metadata['place']),
1633
			'thumbnail' => $this->_getThumbnail(TRUE),
1634
			'metadata' => serialize($listed),
1635
			'metadata_sorting' => serialize($sortable),
1636
			'structure' => $metadata['type'][0],
1637
			'partof' => $partof,
1638
			'volume' => $metadata['volume'][0],
1639
			'volume_sorting' => $metadata['volume_sorting'][0],
1640
			'collections' => $metadata['collection'],
1641
			'owner' => $metadata['owner'][0],
1642
			'solrcore' => $core,
1643
			'status' => 0,
1644
		);
1645
1646
		// Unhide hidden documents.
1647
		if (!empty($conf['unhideOnIndex'])) {
1648
1649
			$data['tx_dlf_documents'][$this->uid][$GLOBALS['TCA']['tx_dlf_documents']['ctrl']['enablecolumns']['disabled']] = 0;
1650
1651
		}
1652
1653
		// Process data.
1654
		$newIds = tx_dlf_helper::processDB($data);
1655
1656
		// Replace placeholder with actual UID.
1657
		if (strpos($this->uid, 'NEW') === 0) {
1658
1659
			$this->uid = $newIds[$this->uid];
1660
1661
			$this->pid = $pid;
1662
1663
			$this->parentId = $partof;
1664
1665
		}
1666
1667
		if (!defined('TYPO3_cliMode')) {
1668
1669
			$message = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
1670
				'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
1671
				htmlspecialchars(sprintf(tx_dlf_helper::getLL('flash.documentSaved'), $metadata['title'][0], $this->uid)),
1672
				tx_dlf_helper::getLL('flash.done', TRUE),
1673
				\TYPO3\CMS\Core\Messaging\FlashMessage::OK,
1674
				TRUE
1675
			);
1676
1677
			tx_dlf_helper::addMessage($message);
1678
1679
		}
1680
1681
		// Add document to index.
1682
		if ($core) {
1683
1684
			tx_dlf_indexing::add($this, $core);
1685
1686
		} else {
1687
1688
			if (TYPO3_DLOG) {
1689
1690
				\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...
1691
1692
			}
1693
1694
		}
1695
1696
		return TRUE;
1697
1698
	}
1699
1700
	/**
1701
	 * This returns $this->cPid via __get()
1702
	 *
1703
	 * @access	protected
1704
	 *
1705
	 * @return	integer		The PID of the metadata definitions
1706
	 */
1707
	protected function _getCPid() {
1708
1709
		return $this->cPid;
1710
1711
	}
1712
1713
	/**
1714
	 * This builds an array of the document's dmdSecs
1715
	 *
1716
	 * @access	protected
1717
	 *
1718
	 * @return	array		Array of dmdSecs with their IDs as array key
1719
	 */
1720
	protected function _getDmdSec() {
1721
1722
		if (!$this->dmdSecLoaded) {
1723
1724
			// Get available data formats.
1725
			$this->loadFormats();
1726
1727
			// Get dmdSec nodes from METS.
1728
			$dmdIds = $this->mets->xpath('./mets:dmdSec/@ID');
1729
1730
			foreach ($dmdIds as $dmdId) {
1731
1732
				if ($type = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[not(@MDTYPE="OTHER")]/@MDTYPE')) {
1733
1734 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...
1735
1736
						$type = (string) $type[0];
1737
1738
						$xml = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="'.$type.'"]/mets:xmlData/'.strtolower($type).':'.$this->formats[$type]['rootElement']);
1739
1740
					}
1741
1742
				} elseif ($type = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="OTHER"]/@OTHERMDTYPE')) {
1743
1744 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...
1745
1746
						$type = (string) $type[0];
1747
1748
						$xml = $this->mets->xpath('./mets:dmdSec[@ID="'.(string) $dmdId.'"]/mets:mdWrap[@MDTYPE="OTHER"][@OTHERMDTYPE="'.$type.'"]/mets:xmlData/'.strtolower($type).':'.$this->formats[$type]['rootElement']);
1749
1750
					}
1751
1752
				}
1753
1754
				if ($xml) {
0 ignored issues
show
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...
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...
1755
1756
					$this->dmdSec[(string) $dmdId]['type'] = $type;
1757
1758
					$this->dmdSec[(string) $dmdId]['xml'] = $xml[0];
1759
1760
					$this->registerNamespaces($this->dmdSec[(string) $dmdId]['xml']);
1761
1762
				}
1763
1764
			}
1765
1766
			$this->dmdSecLoaded = TRUE;
1767
1768
		}
1769
1770
		return $this->dmdSec;
1771
1772
	}
1773
1774
	/**
1775
	 * This builds the file ID -> USE concordance
1776
	 *
1777
	 * @access	protected
1778
	 *
1779
	 * @return	array		Array of file use groups with file IDs
1780
	 */
1781
	protected function _getFileGrps() {
1782
1783
		if (!$this->fileGrpsLoaded) {
1784
1785
			// Get configured USE attributes.
1786
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
1787
1788
			$useGrps = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $extConf['fileGrps']);
1789
1790
			if (!empty($extConf['fileGrpThumbs'])) {
1791
1792
				$useGrps[] = $extConf['fileGrpThumbs'];
1793
1794
			}
1795
1796
			if (!empty($extConf['fileGrpDownload'])) {
1797
1798
				$useGrps[] = $extConf['fileGrpDownload'];
1799
1800
			}
1801
1802
			if (!empty($extConf['fileGrpFulltext'])) {
1803
1804
				$useGrps[] = $extConf['fileGrpFulltext'];
1805
1806
			}
1807
1808
			if (!empty($extConf['fileGrpAudio'])) {
1809
1810
				$useGrps[] = $extConf['fileGrpAudio'];
1811
1812
			}
1813
1814
			// Get all file groups.
1815
			$fileGrps = $this->mets->xpath('./mets:fileSec/mets:fileGrp');
1816
1817
			// Build concordance for configured USE attributes.
1818
			foreach ($fileGrps as $fileGrp) {
1819
1820
				if (in_array((string) $fileGrp['USE'], $useGrps)) {
1821
1822
					foreach ($fileGrp->children('http://www.loc.gov/METS/')->file as $file) {
1823
1824
						$this->fileGrps[(string) $file->attributes()->ID] = (string) $fileGrp['USE'];
1825
1826
					}
1827
1828
				}
1829
1830
			}
1831
1832
			// Are there any fulltext files available?
1833
			if (!empty($extConf['fileGrpFulltext']) && in_array($extConf['fileGrpFulltext'], $this->fileGrps)) {
1834
1835
				$this->hasFulltext = TRUE;
1836
1837
			}
1838
1839
			$this->fileGrpsLoaded = TRUE;
1840
1841
		}
1842
1843
		return $this->fileGrps;
1844
1845
	}
1846
1847
	/**
1848
	 * This returns $this->hasFulltext via __get()
1849
	 *
1850
	 * @access	protected
1851
	 *
1852
	 * @return	boolean		Are there any fulltext files available?
1853
	 */
1854
	protected function _getHasFulltext() {
1855
1856
		// Are the fileGrps already loaded?
1857
		if (!$this->fileGrpsLoaded) {
1858
1859
			$this->_getFileGrps();
1860
1861
		}
1862
1863
		return $this->hasFulltext;
1864
1865
	}
1866
1867
	/**
1868
	 * This returns $this->location via __get()
1869
	 *
1870
	 * @access	protected
1871
	 *
1872
	 * @return	string		The location of the document
1873
	 */
1874
	protected function _getLocation() {
1875
1876
		return $this->location;
1877
1878
	}
1879
1880
	/**
1881
	 * This builds an array of the document's metadata
1882
	 *
1883
	 * @access	protected
1884
	 *
1885
	 * @return	array		Array of metadata with their corresponding logical structure node ID as key
1886
	 */
1887
	protected function _getMetadataArray() {
1888
1889
		// Set metadata definitions' PID.
1890
		$cPid = ($this->cPid ? $this->cPid : $this->pid);
1891
1892
		if (!$cPid) {
1893
1894
			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...
1895
1896
				\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...
1897
1898
			}
1899
1900
			return array ();
1901
1902
		}
1903
1904
		if (!$this->metadataArrayLoaded || $this->metadataArray[0] != $cPid) {
1905
1906
			// Get all logical structure nodes with metadata.
1907
			if (($ids = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@DMDID]/@ID'))) {
1908
1909
				foreach ($ids as $id) {
1910
1911
					$this->metadataArray[(string) $id] = $this->getMetadata((string) $id, $cPid);
1912
1913
				}
1914
1915
			}
1916
1917
			// Set current PID for metadata definitions.
1918
			$this->metadataArray[0] = $cPid;
1919
1920
			$this->metadataArrayLoaded = TRUE;
1921
1922
		}
1923
1924
		return $this->metadataArray;
1925
1926
	}
1927
1928
	/**
1929
	 * This returns $this->mets via __get()
1930
	 *
1931
	 * @access	protected
1932
	 *
1933
	 * @return	SimpleXMLElement		The XML's METS part as SimpleXMLElement object
1934
	 */
1935
	protected function _getMets() {
1936
1937
		return $this->mets;
1938
1939
	}
1940
1941
	/**
1942
	 * This returns $this->numPages via __get()
1943
	 *
1944
	 * @access	protected
1945
	 *
1946
	 * @return	integer		The total number of pages and/or tracks
1947
	 */
1948
	protected function _getNumPages() {
1949
1950
		$this->_getPhysicalStructure();
1951
1952
		return $this->numPages;
1953
1954
	}
1955
1956
	/**
1957
	 * This returns $this->parentId via __get()
1958
	 *
1959
	 * @access	protected
1960
	 *
1961
	 * @return	integer		The UID of the parent document or zero if not applicable
1962
	 */
1963
	protected function _getParentId() {
1964
1965
		return $this->parentId;
1966
1967
	}
1968
1969
	/**
1970
	 * This builds an array of the document's physical structure
1971
	 *
1972
	 * @access	protected
1973
	 *
1974
	 * @return	array		Array of physical elements' id, type, label and file representations ordered by @ORDER attribute
1975
	 */
1976
	protected function _getPhysicalStructure() {
1977
1978
		// Is there no physical structure array yet?
1979
		if (!$this->physicalStructureLoaded) {
1980
1981
			// Does the document have a structMap node of type "PHYSICAL"?
1982
			$elementNodes = $this->mets->xpath('./mets:structMap[@TYPE="PHYSICAL"]/mets:div[@TYPE="physSequence"]/mets:div');
1983
1984
			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...
1985
1986
				// Get file groups.
1987
				$fileUse = $this->_getFileGrps();
1988
1989
				// Get the physical sequence's metadata.
1990
				$physNode = $this->mets->xpath('./mets:structMap[@TYPE="PHYSICAL"]/mets:div[@TYPE="physSequence"]');
1991
1992
				$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...
1993
1994
				$this->physicalStructureInfo[$physSeq[0]]['id'] = $physNode[0]['ID'];
1995
1996
				$this->physicalStructureInfo[$physSeq[0]]['dmdId'] = (isset($physNode[0]['DMDID']) ? (string) $physNode[0]['DMDID'] : '');
1997
1998
				$this->physicalStructureInfo[$physSeq[0]]['label'] = (isset($physNode[0]['LABEL']) ? (string) $physNode[0]['LABEL'] : '');
1999
2000
				$this->physicalStructureInfo[$physSeq[0]]['orderlabel'] = (isset($physNode[0]['ORDERLABEL']) ? (string) $physNode[0]['ORDERLABEL'] : '');
2001
2002
				$this->physicalStructureInfo[$physSeq[0]]['type'] = (string) $physNode[0]['TYPE'];
2003
2004
				$this->physicalStructureInfo[$physSeq[0]]['contentIds'] = (isset($physNode[0]['CONTENTIDS']) ? (string) $physNode[0]['CONTENTIDS'] : '');
2005
2006
				// Get the file representations from fileSec node.
2007 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...
2008
2009
					// Check if file has valid @USE attribute.
2010
					if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
2011
2012
						$this->physicalStructureInfo[$physSeq[0]]['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
2013
2014
					}
2015
2016
				}
2017
2018
				// Build the physical elements' array from the physical structMap node.
2019
				foreach ($elementNodes as $elementNode) {
2020
2021
					$elements[(int) $elementNode['ORDER']] = (string) $elementNode['ID'];
2022
2023
					$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 2021. Are you sure it is defined here?
Loading history...
2024
2025
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['dmdId'] = (isset($elementNode['DMDID']) ? (string) $elementNode['DMDID'] : '');
2026
2027
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['label'] = (isset($elementNode['LABEL']) ? (string) $elementNode['LABEL'] : '');
2028
2029
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['orderlabel'] = (isset($elementNode['ORDERLABEL']) ? (string) $elementNode['ORDERLABEL'] : '');
2030
2031
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['type'] = (string) $elementNode['TYPE'];
2032
2033
					$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['contentIds'] = (isset($elementNode['CONTENTIDS']) ? (string) $elementNode['CONTENTIDS'] : '');
2034
2035
					// Get the file representations from fileSec node.
2036 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...
2037
2038
						// Check if file has valid @USE attribute.
2039
						if (!empty($fileUse[(string) $fptr->attributes()->FILEID])) {
2040
2041
							$this->physicalStructureInfo[$elements[(int) $elementNode['ORDER']]]['files'][$fileUse[(string) $fptr->attributes()->FILEID]] = (string) $fptr->attributes()->FILEID;
2042
2043
						}
2044
2045
					}
2046
2047
				}
2048
2049
				// Sort array by keys (= @ORDER).
2050
				if (ksort($elements)) {
2051
2052
					// Set total number of pages/tracks.
2053
					$this->numPages = count($elements);
2054
2055
					// Merge and re-index the array to get nice numeric indexes.
2056
					$this->physicalStructure = array_merge($physSeq, $elements);
2057
2058
				}
2059
2060
			}
2061
2062
			$this->physicalStructureLoaded = TRUE;
2063
2064
		}
2065
2066
		return $this->physicalStructure;
2067
2068
	}
2069
2070
	/**
2071
	 * This gives an array of the document's physical structure metadata
2072
	 *
2073
	 * @access	protected
2074
	 *
2075
	 * @return	array		Array of elements' type, label and file representations ordered by @ID attribute
2076
	 */
2077
	protected function _getPhysicalStructureInfo() {
2078
2079
		// Is there no physical structure array yet?
2080
		if (!$this->physicalStructureLoaded) {
2081
2082
			// Build physical structure array.
2083
			$this->_getPhysicalStructure();
2084
2085
		}
2086
2087
		return $this->physicalStructureInfo;
2088
2089
	}
2090
2091
	/**
2092
	 * This returns $this->pid via __get()
2093
	 *
2094
	 * @access	protected
2095
	 *
2096
	 * @return	integer		The PID of the document or zero if not in database
2097
	 */
2098
	protected function _getPid() {
2099
2100
		return $this->pid;
2101
2102
	}
2103
2104
	/**
2105
	 * This returns $this->ready via __get()
2106
	 *
2107
	 * @access	protected
2108
	 *
2109
	 * @return	boolean		Is the document instantiated successfully?
2110
	 */
2111
	protected function _getReady() {
2112
2113
		return $this->ready;
2114
2115
	}
2116
2117
	/**
2118
	 * This returns $this->recordId via __get()
2119
	 *
2120
	 * @access	protected
2121
	 *
2122
	 * @return	mixed		The METS file's record identifier
2123
	 */
2124
	protected function _getRecordId() {
2125
2126
		return $this->recordId;
2127
2128
	}
2129
2130
	/**
2131
	 * This returns $this->rootId via __get()
2132
	 *
2133
	 * @access	protected
2134
	 *
2135
	 * @return	integer		The UID of the root document or zero if not applicable
2136
	 */
2137
	protected function _getRootId() {
2138
2139
		if (!$this->rootIdLoaded) {
2140
2141
			if ($this->parentId) {
2142
2143
				$parent = self::getInstance($this->parentId, $this->pid);
2144
2145
				$this->rootId = $parent->rootId;
2146
2147
			}
2148
2149
			$this->rootIdLoaded = TRUE;
2150
2151
		}
2152
2153
		return $this->rootId;
2154
2155
	}
2156
2157
	/**
2158
	 * This returns the smLinks between logical and physical structMap
2159
	 *
2160
	 * @access	protected
2161
	 *
2162
	 * @return	array		The links between logical and physical nodes
2163
	 */
2164
	protected function _getSmLinks() {
2165
2166
		if (!$this->smLinksLoaded) {
2167
2168
			$smLinks = $this->mets->xpath('./mets:structLink/mets:smLink');
2169
2170
			foreach ($smLinks as $smLink) {
2171
2172
				$this->smLinks['l2p'][(string) $smLink->attributes('http://www.w3.org/1999/xlink')->from][] = (string) $smLink->attributes('http://www.w3.org/1999/xlink')->to;
2173
2174
				$this->smLinks['p2l'][(string) $smLink->attributes('http://www.w3.org/1999/xlink')->to][] = (string) $smLink->attributes('http://www.w3.org/1999/xlink')->from;
2175
2176
			}
2177
2178
			$this->smLinksLoaded = TRUE;
2179
2180
		}
2181
2182
		return $this->smLinks;
2183
2184
	}
2185
2186
	/**
2187
	 * This builds an array of the document's logical structure
2188
	 *
2189
	 * @access	protected
2190
	 *
2191
	 * @return	array		Array of structure nodes' id, label, type and physical page indexes/mptr link with original hierarchy preserved
2192
	 */
2193
	protected function _getTableOfContents() {
2194
2195
		// Is there no logical structure array yet?
2196
		if (!$this->tableOfContentsLoaded) {
2197
2198
			// Get all logical structures.
2199
			$this->getLogicalStructure('', TRUE);
2200
2201
			$this->tableOfContentsLoaded = TRUE;
2202
2203
		}
2204
2205
		return $this->tableOfContents;
2206
2207
	}
2208
2209
	/**
2210
	 * This returns the document's thumbnail location
2211
	 *
2212
	 * @access	protected
2213
	 *
2214
	 * @param	boolean		$forceReload: Force reloading the thumbnail instead of returning the cached value
2215
	 *
2216
	 * @return	string		The document's thumbnail location
2217
	 */
2218
	protected function _getThumbnail($forceReload = FALSE) {
2219
2220
		if (!$this->thumbnailLoaded || $forceReload) {
2221
2222
			// Retain current PID.
2223
			$cPid = ($this->cPid ? $this->cPid : $this->pid);
2224
2225 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...
2226
2227
				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...
2228
2229
					\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...
2230
2231
				}
2232
2233
				$this->thumbnailLoaded = TRUE;
2234
2235
				return $this->thumbnail;
2236
2237
			}
2238
2239
			// Load extension configuration.
2240
			$extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
2241
2242 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...
2243
2244
				if (TYPO3_DLOG) {
2245
2246
					\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...
2247
2248
				}
2249
2250
				$this->thumbnailLoaded = TRUE;
2251
2252
				return $this->thumbnail;
2253
2254
			}
2255
2256
			$strctId = $this->_getToplevelId();
2257
2258
			$metadata = $this->getTitledata($cPid);
2259
2260
			// Get structure element to get thumbnail from.
2261
			$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2262
				'tx_dlf_structures.thumbnail AS thumbnail',
2263
				'tx_dlf_structures',
2264
				'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'),
2265
				'',
2266
				'',
2267
				'1'
2268
			);
2269
2270
			if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
2271
2272
				$resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
2273
2274
				// Get desired thumbnail structure if not the toplevel structure itself.
2275
				if (!empty($resArray['thumbnail'])) {
2276
2277
					$strctType = tx_dlf_helper::getIndexName($resArray['thumbnail'], 'tx_dlf_structures', $cPid);
2278
2279
					// Check if this document has a structure element of the desired type.
2280
					$strctIds = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@TYPE="'.$strctType.'"]/@ID');
2281
2282
					if (!empty($strctIds)) {
2283
2284
						$strctId = (string) $strctIds[0];
2285
2286
					}
2287
2288
				}
2289
2290
				// Load smLinks.
2291
				$this->_getSmLinks();
2292
2293
				// Get thumbnail location.
2294
				if ($this->_getPhysicalStructure() && !empty($this->smLinks['l2p'][$strctId])) {
2295
2296
					$this->thumbnail = $this->getFileLocation($this->physicalStructureInfo[$this->smLinks['l2p'][$strctId][0]]['files'][$extConf['fileGrpThumbs']]);
2297
2298
				} else {
2299
2300
					$this->thumbnail = $this->getFileLocation($this->physicalStructureInfo[$this->physicalStructure[1]]['files'][$extConf['fileGrpThumbs']]);
2301
2302
				}
2303
2304
			} elseif (TYPO3_DLOG) {
2305
2306
				\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);
2307
2308
			}
2309
2310
			$this->thumbnailLoaded = TRUE;
2311
2312
		}
2313
2314
		return $this->thumbnail;
2315
2316
	}
2317
2318
	/**
2319
	 * This returns the ID of the toplevel logical structure node
2320
	 *
2321
	 * @access	protected
2322
	 *
2323
	 * @return	string		The logical structure node's ID
2324
	 */
2325
	protected function _getToplevelId() {
2326
2327
		if (empty($this->toplevelId)) {
2328
2329
			// Get all logical structure nodes with metadata, but without associated METS-Pointers.
2330
			if (($divs = $this->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@DMDID and not(./mets:mptr)]'))) {
2331
2332
				// Load smLinks.
2333
				$this->_getSmLinks();
2334
2335
				foreach ($divs as $div) {
2336
2337
					$id = (string) $div['ID'];
2338
2339
					// Are there physical structure nodes for this logical structure?
2340
					if (array_key_exists($id, $this->smLinks['l2p'])) {
2341
2342
						// Yes. That's what we're looking for.
2343
						$this->toplevelId = $id;
2344
2345
						break;
2346
2347
					} elseif (empty($this->toplevelId)) {
2348
2349
						// No. Remember this anyway, but keep looking for a better one.
2350
						$this->toplevelId = $id;
2351
2352
					}
2353
2354
				}
2355
2356
			}
2357
2358
		}
2359
2360
		return $this->toplevelId;
2361
2362
	}
2363
2364
	/**
2365
	 * This returns $this->uid via __get()
2366
	 *
2367
	 * @access	protected
2368
	 *
2369
	 * @return	mixed		The UID or the URL of the document
2370
	 */
2371
	protected function _getUid() {
2372
2373
		return $this->uid;
2374
2375
	}
2376
2377
	/**
2378
	 * This sets $this->cPid via __set()
2379
	 *
2380
	 * @access	protected
2381
	 *
2382
	 * @param	integer		$value: The new PID for the metadata definitions
2383
	 *
2384
	 * @return	void
2385
	 */
2386
	protected function _setCPid($value) {
2387
2388
		$this->cPid = max(intval($value), 0);
2389
2390
	}
2391
2392
	/**
2393
	 * This magic method is invoked each time a clone is called on the object variable
2394
	 * (This method is defined as private/protected because singleton objects should not be cloned)
2395
	 *
2396
	 * @access	protected
2397
	 *
2398
	 * @return	void
2399
	 */
2400
	protected function __clone() {}
2401
2402
	/**
2403
	 * This is a singleton class, thus the constructor should be private/protected
2404
	 *
2405
	 * @access	protected
2406
	 *
2407
	 * @param	integer		$uid: The UID of the document to parse or URL to XML file
2408
	 * @param	integer		$pid: If > 0, then only document with this PID gets loaded
2409
	 *
2410
	 * @return	void
2411
	 */
2412
	protected function __construct($uid, $pid) {
2413
2414
		// Prepare to check database for the requested document.
2415
		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...
2416
2417
			$whereClause = 'tx_dlf_documents.uid='.intval($uid).tx_dlf_helper::whereClause('tx_dlf_documents');
2418
2419
		} else {
2420
2421
			// Cast to string for safety reasons.
2422
			$location = (string) $uid;
2423
2424
			// Try to load METS file.
2425
			if (\TYPO3\CMS\Core\Utility\GeneralUtility::isValidUrl($location) && $this->load($location)) {
2426
2427
				// Initialize core METS object.
2428
				$this->init();
2429
2430
				if ($this->mets !== NULL) {
2431
2432
					// Check for METS object @ID.
2433
					if (!empty($this->mets['OBJID'])) {
2434
2435
						$this->recordId = (string) $this->mets['OBJID'];
2436
2437
					}
2438
2439
					// Get hook objects.
2440
					$hookObjects = tx_dlf_helper::getHookObjects('common/class.tx_dlf_document.php');
2441
2442
					// Apply hooks.
2443
					foreach($hookObjects as $hookObj) {
2444
2445
						if (method_exists($hookObj, 'construct_postProcessRecordId')) {
2446
2447
							$hookObj->construct_postProcessRecordId($this->xml, $this->recordId);
2448
2449
						}
2450
2451
					}
2452
2453
				} else {
2454
2455
					// No METS part found.
2456
					return;
2457
2458
				}
2459
2460
			} else {
2461
2462
				// Loading failed.
2463
				return;
2464
2465
			}
2466
2467
			if (!empty($this->recordId)) {
2468
2469
				$whereClause = 'tx_dlf_documents.record_id='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->recordId, 'tx_dlf_documents').tx_dlf_helper::whereClause('tx_dlf_documents');
2470
2471
			} else {
2472
2473
				// There is no record identifier and there should be no hit in the database.
2474
				$whereClause = '1=-1';
2475
2476
			}
2477
2478
		}
2479
2480
		// Check for PID if needed.
2481
		if ($pid) {
2482
2483
			$whereClause .= ' AND tx_dlf_documents.pid='.intval($pid);
2484
2485
		}
2486
2487
		// Get document PID and location from database.
2488
		$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
2489
			'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',
2490
			'tx_dlf_documents',
2491
			$whereClause,
2492
			'',
2493
			'',
2494
			'1'
2495
		);
2496
2497
		if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
2498
2499
			list ($this->uid, $this->pid, $this->recordId, $this->parentId, $this->thumbnail, $this->location) = $GLOBALS['TYPO3_DB']->sql_fetch_row($result);
2500
2501
			$this->thumbnailLoaded = TRUE;
2502
2503
			// Load XML file if necessary...
2504
			if ($this->mets === NULL && $this->load($this->location)) {
2505
2506
				// ...and set some basic properties.
2507
				$this->init();
2508
2509
			}
2510
2511
			// Do we have a METS object now?
2512
			if ($this->mets !== NULL) {
2513
2514
				// Set new location if necessary.
2515
				if (!empty($location)) {
2516
2517
					$this->location = $location;
2518
2519
				}
2520
2521
				// Document ready!
2522
				$this->ready = TRUE;
2523
2524
			}
2525
2526
		} elseif ($this->mets !== NULL) {
2527
2528
			// Set location as UID for documents not in database.
2529
			$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...
2530
2531
			$this->location = $location;
2532
2533
			// Document ready!
2534
			$this->ready = TRUE;
2535
2536
		} else {
2537
2538
			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...
2539
2540
				\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...
2541
2542
			}
2543
2544
		}
2545
2546
	}
2547
2548
	/**
2549
	 * This magic method is called each time an invisible property is referenced from the object
2550
	 *
2551
	 * @access	public
2552
	 *
2553
	 * @param	string		$var: Name of variable to get
2554
	 *
2555
	 * @return	mixed		Value of $this->$var
2556
	 */
2557
	public function __get($var) {
2558
2559
		$method = '_get'.ucfirst($var);
2560
2561
		if (!property_exists($this, $var) || !method_exists($this, $method)) {
2562
2563
			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...
2564
2565
				\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...
2566
2567
			}
2568
2569
			return;
2570
2571
		} else {
2572
2573
			return $this->$method();
2574
2575
		}
2576
2577
	}
2578
2579
	/**
2580
	 * This magic method is called each time an invisible property is referenced from the object
2581
	 *
2582
	 * @access	public
2583
	 *
2584
	 * @param	string		$var: Name of variable to set
2585
	 * @param	mixed		$value: New value of variable
2586
	 *
2587
	 * @return	void
2588
	 */
2589 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...
2590
2591
		$method = '_set'.ucfirst($var);
2592
2593
		if (!property_exists($this, $var) || !method_exists($this, $method)) {
2594
2595
			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...
2596
2597
				\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...
2598
2599
			}
2600
2601
		} else {
2602
2603
			$this->$method($value);
2604
2605
		}
2606
2607
	}
2608
2609
	/**
2610
	 * This magic method is executed prior to any serialization of the object
2611
	 * @see __wakeup()
2612
	 *
2613
	 * @access	public
2614
	 *
2615
	 * @return	array		Properties to be serialized
2616
	 */
2617
	public function __sleep() {
2618
2619
		// SimpleXMLElement objects can't be serialized, thus save the XML as string for serialization
2620
		$this->asXML = $this->xml->asXML();
2621
2622
		return array ('uid', 'pid', 'recordId', 'parentId', 'asXML');
2623
2624
	}
2625
2626
	/**
2627
	 * This magic method is used for setting a string value for the object
2628
	 *
2629
	 * @access	public
2630
	 *
2631
	 * @return	string		String representing the METS object
2632
	 */
2633
	public function __toString() {
2634
2635
		$xml = new DOMDocument('1.0', 'utf-8');
2636
2637
		$xml->appendChild($xml->importNode(dom_import_simplexml($this->mets), TRUE));
2638
2639
		$xml->formatOutput = TRUE;
2640
2641
		return $xml->saveXML();
2642
2643
	}
2644
2645
	/**
2646
	 * This magic method is executed after the object is deserialized
2647
	 * @see __sleep()
2648
	 *
2649
	 * @access	public
2650
	 *
2651
	 * @return	void
2652
	 */
2653
	public function __wakeup() {
2654
2655
		// Turn off libxml's error logging.
2656
		$libxmlErrors = libxml_use_internal_errors(TRUE);
2657
2658
		// Reload XML from string.
2659
		$xml = @simplexml_load_string($this->asXML);
2660
2661
		// Reset libxml's error logging.
2662
		libxml_use_internal_errors($libxmlErrors);
2663
2664
		if ($xml !== FALSE) {
2665
2666
			$this->asXML = '';
2667
2668
			$this->xml = $xml;
2669
2670
			// Rebuild the unserializable properties.
2671
			$this->init();
2672
2673
		} else {
2674
2675
			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...
2676
2677
				\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...
2678
2679
			}
2680
2681
		}
2682
2683
	}
2684
2685
}
2686