Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.62% covered (success)
93.62%
44 / 47
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
MetadataLoader
93.62% covered (success)
93.62%
44 / 47
50.00% covered (danger)
50.00%
2 / 4
13.04
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 loadMetadata
92.31% covered (success)
92.31%
24 / 26
0.00% covered (danger)
0.00%
0 / 1
6.02
 getFileNode
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
4.05
 getPages
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5/**
6 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7 * SPDX-License-Identifier: AGPL-3.0-or-later
8 */
9
10namespace OCA\Libresign\Service\File;
11
12use OCA\Libresign\Db\File;
13use OCA\Libresign\Service\FolderService;
14use OCP\Files\IMimeTypeDetector;
15use OCP\IURLGenerator;
16use Psr\Log\LoggerInterface;
17use stdClass;
18
19class MetadataLoader {
20    public function __construct(
21        private FolderService $folderService,
22        private IMimeTypeDetector $mimeTypeDetector,
23        private IURLGenerator $urlGenerator,
24        private FileContentProvider $contentProvider,
25        private LoggerInterface $logger,
26    ) {
27    }
28
29    public function loadMetadata(?File $file, stdClass $fileData): void {
30        if (!$file) {
31            return;
32        }
33
34        $rawMetadata = $file->getMetadata() ?? [];
35
36        try {
37            $fileNode = $this->getFileNode($file);
38            $metadata = $rawMetadata;
39
40            if (method_exists($fileNode, 'getSize')) {
41                $fileData->size = $fileNode->getSize();
42            }
43
44            if (method_exists($fileNode, 'getMimeType')) {
45                $fileData->mime = $fileNode->getMimeType();
46            } else {
47                $content = $this->contentProvider->getContentFromLibresignFile($file);
48                $fileData->mime = $this->mimeTypeDetector->detectString($content);
49            }
50
51            $fileData->pages = $this->getPages($file);
52            $fileData->totalPages = (int)($metadata['p'] ?? count($fileData->pages ?? []));
53            $fileData->pdfVersion = (string)($metadata['pdfVersion'] ?? '');
54
55            $metadata = ValidationMetadataNormalizer::normalize($metadata, $file->getName(), $fileData->totalPages);
56            $fileData->metadata = $metadata;
57        } catch (\Throwable $e) {
58            $this->logger->warning('Failed to load file metadata: ' . $e->getMessage());
59        }
60
61        $fileData->size ??= 0;
62        $fileData->totalPages ??= 0;
63        $fileData->pdfVersion ??= '';
64        $fileData->metadata = ValidationMetadataNormalizer::normalize(
65            is_array($fileData->metadata ?? null) ? $fileData->metadata : $rawMetadata,
66            $file->getName(),
67            (int)$fileData->totalPages,
68        );
69    }
70
71    /**
72     * Get file node from File entity
73     *
74     * @throws \OCA\Libresign\Exception\LibresignException
75     */
76    private function getFileNode(File $file): \OCP\Files\File|\OCP\Files\Folder {
77        $nodeId = $file->getSignedNodeId();
78        if (!$nodeId) {
79            $nodeId = $file->getNodeId();
80        }
81
82        $fileNode = $this->folderService->getReadableNodeById($file->getUserId(), $nodeId);
83
84        if (!$fileNode instanceof \OCP\Files\File && !$fileNode instanceof \OCP\Files\Folder) {
85            throw new \OCA\Libresign\Exception\LibresignException('File not found', 404);
86        }
87
88        return $fileNode;
89    }
90
91    /**
92     * Get pages array with URLs and resolutions
93     *
94     * @return array<int, array{number: int, url: string, resolution: mixed}>
95     */
96    private function getPages(File $file): array {
97        $return = [];
98
99        $metadata = $file->getMetadata();
100        $pageCount = $metadata['p'] ?? 0;
101
102        for ($page = 1; $page <= $pageCount; $page++) {
103            $return[] = [
104                'number' => $page,
105                'url' => $this->urlGenerator->linkToRoute('libresign.page.getPdf', [
106                    'uuid' => $file->getUuid(),
107                    'page' => $page,
108                ]),
109                'resolution' => $metadata['d'][$page - 1] ?? null,
110            ];
111        }
112
113        return $return;
114    }
115}