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 ( d27b89...31a6e8 )
by
unknown
04:57 queued 32s
created

MetadataController::setDefault()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
nc 2
nop 2
dl 0
loc 4
rs 10
c 2
b 0
f 0
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\Helper;
16
use Kitodo\Dlf\Common\IiifManifest;
17
use Kitodo\Dlf\Domain\Repository\CollectionRepository;
18
use Kitodo\Dlf\Domain\Repository\MetadataRepository;
19
use Kitodo\Dlf\Domain\Repository\StructureRepository;
20
use Ubl\Iiif\Context\IRI;
21
22
/**
23
 * Controller class for the plugin 'Metadata'.
24
 *
25
 * @package TYPO3
26
 * @subpackage dlf
27
 *
28
 * @access public
29
 */
30
class MetadataController extends AbstractController
31
{
32
    /**
33
     * @access private
34
     * @var AbstractDocument
35
     */
36
    private $currentDocument;
37
38
    /**
39
     * @access private
40
     * @var bool
41
     */
42
    private $useOriginalIiifManifestMetadata;
43
44
    /**
45
     * @access protected
46
     * @var CollectionRepository
47
     */
48
    protected CollectionRepository $collectionRepository;
49
50
    /**
51
     * @access public
52
     *
53
     * @param CollectionRepository $collectionRepository
54
     *
55
     * @return void
56
     */
57
    public function injectCollectionRepository(CollectionRepository $collectionRepository): void
58
    {
59
        $this->collectionRepository = $collectionRepository;
60
    }
61
62
    /**
63
     * @access protected
64
     * @var MetadataRepository
65
     */
66
    protected MetadataRepository $metadataRepository;
67
68
    /**
69
     * @access public
70
     *
71
     * @param MetadataRepository $metadataRepository
72
     *
73
     * @return void
74
     */
75
    public function injectMetadataRepository(MetadataRepository $metadataRepository): void
76
    {
77
        $this->metadataRepository = $metadataRepository;
78
    }
79
80
    /**
81
     * @access protected
82
     * @var StructureRepository
83
     */
84
    protected StructureRepository $structureRepository;
85
86
    /**
87
     * @access public
88
     *
89
     * @param StructureRepository $structureRepository
90
     *
91
     * @return void
92
     */
93
    public function injectStructureRepository(StructureRepository $structureRepository): void
94
    {
95
        $this->structureRepository = $structureRepository;
96
    }
97
98
    /**
99
     * @access public
100
     *
101
     * @return void
102
     */
103
    public function mainAction(): void
104
    {
105
        // Load current document.
106
        $this->loadDocument();
107
        if ($this->isDocMissing()) {
108
            // Quit without doing anything if required variables are not set.
109
            return;
110
        }
111
112
        $this->setPage();
113
114
        $this->currentDocument = $this->document->getCurrentDocument();
115
        $this->useOriginalIiifManifestMetadata = $this->settings['originalIiifMetadata'] == 1 && $this->currentDocument instanceof IiifManifest;
116
117
        $metadata = $this->getMetadata();
118
        $topLevelId = $this->currentDocument->toplevelId;
119
        // Get toplevel metadata?
120
        if (!$metadata || ($this->settings['rootline'] == 1 && $metadata[0]['_id'] != $topLevelId)) {
121
            $data = [];
122
            if ($this->useOriginalIiifManifestMetadata) {
123
                // @phpstan-ignore-next-line
124
                $data = $this->currentDocument->getManifestMetadata($topLevelId, $this->settings['storagePid']);
0 ignored issues
show
Bug introduced by
The method getManifestMetadata() does not exist on Kitodo\Dlf\Common\AbstractDocument. It seems like you code against a sub-type of Kitodo\Dlf\Common\AbstractDocument such as Kitodo\Dlf\Common\IiifManifest. ( Ignorable by Annotation )

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

124
                /** @scrutinizer ignore-call */ 
125
                $data = $this->currentDocument->getManifestMetadata($topLevelId, $this->settings['storagePid']);
Loading history...
125
            } else {
126
                $data = $this->currentDocument->getToplevelMetadata($this->settings['storagePid']);
127
            }
128
            $data['_id'] = $topLevelId;
129
            array_unshift($metadata, $data);
130
        }
131
132
        if (empty(array_filter($metadata))) {
133
            $this->logger->warning('No metadata found for document with UID ' . $this->document->getUid());
134
            return;
135
        }
136
        ksort($metadata);
137
138
        $this->printMetadata($metadata);
139
    }
140
141
    /**
142
     * Prepares the metadata array for output
143
     *
144
     * @access protected
145
     *
146
     * @param array $metadata The metadata array
147
     *
148
     * @return void
149
     */
150
    protected function printMetadata(array $metadata): void
151
    {
152
        if ($this->useOriginalIiifManifestMetadata) {
153
            $this->view->assign('useIiif', true);
154
            $this->view->assign('iiifData', $this->buildIiifData($metadata));
155
        } else {
156
            // findBySettings also sorts entries by the `sorting` field
157
            $metadataResult = $this->metadataRepository->findBySettings(
158
                [
159
                    'is_listed' => !$this->settings['showFull'],
160
                ]
161
            );
162
163
            foreach ($metadata as $i => $section) {
164
165
                foreach ($section as $name => $value) {
166
                    // NOTE: Labels are to be escaped in Fluid template
167
168
                    $metadata[$i][$name] = is_array($value)
169
                        ? implode($this->settings['separator'], $value)
170
                        : $value;
171
172
                    if ($metadata[$i][$name] === 'Array') {
173
                        $metadata[$i][$name] = [];
174
                        foreach ($value as $subKey => $subValue) {
175
                            $metadata[$i][$name][$subKey] = $subValue;
176
                        }
177
                    }
178
179
                    $this->parseMetadata($i, $name, $value, $metadata);
180
181
                    if (is_array($metadata[$i][$name])) {
182
                        $metadata[$i][$name] = array_values(array_filter($metadata[$i][$name], function ($metadataValue) {
183
                            return !empty($metadataValue);
184
                        }));
185
                    }
186
                }
187
            }
188
189
            $this->view->assign('buildUrl', $this->buildUrlFromMetadata($metadata));
190
            $this->view->assign('externalUrl', $this->buildExternalUrlFromMetadata($metadata));
191
            $this->view->assign('documentMetadataSections', $metadata);
192
            $this->view->assign('configMetadata', $metadataResult);
193
            $this->view->assign('separator', $this->settings['separator']);
194
            $this->view->assign('metaConfigObjectData', $this->buildMetaConfigObjectData($metadata));
195
        }
196
    }
197
198
    /**
199
     * Builds the IIIF data array from metadata array
200
     *
201
     * @access private
202
     *
203
     * @param array $metadata The metadata array
204
     *
205
     * @return array The IIIF data array ready for output
206
     */
207
    private function buildIiifData(array $metadata): array
208
    {
209
        $iiifData = [];
210
211
        foreach ($metadata as $row) {
212
            foreach ($row as $key => $group) {
213
                if ($key == '_id') {
214
                    continue;
215
                }
216
217
                if (!is_array($group)) {
218
                    $iiifData[$key] = $this->buildIiifDataGroup($key, $group);
219
                } else {
220
                    foreach ($group as $label => $value) {
221
                        if ($label == '_id') {
222
                            continue;
223
                        }
224
                        if (is_array($value)) {
225
                            $value = implode($this->settings['separator'], $value);
226
                        }
227
228
                        $iiifData[$key]['data'][] = $this->buildIiifDataGroup($label, $value);
229
                    }
230
                }
231
            }
232
        }
233
234
        return $iiifData;
235
    }
236
237
    /**
238
     * Builds the IIIF data array from label and value
239
     *
240
     * @access private
241
     *
242
     * @param string $label The label string
243
     * @param string $value The value string
244
     *
245
     * @return array The IIIF data array ready for output
246
     */
247
    private function buildIiifDataGroup(string $label, string $value): array
248
    {
249
        // NOTE: Labels are to be escaped in Fluid template
250
        $scheme = (new IRI($value))->getScheme();
251
        if (IRI::isAbsoluteIri($value) && ($scheme == 'http' || $scheme == 'https')) {
252
            //TODO: should really label be converted to empty string if equal to value?
253
            $label = $value == $label ? '' : $label;
254
            $buildUrl = true;
255
        } else {
256
            $buildUrl = false;
257
        }
258
259
        return [
260
            'label' => $label,
261
            'value' => $value,
262
            'buildUrl' => $buildUrl,
263
        ];
264
    }
265
266
    /**
267
     * Collects raw metadata into an array that will be passed as data to cObj.
268
     * This lets metadata wraps reference (own or foreign) values via TypoScript "field".
269
     *
270
     * @access private
271
     *
272
     * @param array $metadata The metadata array
273
     *
274
     * @return array The raw metadata array ready for output
275
     */
276
    private function buildMetaConfigObjectData(array $metadata): array
277
    {
278
        $metaConfigObjectData = [];
279
280
        foreach ($metadata as $i => $section) {
281
            $metaConfigObjectData[$i] = [];
282
283
            foreach ($section as $name => $value) {
284
                $metaConfigObjectData[$i][$name] = is_array($value)
285
                    ? implode($this->settings['separator'], $value)
286
                    : $value;
287
            }
288
        }
289
290
        return $metaConfigObjectData;
291
    }
292
293
    /**
294
     * Builds URLs array for given metadata array.
295
     *
296
     * @access private
297
     *
298
     * @param array $metadata The metadata array
299
     *
300
     * @return array URLs
301
     */
302
    private function buildUrlFromMetadata(array $metadata): array
303
    {
304
        $buildUrl = [];
305
306
        foreach ($metadata as $i => $section) {
307
            if ($this->settings['linkTitle'] && $section['_id'] && isset($section['title']) && !empty($section['title'])) {
308
                $details = $this->currentDocument->getLogicalStructure($section['_id']);
309
                $buildUrl[$i]['title'] = [
310
                    'id' => $this->document->getUid(),
0 ignored issues
show
Bug introduced by
The method getUid() 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

310
                    'id' => $this->document->/** @scrutinizer ignore-call */ getUid(),

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...
311
                    'page' => (!empty($details['points']) ? (int) $details['points'] : 1),
312
                    'targetPid' => (!empty($this->settings['targetPid']) ? $this->settings['targetPid'] : 0),
313
                ];
314
            }
315
        }
316
317
        return $buildUrl;
318
    }
319
320
    /**
321
     * Builds external URLs array for given metadata array.
322
     *
323
     * @access private
324
     *
325
     * @param array $metadata The metadata array
326
     *
327
     * @return array external URLs
328
     */
329
    private function buildExternalUrlFromMetadata(array $metadata): array
330
    {
331
        $externalUrl = [];
332
333
        foreach ($metadata as $i => $section) {
334
            foreach ($section as $name => $value) {
335
                if (($name == 'author' || $name == 'holder') && !empty($value) && !empty($value[0]['url'])) {
336
                    $externalUrl[$i][$name]['externalUrl'] = $value[0];
337
                } elseif (($name == 'geonames' || $name == 'wikidata' || $name == 'wikipedia') && !empty($value)) {
338
                    $externalUrl[$i][$name]['externalUrl'] = [
339
                        'name' => $value[0],
340
                        'url' => $value[0]
341
                    ];
342
                }
343
            }
344
        }
345
346
        return $externalUrl;
347
    }
348
349
    /**
350
     * Parses metadata.
351
     *
352
     * @access private
353
     *
354
     * @param int $i The index of metadata array
355
     * @param string $name The name of section in metadata array
356
     * @param mixed $value The value of section in metadata array
357
     * @param array $metadata The metadata array passed as reference
358
     *
359
     * @return void
360
     */
361
    private function parseMetadata(int $i, string $name, $value, array &$metadata) : void
362
    {
363
        if ($name == 'title') {
364
            // Get title of parent document if needed.
365
            $this->parseParentTitle($i, $value, $metadata);
366
        } elseif ($name == 'owner' && empty($value)) {
367
            // no owner is found by metadata records --> take the one associated to the document
368
            $this->parseOwner($i, $metadata);
369
        } elseif ($name == 'type' && !empty($value)) {
370
            // Translate document type.
371
            $this->parseType($i, $metadata);
372
        } elseif ($name == 'collection' && !empty($value)) {
373
            // Check if collections isn't hidden.
374
            $this->parseCollections($i, $value, $metadata);
375
        } elseif ($name == 'language' && !empty($value)) {
376
            // Translate ISO 639 language code.
377
            foreach ($metadata[$i][$name] as &$langValue) {
378
                $langValue = Helper::getLanguageName($langValue);
379
            }
380
        }
381
    }
382
383
    /**
384
     * Parse title of parent document if needed.
385
     *
386
     * @access private
387
     *
388
     * @param int $i The index of metadata array
389
     * @param mixed $value The value of section in metadata array
390
     * @param array $metadata The metadata array passed as reference
391
     *
392
     * @return void
393
     */
394
    private function parseParentTitle(int $i, $value, array &$metadata) : void
395
    {
396
        if (empty(implode('', $value)) && $this->settings['getTitle'] && $this->document->getPartof()) {
397
            $superiorTitle = AbstractDocument::getTitle($this->document->getPartof(), true);
398
            if (!empty($superiorTitle)) {
399
                $metadata[$i]['title'] = ['[' . $superiorTitle . ']'];
400
            }
401
        }
402
    }
403
404
    /**
405
     * Parse owner if no owner is found by metadata records. Take the one associated to the document.
406
     *
407
     * @access private
408
     *
409
     * @param int $i The index of metadata array
410
     * @param array $metadata The metadata array passed as reference
411
     *
412
     * @return void
413
     */
414
    private function parseOwner(int $i, array &$metadata) : void
415
    {
416
        $library = $this->document->getOwner();
417
        if ($library) {
0 ignored issues
show
introduced by
$library is of type Kitodo\Dlf\Domain\Model\Library, thus it always evaluated to true.
Loading history...
418
            $metadata[$i]['owner'][0] = $library->getLabel();
419
        }
420
    }
421
422
    /**
423
     * Parse type - translate document type.
424
     *
425
     * @access private
426
     *
427
     * @param int $i The index of metadata array
428
     * @param array $metadata The metadata array passed as reference
429
     *
430
     * @return void
431
     */
432
    private function parseType(int $i, array &$metadata) : void
433
    {
434
        $structure = $this->structureRepository->findOneByIndexName($metadata[$i]['type']);
0 ignored issues
show
Bug introduced by
The method findOneByIndexName() does not exist on Kitodo\Dlf\Domain\Repository\StructureRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

434
        /** @scrutinizer ignore-call */ 
435
        $structure = $this->structureRepository->findOneByIndexName($metadata[$i]['type']);
Loading history...
435
        if ($structure) {
436
            $metadata[$i]['type'] = $structure->getLabel();
0 ignored issues
show
Bug introduced by
The method getLabel() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

436
            /** @scrutinizer ignore-call */ 
437
            $metadata[$i]['type'] = $structure->getLabel();

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...
437
        }
438
    }
439
440
    /**
441
     * Parse collections - check if collections isn't hidden.
442
     *
443
     * @access private
444
     *
445
     * @param int $i The index of metadata array
446
     * @param mixed $value The value of section in metadata array
447
     * @param array $metadata The metadata array passed as reference
448
     *
449
     * @return void
450
     */
451
    private function parseCollections(int $i, $value, array &$metadata) : void
452
    {
453
        $j = 0;
454
        foreach ($value as $entry) {
455
            $collection = $this->collectionRepository->findOneByIndexName($entry);
0 ignored issues
show
Bug introduced by
The method findOneByIndexName() does not exist on Kitodo\Dlf\Domain\Repository\CollectionRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

455
            /** @scrutinizer ignore-call */ 
456
            $collection = $this->collectionRepository->findOneByIndexName($entry);
Loading history...
456
            if ($collection) {
457
                $metadata[$i]['collection'][$j] = $collection->getLabel() ? : '';
458
                $j++;
459
            }
460
        }
461
    }
462
463
    /**
464
     * Get metadata for given id array.
465
     *
466
     * @access private
467
     *
468
     * @return array metadata
469
     */
470
    private function getMetadata(): array
471
    {
472
        $metadata = [];
473
        if ($this->settings['rootline'] < 2) {
474
            // Get current structure's @ID.
475
            $ids = [];
476
            $page = $this->currentDocument->physicalStructure[$this->requestData['page']];
477
            if (!empty($page) && !empty($this->currentDocument->smLinks['p2l'][$page])) {
478
                foreach ($this->currentDocument->smLinks['p2l'][$page] as $logId) {
479
                    $count = $this->currentDocument->getStructureDepth($logId);
480
                    $ids[$count][] = $logId;
481
                }
482
            }
483
            ksort($ids);
484
            reset($ids);
485
            // Check if we should display all metadata up to the root.
486
            if ($this->settings['rootline'] == 1) {
487
                foreach ($ids as $id) {
488
                    $metadata = $this->getMetadataForIds($id, $metadata);
489
                }
490
            } else {
491
                $id = array_pop($ids);
492
                if (is_array($id)) {
493
                    $metadata = $this->getMetadataForIds($id, $metadata);
494
                }
495
            }
496
        }
497
        return $metadata;
498
    }
499
500
    /**
501
     * Get metadata for given id array.
502
     *
503
     * @access private
504
     *
505
     * @param array $id An array with ids
506
     * @param array $metadata An array with metadata
507
     *
508
     * @return array metadata
509
     */
510
    private function getMetadataForIds(array $id, array $metadata): array
511
    {
512
        foreach ($id as $sid) {
513
            if ($this->useOriginalIiifManifestMetadata) {
514
                // @phpstan-ignore-next-line
515
                $data = $this->currentDocument->getManifestMetadata($sid, $this->settings['storagePid']);
516
            } else {
517
                $data = $this->currentDocument->getMetadata($sid, $this->settings['storagePid']);
518
            }
519
            if (!empty($data)) {
520
                $data['_id'] = $sid;
521
                $metadata[] = $data;
522
            }
523
        }
524
        return $metadata;
525
    }
526
}
527