Scrutinizer GitHub App not installed

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

Install GitHub App

GitHub Access Token became invalid

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

PageViewController::getMeasures()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 51
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 36
c 0
b 0
f 0
nc 6
nop 3
dl 0
loc 51
rs 8.4106

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
4
 *
5
 * This file is part of the Kitodo and TYPO3 projects.
6
 *
7
 * @license GNU General Public License version 3 or later.
8
 * For the full copyright and license information, please read the
9
 * LICENSE.txt file that was distributed with this source code.
10
 */
11
12
namespace Kitodo\Dlf\Controller;
13
14
use Kitodo\Dlf\Common\AbstractDocument;
15
use Kitodo\Dlf\Common\DocumentAnnotation;
16
use Kitodo\Dlf\Common\IiifManifest;
17
use Kitodo\Dlf\Common\MetsDocument;
18
use Kitodo\Dlf\Domain\Model\Document;
19
use Kitodo\Dlf\Domain\Model\FormAddDocument;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Core\Utility\MathUtility;
22
use Ubl\Iiif\Presentation\Common\Model\Resources\ManifestInterface;
23
use Ubl\Iiif\Presentation\Common\Vocabulary\Motivation;
24
25
/**
26
 * Controller class for the plugin 'Page View'.
27
 *
28
 * @package TYPO3
29
 * @subpackage dlf
30
 *
31
 * @access public
32
 */
33
class PageViewController extends AbstractController
34
{
35
    /**
36
     * @access protected
37
     * @var array Holds the controls to add to the map
38
     */
39
    protected array $controls = [];
40
41
    /**
42
     * @access protected
43
     * @var array Holds the current images' URLs and MIME types
44
     */
45
    protected array $images = [];
46
47
    /**
48
     * Holds the current scores' URL, MIME types and the
49
     * id of the current page
50
     *
51
     * @var array
52
     * @access protected
53
     */
54
    protected $scores = [];
55
56
    /**
57
     * @var array
58
     * @access protected
59
     */
60
    protected $measures = [];
61
62
    /**
63
     * Holds the current fulltexts' URLs
64
     *
65
     * @var array
66
     * @access protected
67
     * @var array Holds the current full texts' URLs
68
     */
69
    protected array $fulltexts = [];
70
71
    /**
72
     * Holds the current AnnotationLists / AnnotationPages
73
     *
74
     * @access protected
75
     * @var array Holds the current AnnotationLists / AnnotationPages
76
     */
77
    protected array $annotationContainers = [];
78
79
80
    /**
81
     * Holds the verovio relevant annotations
82
     *
83
     * @var array
84
     */
85
    protected $verovioAnnotations = [];
86
87
    /**
88
     * The main method of the plugin
89
     *
90
     * @access public
91
     *
92
     * @return void
93
     */
94
    public function mainAction(): void
95
    {
96
        // Load current document.
97
        $this->loadDocument();
98
        if ($this->isDocMissingOrEmpty()) {
99
            // Quit without doing anything if required variables are not set.
100
            return;
101
        } else {
102
            if (isset($this->settings['multiViewType']) && $this->document->getCurrentDocument()->tableOfContents[0]['type'] === $this->settings['multiViewType'] && empty($this->requestData['multiview'])) {
103
                $params = array_merge(
104
                    ['tx_dlf' => $this->requestData],
105
                    ['tx_dlf[multiview]' => 1]
106
                );
107
                $uriBuilder = $this->uriBuilder;
108
                $uri = $uriBuilder
109
                    ->setArguments($params)
110
                    ->setArgumentPrefix('tx_dlf')
111
                    ->uriFor('main');
112
                $this->redirectToUri($uri);
113
            }
114
            $this->setPage();
115
            $this->requestData['double'] = MathUtility::forceIntegerInRange($this->requestData['double'], 0, 1, 0);
116
117
            $documentAnnotation = DocumentAnnotation::getInstance($this->document);
118
            $this->verovioAnnotations = $documentAnnotation->getVerovioRelevantAnnotations();
119
        }
120
121
        $this->setPage();
122
123
        // Get image data.
124
        $this->images[0] = $this->getImage($this->requestData['page']);
125
        $this->fulltexts[0] = $this->getFulltext($this->requestData['page']);
126
        $this->annotationContainers[0] = $this->getAnnotationContainers($this->requestData['page']);
127
        if ($this->requestData['double'] && $this->requestData['page'] < $this->document->getCurrentDocument()->numPages) {
128
            $this->images[1] = $this->getImage($this->requestData['page'] + 1);
129
            $this->fulltexts[1] = $this->getFulltext($this->requestData['page'] + 1);
130
            $this->annotationContainers[1] = $this->getAnnotationContainers($this->requestData['page'] + 1);
131
        }
132
133
        $this->scores = $this->getScore($this->requestData['page']);
134
        $this->measures = $this->getMeasures($this->requestData['page']);
135
136
        // Get the controls for the map.
137
        $this->controls = explode(',', $this->settings['features']);
138
139
        $this->view->assign('forceAbsoluteUrl', $this->extConf['general']['forceAbsoluteUrl']);
140
141
        $this->addViewerJS();
142
143
        $this->view->assign('docCount', count($this->documentArray));
144
        $this->view->assign('docArray', $this->documentArray);
145
        $this->view->assign('docPage', $this->requestData['docPage']);
146
        $this->view->assign('docType', $this->document->getCurrentDocument()->tableOfContents[0]['type']);
147
148
        $this->view->assign('multiview', $this->requestData['multiview']);
149
        if ($this->requestData['multiview']) {
150
            $this->multipageNavigation();
151
        }
152
153
        $this->view->assign('images', $this->images);
154
        $this->view->assign('docId', $this->requestData['id']);
155
        $this->view->assign('page', $this->requestData['page']);
156
157
    }
158
159
    /**
160
     * Add multi page navigation
161
     * @return void
162
     */
163
    protected function multipageNavigation(): void
164
    {
165
        $navigationArray = [];
166
        $navigationMeasureArray = [];
167
        $navigateAllPageNext = [];
168
        $navigateAllPagePrev = [];
169
        $navigateAllMeasureNext = [];
170
        $navigateAllMeasurePrev = [];
171
        $docNumPages = [];
172
        $i = 0;
173
        foreach ($this->documentArray as $document) {
174
            // convert either page or measure if requestData exists
175
            if ($this->requestData['docPage'][$i] && empty($this->requestData['docMeasure'][$i])) {
176
                // convert document page information to measure count information
177
                $this->requestData['docMeasure'][$i] = $this->convertMeasureOrPage($document, null, $this->requestData['docPage'][$i]);
178
179
            } elseif ((empty($this->requestData['docPage'][$i]) || $this->requestData['docPage'][$i] === 1) && $this->requestData['docMeasure'][$i]) {
180
                $this->requestData['docPage'][$i] = $this->convertMeasureOrPage($document, $this->requestData['docMeasure'][$i]);
181
            }
182
183
            $navigationArray[$i]['next'] = [
184
                'tx_dlf[docPage][' . $i . ']' =>
185
                    MathUtility::forceIntegerInRange((int) $this->requestData['docPage'][$i] + 1, 1, $document->numPages, 1)
186
            ];
187
            $navigationArray[$i]['prev'] = [
188
                'tx_dlf[docPage][' . $i . ']' =>
189
                    MathUtility::forceIntegerInRange((int) $this->requestData['docPage'][$i] - 1, 1, $document->numPages, 1)
190
            ];
191
192
            $navigateAllPageNext = array_merge(
193
                $navigateAllPageNext,
194
                [
195
                    'tx_dlf[docPage][' . $i . ']' =>
196
                        MathUtility::forceIntegerInRange((int) $this->requestData['docPage'][$i] + 1, 1, $document->numPages, 1)
197
                ]
198
            );
199
200
            $navigateAllPagePrev = array_merge(
201
                $navigateAllPagePrev,
202
                [
203
                    'tx_dlf[docPage][' . $i . ']' =>
204
                        MathUtility::forceIntegerInRange((int) $this->requestData['docPage'][$i] - 1, 1, $document->numPages, 1)
205
                ]
206
            );
207
208
            $navigateAllMeasureNext = array_merge(
209
                $navigateAllMeasureNext,
210
                [
211
                    'tx_dlf[docMeasure][' . $i . ']' =>
212
                        MathUtility::forceIntegerInRange((int) $this->requestData['docMeasure'][$i] + 1, 1, $document->numMeasures, 1)
213
                ]
214
            );
215
216
            $navigateAllMeasurePrev = array_merge(
217
                $navigateAllMeasurePrev,
218
                [
219
                    'tx_dlf[docMeasure][' . $i . ']' =>
220
                        MathUtility::forceIntegerInRange((int) $this->requestData['docMeasure'][$i] - 1, 1, $document->numMeasures, 1)
221
                ]
222
            );
223
224
            if ($document->numMeasures > 0) {
225
                $navigationMeasureArray[$i]['next'] = [
226
                    'tx_dlf[docMeasure][' . $i . ']' =>
227
                        MathUtility::forceIntegerInRange((int) $this->requestData['docMeasure'][$i] + 1, 1, $document->numMeasures, 1)
228
                ];
229
230
                $navigationMeasureArray[$i]['prev'] = [
231
                    'tx_dlf[docMeasure][' . $i . ']' =>
232
                        MathUtility::forceIntegerInRange((int) $this->requestData['docMeasure'][$i] - 1, 1, $document->numMeasures, 1)
233
                ];
234
            }
235
236
            $docNumPages[$i] = $document->numPages;
237
            $i++;
238
        }
239
240
        // page navigation
241
        $this->view->assign('navigationArray', $navigationArray);
242
        $this->view->assign('navigateAllPageNext', $navigateAllPageNext);
243
        $this->view->assign('navigateAllPagePrev', $navigateAllPagePrev);
244
        // measure navigation
245
        $this->view->assign('navigateAllMeasurePrev', $navigateAllMeasurePrev);
246
        $this->view->assign('navigateAllMeasureNext', $navigateAllMeasureNext);
247
        $this->view->assign('navigationMeasureArray', $navigationMeasureArray);
248
249
        $this->view->assign('docNumPage', $docNumPages);
250
    }
251
252
    /**
253
     * Converts either measure into page or page into measure
254
     * @param $document
255
     * @param $measure
256
     * @param $page
257
     * @return false|int|mixed|string|null
258
     */
259
    public function convertMeasureOrPage($document, $measure = null, $page = null)
260
    {
261
        $return = null;
262
        $measure2Page = array_column($document->musicalStructure, 'page');
263
        if ($measure) {
264
            $return = $measure2Page[$measure];
265
        } elseif ($page) {
266
            $return = array_search($page, $measure2Page);
267
        }
268
269
        return $return;
270
    }
271
272
    /**
273
     * Action to add multiple mets sources (multi page view)
274
     * @return void
275
     */
276
    public function addDocumentAction(FormAddDocument $formAddDocument)
277
    {
278
        if (GeneralUtility::isValidUrl($formAddDocument->getLocation())) {
279
            $nextMultipleSourceKey = 0;
280
            if ($this->requestData['multipleSource']) {
281
                $nextMultipleSourceKey = max(array_keys($this->requestData['multipleSource'])) + 1;
282
            }
283
            $params = array_merge(
284
                ['tx_dlf' => $this->requestData],
285
                ['tx_dlf[multipleSource][' . $nextMultipleSourceKey . ']' => $formAddDocument->getLocation()],
286
                ['tx_dlf[multiview]' => 1]
287
            );
288
            $uriBuilder = $this->uriBuilder;
289
            $uri = $uriBuilder
290
                ->setArguments($params)
291
                ->setArgumentPrefix('tx_dlf')
292
                ->uriFor('main');
293
294
            $this->redirectToUri($uri);
295
        }
296
297
    }
298
299
    /**
300
     * Get all measures from musical struct
301
     * @param int $page
302
     * @param ?MetsDocument $specificDoc
303
     * @param int|null $docNumber
304
     * @return array
305
     */
306
    protected function getMeasures(int $page, MetsDocument $specificDoc = null, $docNumber = null): array
307
    {
308
        if ($specificDoc) {
309
            $doc = $specificDoc;
310
        } else {
311
            $doc = $this->document->getCurrentDocument();
0 ignored issues
show
Bug introduced by
The method getCurrentDocument() does not exist on null. ( Ignorable by Annotation )

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

311
            /** @scrutinizer ignore-call */ 
312
            $doc = $this->document->getCurrentDocument();

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...
312
        }
313
        $currentPhysId = $doc->physicalStructure[$page];
314
        $measureCoordsFromCurrentSite = [];
315
        $measureCounterToMeasureId = [];
316
        $measureLinks = [];
317
        $defaultFileId = $doc->physicalStructureInfo[$currentPhysId]['files']['DEFAULT'];
318
        if ($doc instanceof MetsDocument) {
319
            if (isset($defaultFileId)) {
320
                $musicalStruct = $doc->musicalStructureInfo;
321
322
                $i = 0;
323
                foreach ($musicalStruct as $measureData) {
324
                    if ($defaultFileId == $measureData['files']['DEFAULT']['fileid']) {
325
                        $measureCoordsFromCurrentSite[$measureData['files']['SCORE']['begin']] = $measureData['files']['DEFAULT']['coords'];
326
                        $measureCounterToMeasureId[$i] = $measureData['files']['SCORE']['begin'];
327
328
                        if ($specificDoc) {
329
                            // build link for each measure
330
                            $params = [
331
                                'tx_dlf' => $this->requestData,
332
                                'tx_dlf[docMeasure][' . $docNumber . ']' => $i
333
                            ];
334
                        } else {
335
                            // build link for each measure
336
                            $params = [
337
                                'tx_dlf' => $this->requestData,
338
                                'tx_dlf[measure]' => $i
339
                            ];
340
                        }
341
                        $uriBuilder = $this->uriBuilder;
342
                        $uri = $uriBuilder
343
                            ->setArguments($params)
344
                            ->setArgumentPrefix('tx_dlf')
345
                            ->uriFor('main');
346
                        $measureLinks[$measureData['files']['SCORE']['begin']] = $uri;
347
348
                    }
349
                    $i++;
350
                }
351
            }
352
        }
353
        return [
354
            'measureCoordsCurrentSite' => $measureCoordsFromCurrentSite,
355
            'measureCounterToMeasureId' => $measureCounterToMeasureId,
356
            'measureLinks' => $measureLinks
357
        ];
358
    }
359
360
    /**
361
     * Get score URL and MIME type
362
     *
363
     * @access protected
364
     *
365
     * @param int $page: Page number
366
     * @param ?MetsDocument $specificDoc
367
     *
368
     * @return array URL and MIME type of fulltext file
369
     */
370
    protected function getScore(int $page, MetsDocument $specificDoc = null)
371
    {
372
        $score = [];
373
        $loc = '';
374
        if ($specificDoc) {
375
            $doc = $specificDoc;
376
        } else {
377
            $doc = $this->document->getCurrentDocument();
378
        }
379
        if ($doc instanceof MetsDocument) {
380
            $fileGrpsScores = GeneralUtility::trimExplode(',', $this->extConf['files']['fileGrpScore']);
381
382
            $pageId = $doc->physicalStructure[$page];
383
            $files = $doc->physicalStructureInfo[$pageId]['files'] ?? [];
384
385
            foreach ($fileGrpsScores as $fileGrpScore) {
386
                if (isset($files[$fileGrpScore])) {
387
                    $loc = $files[$fileGrpScore];
388
                    break;
389
                }
390
            }
391
392
            if (!empty($loc)) {
393
                $score['mimetype'] = $doc->getFileMimeType($loc);
394
                $score['pagebeginning'] = $doc->getPageBeginning($pageId, $loc);
395
                $score['url'] = $doc->getFileLocation($loc);
396
                if ($this->settings['useInternalProxy']) {
397
                    // Configure @action URL for form.
398
                    $uri = $this->uriBuilder->reset()
399
                        ->setTargetPageUid($this->pageUid)
400
                        ->setCreateAbsoluteUri(!empty($this->settings['forceAbsoluteUrl']) ? true : false)
401
                        ->setArguments(
402
                            [
403
                                'eID' => 'tx_dlf_pageview_proxy',
404
                                'url' => $score['url'],
405
                                'uHash' => GeneralUtility::hmac($score['url'], 'PageViewProxy')
406
                            ]
407
                        )
408
                        ->build();
409
410
                    $score['url'] = $uri;
411
                }
412
            }
413
        }
414
415
        if (empty($score)) {
416
            $this->logger->notice('No score file found for page "' . $page . '" in fileGrps "' . $this->settings['fileGrpScore'] . '"');
417
        }
418
        return $score;
419
    }
420
421
    /**
422
     * Get fulltext URL and MIME type
423
     *
424
     * @access protected
425
     *
426
     * @param int $page Page number
427
     *
428
     * @return array URL and MIME type of fulltext file
429
     */
430
    protected function getFulltext(int $page): array
431
    {
432
        $fulltext = [];
433
        // Get fulltext link.
434
        $fileGrpsFulltext = GeneralUtility::trimExplode(',', $this->extConf['files']['fileGrpFulltext']);
435
        while ($fileGrpFulltext = array_shift($fileGrpsFulltext)) {
436
            $physicalStructureInfo = $this->document->getCurrentDocument()->physicalStructureInfo[$this->document->getCurrentDocument()->physicalStructure[$page]];
437
            $files = $physicalStructureInfo['files'];
438
            if (!empty($files[$fileGrpFulltext])) {
439
                $file = $this->document->getCurrentDocument()->getFileInfo($files[$fileGrpFulltext]);
440
                $fulltext['url'] = $file['location'];
441
                if ($this->settings['useInternalProxy']) {
442
                    $this->configureProxyUrl($fulltext['url']);
443
                }
444
                $fulltext['mimetype'] = $file['mimeType'];
445
                break;
446
            } else {
447
                $this->logger->notice('No full-text file found for page "' . $page . '" in fileGrp "' . $fileGrpFulltext . '"');
448
            }
449
        }
450
        if (empty($fulltext)) {
451
            $this->logger->notice('No full-text file found for page "' . $page . '" in fileGrps "' . $this->extConf['files']['fileGrpFulltext'] . '"');
452
        }
453
        return $fulltext;
454
    }
455
456
    /**
457
     * Adds Viewer javascript
458
     *
459
     * @access protected
460
     *
461
     * @return void
462
     */
463
    protected function addViewerJS(): void
464
    {
465
        if (count($this->documentArray) > 1) {
466
            $jsViewer = 'tx_dlf_viewer = [];';
467
            $i = 0;
468
            foreach ($this->documentArray as $document) {
469
                if ($document !== null) {
470
                    $docPage = $this->requestData['docPage'][$i];
471
                    $docImage = [];
472
                    $docFulltext = [];
473
                    $docAnnotationContainers = [];
474
475
                    if ($this->document->getCurrentDocument() instanceof MetsDocument) {
476
                        // check if page or measure is set
477
                        if ($this->requestData['docMeasure'][$i]) {
478
                            // convert document page information to measure count information
479
                            $measure2Page = array_column($document->musicalStructure, 'page');
480
                            $docPage = $measure2Page[$this->requestData['docMeasure'][$i]];
481
                        }
482
                    }
483
                    if ($docPage == null) {
484
                        $docPage = 1;
485
                    }
486
                    $docImage[0] = $this->getImage($docPage, $document);
487
                    $currentMeasureId = '';
488
489
                    $docScore = $this->getScore($docPage, $document);
490
                    $docMeasures = $this->getMeasures($docPage, $document);
491
492
                    if ($this->requestData['docMeasure'][$i]) {
493
                        $currentMeasureId = $docMeasures['measureCounterToMeasureId'][$this->requestData['docMeasure'][$i]];
494
                    }
495
496
                    $jsViewer .= 'tx_dlf_viewer[' . $i . '] = new dlfViewer({
497
                                controls: ["' . implode('", "', $this->controls) . '"],
498
                                div: "tx-dfgviewer-map-' . $i . '",
499
                                progressElementId: "' . $this->settings['progressElementId'] . '",
500
                                counter: "' . $i . '",
501
                                images: ' . json_encode($docImage) . ',
502
                                fulltexts: ' . json_encode($docFulltext) . ',
503
                                score: ' . json_encode($docScore) . ',
504
                                annotationContainers: ' . json_encode($docAnnotationContainers) . ',
505
                                measureCoords: ' . json_encode($docMeasures['measureCoordsCurrentSite']) . ',
506
                                useInternalProxy: ' . ($this->settings['useInternalProxy'] ? 1 : 0) . ',
507
                                currentMeasureId: "' . $currentMeasureId . '",
508
                                measureIdLinks: ' . json_encode($docMeasures['measureLinks']) . '
509
                            });
510
                            ';
511
                    $i++;
512
                }
513
            }
514
515
            // Viewer configuration.
516
            $viewerConfiguration = '$(document).ready(function() {
517
                    if (dlfUtils.exists(dlfViewer)) {
518
                        ' . $jsViewer . '
519
                        viewerCount = ' . ($i - 1) . ';
520
                    }
521
                });';
522
        } else {
523
            $currentMeasureId = '';
524
            $docPage = $this->requestData['page'];
525
526
            $docMeasures = $this->getMeasures($docPage);
527
            if ($this->requestData['measure']) {
528
                $currentMeasureId = $docMeasures['measureCounterToMeasureId'][$this->requestData['measure']];
529
            }
530
531
            // Viewer configuration.
532
            $viewerConfiguration = '$(document).ready(function() {
533
                    if (dlfUtils.exists(dlfViewer)) {
534
                        tx_dlf_viewer = new dlfViewer({
535
                            controls: ["' . implode('", "', $this->controls) . '"],
536
                            div: "' . $this->settings['elementId'] . '",
537
                            progressElementId: "' . $this->settings['progressElementId'] . '",
538
                            images: ' . json_encode($this->images) . ',
539
                            fulltexts: ' . json_encode($this->fulltexts) . ',
540
                            score: ' . json_encode($this->scores) . ',
541
                            annotationContainers: ' . json_encode($this->annotationContainers) . ',
542
                            measureCoords: ' . json_encode($docMeasures['measureCoordsCurrentSite']) . ',
543
                            useInternalProxy: ' . ($this->settings['useInternalProxy'] ? 1 : 0) . ',
544
                            verovioAnnotations: ' . json_encode($this->verovioAnnotations) . ',
545
                            currentMeasureId: "' . $currentMeasureId . '",
546
                            measureIdLinks: ' . json_encode($docMeasures['measureLinks']) . '
547
                        });
548
                    }
549
                });';
550
        }
551
        $this->view->assign('viewerConfiguration', $viewerConfiguration);
552
    }
553
554
    /**
555
     * Get all AnnotationPages / AnnotationLists that contain text Annotations with motivation "painting"
556
     *
557
     * @access protected
558
     *
559
     * @param int $page Page number
560
     * @return array An array containing the IRIs of the AnnotationLists / AnnotationPages as well as some information about the canvas.
561
     */
562
    protected function getAnnotationContainers(int $page): array
563
    {
564
        if ($this->document->getCurrentDocument() instanceof IiifManifest) {
565
            $canvasId = $this->document->getCurrentDocument()->physicalStructure[$page];
566
            $iiif = $this->document->getCurrentDocument()->getIiif();
567
            if ($iiif instanceof ManifestInterface) {
0 ignored issues
show
introduced by
$iiif is always a sub-type of Ubl\Iiif\Presentation\Co...urces\ManifestInterface.
Loading history...
568
                $canvas = $iiif->getContainedResourceById($canvasId);
569
                /* @var $canvas \Ubl\Iiif\Presentation\Common\Model\Resources\CanvasInterface */
570
                if ($canvas != null && !empty($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING))) {
571
                    $annotationContainers = [];
572
                    /*
573
                     *  TODO Analyzing the annotations on the server side requires loading the annotation lists / pages
574
                     *  just to determine whether they contain text annotations for painting. This will take time and lead to a bad user experience.
575
                     *  It would be better to link every annotation and analyze the data on the client side.
576
                     *
577
                     *  On the other hand, server connections are potentially better than client connections. Downloading annotation lists
578
                     */
579
                    foreach ($canvas->getPossibleTextAnnotationContainers(Motivation::PAINTING) as $annotationContainer) {
580
                        if (($textAnnotations = $annotationContainer->getTextAnnotations(Motivation::PAINTING)) != null) {
581
                            foreach ($textAnnotations as $annotation) {
582
                                if (
583
                                    $annotation->getBody()->getFormat() == 'text/plain'
584
                                    && $annotation->getBody()->getChars() != null
585
                                ) {
586
                                    $annotationListData = [];
587
                                    $annotationListData['uri'] = $annotationContainer->getId();
588
                                    $annotationListData['label'] = $annotationContainer->getLabelForDisplay();
589
                                    $annotationContainers[] = $annotationListData;
590
                                    break;
591
                                }
592
                            }
593
                        }
594
                    }
595
                    $result = [
596
                        'canvas' => [
597
                            'id' => $canvas->getId(),
598
                            'width' => $canvas->getWidth(),
599
                            'height' => $canvas->getHeight(),
600
                        ],
601
                        'annotationContainers' => $annotationContainers
602
                    ];
603
                    return $result;
604
                }
605
            }
606
        }
607
        return [];
608
    }
609
610
    /**
611
     * Get image's URL and MIME type
612
     *
613
     * @access protected
614
     *
615
     * @param int $page Page number
616
     *
617
     * @param ?MetsDocument $specificDoc
618
     *
619
     * @return array URL and MIME type of image file
620
     */
621
    protected function getImage(int $page, MetsDocument $specificDoc = null): array
622
    {
623
        $image = [];
624
        // Get @USE value of METS fileGrp.
625
        $fileGrpsImages = GeneralUtility::trimExplode(',', $this->extConf['files']['fileGrpImages']);
626
        while ($fileGrpImages = array_pop($fileGrpsImages)) {
627
            if ($specificDoc) {
628
                // Get image link.
629
                $physicalStructureInfo = $specificDoc->physicalStructureInfo[$specificDoc->physicalStructure[$page]];
630
                $files = $physicalStructureInfo['files'];
631
                if (!empty($files[$fileGrpImages])) {
632
                    $file = $specificDoc->getFileInfo($files[$fileGrpImages]);
633
                    $image['url'] = $file['location'];
634
                    $image['mimetype'] = $file['mimeType'];
635
636
                    // Only deliver static images via the internal PageViewProxy.
637
                    // (For IIP and IIIF, the viewer needs to build and access a separate metadata URL, see `getMetadataURL` in `OLSources.js`.)
638
                    if ($this->settings['useInternalProxy'] && !str_contains(strtolower($image['mimetype']), 'application')) {
639
                        $this->configureProxyUrl($image['url']);
640
                    }
641
                    break;
642
                } else {
643
                    $this->logger->notice('No image file found for page "' . $page . '" in fileGrp "' . $fileGrpImages . '"');
644
                }
645
646
            } else {
647
648
                // Get image link.
649
                $physicalStructureInfo = $this->document->getCurrentDocument()->physicalStructureInfo[$this->document->getCurrentDocument()->physicalStructure[$page]];
650
                $files = $physicalStructureInfo['files'];
651
                if (!empty($files[$fileGrpImages])) {
652
                    $file = $this->document->getCurrentDocument()->getFileInfo($files[$fileGrpImages]);
653
                    $image['url'] = $file['location'];
654
                    $image['mimetype'] = $file['mimeType'];
655
656
                    // Only deliver static images via the internal PageViewProxy.
657
                    // (For IIP and IIIF, the viewer needs to build and access a separate metadata URL, see `getMetadataURL` in `OLSources.js`.)
658
                    if ($this->settings['useInternalProxy'] && !str_contains(strtolower($image['mimetype']), 'application')) {
659
                        $this->configureProxyUrl($image['url']);
660
                    }
661
                    break;
662
                } else {
663
                    $this->logger->notice('No image file found for page "' . $page . '" in fileGrp "' . $fileGrpImages . '"');
664
                }
665
            }
666
        }
667
        if (empty($image)) {
668
            $this->logger->warning('No image file found for page "' . $page . '" in fileGrps "' . $this->extConf['files']['fileGrpImages'] . '"');
669
        }
670
        return $image;
671
    }
672
}
673