|
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) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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
|
|
|
*/ |
|
|
|
|
|
|
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']; |
|
|
|
|
|
|
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])) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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 { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
786
|
|
|
|
|
787
|
|
|
} |
|
788
|
|
|
|
|
789
|
|
|
} |
|
790
|
|
|
|
|
791
|
|
|
} |
|
792
|
|
|
|
|
793
|
|
View Code Duplication |
} else { |
|
|
|
|
|
|
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)) { |
|
|
|
|
|
|
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)) { |
|
|
|
|
|
|
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])) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
1063
|
|
|
|
|
1064
|
|
|
$this->mets = $mets[0]; |
|
1065
|
|
|
|
|
1066
|
|
|
// Register namespaces. |
|
1067
|
|
|
$this->registerNamespaces($this->mets); |
|
1068
|
|
|
|
|
1069
|
|
|
} else { |
|
1070
|
|
|
|
|
1071
|
|
|
if (TYPO3_DLOG) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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']); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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') { |
|
|
|
|
|
|
1250
|
|
|
|
|
1251
|
|
|
if (TYPO3_DLOG) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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'), |
|
|
|
|
|
|
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 { |
|
|
|
|
|
|
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]; |
|
|
|
|
|
|
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, |
|
|
|
|
|
|
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 ( |
|
|
|
|
|
|
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])) { |
|
|
|
|
|
|
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])) { |
|
|
|
|
|
|
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 ( |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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]])) { |
|
|
|
|
|
|
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]])) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
1895
|
|
|
|
|
1896
|
|
|
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->getMetadataArray()] Invalid PID "'.$cPid.'" for metadata definitions', self::$extKey, SYSLOG_SEVERITY_ERROR); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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']; |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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']; |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
2226
|
|
|
|
|
2227
|
|
|
if (TYPO3_DLOG) { |
|
|
|
|
|
|
2228
|
|
|
|
|
2229
|
|
|
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->_getThumbnail()] Invalid PID "'.$cPid.'" for structure definitions', self::$extKey, SYSLOG_SEVERITY_ERROR); |
|
|
|
|
|
|
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'])) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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)) { |
|
|
|
|
|
|
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; |
|
|
|
|
|
|
2530
|
|
|
|
|
2531
|
|
|
$this->location = $location; |
|
2532
|
|
|
|
|
2533
|
|
|
// Document ready! |
|
2534
|
|
|
$this->ready = TRUE; |
|
2535
|
|
|
|
|
2536
|
|
|
} else { |
|
2537
|
|
|
|
|
2538
|
|
|
if (TYPO3_DLOG) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
2590
|
|
|
|
|
2591
|
|
|
$method = '_set'.ucfirst($var); |
|
2592
|
|
|
|
|
2593
|
|
|
if (!property_exists($this, $var) || !method_exists($this, $method)) { |
|
2594
|
|
|
|
|
2595
|
|
|
if (TYPO3_DLOG) { |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
2676
|
|
|
|
|
2677
|
|
|
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('[tx_dlf_document->__wakeup()] Could not load XML after deserialization', self::$extKey, SYSLOG_SEVERITY_ERROR); |
|
|
|
|
|
|
2678
|
|
|
|
|
2679
|
|
|
} |
|
2680
|
|
|
|
|
2681
|
|
|
} |
|
2682
|
|
|
|
|
2683
|
|
|
} |
|
2684
|
|
|
|
|
2685
|
|
|
} |
|
2686
|
|
|
|
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.