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 (#650)
by Alexander
03:43 queued 51s
created

IiifManifest::_getThumbnail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
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\Document;
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 $hasFullTextSet 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 FullTextDocument
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\Document\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
Bug introduced by
The property recordId is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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;
0 ignored issues
show
Bug introduced by
The property physicalStructureInfo is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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;
0 ignored issues
show
Bug introduced by
The property hasFullText is declared read-only in Kitodo\Dlf\Common\Document\FullTextDocument.
Loading history...
293
                    $this->hasFullTextSet = true;
0 ignored issues
show
Bug introduced by
The property hasFullTextSet is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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;
0 ignored issues
show
Bug introduced by
The property numPages is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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...
Bug introduced by
The property physicalStructure is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
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);
0 ignored issues
show
Bug introduced by
The property tableOfContents is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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();
0 ignored issues
show
Bug introduced by
The property smLinks is declared read-only in Kitodo\Dlf\Common\Document\IiifManifest.
Loading history...
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::getRawText()
790
     */
791
    public function getRawText($id)
792
    {
793
        $rawText = '';
794
        // Get text from raw text array if available.
795
        if (!empty($this->rawTextArray[$id])) {
796
            return $this->rawTextArray[$id];
797
        }
798
        $this->ensureHasFulltextIsSet();
799
        if ($this->hasFullText) {
800
            // Load physical structure ...
801
            $this->_getPhysicalStructure();
802
            // ... and extension configuration.
803
            $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
804
            $fileGrpsFulltext = GeneralUtility::trimExplode(',', $extConf['fileGrpFulltext']);
805
            if (!empty($this->physicalStructureInfo[$id])) {
806
                while ($fileGrpFulltext = array_shift($fileGrpsFulltext)) {
807
                    if (!empty($this->physicalStructureInfo[$id]['files'][$fileGrpFulltext])) {
808
                        $rawText = parent::getRawTextFromXml($id);
809
                        break;
810
                    }
811
                }
812
                if ($extConf['indexAnnotations'] == 1) {
813
                    $iiifResource = $this->iiif->getContainedResourceById($id);
814
                    // Get annotation containers
815
                    $annotationContainerIds = $this->physicalStructureInfo[$id]['annotationContainers'];
816
                    if (!empty($annotationContainerIds)) {
817
                        $annotationTexts = [];
818
                        foreach ($annotationContainerIds as $annotationListId) {
819
                            $annotationContainer = $this->iiif->getContainedResourceById($annotationListId);
820
                            /* @var $annotationContainer \Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface */
821
                            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

821
                            foreach ($annotationContainer->/** @scrutinizer ignore-call */ getTextAnnotations(Motivation::PAINTING) as $annotation) {
Loading history...
822
                                if (
823
                                    $annotation->getTargetResourceId() == $iiifResource->getId() &&
824
                                    $annotation->getBody() != null && $annotation->getBody()->getChars() != null
825
                                ) {
826
                                    $annotationTexts[] = $annotation->getBody()->getChars();
827
                                }
828
                            }
829
                        }
830
                        $rawText .= implode(' ', $annotationTexts);
831
                    }
832
                }
833
            } else {
834
                $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

834
                $this->logger->/** @scrutinizer ignore-call */ 
835
                               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...
835
                return $rawText;
836
            }
837
            $this->rawTextArray[$id] = $rawText;
838
        }
839
        return $rawText;
840
    }
841
842
    /**
843
     * Returns the underlying IiifResourceInterface.
844
     *
845
     * @access public
846
     *
847
     * @return IiifResourceInterface
848
     */
849
    public function getIiif()
850
    {
851
        return $this->iiif;
852
    }
853
854
    /**
855
     * {@inheritDoc}
856
     * @see Document::init()
857
     */
858
    protected function init()
859
    {
860
        // Nothing to do here, at the moment
861
    }
862
863
    /**
864
     * {@inheritDoc}
865
     * @see Document::loadLocation()
866
     */
867
    protected function loadLocation($location)
868
    {
869
        $fileResource = GeneralUtility::getUrl($location);
870
        if ($fileResource !== false) {
871
            $conf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
872
            IiifHelper::setUrlReader(IiifUrlReader::getInstance());
0 ignored issues
show
Bug introduced by
The type Kitodo\Dlf\Common\Document\IiifUrlReader 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...
873
            IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
874
            IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
875
            $resource = IiifHelper::loadIiifResource($fileResource);
876
            if ($resource != null) {
877
                if ($resource instanceof ManifestInterface) {
878
                    $this->iiif = $resource;
879
                    return true;
880
                }
881
            }
882
        }
883
        $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

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