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 (#336)
by
unknown
03:50
created

IiifManifest::getLogicalStructureInfo()   F

Complexity

Conditions 23
Paths 2592

Size

Total Lines 74
Code Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 74
rs 0
c 0
b 0
f 0
cc 23
nc 2592
nop 3

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
namespace Kitodo\Dlf\Common;
3
4
/**
5
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
6
 *
7
 * This file is part of the Kitodo and TYPO3 projects.
8
 *
9
 * @license GNU General Public License version 3 or later.
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 */
13
14
use Flow\JSONPath\JSONPath;
15
use TYPO3\CMS\Core\Utility\GeneralUtility;
16
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface;
17
use Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationInterface;
18
use Ubl\Iiif\Presentation\Common\Model\Resources\CanvasInterface;
19
use Ubl\Iiif\Presentation\Common\Model\Resources\ContentResourceInterface;
20
use Ubl\Iiif\Presentation\Common\Model\Resources\IiifResourceInterface;
21
use Ubl\Iiif\Presentation\Common\Model\Resources\ManifestInterface;
22
use Ubl\Iiif\Presentation\Common\Model\Resources\RangeInterface;
23
use Ubl\Iiif\Presentation\Common\Vocabulary\Motivation;
24
use Ubl\Iiif\Presentation\V1\Model\Resources\AbstractIiifResource1;
25
use Ubl\Iiif\Presentation\V2\Model\Resources\AbstractIiifResource2;
26
use Ubl\Iiif\Presentation\V3\Model\Resources\AbstractIiifResource3;
27
use Ubl\Iiif\Services\AbstractImageService;
28
use Ubl\Iiif\Services\Service;
29
use Ubl\Iiif\Tools\IiifHelper;
30
31
/**
32
 * IiifManifest class for the 'dlf' extension. This class
33
 * represents a IIIF manifest in the conext of this TYPO3 extension.
34
 *
35
 * @author Lutz Helm <[email protected]>
36
 * @package	TYPO3
37
 * @subpackage	tx_dlf
38
 * @access	public
39
 */
40
final class IiifManifest extends Document
41
{
42
    /**
43
     * This holds the manifest file as string for serialization purposes
44
     * @see __sleep() / __wakeup()
45
     *
46
     * @var string
47
     * @access protected
48
     */
49
    protected $asJson = '';
50
51
    /**
52
     * A PHP object representation of a IIIF manifest.
53
     * @var ManifestInterface
54
     * @access protected
55
     */
56
    protected $iiif;
57
58
    /**
59
     * 'IIIF1', 'IIIF2' or 'IIIF3', depending on the API $this->iiif confrms to:
60
     * IIIF Metadata API 1, IIIF Presentation API 2 or 3
61
     * @var string
62
     * @access protected
63
     */
64
    protected $iiifVersion;
65
66
    /**
67
     * Document has already been analyzed if it contains fulltext for the Solr index
68
     * @var boolean
69
     * @access protected
70
     */
71
    protected $hasFulltextSet = false;
72
73
    /**
74
     * This holds the original manifest's parsed metadata array with their corresponding
75
     * resource (Manifest / Sequence / Range) ID as array key
76
     *
77
     * @var array
78
     * @access protected
79
     */
80
    protected $originalMetadataArray = array ();
81
82
    /**
83
     * Holds the mime types of linked resources in the manifest (extreacted during parsing) for later use.
84
     * @var array
85
     * @access protected
86
     */
87
    protected $mimeTypes = [];
88
89
    /**
90
     * The extension key
91
     *
92
     * @var string
93
     * @static
94
     * @access public
95
     */
96
    public static $extKey = 'dlf';
97
98
    /**
99
     * {@inheritDoc}
100
     * @see Document::establishRecordId()
101
     */
102
    protected function establishRecordId($pid)
103
    {
104
        if ($this->iiif !== null) {
105
            /*
106
             *  FIXME This will not consistently work because we can not be sure to have the pid at hand. It may miss
107
             *  if the plugin that actually loads the manifest allows content from other pages.
108
             *  Up until now the cPid is only set after the document has been initialized. We need it before to
109
             *  check the configuration.
110
             *  TODO Saving / indexing should still work - check!
111
             */
112
            $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
113
                'tx_dlf_metadataformat.xpath AS querypath',
114
                'tx_dlf_metadata,tx_dlf_metadataformat,tx_dlf_formats',
115
                'tx_dlf_metadata.pid='.$pid.' AND tx_dlf_metadataformat.pid='.$pid.' AND ((tx_dlf_metadata.uid=tx_dlf_metadataformat.parent_id AND tx_dlf_metadataformat.encoded=tx_dlf_formats.uid'
116
                .' AND tx_dlf_metadata.index_name="record_id" AND tx_dlf_formats.type='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->getIiifVersion(), 'tx_dlf_formats').') OR tx_dlf_metadata.format=0)'
117
                .Helper::whereClause('tx_dlf_metadata', TRUE)
118
                .Helper::whereClause('tx_dlf_metadataformat')
119
                .Helper::whereClause('tx_dlf_formats'),
120
                '',
121
                '',
122
                ''
123
                );
124
            if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
125
                for ($i = 0, $j = $GLOBALS['TYPO3_DB']->sql_num_rows($result); $i < $j; $i++) {
126
                    $resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
127
                    $recordIdPath = $resArray['querypath'];
128
                    if (!empty($recordIdPath)) {
129
                        $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...
130
                    }
131
                }
132
            }
133
            // For now, it's a hardcoded ID, not only as a fallback
134
            if (!isset($this->recordId)) {
135
                $this->recordId = $this->iiif->getId();
136
            }
137
        }
138
    }
139
140
    /**
141
     * {@inheritDoc}
142
     * @see Document::getDocument()
143
     */
144
    protected function getDocument()
145
    {
146
        return $this->iiif;
147
    }
148
149
    /**
150
     * Returns a string representing the Metadata / Presentation API version which the IIIF resource
151
     * conforms to. This is used for example to extract metadata according to configured patterns.
152
     *
153
     * @access public
154
     *
155
     * @return string 'IIIF1' if the resource is a Metadata API 1 resource, 'IIIF2' / 'IIIF3' if
156
     * the resource is a Presentation API 2 / 3 resource
157
     */
158
    public function getIiifVersion() {
159
        if (!isset($this->iiifVersion)) {
160
            if ($this->iiif instanceof AbstractIiifResource1) {
161
                $this->iiifVersion = 'IIIF1';
162
            } elseif ($this->iiif instanceof AbstractIiifResource2) {
163
                $this->iiifVersion = 'IIIF2';
164
            } elseif ($this->iiif instanceof AbstractIiifResource3) {
165
                $this->iiifVersion = 'IIIF3';
166
            }
167
        }
168
        return $this->iiifVersion;
169
    }
170
171
    /**
172
     * True if getUseGroups() has been called and $this-useGrps is loaded
173
     *
174
     * @var boolean
175
     * @access protected
176
     */
177
    protected $useGrpsLoaded;
178
179
    /**
180
     * Holds the configured useGrps as array.
181
     *
182
     * @var array
183
     * @access protected
184
     */
185
    protected $useGrps;
186
187
    /**
188
     * IiifManifest also populates the physical stucture array entries for matching
189
     * 'fileGrp's. To do that, the configuration has to be loaded; afterwards configured
190
     * 'fileGrp's for thumbnails, downloads, audio, fulltext and the 'fileGrp's for images
191
     * can be requested with this method.
192
     *
193
     * @access protected
194
     *
195
     * @param string $use
196
     *
197
     * @return array|string
198
     */
199
    protected function getUseGroups($use)
200
    {
201
        if (!$this->useGrpsLoaded) {
202
            // Get configured USE attributes.
203
            $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
204
            if (!empty($extConf['fileGrps'])) {
205
                $this->useGrps['fileGrps'] = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $extConf['fileGrps']);
206
            }
207
            if (!empty($extConf['fileGrpThumbs'])) {
208
                $this->useGrps['fileGrpThumbs'] = $extConf['fileGrpThumbs'];
209
            }
210
            if (!empty($extConf['fileGrpDownload'])) {
211
                $this->useGrps['fileGrpDownload'] = $extConf['fileGrpDownload'];
212
            }
213
            if (!empty($extConf['fileGrpFulltext'])) {
214
                $this->useGrps['fileGrpFulltext'] = $extConf['fileGrpFulltext'];
215
            }
216
            if (!empty($extConf['fileGrpAudio'])) {
217
                $this->useGrps['fileGrpAudio'] = $extConf['fileGrpAudio'];
218
            }
219
        }
220
        return array_key_exists($use, $this->useGrps) ? $this->useGrps[$use] : [];
221
    }
222
223
    /**
224
     * {@inheritDoc}
225
     * @see Document::_getPhysicalStructure()
226
     */
227
    protected function _getPhysicalStructure()
228
    {
229
        // Is there no physical structure array yet?
230
        if (!$this->physicalStructureLoaded) {
231
            if ($this->iiif == null || !($this->iiif instanceof ManifestInterface)) {
232
                return null;
233
            }
234
            $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
235
            $iiifId = $this->iiif->getId();
236
            $physSeq[0] = $iiifId;
1 ignored issue
show
Comprehensibility Best Practice introduced by
$physSeq was never initialized. Although not strictly required by PHP, it is generally a good practice to add $physSeq = array(); before regardless.
Loading history...
237
            $this->physicalStructureInfo[$physSeq[0]]['id'] = $iiifId;
238
            $this->physicalStructureInfo[$physSeq[0]]['dmdId'] = $iiifId;
239
            $this->physicalStructureInfo[$physSeq[0]]['label'] = $this->iiif->getLabelForDisplay();
240
            $this->physicalStructureInfo[$physSeq[0]]['orderlabel'] = $this->iiif->getLabelForDisplay();
241
            $this->physicalStructureInfo[$physSeq[0]]['type'] = 'physSequence';
242
            $this->physicalStructureInfo[$physSeq[0]]['contentIds'] = null;
243
            $fileUseDownload = $this->getUseGroups('fileGrpDownload');
244
            $fileUseFulltext = $this->getUseGroups('fileGrpFulltext');
245
            $fileUseThumbs = $this->getUseGroups('fileGrpThumbs');
246
            $fileUses = $this->getUseGroups('fileGrps');
247
            if (isset($fileUseDownload)) {
248
                $docPdfRendering = $this->iiif->getRenderingUrlsForFormat('application/pdf');
249
                if (!empty($docPdfRendering)) {
250
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseDownload] = $docPdfRendering[0];
251
                }
252
            }
253
            if (isset($fileUseFulltext)) {
254
                $iiifAlto = $this->iiif->getSeeAlsoUrlsForFormat("application/alto+xml");
255
                if (empty($iiifAlto)) {
256
                    $iiifAlto = $this->iiif->getSeeAlsoUrlsForProfile("http://www.loc.gov/standards/alto/", true);
257
                }
258
                if (!empty($iiifAlto)) {
259
                    // TODO use multiple possible alto files?
260
                    $this->mimeTypes[$iiifAlto[0]] = "application/alto+xml";
261
                    $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseFulltext] = $iiifAlto[0];
262
                    $this->hasFulltext = true;
263
                    $this->hasFulltextSet = true;
264
                }
265
            }
266
            if (!empty($this->iiif->getDefaultCanvases())) {
267
                // canvases have not order property, but the context defines canveses as @list with a specific order, so we can provide an alternative
268
                $canvasOrder = 0;
269
                foreach ($this->iiif->getDefaultCanvases() as $canvas) {
270
                    $canvasOrder++;
271
                    $thumbnailUrl = $canvas->getThumbnailUrl();
272
                    // put thumbnails in thumbnail filegroup
273
                    if (isset($thumbnailUrl)) {
274
                        $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUseThumbs] = $thumbnailUrl;
275
                    }
276
                    $image = $canvas->getImageAnnotations()[0];
277
                    // put images in all non specific filegroups
278
                    if (isset($fileUses)) {
279
                        foreach ($fileUses as $fileUse) {
280
                            if ($image->getBody() != null && $image->getBody() instanceof ContentResourceInterface) {
281
                                $this->physicalStructureInfo[$physSeq[0]]['files'][$fileUse] = $image->getBody()->getId();
282
                            }
283
                        }
284
                    }
285
                    // populate structural metadata info
286
                    $elements[$canvasOrder] = $canvas->getId();
287
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['id']=$canvas->getId();
288
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['dmdId']=null;
289
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['label']=$canvas->getLabelForDisplay();
290
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['orderlabel']=$canvas->getLabelForDisplay();
291
                    // assume that a canvas always represents a page
292
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['type']='page';
293
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['contentIds']=null;
294
                    $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = null;
295
                    if (!empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
0 ignored issues
show
Unused Code introduced by
The call to Ubl\Iiif\Presentation\Co...tAnnotationContainers() has too many arguments starting with Ubl\Iiif\Presentation\Co...ry\Motivation::PAINTING. ( Ignorable by Annotation )

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

295
                    if (!empty($canvas->/** @scrutinizer ignore-call */ getPossibleTextAnnotationContainers(Motivation::PAINTING))) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
296
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'] = array();
297
                        $this->physicalStructureInfo[$physSeq[0]]['annotationContainers'] = array();
298
                        foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
299
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['annotationContainers'][] = $annotationContainer->getId();
300
                            if ($extConf['indexAnnotations']) {
301
                                $this->hasFulltext = true;
302
                                $this->hasFulltextSet = true;
303
                            }
304
                        }
305
                    }
306
                    if (isset($fileUseFulltext)) {
307
                        $alto = $canvas->getSeeAlsoUrlsForFormat("application/alto+xml");
308
                        if (empty($alto)) {
309
                            $alto = $canvas->getSeeAlsoUrlsForProfile("http://www.loc.gov/standards/alto/", true);
310
                        }
311
                        if (!empty($alto)) {
312
                            // TODO use all possible alto files?
313
                            $this->mimeTypes[$alto[0]] = "application/alto+xml";
314
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseFulltext] = $alto[0];
315
                            $this->hasFulltext = true;
316
                            $this->hasFulltextSet = true;
317
                        }
318
                    }
319
                    if (isset($fileUses)) {
320
                        foreach ($fileUses as $fileUse) {
321
                            if ($image->getBody() != null && $image->getBody() instanceof ContentResourceInterface) {
322
                                $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUse] = $image->getBody()->getId();
323
                            }
324
                        }
325
                    }
326
                    if (isset($thumbnailUrl)) {
327
                        $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseThumbs] = $thumbnailUrl;
328
                    }
329
                    if (isset($fileUseDownload)) {
330
                        $pdfRenderingUrls = $canvas->getRenderingUrlsForFormat('application/pdf');
331
                        if (!empty($pdfRenderingUrls)) {
332
                            $this->physicalStructureInfo[$elements[$canvasOrder]]['files'][$fileUseDownload] = $pdfRenderingUrls[0];
333
                        }
334
                    }
335
                }
336
                $this->numPages = $canvasOrder;
337
                // Merge and re-index the array to get nice numeric indexes.
338
                $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 269. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
339
            }
340
            $this->physicalStructureLoaded = TRUE;
341
        }
342
        return $this->physicalStructure;
343
    }
344
345
    /**
346
     * {@inheritDoc}
347
     * @see Document::getDownloadLocation()
348
     */
349
    public function getDownloadLocation($id) {
350
        $fileLocation = $this->getFileLocation($id);
351
        $resource = $this->iiif->getContainedResourceById($fileLocation);
352
        if ($resource instanceof AbstractImageService) {
353
            return $resource->getImageUrl();
354
        }
355
        return $fileLocation;
356
    }
357
358
    /**
359
     * {@inheritDoc}
360
     * @see Document::getFileLocation()
361
     */
362
    public function getFileLocation($id)
363
    {
364
        if ($id == null) {
365
            return null;
366
        }
367
        $resource = $this->iiif->getContainedResourceById($id);
368
        if (isset($resource)) {
369
            if ($resource instanceof CanvasInterface) {
370
                return (!empty($resource->getImageAnnotations()) && $resource->getImageAnnotations()->getSingleService() != null) ? $resource->getImageAnnotations()[0]->getSingleService()->getId() : $id;
371
            } elseif ($resource instanceof ContentResourceInterface) {
372
                return $resource->getSingleService() != null && $resource->getSingleService() instanceof Service ? $resource->getSingleService()->getId() : $id;
373
            } elseif ($resource instanceof AbstractImageService) {
374
                return $resource->getId();
375
            } elseif ($resource instanceof AnnotationContainerInterface) {
376
                return $id;
377
            }
378
        } else {
379
            return $id;
380
        }
381
    }
382
383
    /**
384
     * {@inheritDoc}
385
     * @see Document::getFileMimeType()
386
     */
387
    public function getFileMimeType($id)
388
    {
389
        $fileResource = $this->iiif->getContainedResourceById($id);
390
        if ($fileResource instanceof CanvasInterface) {
391
            $format = "application/vnd.kitodo.iiif";
392
        } elseif ($fileResource instanceof AnnotationInterface) {
393
            $format = "application/vnd.kitodo.iiif";
394
        } elseif ($fileResource instanceof ContentResourceInterface) {
395
            if ($fileResource->isText() || $fileResource->isImage() && ($fileResource->getSingleService() == null || !($fileResource->getSingleService() instanceof AbstractImageService))) {
396
                // Support static images without an image service
397
                return $fileResource->getFormat();
398
            }
399
            $format = "application/vnd.kitodo.iiif";
400
        } elseif ($fileResource instanceof AbstractImageService) {
401
            $format = "application/vnd.kitodo.iiif";
402
        } else {
403
            // Assumptions: this can only be the thumbnail and the thumbnail is a jpeg - TODO determine mimetype
404
            $format = "image/jpeg";
405
        }
406
        return $format;
407
    }
408
409
    /**
410
     * {@inheritDoc}
411
     * @see Document::getLogicalStructure()
412
     */
413
    public function getLogicalStructure($id, $recursive = FALSE)
414
    {
415
        $details = array ();
416
        if (!$recursive && !empty($this->logicalUnits[$id])) {
417
            return $this->logicalUnits[$id];
418
        } elseif (!empty($id)) {
419
            $logUnits[] = $this->iiif->getContainedResourceById($id);
1 ignored issue
show
Comprehensibility Best Practice introduced by
$logUnits was never initialized. Although not strictly required by PHP, it is generally a good practice to add $logUnits = array(); before regardless.
Loading history...
420
        } else {
421
            $logUnits[] = $this->iiif;
422
        }
423
        if (!empty($logUnits)) {
424
            if (!$recursive) {
425
                $details = $this->getLogicalStructureInfo($logUnits[0]);
426
            } else {
427
                // cache the ranges - they might occure multiple times in the structures "tree" - with full data as well as referenced as id
428
                $processedStructures = array();
429
                foreach ($logUnits as $logUnit) {
430
                    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 false|integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
431
                        $this->tableOfContents[] = $this->getLogicalStructureInfo($logUnit, TRUE, $processedStructures);
432
                    }
433
                }
434
            }
435
        }
436
        return $details;
437
    }
438
439
    /**
440
     * Get the details about a IIIF resource (manifest or range) in the logical structure
441
     *
442
     * @access protected
443
     *
444
     * @param IiifResourceInterface $resource: IIIF resource, either a manifest or range.
445
     * @param boolean $recursive: Whether to include the child elements
446
     * @param array $processedStructures: IIIF resources that already have been processed
447
     * @return array Logical structure array
448
     */
449
    protected function getLogicalStructureInfo(IiifResourceInterface $resource, $recursive = false, &$processedStructures = array()) {
450
        $details = array ();
451
        $details['id'] = $resource->getId();
452
        $details['dmdId'] = '';
453
        $details['label'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
454
        $details['orderlabel'] = $resource->getLabelForDisplay() !== null ? $resource->getLabelForDisplay() : '';
0 ignored issues
show
introduced by
The condition $resource->getLabelForDisplay() !== null is always true.
Loading history...
455
        $details['contentIds'] = '';
456
        $details['volume'] = '';
457
        $details['pagination'] = '';
458
        $cPid = ($this->cPid ? $this->cPid : $this->pid);
459
        if ($details['id'] == $this->_getToplevelId()) {
460
            $metadata = $this->getMetadata($details['id'], $cPid);
461
            if (!empty($metadata['type'][0])) {
462
                $details['type'] = $metadata['type'][0];
463
            }
464
        }
465
        $details['thumbnailId'] = $resource->getThumbnailUrl();
466
        $details['points'] = '';
467
        // Load strucural mapping
468
        $this->_getSmLinks();
469
        // Load physical structure.
470
        $this-> _getPhysicalStructure();
471
        $canvases = array();
472
        if ($resource instanceof ManifestInterface) {
473
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
474
            $canvases = $resource->getDefaultCanvases();
0 ignored issues
show
Unused Code introduced by
The assignment to $canvases is dead and can be removed.
Loading history...
475
        } elseif ($resource instanceof RangeInterface) {
476
            $startCanvas = $resource->getStartCanvasOrFirstCanvas();
477
            $canvases = $resource->getAllCanvases();
478
        }
479
        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...
480
            $details['pagination'] = $startCanvas->getLabel();
481
            $startCanvasIndex = array_search($startCanvas, $this->iiif->getDefaultCanvases());
482
            if ($startCanvasIndex!==false) {
483
                $details['points'] = $startCanvasIndex + 1;
484
            }
485
        }
486
        $useGroups = $this->getUseGroups('fileGrps');
487
        if (is_string($useGroups)) {
488
            $useGroups = array($useGroups);
0 ignored issues
show
Unused Code introduced by
The assignment to $useGroups is dead and can be removed.
Loading history...
489
        }
490
        // Keep for later usage.
491
        $this->logicalUnits[$details['id']] = $details;
492
        // Walk the structure recursively? And are there any children of the current element?
493
        if ($recursive) {
494
            $processedStructures[] = $resource->getId();
495
            $details['children'] = array ();
496
            if ($resource instanceof ManifestInterface && $resource->getRootRanges() != null) {
497
                $rangesToAdd = [];
498
                $rootRanges = [];
499
                if (sizeof($this->iiif->getRootRanges()) == 1 && $this->iiif->getRootRanges()[0]->isTopRange()) {
500
                    $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

500
                    /** @scrutinizer ignore-call */ 
501
                    $rangesToAdd = $this->iiif->getRootRanges()[0]->getMemberRangesAndRanges();
Loading history...
501
                } else {
502
                    $rangesToAdd = $this->iiif->getRootRanges();
503
                }
504
                foreach ($rangesToAdd as $range) {
505
                    $rootRanges[] = $range;
506
                }
507
                foreach ($rootRanges as $range) {
508
                    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 false|integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
509
                        $details['children'][] = $this->getLogicalStructureInfo($range, TRUE, $processedStructures);
510
                    }
511
                }
512
            } elseif ($resource instanceof RangeInterface) {
513
                if (!empty($resource->getAllRanges())) {
514
                    foreach ($resource->getAllRanges() as $range) {
515
                        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 false|integer|string against false; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
516
                            $details['children'][] = $this->getLogicalStructureInfo($range, TRUE, $processedStructures);
517
                        }
518
                    }
519
                }
520
            }
521
        }
522
        return $details;
523
    }
524
525
    /**
526
     * Returns metadata for IIIF resources with the ID $id in there original form in
527
     * the manifest, but prepared for display to the user.
528
     *
529
     * @access public
530
     *
531
     * @param string $id: the ID of the IIIF resource
532
     * @param number $cPid: the configuration folder's id
533
     * @param boolean $withDescription: add description / summary to the return value
534
     * @param boolean $withRights: add attribution and license / rights and requiredStatement to the return value
535
     * @param boolean $withRelated: add related links / homepage to the return value
536
     *
537
     * @return array
538
     *
539
     * @todo This method is still in experimental; the method signature may change.
540
     */
541
    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

541
    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...
542
        if (!empty($this->originalMetadataArray[$id])) {
543
            return $this->originalMetadataArray[$id];
544
        }
545
        $iiifResource = $this->iiif->getContainedResourceById($id);
546
        $result = array();
547
        if ($iiifResource != null) {
548
            if ($iiifResource->getLabel()!=null && $iiifResource->getLabel() != "") {
549
                $result['label'] = $iiifResource->getLabel();
550
            }
551
            if (!empty($iiifResource->getMetadata())) {
552
                $result['metadata'] = [];
553
                foreach ($iiifResource->getMetadataForDisplay() as $metadata) {
554
                    $result['metadata'][$metadata['label']] = $metadata['value'];
555
                }
556
            }
557
            if ($withDescription && !empty($iiifResource->getSummary())) {
558
                $result["description"] = $iiifResource->getSummaryForDisplay();
559
            }
560
            if ($withRights) {
561
                if (!empty($iiifResource->getRights())) {
562
                    $result["rights"] = $iiifResource->getRights();
563
                }
564
                if (!empty($iiifResource->getRequiredStatement())) {
565
                    $result["requiredStatement"] = $iiifResource->getRequiredStatementForDisplay();
566
                }
567
            }
568
            if ($withRelated && !empty($iiifResource->getWeblinksForDisplay())) {
569
                $result["weblinks"] = [];
570
                foreach ($iiifResource->getWeblinksForDisplay() as $link) {
571
                    $key = array_key_exists("label", $link) ? $link["label"] : $link["@id"];
572
                    $result["weblinks"][$key] = $link["@id"];
573
                }
574
            }
575
        }
576
        return $result;
577
    }
578
579
    /**
580
     * {@inheritDoc}
581
     * @see Document::getMetadata()
582
     */
583
    public function getMetadata($id, $cPid = 0)
584
    {
585
        if (!empty($this->metadataArray[$id]) && $this->metadataArray[0] == $cPid) {
586
            return $this->metadataArray[$id];
587
        }
588
        // Initialize metadata array with empty values.
589
        // TODO initialize metadata in abstract class
590
        $metadata = array (
591
            'title' => array (),
592
            'title_sorting' => array (),
593
            'author' => array (),
594
            'place' => array (),
595
            'year' => array (),
596
            'prod_id' => array (),
597
            'record_id' => array (),
598
            'opac_id' => array (),
599
            'union_id' => array (),
600
            'urn' => array (),
601
            'purl' => array (),
602
            'type' => array (),
603
            'volume' => array (),
604
            'volume_sorting' => array (),
605
            'collection' => array (),
606
            'owner' => array (),
607
        );
608
        $metadata['document_format'][] = 'IIIF';
609
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
610
            'tx_dlf_metadata.index_name AS index_name,tx_dlf_metadataformat.xpath AS xpath,tx_dlf_metadataformat.xpath_sorting AS xpath_sorting,tx_dlf_metadata.is_sortable AS is_sortable,tx_dlf_metadata.default_value AS default_value,tx_dlf_metadata.format AS format',
611
            'tx_dlf_metadata,tx_dlf_metadataformat,tx_dlf_formats',
612
            'tx_dlf_metadata.pid='.$cPid.' AND tx_dlf_metadataformat.pid='.$cPid.' AND ((tx_dlf_metadata.uid=tx_dlf_metadataformat.parent_id AND tx_dlf_metadataformat.encoded=tx_dlf_formats.uid AND tx_dlf_formats.type='.$GLOBALS['TYPO3_DB']->fullQuoteStr($this->getIiifVersion(), 'tx_dlf_formats').') OR tx_dlf_metadata.format=0)'
613
            .Helper::whereClause('tx_dlf_metadata', TRUE).Helper::whereClause('tx_dlf_metadataformat').Helper::whereClause('tx_dlf_formats'),
614
            '',
615
            '',
616
            ''
617
            );
618
        $iiifResource = $this->iiif->getContainedResourceById($id);
619
        while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
620
            // Set metadata field's value(s).
621
            if ($resArray['format'] > 0 && !empty($resArray['xpath']) && ($values = $iiifResource->jsonPath($resArray['xpath'])) != null) {
622
                if (is_string($values)) {
623
                    $metadata[$resArray['index_name']] = array (trim((string) $values));
624
                } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data())>1 ) {
625
                    $metadata[$resArray['index_name']] = array ();
626
                    foreach ($values->data() as $value) {
627
                        $metadata[$resArray['index_name']][] = trim((string) $value);
628
                    }
629
                }
630
            }
631
            // Set default value if applicable.
632
            if (empty($metadata[$resArray['index_name']][0]) && strlen($resArray['default_value']) > 0) {
633
                $metadata[$resArray['index_name']] = array ($resArray['default_value']);
634
            }
635
            // Set sorting value if applicable.
636
            if (!empty($metadata[$resArray['index_name']]) && $resArray['is_sortable']) {
637
                if ($resArray['format'] > 0 && !empty($resArray['xpath_sorting'])
638
                    && ($values = $iiifResource->jsonPath($resArray['xpath_sorting']) != null)) {
639
                    if ($values instanceof string) {
0 ignored issues
show
Bug introduced by
The type Kitodo\Dlf\Common\string 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...
640
                        $metadata[$resArray['index_name'].'_sorting'][0] = array (trim((string) $values));
641
                    } elseif ($values instanceof JSONPath && is_array($values->data()) && count($values->data()>1 )) {
0 ignored issues
show
Bug introduced by
$values->data() > 1 of type boolean is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

641
                    } elseif ($values instanceof JSONPath && is_array($values->data()) && count(/** @scrutinizer ignore-type */ $values->data()>1 )) {
Loading history...
642
                        $metadata[$resArray['index_name']] = array ();
643
                        foreach ($values->data() as $value) {
644
                            $metadata[$resArray['index_name'].'_sorting'][0] = trim((string) $value);
645
                        }
646
                    }
647
                }
648
                if (empty($metadata[$resArray['index_name'].'_sorting'][0])) {
649
                    $metadata[$resArray['index_name'].'_sorting'][0] = $metadata[$resArray['index_name']][0];
650
                }
651
            }
652
        }
653
        return $metadata;
654
    }
655
656
    /**
657
     * {@inheritDoc}
658
     * @see Document::_getSmLinks()
659
     */
660
    protected function _getSmLinks() {
661
        if (!$this->smLinksLoaded && isset($this->iiif) && $this->iiif instanceof ManifestInterface) {
662
            if (!empty($this->iiif->getDefaultCanvases())) {
663
                foreach ($this->iiif->getDefaultCanvases() as $canvas) {
664
                    $this->smLinkCanvasToResource($canvas, $this->iiif);
665
                }
666
            }
667
            if (!empty($this->iiif->getStructures())) {
668
                foreach ($this->iiif->getStructures() as $range) {
669
                    $this->smLinkRangeCanvasesRecursively($range);
670
                }
671
            }
672
            $this->smLinksLoaded = true;
673
        }
674
        return $this->smLinks;
675
    }
676
677
    /**
678
     * Construct a link between a range and it's sub ranges and all contained canvases.
679
     *
680
     * @access private
681
     *
682
     * @param RangeInterface $range: Current range whose canvases shall be linked
683
     */
684
    private function smLinkRangeCanvasesRecursively(RangeInterface $range) {
685
        // map range's canvases including all child ranges' canvases
686
        if (!$range->isTopRange()) {
687
            foreach ($range->getAllCanvasesRecursively() as $canvas) {
688
                $this->smLinkCanvasToResource($canvas, $range);
689
            }
690
        }
691
        // recursive call for all ranges
692
        if (!empty($range->getAllRanges())) {
693
            foreach ($range->getAllRanges() as $childRange) {
694
                $this->smLinkRangeCanvasesRecursively($childRange);
695
            }
696
        }
697
    }
698
699
    /**
700
     * Link a single canvas to a containing range
701
     *
702
     * @access private
703
     *
704
     * @param CanvasInterface $canvas
705
     * @param IiifResourceInterface $resource
706
     */
707
    private function smLinkCanvasToResource(CanvasInterface $canvas, IiifResourceInterface $resource)
708
    {
709
        $this->smLinks['l2p'][$resource->getId()][] = $canvas->getId();
710
        if (!is_array($this->smLinks['p2l'][$canvas->getId()]) || !in_array($resource->getId(), $this->smLinks['p2l'][$canvas->getId()])) {
711
            $this->smLinks['p2l'][$canvas->getId()][] = $resource->getId();
712
        }
713
    }
714
715
    /**
716
     * Currently not supported for IIIF. Multivolume works _could_ be modelled
717
     * as IIIF Collections, but we can't tell them apart from actual collections.
718
     *
719
     * @access protected
720
     *
721
     * @see Document::getParentDocumentUidForSaving()
722
     */
723
    protected function getParentDocumentUidForSaving($pid, $core)
724
    {
725
        // Do nothing.
726
    }
727
728
    /**
729
     * {@inheritDoc}
730
     * @see Document::getRawText()
731
     */
732
    public function getRawText($id) {
733
        $rawText = '';
734
        // Get text from raw text array if available.
735
        if (!empty($this->rawTextArray[$id])) {
736
            return $this->rawTextArray[$id];
737
        }
738
        $this->ensureHasFulltextIsSet();
739
        if ($this->hasFulltext) {
740
            // Load physical structure ...
741
            $this->_getPhysicalStructure();
742
            // ... and extension configuration.
743
            $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
744
            if (!empty($this->physicalStructureInfo[$id])) {
745
                if (!empty($this->physicalStructureInfo[$id]['files'][$extConf['fileGrpFulltext']])) {
746
                    $rawText = parent::getRawTextFromXml($id);
747
                }
748
                if ($extConf['indexAnnotations'] == 1) {
749
                    $iiifResource = $this->iiif->getContainedResourceById($id);
750
                    // Get annotation containers
751
                    $annotationContainerIds = $this->physicalStructureInfo[$id]['annotationContainers'];
752
                    if (!empty($annotationContainerIds)) {
753
                        $annotationTexts = array();
754
                        foreach ($annotationContainerIds as $annotationListId) {
755
                            $annotationContainer = $this->iiif->getContainedResourceById($annotationListId);
756
                            /* @var $annotationContainer \Ubl\Iiif\Presentation\Common\Model\Resources\AnnotationContainerInterface */
757
                            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

757
                            foreach ($annotationContainer->/** @scrutinizer ignore-call */ getTextAnnotations(Motivation::PAINTING) as $annotation) {
Loading history...
758
                                if ($annotation->getTargetResourceId() == $iiifResource->getId() &&
759
                                    $annotation->getBody()!=null && $annotation->getBody()->getChars()!=null) {
760
                                    $annotationTexts[] = $annotation->getBody()->getChars();
761
                                }
762
                            }
763
                        }
764
                        $rawText .= implode(' ', $annotationTexts);
765
                    }
766
                }
767
            } else {
768
                Helper::devLog('Invalid structure resource @id "'.$id.'"', DEVLOG_SEVERITY_WARNING);
769
                return $rawText;
770
            }
771
            $this->rawTextArray[$id] = $rawText;
772
        }
773
        return $rawText;
774
    }
775
776
    /**
777
     * Returns the underlying IiifResourceInterface.
778
     *
779
     * @access public
780
     *
781
     * @return IiifResourceInterface
782
     */
783
    public function getIiif()
784
    {
785
        return $this->iiif;
786
    }
787
788
    /**
789
     * {@inheritDoc}
790
     * @see Document::init()
791
     */
792
    protected function init()
793
    {
794
        // Nothing to do here, at the moment
795
    }
796
797
    /**
798
     * {@inheritDoc}
799
     * @see Document::loadLocation()
800
     */
801
    protected function loadLocation($location)
802
    {
803
        $content = GeneralUtility::getUrl($location);
804
        $conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
805
        IiifHelper::setUrlReader(IiifUrlReader::getInstance());
806
        IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
807
        IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
808
        $resource = IiifHelper::loadIiifResource($content);
0 ignored issues
show
Bug introduced by
It seems like $content can also be of type false; however, parameter $resource of Ubl\Iiif\Tools\IiifHelper::loadIiifResource() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

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

808
        $resource = IiifHelper::loadIiifResource(/** @scrutinizer ignore-type */ $content);
Loading history...
809
        if ($resource != null ) {
810
            if ($resource instanceof ManifestInterface) {
811
                $this->iiif = $resource;
812
                return true;
813
            }
814
        } else {
815
            Helper::devLog('Could not load IIIF manifest from "'.$location.'"', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Bug introduced by
The constant Kitodo\Dlf\Common\SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Unused Code introduced by
The call to Kitodo\Dlf\Common\Helper::devLog() has too many arguments starting with Kitodo\Dlf\Common\SYSLOG_SEVERITY_ERROR. ( Ignorable by Annotation )

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

815
            Helper::/** @scrutinizer ignore-call */ 
816
                    devLog('Could not load IIIF manifest from "'.$location.'"', self::$extKey, SYSLOG_SEVERITY_ERROR);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
816
        }
817
    }
818
819
    /**
820
     * {@inheritDoc}
821
     * @see \Kitodo\Dlf\Common\Document::prepareMetadataArray()
822
     */
823
    protected function prepareMetadataArray($cPid)
824
    {
825
        $id = $this->iiif->getId();
826
        $this->metadataArray[(string) $id] = $this->getMetadata((string) $id, $cPid);
827
    }
828
829
    /**
830
     * {@inheritDoc}
831
     * @see Document::setPreloadedDocument()
832
     */
833
    protected function setPreloadedDocument($preloadedDocument) {
834
        if ($preloadedDocument instanceof ManifestInterface) {
835
            $this->iiif = $preloadedDocument;
836
            return true;
837
        }
838
        return false;
839
    }
840
841
    /**
842
     * {@inheritDoc}
843
     * @see Document::ensureHasFulltextIsSet()
844
     */
845
    protected function ensureHasFulltextIsSet()
846
    {
847
        /*
848
         *  TODO Check annotations and annotation lists of canvas for ALTO documents.
849
         *  Example:
850
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/manifest.json links
851
         *  https://digi.ub.uni-heidelberg.de/diglit/iiif/hirsch_hamburg1933_04_25/list/0001.json
852
         */
853
        if (!$this->hasFulltextSet && $this->iiif instanceof ManifestInterface) {
854
            $manifest = $this->iiif;
855
            $canvases = $manifest->getDefaultCanvases();
856
            foreach ($canvases as $canvas) {
857
                if (!empty($canvas->getSeeAlsoUrlsForFormat("application/alto+xml")) ||
858
                    !empty($canvas->getSeeAlsoUrlsForProfile("http://www.loc.gov/standards/alto/"))) {
859
                    $this->hasFulltextSet = true;
860
                    $this->hasFulltext = true;
861
                    return;
862
                }
863
                $extConf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
864
                if ($extConf['indexAnnotations'] == 1 && !empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
0 ignored issues
show
Unused Code introduced by
The call to Ubl\Iiif\Presentation\Co...tAnnotationContainers() has too many arguments starting with Ubl\Iiif\Presentation\Co...ry\Motivation::PAINTING. ( Ignorable by Annotation )

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

864
                if ($extConf['indexAnnotations'] == 1 && !empty($canvas->/** @scrutinizer ignore-call */ getPossibleTextAnnotationContainers(Motivation::PAINTING))) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
865
                    foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
866
                        if (($textAnnotations = $annotationContainer->getTextAnnotations(Motivation::PAINTING)) != null) {
867
                            foreach ($textAnnotations as $annotation) {
868
                                if ($annotation->getBody() != null &&
869
                                    $annotation->getBody()->getFormat() == "text/plain" &&
870
                                    $annotation->getBody()->getChars() != null) {
871
                                    $this->hasFulltextSet = true;
872
                                    $this->hasFulltext = true;
873
                                    return;
874
                                }
875
                            }
876
                        }
877
                    }
878
                }
879
            }
880
            $this->hasFulltextSet = true;
881
        }
882
    }
883
884
    /**
885
     * {@inheritDoc}
886
     * @see \Kitodo\Dlf\Common\Document::_getThumbnail()
887
     */
888
    protected function _getThumbnail($forceReload = FALSE)
889
    {
890
        return $this->iiif->getThumbnailUrl();
891
    }
892
893
    /**
894
     * {@inheritDoc}
895
     * @see \Kitodo\Dlf\Common\Document::_getToplevelId()
896
     */
897
    protected function _getToplevelId()
898
    {
899
        if (empty($this->toplevelId)) {
900
            if (isset($this->iiif)) {
901
                $this->toplevelId = $this->iiif->getId();
902
            }
903
        }
904
        return $this->toplevelId;
905
    }
906
907
    /**
908
     * This magic method is executed after the object is deserialized
909
     * @see __sleep()
910
     *
911
     * @access public
912
     *
913
     * @return void
914
     */
915
    public function __wakeup() {
916
        $conf = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][self::$extKey]);
917
        IiifHelper::setUrlReader(IiifUrlReader::getInstance());
918
        IiifHelper::setMaxThumbnailHeight($conf['iiifThumbnailHeight']);
919
        IiifHelper::setMaxThumbnailWidth($conf['iiifThumbnailWidth']);
920
        $resource = IiifHelper::loadIiifResource($this->asJson);
921
        if ($resource != null && $resource instanceof ManifestInterface) {
922
            $this->asJson='';
923
            $this->iiif = $resource;
924
            $this->init();
925
        } else {
926
            Helper::devLog('Could not load IIIF after deserialization', self::$extKey, SYSLOG_SEVERITY_ERROR);
0 ignored issues
show
Unused Code introduced by
The call to Kitodo\Dlf\Common\Helper::devLog() has too many arguments starting with Kitodo\Dlf\Common\SYSLOG_SEVERITY_ERROR. ( Ignorable by Annotation )

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

926
            Helper::/** @scrutinizer ignore-call */ 
927
                    devLog('Could not load IIIF after deserialization', self::$extKey, SYSLOG_SEVERITY_ERROR);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
The constant Kitodo\Dlf\Common\SYSLOG_SEVERITY_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
927
        }
928
    }
929
930
    /**
931
     *
932
     * @return string[]
933
     */
934
    public function __sleep() {
935
        // TODO implement serializiation in IIIF library
936
        $jsonArray = $this->iiif->getOriginalJsonArray();
937
        $this->asJson = json_encode($jsonArray);
938
        return array ('uid', 'pid', 'recordId', 'parentId', 'asJson');
939
    }
940
}
941