Scrutinizer GitHub App not installed

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

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#673)
by Alexander
08:19 queued 05:35
created

IiifManifest::setPreloadedDocument()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Common;
14
15
use Flow\JSONPath\JSONPath;
16
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
17
use TYPO3\CMS\Core\Database\ConnectionPool;
18
use TYPO3\CMS\Core\Utility\GeneralUtility;
19
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface;
20
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationInterface;
21
use Ubl\Iiif\Presentation\Common\Model\Resources\CanvasInterface;
22
use Ubl\Iiif\Presentation\Common\Model\Resources\ContentResourceInterface;
23
use Ubl\Iiif\Presentation\Common\Model\Resources\IiifResourceInterface;
24
use Ubl\Iiif\Presentation\Common\Model\Resources\ManifestInterface;
25
use Ubl\Iiif\Presentation\Common\Model\Resources\RangeInterface;
26
use Ubl\Iiif\Presentation\Common\Vocabulary\Motivation;
27
use Ubl\Iiif\Presentation\V1\Model\Resources\AbstractIiifResource1;
28
use Ubl\Iiif\Presentation\V2\Model\Resources\AbstractIiifResource2;
29
use Ubl\Iiif\Presentation\V3\Model\Resources\AbstractIiifResource3;
30
use Ubl\Iiif\Services\AbstractImageService;
31
use Ubl\Iiif\Services\Service;
32
use Ubl\Iiif\Tools\IiifHelper;
33
34
/**
35
 * IiifManifest class for the 'dlf' extension.
36
 *
37
 * @author Lutz Helm <[email protected]>
38
 * @package TYPO3
39
 * @subpackage dlf
40
 * @access public
41
 * @property int $cPid This holds the PID for the configuration
42
 * @property-read bool $hasFulltext Are there any fulltext files available?
43
 * @property-read string $location This holds the documents location
44
 * @property-read array $metadataArray This holds the documents' parsed metadata array
45
 * @property-read int $numPages The holds the total number of pages
46
 * @property-read int $parentId This holds the UID of the parent document or zero if not multi-volumed
47
 * @property-read array $physicalStructure This holds the physical structure
48
 * @property-read array $physicalStructureInfo This holds the physical structure metadata
49
 * @property-read int $pid This holds the PID of the document or zero if not in database
50
 * @property-read bool $ready Is the document instantiated successfully?
51
 * @property-read string $recordId The IIIF manifest's record identifier
52
 * @property-read int $rootId This holds the UID of the root document or zero if not multi-volumed
53
 * @property-read array $smLinks This holds the connections between resources and canvases
54
 * @property-read array $tableOfContents This holds the logical structure
55
 * @property-read string $thumbnail This holds the document's thumbnail location
56
 * @property-read string $toplevelId This holds the toplevel manifest's @id
57
 * @property-read mixed $uid This holds the UID or the URL of the document
58
 */
59
final class IiifManifest extends Document
60
{
61
    /**
62
     * This holds the manifest file as string for serialization purposes
63
     * @see __sleep() / __wakeup()
64
     *
65
     * @var string
66
     * @access protected
67
     */
68
    protected $asJson = '';
69
70
    /**
71
     * A PHP object representation of a IIIF manifest.
72
     * @var ManifestInterface
73
     * @access protected
74
     */
75
    protected $iiif;
76
77
    /**
78
     * 'IIIF1', 'IIIF2' or 'IIIF3', depending on the API $this->iiif confrms to:
79
     * IIIF Metadata API 1, IIIF Presentation API 2 or 3
80
     * @var string
81
     * @access protected
82
     */
83
    protected $iiifVersion;
84
85
    /**
86
     * Document has already been analyzed if it contains fulltext for the Solr index
87
     * @var bool
88
     * @access protected
89
     */
90
    protected $hasFulltextSet = false;
91
92
    /**
93
     * This holds the original manifest's parsed metadata array with their corresponding
94
     * resource (Manifest / Sequence / Range) ID as array key
95
     *
96
     * @var array
97
     * @access protected
98
     */
99
    protected $originalMetadataArray = [];
100
101
    /**
102
     * Holds the mime types of linked resources in the manifest (extreacted during parsing) for later use.
103
     * @var array
104
     * @access protected
105
     */
106
    protected $mimeTypes = [];
107
108
    /**
109
     * The extension key
110
     *
111
     * @var string
112
     * @static
113
     * @access public
114
     */
115
    public static $extKey = 'dlf';
116
117
    /**
118
     * {@inheritDoc}
119
     * @see Document::establishRecordId()
120
     */
121
    protected function establishRecordId($pid)
122
    {
123
        if ($this->iiif !== null) {
124
            /*
125
             *  FIXME This will not consistently work because we can not be sure to have the pid at hand. It may miss
126
             *  if the plugin that actually loads the manifest allows content from other pages.
127
             *  Up until now the cPid is only set after the document has been initialized. We need it before to
128
             *  check the configuration.
129
             *  TODO Saving / indexing should still work - check!
130
             */
131
            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
132
                ->getQueryBuilderForTable('tx_dlf_metadata');
133
            // Get hidden records, too.
134
            $queryBuilder
135
                ->getRestrictions()
136
                ->removeByType(HiddenRestriction::class);
0 ignored issues
show
Bug introduced by
The type Kitodo\Dlf\Common\HiddenRestriction was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
137
            $result = $queryBuilder
138
                ->select('tx_dlf_metadataformat.xpath AS querypath')
139
                ->from('tx_dlf_metadata')
140
                ->from('tx_dlf_metadataformat')
141
                ->from('tx_dlf_formats')
142
                ->where(
143
                    $queryBuilder->expr()->eq('tx_dlf_metadata.pid', intval($pid)),
144
                    $queryBuilder->expr()->eq('tx_dlf_metadataformat.pid', intval($pid)),
145
                    $queryBuilder->expr()->orX(
146
                        $queryBuilder->expr()->andX(
147
                            $queryBuilder->expr()->eq('tx_dlf_metadata.uid', 'tx_dlf_metadataformat.parent_id'),
148
                            $queryBuilder->expr()->eq('tx_dlf_metadataformat.encoded', 'tx_dlf_formats.uid'),
149
                            $queryBuilder->expr()->eq('tx_dlf_metadata.index_name', $queryBuilder->createNamedParameter('record_id')),
150
                            $queryBuilder->expr()->eq('tx_dlf_formats.type', $queryBuilder->createNamedParameter($this->getIiifVersion()))
151
                        ),
152
                        $queryBuilder->expr()->eq('tx_dlf_metadata.format', 0)
153
                    )
154
                )
155
                ->execute();
156
            while ($resArray = $result->fetch()) {
157
                $recordIdPath = $resArray['querypath'];
158
                if (!empty($recordIdPath)) {
159
                    $this->recordId = $this->iiif->jsonPath($recordIdPath);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->iiif->jsonPath($recordIdPath) can also be of type Ubl\Iiif\Presentation\Co...urces\ManifestInterface or Ubl\Iiif\Presentation\Co...s\AbstractIiifResource1 or Ubl\Iiif\Presentation\Co...s\AbstractIiifResource2 or Ubl\Iiif\Presentation\Co...s\AbstractIiifResource3. However, the property $recordId is declared as type string. Maybe add an additional type check?

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

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

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

class Id
{
    public $id;

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

}

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

$account_id = false;

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

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
160
                }
161
            }
162
            // For now, it's a hardcoded ID, not only as a fallback
163
            if (!isset($this->recordId)) {
164
                $this->recordId = $this->iiif->getId();
165
            }
166
        }
167
    }
168
169
    /**
170
     * {@inheritDoc}
171
     * @see Document::getDocument()
172
     */
173
    protected function getDocument()
174
    {
175
        return $this->iiif;
176
    }
177
178
    /**
179
     * Returns a string representing the Metadata / Presentation API version which the IIIF resource
180
     * conforms to. This is used for example to extract metadata according to configured patterns.
181
     *
182
     * @access public
183
     *
184
     * @return string 'IIIF1' if the resource is a Metadata API 1 resource, 'IIIF2' / 'IIIF3' if
185
     * the resource is a Presentation API 2 / 3 resource
186
     */
187
    public function getIiifVersion()
188
    {
189
        if (!isset($this->iiifVersion)) {
190
            if ($this->iiif instanceof AbstractIiifResource1) {
191
                $this->iiifVersion = 'IIIF1';
192
            } elseif ($this->iiif instanceof AbstractIiifResource2) {
193
                $this->iiifVersion = 'IIIF2';
194
            } elseif ($this->iiif instanceof AbstractIiifResource3) {
195
                $this->iiifVersion = 'IIIF3';
196
            }
197
        }
198
        return $this->iiifVersion;
199
    }
200
201
    /**
202
     * True if getUseGroups() has been called and $this->useGrps is loaded
203
     *
204
     * @var bool
205
     * @access protected
206
     */
207
    protected $useGrpsLoaded = false;
208
209
    /**
210
     * Holds the configured useGrps as array.
211
     *
212
     * @var array
213
     * @access protected
214
     */
215
    protected $useGrps = [];
216
217
    /**
218
     * IiifManifest also populates the physical stucture array entries for matching
219
     * 'fileGrp's. To do that, the configuration has to be loaded; afterwards configured
220
     * 'fileGrp's for thumbnails, downloads, audio, fulltext and the 'fileGrp's for images
221
     * can be requested with this method.
222
     *
223
     * @access protected
224
     *
225
     * @param string $use
226
     *
227
     * @return array|string
228
     */
229
    protected function getUseGroups($use)
230
    {
231
        if (!$this->useGrpsLoaded) {
232
            // Get configured USE attributes.
233
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
234
            if (!empty($extConf['fileGrpImages'])) {
235
                $this->useGrps['fileGrpImages'] = GeneralUtility::trimExplode(',', $extConf['fileGrpImages']);
236
            }
237
            if (!empty($extConf['fileGrpThumbs'])) {
238
                $this->useGrps['fileGrpThumbs'] = GeneralUtility::trimExplode(',', $extConf['fileGrpThumbs']);
239
            }
240
            if (!empty($extConf['fileGrpDownload'])) {
241
                $this->useGrps['fileGrpDownload'] = GeneralUtility::trimExplode(',', $extConf['fileGrpDownload']);
242
            }
243
            if (!empty($extConf['fileGrpFulltext'])) {
244
                $this->useGrps['fileGrpFulltext'] = GeneralUtility::trimExplode(',', $extConf['fileGrpFulltext']);
245
            }
246
            if (!empty($extConf['fileGrpAudio'])) {
247
                $this->useGrps['fileGrpAudio'] = GeneralUtility::trimExplode(',', $extConf['fileGrpAudio']);
248
            }
249
            $this->useGrpsLoaded = true;
250
        }
251
        return array_key_exists($use, $this->useGrps) ? $this->useGrps[$use] : [];
252
    }
253
254
    /**
255
     * {@inheritDoc}
256
     * @see Document::_getPhysicalStructure()
257
     */
258
    protected function _getPhysicalStructure()
259
    {
260
        // Is there no physical structure array yet?
261
        if (!$this->physicalStructureLoaded) {
262
            if ($this->iiif == null || !($this->iiif instanceof ManifestInterface)) {
263
                return null;
264
            }
265
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
266
            $iiifId = $this->iiif->getId();
267
            $physSeq[0] = $iiifId;
268
            $this->physicalStructureInfo[$physSeq[0]]['id'] = $iiifId;
269
            $this->physicalStructureInfo[$physSeq[0]]['dmdId'] = $iiifId;
270
            $this->physicalStructureInfo[$physSeq[0]]['label'] = $this->iiif->getLabelForDisplay();
271
            $this->physicalStructureInfo[$physSeq[0]]['orderlabel'] = $this->iiif->getLabelForDisplay();
272
            $this->physicalStructureInfo[$physSeq[0]]['type'] = 'physSequence';
273
            $this->physicalStructureInfo[$physSeq[0]]['contentIds'] = null;
274
            $fileUseDownload = $this->getUseGroups('fileGrpDownload');
275
            $fileUseFulltext = $this->getUseGroups('fileGrpFulltext');
276
            $fileUseThumbs = $this->getUseGroups('fileGrpThumbs');
277
            $fileUses = $this->getUseGroups('fileGrpImages');
278
            if (!empty($fileUseDownload)) {
279
                $docPdfRendering = $this->iiif->getRenderingUrlsForFormat('application/pdf');
280
                if (!empty($docPdfRendering)) {
281
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseDownload[0]] = $docPdfRendering[0];
282
                }
283
            }
284
            if (!empty($fileUseFulltext)) {
285
                $iiifAlto = $this->iiif->getSeeAlsoUrlsForFormat('application/alto+xml');
286
                if (empty($iiifAlto)) {
287
                    $iiifAlto = $this->iiif->getSeeAlsoUrlsForProfile('http://www.loc.gov/standards/alto/', true);
288
                }
289
                if (!empty($iiifAlto)) {
290
                    $this->mimeTypes[$iiifAlto[0]] = 'application/alto+xml';
291
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseFulltext[0]] = $iiifAlto[0];
292
                    $this->hasFulltext = true;
293
                    $this->hasFulltextSet = true;
294
                }
295
            }
296
            if (!empty($this->iiif->getDefaultCanvases())) {
297
                // canvases have not order property, but the context defines canveses as @list with a specific order, so we can provide an alternative
298
                $canvasOrder = 0;
299
                foreach ($this->iiif->getDefaultCanvases() as $canvas) {
300
                    $canvasOrder++;
301
                    $thumbnailUrl = $canvas->getThumbnailUrl();
302
                    // put thumbnails in thumbnail filegroup
303
                    if (
304
                        !empty($thumbnailUrl)
305
                        && empty($this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseThumbs[0]])
306
                    ) {
307
                        $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseThumbs[0]] = $thumbnailUrl;
308
                    }
309
                    // populate structural metadata info
310
                    $elements[$canvasOrder] = $canvas->getId();
311
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['id'] = $canvas->getId();
312
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['dmdId'] = null;
313
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['label'] = $canvas->getLabelForDisplay();
314
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['orderlabel'] = $canvas->getLabelForDisplay();
315
                    // assume that a canvas always represents a page
316
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['type'] = 'page';
317
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['contentIds'] = null;
318
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = null;
319
                    if (!empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
320
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = [];
321
                        foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
322
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'][] = $annotationContainer->getId();
323
                            if ($extConf['indexAnnotations']) {
324
                                $this->hasFulltext = true;
325
                                $this->hasFulltextSet = true;
326
                            }
327
                        }
328
                    }
329
                    if (!empty($fileUseFulltext)) {
330
                        $alto = $canvas->getSeeAlsoUrlsForFormat('application/alto+xml');
331
                        if (empty($alto)) {
332
                            $alto = $canvas->getSeeAlsoUrlsForProfile('http://www.loc.gov/standards/alto/', true);
333
                        }
334
                        if (!empty($alto)) {
335
                            $this->mimeTypes[$alto[0]] = 'application/alto+xml';
336
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseFulltext[0]] = $alto[0];
337
                            $this->hasFulltext = true;
338
                            $this->hasFulltextSet = true;
339
                        }
340
                    }
341
                    if (!empty($fileUses)) {
342
                        $image = $canvas->getImageAnnotations()[0];
343
                        foreach ($fileUses as $fileUse) {
344
                            if ($image->getBody() !== null && $image->getBody() instanceof ContentResourceInterface) {
345
                                $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUse] = $image->getBody()->getId();
346
                            }
347
                        }
348
                    }
349
                    if (!empty($thumbnailUrl)) {
350
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseThumbs] = $thumbnailUrl;
351
                    }
352
                    if (!empty($fileUseDownload)) {
353
                        $pdfRenderingUrls = $canvas->getRenderingUrlsForFormat('application/pdf');
354
                        if (!empty($pdfRenderingUrls)) {
355
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseDownload[0]] = $pdfRenderingUrls[0];
356
                        }
357
                    }
358
                }
359
                $this->numPages = $canvasOrder;
360
                // Merge and re-index the array to get nice numeric indexes.
361
                $this->physicalStructure = array_merge($physSeq, $elements);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $elements seems to be defined by a foreach iteration on line 299. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
362
            }
363
            $this->physicalStructureLoaded = true;
364
        }
365
        return $this->physicalStructure;
366
    }
367
368
    /**
369
     * {@inheritDoc}
370
     * @see Document::getDownloadLocation()
371
     */
372
    public function getDownloadLocation($id)
373
    {
374
        $fileLocation = $this->getFileLocation($id);
375
        $resource = $this->iiif->getContainedResourceById($fileLocation);
376
        if ($resource instanceof AbstractImageService) {
377
            return $resource->getImageUrl();
378
        }
379
        return $fileLocation;
380
    }
381
382
    /**
383
     * {@inheritDoc}
384
     * @see Document::getFileLocation()
385
     */
386
    public function getFileLocation($id)
387
    {
388
        if ($id == null) {
389
            return null;
390
        }
391
        $resource = $this->iiif->getContainedResourceById($id);
392
        if (isset($resource)) {
393
            if ($resource instanceof CanvasInterface) {
394
                return (!empty($resource->getImageAnnotations()) && $resource->getImageAnnotations()->getSingleService() != null) ? $resource->getImageAnnotations()[0]->getSingleService()->getId() : $id;
395
            } elseif ($resource instanceof ContentResourceInterface) {
396
                return $resource->getSingleService() != null && $resource->getSingleService() instanceof Service ? $resource->getSingleService()->getId() : $id;
397
            } elseif ($resource instanceof AbstractImageService) {
398
                return $resource->getId();
399
            } elseif ($resource instanceof AnnotationContainerInterface) {
400
                return $id;
401
            }
402
        } else {
403
            return $id;
404
        }
405
    }
406
407
    /**
408
     * {@inheritDoc}
409
     * @see Document::getFileMimeType()
410
     */
411
    public function getFileMimeType($id)
412
    {
413
        $fileResource = $this->iiif->getContainedResourceById($id);
414
        if ($fileResource instanceof CanvasInterface) {
415
            $format = "application/vnd.kitodo.iiif";
416
        } elseif ($fileResource instanceof AnnotationInterface) {
417
            $format = "application/vnd.kitodo.iiif";
418
        } elseif ($fileResource instanceof ContentResourceInterface) {
419
            if ($fileResource->isText() || $fileResource->isImage() && ($fileResource->getSingleService() == null || !($fileResource->getSingleService() instanceof AbstractImageService))) {
420
                // Support static images without an image service
421
                return $fileResource->getFormat();
422
            }
423
            $format = "application/vnd.kitodo.iiif";
424
        } elseif ($fileResource instanceof AbstractImageService) {
425
            $format = "application/vnd.kitodo.iiif";
426
        } else {
427
            // Assumptions: this can only be the thumbnail and the thumbnail is a jpeg - TODO determine mimetype
428
            $format = "image/jpeg";
429
        }
430
        return $format;
431
    }
432
433
    /**
434
     * {@inheritDoc}
435
     * @see Document::getLogicalStructure()
436
     */
437
    public function getLogicalStructure($id, $recursive = false)
438
    {
439
        $details = [];
440
        if (!$recursive && !empty($this->logicalUnits[$id])) {
441
            return $this->logicalUnits[$id];
442
        } elseif (!empty($id)) {
443
            $logUnits[] = $this->iiif->getContainedResourceById($id);
444
        } else {
445
            $logUnits[] = $this->iiif;
446
        }
447
        if (!empty($logUnits)) {
448
            if (!$recursive) {
449
                $details = $this->getLogicalStructureInfo($logUnits[0]);
450
            } else {
451
                // cache the ranges - they might occure multiple times in the structures "tree" - with full data as well as referenced as id
452
                $processedStructures = [];
453
                foreach ($logUnits as $logUnit) {
454
                    if (array_search($logUnit->getId(), $processedStructures) == false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing array_search($logUnit->g..., $processedStructures) of type integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
455
                        $this->tableOfContents[] = $this->getLogicalStructureInfo($logUnit, true, $processedStructures);
456
                    }
457
                }
458
            }
459
        }
460
        return $details;
461
    }
462
463
    /**
464
     * Get the details about a IIIF resource (manifest or range) in the logical structure
465
     *
466
     * @access protected
467
     *
468
     * @param IiifResourceInterface $resource: IIIF resource, either a manifest or range.
469
     * @param bool $recursive: Whether to include the child elements
470
     * @param array $processedStructures: IIIF resources that already have been processed
471
     * @return array Logical structure array
472
     */
473
    protected function getLogicalStructureInfo(IiifResourceInterface $resource, $recursive = false, &$processedStructures = [])
474
    {
475
        $details = [];
476
        $details['id'] = $resource->getId();
477
        $details['dmdId'] = '';
478
        $details['label'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
479
        $details['orderlabel'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
480
        $details['contentIds'] = '';
481
        $details['volume'] = '';
482
        $details['pagination'] = '';
483
        $cPid = ($this->cPid ? $this->cPid : $this->pid);
484
        if ($details['id'] == $this->_getToplevelId()) {
485
            $metadata = $this->getMetadata($details['id'], $cPid);
486
            if (!empty($metadata['type'][0])) {
487
                $details['type'] = $metadata['type'][0];
488
            }
489
        }
490
        $details['thumbnailId'] = $resource->getThumbnailUrl();
491
        $details['points'] = '';
492
        // Load strucural mapping
493
        $this->_getSmLinks();
494
        // Load physical structure.
495
        $this->_getPhysicalStructure();
496
        $canvases = [];
497
        if ($resource instanceof ManifestInterface) {
498
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
499
            $canvases = $resource->getDefaultCanvases();
0 ignored issues
show
Unused Code introduced by
The assignment to $canvases is dead and can be removed.
Loading history...
500
        } elseif ($resource instanceof RangeInterface) {
501
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
502
            $canvases = $resource->getAllCanvases();
503
        }
504
        if ($startCanvas != null) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $startCanvas does not seem to be defined for all execution paths leading up to this point.
Loading history...
505
            $details['pagination'] = $startCanvas->getLabel();
506
            $startCanvasIndex = array_search($startCanvas, $this->iiif->getDefaultCanvases());
507
            if ($startCanvasIndex !== false) {
508
                $details['points'] = $startCanvasIndex + 1;
509
            }
510
        }
511
        $useGroups = $this->getUseGroups('fileGrpImages');
512
        if (is_string($useGroups)) {
513
            $useGroups = [$useGroups];
0 ignored issues
show
Unused Code introduced by
The assignment to $useGroups is dead and can be removed.
Loading history...
514
        }
515
        // Keep for later usage.
516
        $this->logicalUnits[$details['id']] = $details;
517
        // Walk the structure recursively? And are there any children of the current element?
518
        if ($recursive) {
519
            $processedStructures[] = $resource->getId();
520
            $details['children'] = [];
521
            if ($resource instanceof ManifestInterface && $resource->getRootRanges() != null) {
522
                $rangesToAdd = [];
523
                $rootRanges = [];
524
                if (sizeof($this->iiif->getRootRanges()) == 1 && $this->iiif->getRootRanges()[0]->isTopRange()) {
525
                    $rangesToAdd = $this->iiif->getRootRanges()[0]->getMemberRangesAndRanges();
0 ignored issues
show
Bug introduced by
The method getMemberRangesAndRanges() does not exist on Ubl\Iiif\Presentation\Co...esources\RangeInterface. It seems like you code against a sub-type of Ubl\Iiif\Presentation\Co...esources\RangeInterface such as Ubl\Iiif\Presentation\V2\Model\Resources\Range2. ( Ignorable by Annotation )

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

525
                    /** @scrutinizer ignore-call */ 
526
                    $rangesToAdd = $this->iiif->getRootRanges()[0]->getMemberRangesAndRanges();
Loading history...
526
                } else {
527
                    $rangesToAdd = $this->iiif->getRootRanges();
528
                }
529
                foreach ($rangesToAdd as $range) {
530
                    $rootRanges[] = $range;
531
                }
532
                foreach ($rootRanges as $range) {
533
                    if ((array_search($range->getId(), $processedStructures) == false)) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing array_search($range->get..., $processedStructures) of type integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
534
                        $details['children'][] = $this->getLogicalStructureInfo($range, true, $processedStructures);
535
                    }
536
                }
537
            } elseif ($resource instanceof RangeInterface) {
538
                if (!empty($resource->getAllRanges())) {
539
                    foreach ($resource->getAllRanges() as $range) {
540
                        if ((array_search($range->getId(), $processedStructures) == false)) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing array_search($range->get..., $processedStructures) of type integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
541
                            $details['children'][] = $this->getLogicalStructureInfo($range, true, $processedStructures);
542
                        }
543
                    }
544
                }
545
            }
546
        }
547
        return $details;
548
    }
549
550
    /**
551
     * Returns metadata for IIIF resources with the ID $id in there original form in
552
     * the manifest, but prepared for display to the user.
553
     *
554
     * @access public
555
     *
556
     * @param string $id: the ID of the IIIF resource
557
     * @param int $cPid: the configuration folder's id
558
     * @param bool $withDescription: add description / summary to the return value
559
     * @param bool $withRights: add attribution and license / rights and requiredStatement to the return value
560
     * @param bool $withRelated: add related links / homepage to the return value
561
     *
562
     * @return array
563
     *
564
     * @todo This method is still in experimental; the method signature may change.
565
     */
566
    public function getManifestMetadata($id, $cPid = 0, $withDescription = true, $withRights = true, $withRelated = true)
0 ignored issues
show
Unused Code introduced by
The parameter $cPid is not used and could be removed. ( Ignorable by Annotation )

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

566
    public function getManifestMetadata($id, /** @scrutinizer ignore-unused */ $cPid = 0, $withDescription = true, $withRights = true, $withRelated = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
567
    {
568
        if (!empty($this->originalMetadataArray[$id])) {
569
            return $this->originalMetadataArray[$id];
570
        }
571
        $iiifResource = $this->iiif->getContainedResourceById($id);
572
        $result = [];
573
        if ($iiifResource != null) {
574
            if ($iiifResource->getLabel() != null && $iiifResource->getLabel() != "") {
575
                $result['label'] = $iiifResource->getLabel();
576
            }
577
            if (!empty($iiifResource->getMetadata())) {
578
                $result['metadata'] = [];
579
                foreach ($iiifResource->getMetadataForDisplay() as $metadata) {
580
                    $result['metadata'][$metadata['label']] = $metadata['value'];
581
                }
582
            }
583
            if ($withDescription && !empty($iiifResource->getSummary())) {
584
                $result["description"] = $iiifResource->getSummaryForDisplay();
585
            }
586
            if ($withRights) {
587
                if (!empty($iiifResource->getRights())) {
588
                    $result["rights"] = $iiifResource->getRights();
589
                }
590
                if (!empty($iiifResource->getRequiredStatement())) {
591
                    $result["requiredStatement"] = $iiifResource->getRequiredStatementForDisplay();
592
                }
593
            }
594
            if ($withRelated && !empty($iiifResource->getWeblinksForDisplay())) {
595
                $result["weblinks"] = [];
596
                foreach ($iiifResource->getWeblinksForDisplay() as $link) {
597
                    $key = array_key_exists("label", $link) ? $link["label"] : $link["@id"];
598
                    $result["weblinks"][$key] = $link["@id"];
599
                }
600
            }
601
        }
602
        return $result;
603
    }
604
605
    /**
606
     * {@inheritDoc}
607
     * @see Document::getMetadata()
608
     */
609
    public function getMetadata($id, $cPid = 0)
610
    {
611
        if (!empty($this->metadataArray[$id]) && $this->metadataArray[0] == $cPid) {
612
            return $this->metadataArray[$id];
613
        }
614
        // Initialize metadata array with empty values.
615
        // TODO initialize metadata in abstract class
616
        $metadata = [
617
            'title' => [],
618
            'title_sorting' => [],
619
            'author' => [],
620
            'place' => [],
621
            'year' => [],
622
            'prod_id' => [],
623
            'record_id' => [],
624
            'opac_id' => [],
625
            'union_id' => [],
626
            'urn' => [],
627
            'purl' => [],
628
            'type' => [],
629
            'volume' => [],
630
            'volume_sorting' => [],
631
            'license' => [],
632
            'terms' => [],
633
            'restrictions' => [],
634
            'out_of_print' => [],
635
            'rights_info' => [],
636
            'collection' => [],
637
            'owner' => [],
638
            'mets_label' => [],
639
            'mets_orderlabel' => [],
640
            'document_format' => ['IIIF'],
641
        ];
642
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
643
            ->getQueryBuilderForTable('tx_dlf_metadata');
644
        // Get hidden records, too.
645
        $queryBuilder
646
            ->getRestrictions()
647
            ->removeByType(HiddenRestriction::class);
648
        $result = $queryBuilder
649
            ->select(
650
                'tx_dlf_metadata.index_name AS index_name',
651
                'tx_dlf_metadataformat.xpath AS xpath',
652
                'tx_dlf_metadataformat.xpath_sorting AS xpath_sorting',
653
                'tx_dlf_metadata.is_sortable AS is_sortable',
654
                'tx_dlf_metadata.default_value AS default_value',
655
                'tx_dlf_metadata.format AS format'
656
            )
657
            ->from('tx_dlf_metadata')
658
            ->from('tx_dlf_metadataformat')
659
            ->from('tx_dlf_formats')
660
            ->where(
661
                $queryBuilder->expr()->eq('tx_dlf_metadata.pid', intval($cPid)),
662
                $queryBuilder->expr()->eq('tx_dlf_metadataformat.pid', intval($cPid)),
663
                $queryBuilder->expr()->orX(
664
                    $queryBuilder->expr()->andX(
665
                        $queryBuilder->expr()->eq('tx_dlf_metadata.uid', 'tx_dlf_metadataformat.parent_id'),
666
                        $queryBuilder->expr()->eq('tx_dlf_metadataformat.encoded', 'tx_dlf_formats.uid'),
667
                        $queryBuilder->expr()->eq('tx_dlf_formats.type', $queryBuilder->createNamedParameter($this->getIiifVersion()))
668
                    ),
669
                    $queryBuilder->expr()->eq('tx_dlf_metadata.format', 0)
670
                )
671
            )
672
            ->execute();
673
        $iiifResource = $this->iiif->getContainedResourceById($id);
674
        while ($resArray = $result->fetch()) {
675
            // Set metadata field's value(s).
676
            if ($resArray['format'] > 0 && !empty($resArray['xpath']) && ($values = $iiifResource->jsonPath($resArray['xpath'])) != null) {
677
                if (is_string($values)) {
678
                    $metadata[$resArray['index_name']] = [trim((string) $values)];
679
                } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data()) > 1) {
680
                    $metadata[$resArray['index_name']] = [];
681
                    foreach ($values->data() as $value) {
682
                        $metadata[$resArray['index_name']][] = trim((string) $value);
683
                    }
684
                }
685
            }
686
            // Set default value if applicable.
687
            if (empty($metadata[$resArray['index_name']][0]) && strlen($resArray['default_value']) > 0) {
688
                $metadata[$resArray['index_name']] = [$resArray['default_value']];
689
            }
690
            // Set sorting value if applicable.
691
            if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) {
692
                if (
693
                    $resArray['format'] > 0 && !empty($resArray['xpath_sorting'])
694
                    && ($values = $iiifResource->jsonPath($resArray['xpath_sorting']) != null)
695
                ) {
696
                    if (is_string($values)) {
697
                        $metadata[$resArray['index_name'] . '_sorting'][0] = [trim((string) $values)];
698
                    } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data()) > 1) {
699
                        $metadata[$resArray['index_name']] = [];
700
                        foreach ($values->data() as $value) {
701
                            $metadata[$resArray['index_name'] . '_sorting'][0] = trim((string) $value);
702
                        }
703
                    }
704
                }
705
                if (empty($metadata[$resArray['index_name'] . '_sorting'][0])) {
706
                    $metadata[$resArray['index_name'] . '_sorting'][0] = $metadata[$resArray['index_name']][0];
707
                }
708
            }
709
        }
710
        return $metadata;
711
    }
712
713
    /**
714
     * {@inheritDoc}
715
     * @see Document::_getSmLinks()
716
     */
717
    protected function _getSmLinks()
718
    {
719
        if (!$this->smLinksLoaded && isset($this->iiif) && $this->iiif instanceof ManifestInterface) {
720
            if (!empty($this->iiif->getDefaultCanvases())) {
721
                foreach ($this->iiif->getDefaultCanvases() as $canvas) {
722
                    $this->smLinkCanvasToResource($canvas, $this->iiif);
723
                }
724
            }
725
            if (!empty($this->iiif->getStructures())) {
726
                foreach ($this->iiif->getStructures() as $range) {
727
                    $this->smLinkRangeCanvasesRecursively($range);
728
                }
729
            }
730
            $this->smLinksLoaded = true;
731
        }
732
        return $this->smLinks;
733
    }
734
735
    /**
736
     * Construct a link between a range and it's sub ranges and all contained canvases.
737
     *
738
     * @access private
739
     *
740
     * @param RangeInterface $range: Current range whose canvases shall be linked
741
     */
742
    private function smLinkRangeCanvasesRecursively(RangeInterface $range)
743
    {
744
        // map range's canvases including all child ranges' canvases
745
        if (!$range->isTopRange()) {
746
            foreach ($range->getAllCanvasesRecursively() as $canvas) {
747
                $this->smLinkCanvasToResource($canvas, $range);
748
            }
749
        }
750
        // recursive call for all ranges
751
        if (!empty($range->getAllRanges())) {
752
            foreach ($range->getAllRanges() as $childRange) {
753
                $this->smLinkRangeCanvasesRecursively($childRange);
754
            }
755
        }
756
    }
757
758
    /**
759
     * Link a single canvas to a containing range
760
     *
761
     * @access private
762
     *
763
     * @param CanvasInterface $canvas
764
     * @param IiifResourceInterface $resource
765
     */
766
    private function smLinkCanvasToResource(CanvasInterface $canvas, IiifResourceInterface $resource)
767
    {
768
        $this->smLinks['l2p'][$resource->getId()][] = $canvas->getId();
769
        if (!is_array($this->smLinks['p2l'][$canvas->getId()]) || !in_array($resource->getId(), $this->smLinks['p2l'][$canvas->getId()])) {
770
            $this->smLinks['p2l'][$canvas->getId()][] = $resource->getId();
771
        }
772
    }
773
774
    /**
775
     * Currently not supported for IIIF. Multivolume works _could_ be modelled
776
     * as IIIF Collections, but we can't tell them apart from actual collections.
777
     *
778
     * @access protected
779
     *
780
     * @see Document::getParentDocumentUidForSaving()
781
     */
782
    protected function getParentDocumentUidForSaving($pid, $core, $owner)
783
    {
784
        // Do nothing.
785
    }
786
787
    /**
788
     * {@inheritDoc}
789
     * @see Document::getFullText()
790
     */
791
    //TODO: rewrite it to get full OCR
792
    public function getFullText($id)
793
    {
794
        $rawText = '';
795
        // Get text from raw text array if available.
796
        if (!empty($this->rawTextArray[$id])) {
797
            return $this->rawTextArray[$id];
798
        }
799
        $this->ensureHasFulltextIsSet();
800
        if ($this->hasFulltext) {
801
            // Load physical structure ...
802
            $this->_getPhysicalStructure();
803
            // ... and extension configuration.
804
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
805
            $fileGrpsFulltext = GeneralUtility::trimExplode(',', $extConf['fileGrpFulltext']);
806
            if (!empty($this->physicalStructureInfo[$id])) {
807
                while ($fileGrpFulltext = array_shift($fileGrpsFulltext)) {
808
                    if (!empty($this->physicalStructureInfo[$id]['files'][$fileGrpFulltext])) {
809
                        $rawText = parent::getFullTextFromXml($id);
810
                        break;
811
                    }
812
                }
813
                if ($extConf['indexAnnotations'] == 1) {
814
                    $iiifResource = $this->iiif->getContainedResourceById($id);
815
                    // Get annotation containers
816
                    $annotationContainerIds = $this->physicalStructureInfo[$id]['annotationContainers'];
817
                    if (!empty($annotationContainerIds)) {
818
                        $annotationTexts = [];
819
                        foreach ($annotationContainerIds as $annotationListId) {
820
                            $annotationContainer = $this->iiif->getContainedResourceById($annotationListId);
821
                            /* @var $annotationContainer \Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface */
822
                            foreach ($annotationContainer->getTextAnnotations(Motivation::PAINTING) as $annotation) {
0 ignored issues
show
Bug introduced by
The method getTextAnnotations() does not exist on Ubl\Iiif\Presentation\Co...s\IiifResourceInterface. It seems like you code against a sub-type of Ubl\Iiif\Presentation\Co...s\IiifResourceInterface such as Ubl\Iiif\Presentation\Co...ationContainerInterface or Ubl\Iiif\Presentation\V2...sources\AnnotationList2 or Ubl\Iiif\Presentation\V3...sources\AnnotationPage3 or Ubl\Iiif\Presentation\V1...sources\AnnotationList1 or Ubl\Iiif\Presentation\V2...sources\AnnotationList2 or Ubl\Iiif\Presentation\V3...sources\AnnotationPage3 or Ubl\Iiif\Presentation\V1...sources\AnnotationList1. ( Ignorable by Annotation )

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

822
                            foreach ($annotationContainer->/** @scrutinizer ignore-call */ getTextAnnotations(Motivation::PAINTING) as $annotation) {
Loading history...
823
                                if (
824
                                    $annotation->getTargetResourceId() == $iiifResource->getId() &&
825
                                    $annotation->getBody() != null && $annotation->getBody()->getChars() != null
826
                                ) {
827
                                    $annotationTexts[] = $annotation->getBody()->getChars();
828
                                }
829
                            }
830
                        }
831
                        $rawText .= implode(' ', $annotationTexts);
832
                    }
833
                }
834
            } else {
835
                $this->logger->warning('Invalid structure resource @id "' . $id . '"');
1 ignored issue
show
Bug introduced by
The method warning() does not exist on TYPO3\CMS\Core\Log\LogManager. ( Ignorable by Annotation )

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

835
                $this->logger->/** @scrutinizer ignore-call */ 
836
                               warning('Invalid structure resource @id "' . $id . '"');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
836
                return $rawText;
837
            }
838
            $this->rawTextArray[$id] = $rawText;
839
        }
840
        return $rawText;
841
    }
842
843
    /**
844
     * Returns the underlying IiifResourceInterface.
845
     *
846
     * @access public
847
     *
848
     * @return IiifResourceInterface
849
     */
850
    public function getIiif()
851
    {
852
        return $this->iiif;
853
    }
854
855
    /**
856
     * {@inheritDoc}
857
     * @see Document::init()
858
     */
859
    protected function init()
860
    {
861
        // Nothing to do here, at the moment
862
    }
863
864
    /**
865
     * {@inheritDoc}
866
     * @see Document::loadLocation()
867
     */
868
    protected function loadLocation($location)
869
    {
870
        $fileResource = GeneralUtility::getUrl($location);
871
        if ($fileResource !== false) {
872
            $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
873
            IiifHelper::setUrlReader(IiifUrlReader::getInstance());
874
            IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
875
            IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
876
            $resource = IiifHelper::loadIiifResource($fileResource);
877
            if ($resource != null) {
878
                if ($resource instanceof ManifestInterface) {
879
                    $this->iiif = $resource;
880
                    return true;
881
                }
882
            }
883
        }
884
        $this->logger->error('Could not load IIIF manifest from "' . $location . '"');
1 ignored issue
show
Bug introduced by
The method error() does not exist on TYPO3\CMS\Core\Log\LogManager. ( Ignorable by Annotation )

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

884
        $this->logger->/** @scrutinizer ignore-call */ 
885
                       error('Could not load IIIF manifest from "' . $location . '"');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
885
        return false;
886
    }
887
888
    /**
889
     * {@inheritDoc}
890
     * @see \Kitodo\Dlf\Common\Document::prepareMetadataArray()
891
     */
892
    protected function prepareMetadataArray($cPid)
893
    {
894
        $id = $this->iiif->getId();
895
        $this->metadataArray[(string) $id] = $this->getMetadata((string) $id, $cPid);
896
    }
897
898
    /**
899
     * {@inheritDoc}
900
     * @see Document::setPreloadedDocument()
901
     */
902
    protected function setPreloadedDocument($preloadedDocument)
903
    {
904
        if ($preloadedDocument instanceof ManifestInterface) {
905
            $this->iiif = $preloadedDocument;
906
            return true;
907
        }
908
        return false;
909
    }
910
911
    /**
912
     * {@inheritDoc}
913
     * @see Document::ensureHasFulltextIsSet()
914
     */
915
    protected function ensureHasFulltextIsSet()
916
    {
917
        /*
918
         *  TODO Check annotations and annotation lists of canvas for ALTO documents.
919
         *  Example:
920
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/manifest.json links
921
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/list/0001.json
922
         */
923
        if (!$this->hasFulltextSet && $this->iiif instanceof ManifestInterface) {
924
            $manifest = $this->iiif;
925
            $canvases = $manifest->getDefaultCanvases();
926
            foreach ($canvases as $canvas) {
927
                if (
928
                    !empty($canvas->getSeeAlsoUrlsForFormat("application/alto+xml")) ||
929
                    !empty($canvas->getSeeAlsoUrlsForProfile("http://www.loc.gov/standards/alto/"))
930
                ) {
931
                    $this->hasFulltextSet = true;
932
                    $this->hasFulltext = true;
933
                    return;
934
                }
935
                $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
936
                if ($extConf['indexAnnotations'] == 1 && !empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
937
                    foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
938
                        if (($textAnnotations = $annotationContainer->getTextAnnotations(Motivation::PAINTING)) != null) {
939
                            foreach ($textAnnotations as $annotation) {
940
                                if (
941
                                    $annotation->getBody() != null &&
942
                                    $annotation->getBody()->getFormat() == "text/plain" &&
943
                                    $annotation->getBody()->getChars() != null
944
                                ) {
945
                                    $this->hasFulltextSet = true;
946
                                    $this->hasFulltext = true;
947
                                    return;
948
                                }
949
                            }
950
                        }
951
                    }
952
                }
953
            }
954
            $this->hasFulltextSet = true;
955
        }
956
    }
957
958
    /**
959
     * {@inheritDoc}
960
     * @see \Kitodo\Dlf\Common\Document::_getThumbnail()
961
     */
962
    protected function _getThumbnail($forceReload = false)
963
    {
964
        return $this->iiif->getThumbnailUrl();
965
    }
966
967
    /**
968
     * {@inheritDoc}
969
     * @see \Kitodo\Dlf\Common\Document::_getToplevelId()
970
     */
971
    protected function _getToplevelId()
972
    {
973
        if (empty($this->toplevelId)) {
974
            if (isset($this->iiif)) {
975
                $this->toplevelId = $this->iiif->getId();
976
            }
977
        }
978
        return $this->toplevelId;
979
    }
980
981
    /**
982
     * This magic method is executed after the object is deserialized
983
     * @see __sleep()
984
     *
985
     * @access public
986
     *
987
     * @return void
988
     */
989
    public function __wakeup()
990
    {
991
        $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
992
        IiifHelper::setUrlReader(IiifUrlReader::getInstance());
993
        IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
994
        IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
995
        $resource = IiifHelper::loadIiifResource($this->asJson);
996
        if ($resource != null && $resource instanceof ManifestInterface) {
997
            $this->asJson = '';
998
            $this->iiif = $resource;
999
            $this->init();
1000
        } else {
1001
            $this->logger->error('Could not load IIIF after deserialization');
1002
        }
1003
    }
1004
1005
    /**
1006
     *
1007
     * @return string[]
1008
     */
1009
    public function __sleep()
1010
    {
1011
        // TODO implement serializiation in IIIF library
1012
        $jsonArray = $this->iiif->getOriginalJsonArray();
1013
        $this->asJson = json_encode($jsonArray);
1014
        return ['uid', 'pid', 'recordId', 'parentId', 'asJson'];
1015
    }
1016
}
1017