Scrutinizer GitHub App not installed

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

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 8c4913...9583e9 )
by
unknown
03:53
created

IiifManifest::_getPhysicalStructure()   D

Complexity

Conditions 26
Paths 32

Size

Total Lines 108
Code Lines 77

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 77
c 0
b 0
f 0
dl 0
loc 108
rs 4.1666
cc 26
nc 32
nop 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
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\Database\Query\Restriction\HiddenRestriction;
19
use TYPO3\CMS\Core\Log\LogManager;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface;
22
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationInterface;
23
use Ubl\Iiif\Presentation\Common\Model\Resources\CanvasInterface;
24
use Ubl\Iiif\Presentation\Common\Model\Resources\ContentResourceInterface;
25
use Ubl\Iiif\Presentation\Common\Model\Resources\IiifResourceInterface;
26
use Ubl\Iiif\Presentation\Common\Model\Resources\ManifestInterface;
27
use Ubl\Iiif\Presentation\Common\Model\Resources\RangeInterface;
28
use Ubl\Iiif\Presentation\Common\Vocabulary\Motivation;
29
use Ubl\Iiif\Presentation\V1\Model\Resources\AbstractIiifResource1;
30
use Ubl\Iiif\Presentation\V2\Model\Resources\AbstractIiifResource2;
31
use Ubl\Iiif\Presentation\V3\Model\Resources\AbstractIiifResource3;
32
use Ubl\Iiif\Services\AbstractImageService;
33
use Ubl\Iiif\Services\Service;
34
use Ubl\Iiif\Tools\IiifHelper;
35
36
/**
37
 * IiifManifest class for the 'dlf' extension.
38
 *
39
 * @author Lutz Helm <[email protected]>
40
 * @package TYPO3
41
 * @subpackage dlf
42
 * @access public
43
 * @property int $cPid This holds the PID for the configuration
44
 * @property-read bool $hasFulltext Are there any fulltext files available?
45
 * @property-read array $metadataArray This holds the documents' parsed metadata array
46
 * @property-read int $numPages The holds the total number of pages
47
 * @property-read int $parentId This holds the UID of the parent document or zero if not multi-volumed
48
 * @property-read array $physicalStructure This holds the physical structure
49
 * @property-read array $physicalStructureInfo This holds the physical structure metadata
50
 * @property-read int $pid This holds the PID of the document or zero if not in database
51
 * @property-read bool $ready Is the document instantiated successfully?
52
 * @property-read string $recordId The IIIF manifest's record identifier
53
 * @property-read int $rootId This holds the UID of the root document or zero if not multi-volumed
54
 * @property-read array $smLinks This holds the connections between resources and canvases
55
 * @property-read array $tableOfContents This holds the logical structure
56
 * @property-read string $thumbnail This holds the document's thumbnail location
57
 * @property-read string $toplevelId This holds the toplevel manifest's @id
58
 */
59
final class IiifManifest extends AbstractDocument
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 AbstractDocument::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);
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->fetchAssociative()) {
157
                $recordIdPath = $resArray['querypath'];
158
                if (!empty($recordIdPath)) {
159
                    try {
160
                        $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...
161
                    } catch (\Exception $e) {
162
                        $this->logger->warning('Could not evaluate JSONPath to get IIIF record ID');
163
                    }
164
                }
165
            }
166
            // For now, it's a hardcoded ID, not only as a fallback
167
            if (!isset($this->recordId)) {
168
                $this->recordId = $this->iiif->getId();
169
            }
170
        }
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     * @see AbstractDocument::getDocument()
176
     */
177
    protected function getDocument()
178
    {
179
        return $this->iiif;
180
    }
181
182
    /**
183
     * Returns a string representing the Metadata / Presentation API version which the IIIF resource
184
     * conforms to. This is used for example to extract metadata according to configured patterns.
185
     *
186
     * @access public
187
     *
188
     * @return string 'IIIF1' if the resource is a Metadata API 1 resource, 'IIIF2' / 'IIIF3' if
189
     * the resource is a Presentation API 2 / 3 resource
190
     */
191
    public function getIiifVersion()
192
    {
193
        if (!isset($this->iiifVersion)) {
194
            if ($this->iiif instanceof AbstractIiifResource1) {
195
                $this->iiifVersion = 'IIIF1';
196
            } elseif ($this->iiif instanceof AbstractIiifResource2) {
197
                $this->iiifVersion = 'IIIF2';
198
            } elseif ($this->iiif instanceof AbstractIiifResource3) {
199
                $this->iiifVersion = 'IIIF3';
200
            }
201
        }
202
        return $this->iiifVersion;
203
    }
204
205
    /**
206
     * True if getUseGroups() has been called and $this->useGrps is loaded
207
     *
208
     * @var bool
209
     * @access protected
210
     */
211
    protected $useGrpsLoaded = false;
212
213
    /**
214
     * Holds the configured useGrps as array.
215
     *
216
     * @var array
217
     * @access protected
218
     */
219
    protected $useGrps = [];
220
221
    /**
222
     * IiifManifest also populates the physical structure array entries for matching
223
     * 'fileGrp's. To do that, the configuration has to be loaded; afterwards configured
224
     * 'fileGrp's for thumbnails, downloads, audio, fulltext and the 'fileGrp's for images
225
     * can be requested with this method.
226
     *
227
     * @access protected
228
     *
229
     * @param string $use
230
     *
231
     * @return array|string
232
     */
233
    protected function getUseGroups($use)
234
    {
235
        if (!$this->useGrpsLoaded) {
236
            // Get configured USE attributes.
237
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
238
            if (!empty($extConf['fileGrpImages'])) {
239
                $this->useGrps['fileGrpImages'] = GeneralUtility::trimExplode(',', $extConf['fileGrpImages']);
240
            }
241
            if (!empty($extConf['fileGrpThumbs'])) {
242
                $this->useGrps['fileGrpThumbs'] = GeneralUtility::trimExplode(',', $extConf['fileGrpThumbs']);
243
            }
244
            if (!empty($extConf['fileGrpDownload'])) {
245
                $this->useGrps['fileGrpDownload'] = GeneralUtility::trimExplode(',', $extConf['fileGrpDownload']);
246
            }
247
            if (!empty($extConf['fileGrpFulltext'])) {
248
                $this->useGrps['fileGrpFulltext'] = GeneralUtility::trimExplode(',', $extConf['fileGrpFulltext']);
249
            }
250
            if (!empty($extConf['fileGrpAudio'])) {
251
                $this->useGrps['fileGrpAudio'] = GeneralUtility::trimExplode(',', $extConf['fileGrpAudio']);
252
            }
253
            $this->useGrpsLoaded = true;
254
        }
255
        return array_key_exists($use, $this->useGrps) ? $this->useGrps[$use] : [];
256
    }
257
258
    /**
259
     * {@inheritDoc}
260
     * @see AbstractDocument::_getPhysicalStructure()
261
     */
262
    protected function _getPhysicalStructure()
263
    {
264
        // Is there no physical structure array yet?
265
        if (!$this->physicalStructureLoaded) {
266
            if ($this->iiif == null || !($this->iiif instanceof ManifestInterface)) {
267
                return null;
268
            }
269
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
270
            $iiifId = $this->iiif->getId();
271
            $physSeq[0] = $iiifId;
272
            $this->physicalStructureInfo[$physSeq[0]]['id'] = $iiifId;
273
            $this->physicalStructureInfo[$physSeq[0]]['dmdId'] = $iiifId;
274
            $this->physicalStructureInfo[$physSeq[0]]['label'] = $this->iiif->getLabelForDisplay();
275
            $this->physicalStructureInfo[$physSeq[0]]['orderlabel'] = $this->iiif->getLabelForDisplay();
276
            $this->physicalStructureInfo[$physSeq[0]]['type'] = 'physSequence';
277
            $this->physicalStructureInfo[$physSeq[0]]['contentIds'] = null;
278
            $fileUseDownload = $this->getUseGroups('fileGrpDownload');
279
            $fileUseFulltext = $this->getUseGroups('fileGrpFulltext');
280
            $fileUseThumbs = $this->getUseGroups('fileGrpThumbs');
281
            $fileUses = $this->getUseGroups('fileGrpImages');
282
            if (!empty($fileUseDownload)) {
283
                $docPdfRendering = $this->iiif->getRenderingUrlsForFormat('application/pdf');
284
                if (!empty($docPdfRendering)) {
285
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseDownload[0]] = $docPdfRendering[0];
286
                }
287
            }
288
            if (!empty($fileUseFulltext)) {
289
                $iiifAlto = $this->iiif->getSeeAlsoUrlsForFormat('application/alto+xml');
290
                if (empty($iiifAlto)) {
291
                    $iiifAlto = $this->iiif->getSeeAlsoUrlsForProfile('http://www.loc.gov/standards/alto/', true);
292
                }
293
                if (!empty($iiifAlto)) {
294
                    $this->mimeTypes[$iiifAlto[0]] = 'application/alto+xml';
295
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseFulltext[0]] = $iiifAlto[0];
296
                    $this->hasFulltext = true;
297
                    $this->hasFulltextSet = true;
298
                }
299
            }
300
            if (!empty($this->iiif->getDefaultCanvases())) {
301
                // canvases have not order property, but the context defines canveses as @list with a specific order, so we can provide an alternative
302
                $canvasOrder = 0;
303
                foreach ($this->iiif->getDefaultCanvases() as $canvas) {
304
                    $canvasOrder++;
305
                    $thumbnailUrl = $canvas->getThumbnailUrl();
306
                    // put thumbnails in thumbnail filegroup
307
                    if (
308
                        !empty($thumbnailUrl)
309
                        && empty($this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseThumbs[0]])
310
                    ) {
311
                        $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseThumbs[0]] = $thumbnailUrl;
312
                    }
313
                    // populate structural metadata info
314
                    $elements[$canvasOrder] = $canvas->getId();
315
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['id'] = $canvas->getId();
316
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['dmdId'] = null;
317
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['label'] = $canvas->getLabelForDisplay();
318
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['orderlabel'] = $canvas->getLabelForDisplay();
319
                    // assume that a canvas always represents a page
320
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['type'] = 'page';
321
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['contentIds'] = null;
322
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = null;
323
                    if (!empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
324
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = [];
325
                        foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
326
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'][] = $annotationContainer->getId();
327
                            if ($extConf['indexAnnotations']) {
328
                                $this->hasFulltext = true;
329
                                $this->hasFulltextSet = true;
330
                            }
331
                        }
332
                    }
333
                    if (!empty($fileUseFulltext)) {
334
                        $alto = $canvas->getSeeAlsoUrlsForFormat('application/alto+xml');
335
                        if (empty($alto)) {
336
                            $alto = $canvas->getSeeAlsoUrlsForProfile('http://www.loc.gov/standards/alto/', true);
337
                        }
338
                        if (!empty($alto)) {
339
                            $this->mimeTypes[$alto[0]] = 'application/alto+xml';
340
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseFulltext[0]] = $alto[0];
341
                            $this->hasFulltext = true;
342
                            $this->hasFulltextSet = true;
343
                        }
344
                    }
345
                    if (!empty($fileUses)) {
346
                        $image = $canvas->getImageAnnotations()[0];
347
                        foreach ($fileUses as $fileUse) {
348
                            if ($image->getBody() !== null && $image->getBody() instanceof ContentResourceInterface) {
349
                                $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUse] = $image->getBody()->getId();
350
                            }
351
                        }
352
                    }
353
                    if (!empty($thumbnailUrl)) {
354
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseThumbs] = $thumbnailUrl;
355
                    }
356
                    if (!empty($fileUseDownload)) {
357
                        $pdfRenderingUrls = $canvas->getRenderingUrlsForFormat('application/pdf');
358
                        if (!empty($pdfRenderingUrls)) {
359
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseDownload[0]] = $pdfRenderingUrls[0];
360
                        }
361
                    }
362
                }
363
                $this->numPages = $canvasOrder;
364
                // Merge and re-index the array to get nice numeric indexes.
365
                $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 303. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
366
            }
367
            $this->physicalStructureLoaded = true;
368
        }
369
        return $this->physicalStructure;
370
    }
371
372
    /**
373
     * {@inheritDoc}
374
     * @see AbstractDocument::getDownloadLocation()
375
     */
376
    public function getDownloadLocation($id)
377
    {
378
        $fileLocation = $this->getFileLocation($id);
379
        $resource = $this->iiif->getContainedResourceById($fileLocation);
380
        if ($resource instanceof AbstractImageService) {
381
            return $resource->getImageUrl();
382
        }
383
        return $fileLocation;
384
    }
385
386
    /**
387
     * {@inheritDoc}
388
     * @see AbstractDocument::getFileInfo()
389
     */
390
    public function getFileInfo($id)
391
    {
392
        if (empty($this->fileInfos[$id]['location'])) {
393
            $this->fileInfos[$id]['location'] = $this->getFileLocation($id);
0 ignored issues
show
Bug introduced by
The property fileInfos is declared read-only in Kitodo\Dlf\Common\AbstractDocument.
Loading history...
394
        }
395
396
        if (empty($this->fileInfos[$id]['mimeType'])) {
397
            $this->fileInfos[$id]['mimeType'] = $this->getFileMimeType($id);
398
        }
399
400
        return $this->fileInfos[$id];
401
    }
402
403
    /**
404
     * {@inheritDoc}
405
     * @see AbstractDocument::getFileLocation()
406
     */
407
    public function getFileLocation($id)
408
    {
409
        if ($id == null) {
410
            return null;
411
        }
412
        $resource = $this->iiif->getContainedResourceById($id);
413
        if (isset($resource)) {
414
            if ($resource instanceof CanvasInterface) {
415
                return (!empty($resource->getImageAnnotations()) && $resource->getImageAnnotations()->getSingleService() != null) ? $resource->getImageAnnotations()[0]->getSingleService()->getId() : $id;
416
            } elseif ($resource instanceof ContentResourceInterface) {
417
                return $resource->getSingleService() != null && $resource->getSingleService() instanceof Service ? $resource->getSingleService()->getId() : $id;
418
            } elseif ($resource instanceof AbstractImageService) {
419
                return $resource->getId();
420
            } elseif ($resource instanceof AnnotationContainerInterface) {
421
                return $id;
422
            }
423
        } else {
424
            return $id;
425
        }
426
    }
427
428
    /**
429
     * {@inheritDoc}
430
     * @see AbstractDocument::getFileMimeType()
431
     */
432
    public function getFileMimeType($id)
433
    {
434
        $fileResource = $this->iiif->getContainedResourceById($id);
435
        if ($fileResource instanceof CanvasInterface) {
436
            $format = "application/vnd.kitodo.iiif";
437
        } elseif ($fileResource instanceof AnnotationInterface) {
438
            $format = "application/vnd.kitodo.iiif";
439
        } elseif ($fileResource instanceof ContentResourceInterface) {
440
            if ($fileResource->isText() || $fileResource->isImage() && ($fileResource->getSingleService() == null || !($fileResource->getSingleService() instanceof AbstractImageService))) {
441
                // Support static images without an image service
442
                return $fileResource->getFormat();
443
            }
444
            $format = "application/vnd.kitodo.iiif";
445
        } elseif ($fileResource instanceof AbstractImageService) {
446
            $format = "application/vnd.kitodo.iiif";
447
        } else {
448
            // Assumptions: this can only be the thumbnail and the thumbnail is a jpeg - TODO determine mimetype
449
            $format = "image/jpeg";
450
        }
451
        return $format;
452
    }
453
454
    /**
455
     * {@inheritDoc}
456
     * @see AbstractDocument::getLogicalStructure()
457
     */
458
    public function getLogicalStructure($id, $recursive = false)
459
    {
460
        $details = [];
461
        if (!$recursive && !empty($this->logicalUnits[$id])) {
462
            return $this->logicalUnits[$id];
463
        } elseif (!empty($id)) {
464
            $logUnits[] = $this->iiif->getContainedResourceById($id);
465
        } else {
466
            $logUnits[] = $this->iiif;
467
        }
468
        if (!empty($logUnits)) {
469
            if (!$recursive) {
470
                $details = $this->getLogicalStructureInfo($logUnits[0]);
471
            } else {
472
                // cache the ranges - they might occur multiple times in the structures "tree" - with full data as well as referenced as id
473
                $processedStructures = [];
474
                foreach ($logUnits as $logUnit) {
475
                    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...
476
                        $this->tableOfContents[] = $this->getLogicalStructureInfo($logUnit, true, $processedStructures);
477
                    }
478
                }
479
            }
480
        }
481
        return $details;
482
    }
483
484
    /**
485
     * Get the details about a IIIF resource (manifest or range) in the logical structure
486
     *
487
     * @access protected
488
     *
489
     * @param IiifResourceInterface $resource: IIIF resource, either a manifest or range.
490
     * @param bool $recursive: Whether to include the child elements
491
     * @param array $processedStructures: IIIF resources that already have been processed
492
     * @return array Logical structure array
493
     */
494
    protected function getLogicalStructureInfo(IiifResourceInterface $resource, $recursive = false, &$processedStructures = [])
495
    {
496
        $details = [];
497
        $details['id'] = $resource->getId();
498
        $details['dmdId'] = '';
499
        $details['label'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
500
        $details['orderlabel'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
501
        $details['contentIds'] = '';
502
        $details['volume'] = '';
503
        $details['pagination'] = '';
504
        $cPid = ($this->cPid ? $this->cPid : $this->pid);
505
        if ($details['id'] == $this->_getToplevelId()) {
506
            $metadata = $this->getMetadata($details['id'], $cPid);
507
            if (!empty($metadata['type'][0])) {
508
                $details['type'] = $metadata['type'][0];
509
            }
510
        }
511
        $details['thumbnailId'] = $resource->getThumbnailUrl();
512
        $details['points'] = '';
513
        // Load strucural mapping
514
        $this->_getSmLinks();
515
        // Load physical structure.
516
        $this->_getPhysicalStructure();
517
        $canvases = [];
518
        if ($resource instanceof ManifestInterface) {
519
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
520
            $canvases = $resource->getDefaultCanvases();
0 ignored issues
show
Unused Code introduced by
The assignment to $canvases is dead and can be removed.
Loading history...
521
        } elseif ($resource instanceof RangeInterface) {
522
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
523
            $canvases = $resource->getAllCanvases();
524
        }
525
        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...
526
            $details['pagination'] = $startCanvas->getLabel();
527
            $startCanvasIndex = array_search($startCanvas, $this->iiif->getDefaultCanvases());
528
            if ($startCanvasIndex !== false) {
529
                $details['points'] = $startCanvasIndex + 1;
530
            }
531
        }
532
        $useGroups = $this->getUseGroups('fileGrpImages');
533
        if (is_string($useGroups)) {
534
            $useGroups = [$useGroups];
0 ignored issues
show
Unused Code introduced by
The assignment to $useGroups is dead and can be removed.
Loading history...
535
        }
536
        // Keep for later usage.
537
        $this->logicalUnits[$details['id']] = $details;
538
        // Walk the structure recursively? And are there any children of the current element?
539
        if ($recursive) {
540
            $processedStructures[] = $resource->getId();
541
            $details['children'] = [];
542
            if ($resource instanceof ManifestInterface && $resource->getRootRanges() != null) {
543
                $rangesToAdd = [];
544
                $rootRanges = [];
545
                if (sizeof($this->iiif->getRootRanges()) == 1 && $this->iiif->getRootRanges()[0]->isTopRange()) {
546
                    $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

546
                    /** @scrutinizer ignore-call */ 
547
                    $rangesToAdd = $this->iiif->getRootRanges()[0]->getMemberRangesAndRanges();
Loading history...
547
                } else {
548
                    $rangesToAdd = $this->iiif->getRootRanges();
549
                }
550
                foreach ($rangesToAdd as $range) {
551
                    $rootRanges[] = $range;
552
                }
553
                foreach ($rootRanges as $range) {
554
                    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...
555
                        $details['children'][] = $this->getLogicalStructureInfo($range, true, $processedStructures);
556
                    }
557
                }
558
            } elseif ($resource instanceof RangeInterface) {
559
                if (!empty($resource->getAllRanges())) {
560
                    foreach ($resource->getAllRanges() as $range) {
561
                        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...
562
                            $details['children'][] = $this->getLogicalStructureInfo($range, true, $processedStructures);
563
                        }
564
                    }
565
                }
566
            }
567
        }
568
        return $details;
569
    }
570
571
    /**
572
     * Returns metadata for IIIF resources with the ID $id in there original form in
573
     * the manifest, but prepared for display to the user.
574
     *
575
     * @access public
576
     *
577
     * @param string $id: the ID of the IIIF resource
578
     * @param int $cPid: the configuration folder's id
579
     * @param bool $withDescription: add description / summary to the return value
580
     * @param bool $withRights: add attribution and license / rights and requiredStatement to the return value
581
     * @param bool $withRelated: add related links / homepage to the return value
582
     *
583
     * @return array
584
     *
585
     * @todo This method is still in experimental; the method signature may change.
586
     */
587
    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

587
    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...
588
    {
589
        if (!empty($this->originalMetadataArray[$id])) {
590
            return $this->originalMetadataArray[$id];
591
        }
592
        $iiifResource = $this->iiif->getContainedResourceById($id);
593
        $result = [];
594
        if ($iiifResource != null) {
595
            if ($iiifResource->getLabel() != null && $iiifResource->getLabel() != "") {
596
                $result['label'] = $iiifResource->getLabel();
597
            }
598
            if (!empty($iiifResource->getMetadata())) {
599
                $result['metadata'] = [];
600
                foreach ($iiifResource->getMetadataForDisplay() as $metadata) {
601
                    $result['metadata'][$metadata['label']] = $metadata['value'];
602
                }
603
            }
604
            if ($withDescription && !empty($iiifResource->getSummary())) {
605
                $result["description"] = $iiifResource->getSummaryForDisplay();
606
            }
607
            if ($withRights) {
608
                if (!empty($iiifResource->getRights())) {
609
                    $result["rights"] = $iiifResource->getRights();
610
                }
611
                if (!empty($iiifResource->getRequiredStatement())) {
612
                    $result["requiredStatement"] = $iiifResource->getRequiredStatementForDisplay();
613
                }
614
            }
615
            if ($withRelated && !empty($iiifResource->getWeblinksForDisplay())) {
616
                $result["weblinks"] = [];
617
                foreach ($iiifResource->getWeblinksForDisplay() as $link) {
618
                    $key = array_key_exists("label", $link) ? $link["label"] : $link["@id"];
619
                    $result["weblinks"][$key] = $link["@id"];
620
                }
621
            }
622
        }
623
        return $result;
624
    }
625
626
    /**
627
     * {@inheritDoc}
628
     * @see AbstractDocument::getMetadata()
629
     */
630
    public function getMetadata($id, $cPid = 0)
631
    {
632
        if (!empty($this->metadataArray[$id]) && $this->metadataArray[0] == $cPid) {
633
            return $this->metadataArray[$id];
634
        }
635
636
        $metadata = $this->initializeMetadata('IIIF');
637
638
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
639
            ->getQueryBuilderForTable('tx_dlf_metadata');
640
        // Get hidden records, too.
641
        $queryBuilder
642
            ->getRestrictions()
643
            ->removeByType(HiddenRestriction::class);
644
        $result = $queryBuilder
645
            ->select(
646
                'tx_dlf_metadata.index_name AS index_name',
647
                'tx_dlf_metadataformat.xpath AS xpath',
648
                'tx_dlf_metadataformat.xpath_sorting AS xpath_sorting',
649
                'tx_dlf_metadata.is_sortable AS is_sortable',
650
                'tx_dlf_metadata.default_value AS default_value',
651
                'tx_dlf_metadata.format AS format'
652
            )
653
            ->from('tx_dlf_metadata')
654
            ->from('tx_dlf_metadataformat')
655
            ->from('tx_dlf_formats')
656
            ->where(
657
                $queryBuilder->expr()->eq('tx_dlf_metadata.pid', intval($cPid)),
658
                $queryBuilder->expr()->eq('tx_dlf_metadataformat.pid', intval($cPid)),
659
                $queryBuilder->expr()->orX(
660
                    $queryBuilder->expr()->andX(
661
                        $queryBuilder->expr()->eq('tx_dlf_metadata.uid', 'tx_dlf_metadataformat.parent_id'),
662
                        $queryBuilder->expr()->eq('tx_dlf_metadataformat.encoded', 'tx_dlf_formats.uid'),
663
                        $queryBuilder->expr()->eq('tx_dlf_formats.type', $queryBuilder->createNamedParameter($this->getIiifVersion()))
664
                    ),
665
                    $queryBuilder->expr()->eq('tx_dlf_metadata.format', 0)
666
                )
667
            )
668
            ->execute();
669
        $iiifResource = $this->iiif->getContainedResourceById($id);
670
        while ($resArray = $result->fetchAssociative()) {
671
            // Set metadata field's value(s).
672
            if ($resArray['format'] > 0 && !empty($resArray['xpath']) && ($values = $iiifResource->jsonPath($resArray['xpath'])) != null) {
673
                if (is_string($values)) {
674
                    $metadata[$resArray['index_name']] = [trim((string) $values)];
675
                } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data()) > 1) {
676
                    $metadata[$resArray['index_name']] = [];
677
                    foreach ($values->data() as $value) {
678
                        $metadata[$resArray['index_name']][] = trim((string) $value);
679
                    }
680
                }
681
            }
682
            // Set default value if applicable.
683
            if (empty($metadata[$resArray['index_name']][0]) && strlen($resArray['default_value']) > 0) {
684
                $metadata[$resArray['index_name']] = [$resArray['default_value']];
685
            }
686
            // Set sorting value if applicable.
687
            if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) {
688
                if (
689
                    $resArray['format'] > 0 && !empty($resArray['xpath_sorting'])
690
                    && ($values = $iiifResource->jsonPath($resArray['xpath_sorting']) != null)
691
                ) {
692
                    if (is_string($values)) {
693
                        $metadata[$resArray['index_name'] . '_sorting'][0] = [trim((string) $values)];
694
                    } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data()) > 1) {
695
                        $metadata[$resArray['index_name']] = [];
696
                        foreach ($values->data() as $value) {
697
                            $metadata[$resArray['index_name'] . '_sorting'][0] = trim((string) $value);
698
                        }
699
                    }
700
                }
701
                if (empty($metadata[$resArray['index_name'] . '_sorting'][0])) {
702
                    $metadata[$resArray['index_name'] . '_sorting'][0] = $metadata[$resArray['index_name']][0];
703
                }
704
            }
705
        }
706
        // Set date to empty string if not present.
707
        if (empty($metadata['date'][0])) {
708
            $metadata['date'][0] = '';
709
        }
710
        return $metadata;
711
    }
712
713
    /**
714
     * {@inheritDoc}
715
     * @see AbstractDocument::_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
     * {@inheritDoc}
776
     * @see AbstractDocument::getFullText()
777
     */
778
    //TODO: rewrite it to get full OCR
779
    public function getFullText($id)
780
    {
781
        $rawText = '';
782
        // Get text from raw text array if available.
783
        if (!empty($this->rawTextArray[$id])) {
784
            return $this->rawTextArray[$id];
785
        }
786
        $this->ensureHasFulltextIsSet();
787
        if ($this->hasFulltext) {
788
            // Load physical structure ...
789
            $this->_getPhysicalStructure();
790
            // ... and extension configuration.
791
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
792
            $fileGrpsFulltext = GeneralUtility::trimExplode(',', $extConf['fileGrpFulltext']);
793
            if (!empty($this->physicalStructureInfo[$id])) {
794
                while ($fileGrpFulltext = array_shift($fileGrpsFulltext)) {
795
                    if (!empty($this->physicalStructureInfo[$id]['files'][$fileGrpFulltext])) {
796
                        $rawText = parent::getFullTextFromXml($id);
797
                        break;
798
                    }
799
                }
800
                if ($extConf['indexAnnotations'] == 1) {
801
                    $iiifResource = $this->iiif->getContainedResourceById($id);
802
                    // Get annotation containers
803
                    $annotationContainerIds = $this->physicalStructureInfo[$id]['annotationContainers'];
804
                    if (!empty($annotationContainerIds)) {
805
                        $annotationTexts = [];
806
                        foreach ($annotationContainerIds as $annotationListId) {
807
                            $annotationContainer = $this->iiif->getContainedResourceById($annotationListId);
808
                            /* @var $annotationContainer \Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface */
809
                            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

809
                            foreach ($annotationContainer->/** @scrutinizer ignore-call */ getTextAnnotations(Motivation::PAINTING) as $annotation) {
Loading history...
810
                                if (
811
                                    $annotation->getTargetResourceId() == $iiifResource->getId() &&
812
                                    $annotation->getBody() != null && $annotation->getBody()->getChars() != null
813
                                ) {
814
                                    $annotationTexts[] = $annotation->getBody()->getChars();
815
                                }
816
                            }
817
                        }
818
                        $rawText .= implode(' ', $annotationTexts);
819
                    }
820
                }
821
            } else {
822
                $this->logger->warning('Invalid structure resource @id "' . $id . '"');
823
                return $rawText;
824
            }
825
            $this->rawTextArray[$id] = $rawText;
826
        }
827
        return $rawText;
828
    }
829
830
    /**
831
     * Returns the underlying IiifResourceInterface.
832
     *
833
     * @access public
834
     *
835
     * @return IiifResourceInterface
836
     */
837
    public function getIiif()
838
    {
839
        return $this->iiif;
840
    }
841
842
    /**
843
     * {@inheritDoc}
844
     * @see AbstractDocument::init()
845
     */
846
    protected function init($location)
847
    {
848
        $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(static::class);
849
    }
850
851
    /**
852
     * {@inheritDoc}
853
     * @see AbstractDocument::loadLocation()
854
     */
855
    protected function loadLocation($location)
856
    {
857
        $fileResource = GeneralUtility::getUrl($location);
858
        if ($fileResource !== false) {
859
            $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
860
            IiifHelper::setUrlReader(IiifUrlReader::getInstance());
861
            IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
862
            IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
863
            $resource = IiifHelper::loadIiifResource($fileResource);
864
            if ($resource != null) {
865
                if ($resource instanceof ManifestInterface) {
866
                    $this->iiif = $resource;
867
                    return true;
868
                }
869
            }
870
        }
871
        $this->logger->error('Could not load IIIF manifest from "' . $location . '"');
872
        return false;
873
    }
874
875
    /**
876
     * {@inheritDoc}
877
     * @see AbstractDocument::prepareMetadataArray()
878
     */
879
    protected function prepareMetadataArray($cPid)
880
    {
881
        $id = $this->iiif->getId();
882
        $this->metadataArray[(string) $id] = $this->getMetadata((string) $id, $cPid);
883
    }
884
885
    /**
886
     * {@inheritDoc}
887
     * @see AbstractDocument::setPreloadedDocument()
888
     */
889
    protected function setPreloadedDocument($preloadedDocument)
890
    {
891
        if ($preloadedDocument instanceof ManifestInterface) {
892
            $this->iiif = $preloadedDocument;
893
            return true;
894
        }
895
        return false;
896
    }
897
898
    /**
899
     * {@inheritDoc}
900
     * @see AbstractDocument::ensureHasFulltextIsSet()
901
     */
902
    protected function ensureHasFulltextIsSet()
903
    {
904
        /*
905
         *  TODO Check annotations and annotation lists of canvas for ALTO documents.
906
         *  Example:
907
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/manifest.json links
908
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/list/0001.json
909
         */
910
        if (!$this->hasFulltextSet && $this->iiif instanceof ManifestInterface) {
911
            $manifest = $this->iiif;
912
            $canvases = $manifest->getDefaultCanvases();
913
            foreach ($canvases as $canvas) {
914
                if (
915
                    !empty($canvas->getSeeAlsoUrlsForFormat("application/alto+xml")) ||
916
                    !empty($canvas->getSeeAlsoUrlsForProfile("http://www.loc.gov/standards/alto/"))
917
                ) {
918
                    $this->hasFulltextSet = true;
919
                    $this->hasFulltext = true;
920
                    return;
921
                }
922
                $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
923
                if ($extConf['indexAnnotations'] == 1 && !empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
924
                    foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
925
                        if (($textAnnotations = $annotationContainer->getTextAnnotations(Motivation::PAINTING)) != null) {
926
                            foreach ($textAnnotations as $annotation) {
927
                                if (
928
                                    $annotation->getBody() != null &&
929
                                    $annotation->getBody()->getFormat() == "text/plain" &&
930
                                    $annotation->getBody()->getChars() != null
931
                                ) {
932
                                    $this->hasFulltextSet = true;
933
                                    $this->hasFulltext = true;
934
                                    return;
935
                                }
936
                            }
937
                        }
938
                    }
939
                }
940
            }
941
            $this->hasFulltextSet = true;
942
        }
943
    }
944
945
    /**
946
     * {@inheritDoc}
947
     * @see AbstractDocument::_getThumbnail()
948
     */
949
    protected function _getThumbnail($forceReload = false)
950
    {
951
        return $this->iiif->getThumbnailUrl();
952
    }
953
954
    /**
955
     * {@inheritDoc}
956
     * @see AbstractDocument::_getToplevelId()
957
     */
958
    protected function _getToplevelId()
959
    {
960
        if (empty($this->toplevelId)) {
961
            if (isset($this->iiif)) {
962
                $this->toplevelId = $this->iiif->getId();
963
            }
964
        }
965
        return $this->toplevelId;
966
    }
967
968
    /**
969
     * This magic method is executed after the object is deserialized
970
     * @see __sleep()
971
     *
972
     * @access public
973
     *
974
     * @return void
975
     */
976
    public function __wakeup()
977
    {
978
        $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
979
        IiifHelper::setUrlReader(IiifUrlReader::getInstance());
980
        IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
981
        IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
982
        $resource = IiifHelper::loadIiifResource($this->asJson);
983
        if ($resource != null && $resource instanceof ManifestInterface) {
984
            $this->asJson = '';
985
            $this->iiif = $resource;
986
            $this->init('');
987
        } else {
988
            $this->logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(static::class);
989
            $this->logger->error('Could not load IIIF after deserialization');
990
        }
991
    }
992
993
    /**
994
     *
995
     * @return string[]
996
     */
997
    public function __sleep()
998
    {
999
        // TODO implement serializiation in IIIF library
1000
        $jsonArray = $this->iiif->getOriginalJsonArray();
1001
        $this->asJson = json_encode($jsonArray);
1002
        return ['uid', 'pid', 'recordId', 'parentId', 'asJson'];
1003
    }
1004
}
1005