• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 21004797917

14 Jan 2026 06:08PM UTC coverage: 43.74%. First build
21004797917

Pull #6436

github

web-flow
Merge 4496f61e1 into 9bd4c65c5
Pull Request #6436: feat: async parallel signing

294 of 860 new or added lines in 35 files covered. (34.19%)

6921 of 15823 relevant lines covered (43.74%)

4.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.85
/lib/Service/File/Pdf/PdfMetadataExtractor.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9

10
namespace OCA\Libresign\Service\File\Pdf;
11

12
use OCA\Libresign\Exception\LibresignException;
13
use OCA\Libresign\Vendor\Smalot\PdfParser\Document;
14
use OCP\Files\File;
15
use OCP\ITempManager;
16
use Psr\Log\LoggerInterface;
17

18
class PdfMetadataExtractor {
19
        private string $content = '';
20
        private string $fileName = '';
21
        private ?Document $document = null;
22

23
        public function __construct(
24
                private PdfParser $pdfParser,
25
                private ITempManager $tempManager,
26
                private LoggerInterface $logger,
27
        ) {
28
        }
54✔
29

30
        /**
31
         * @throws LibresignException
32
         */
33
        public function setFile(File $file): self {
34
                $fileName = $file->getName();
21✔
35
                try {
36
                        $this->content = $file->getContent();
21✔
37
                } catch (\Throwable $e) {
1✔
38
                        throw new LibresignException(
1✔
39
                                sprintf('Unable to read file "%s": %s', $fileName, $e->getMessage())
1✔
40
                        );
1✔
41
                }
42
                if (!$this->content) {
20✔
43
                        throw new LibresignException(sprintf('The file "%s" is empty.', $fileName));
1✔
44
                }
45
                $this->fileName = $fileName;
19✔
46
                $this->document = null;
19✔
47
                return $this;
19✔
48
        }
49

50
        private function getContent(): string {
51
                if (!$this->content) {
20✔
52
                        throw new LibresignException('File not defined to be parsed.');
1✔
53
                }
54
                return $this->content;
19✔
55
        }
56

57
        private function getDocument(): Document {
58
                if (!$this->document) {
×
59
                        $content = $this->getContent();
×
NEW
60
                        $this->document = $this->pdfParser->parse($content, $this->fileName);
×
61
                }
62
                return $this->document;
×
63
        }
64

65
        /**
66
         * @return (array[]|int)[]
67
         * @throws LibresignException
68
         * @psalm-return array{p: int, d?: non-empty-list<array{w: mixed, h: mixed}>}
69
         */
70
        public function getPageDimensions(): array {
71
                if ($return = $this->getPageDimensionsWithPdfInfo()) {
16✔
72
                        return $return;
15✔
73
                }
74
                return $this->getPageDimensionsWithSmalotPdfParser();
×
75
        }
76

77
        private function getPageDimensionsWithSmalotPdfParser(): array {
78
                $document = $this->getDocument();
×
79
                $pages = $document->getPages();
×
80
                $output = [
×
81
                        'p' => count($pages),
×
82
                ];
×
83
                foreach ($pages as $page) {
×
84
                        $details = $page->getDetails();
×
85
                        if (!isset($details['MediaBox'])) {
×
86
                                $pages = $document->getObjectsByType('Pages');
×
87
                                $details = reset($pages)->getHeader()->getDetails();
×
88
                        }
89
                        if (!isset($details['MediaBox']) || !is_numeric($details['MediaBox'][2]) || !is_numeric($details['MediaBox'][3])) {
×
90
                                $this->logger->error('Impossible get metadata from this file: Error to get page width and height. If possible, open an issue at github.com/libresign/libresign with the file that you used.');
×
91
                                throw new LibresignException('Impossible get metadata from this file.');
×
92
                        }
93
                        $output['d'][] = [
×
94
                                'w' => $details['MediaBox'][2],
×
95
                                'h' => $details['MediaBox'][3],
×
96
                        ];
×
97
                }
98
                $pending = $output['p'] - count($output['d']);
×
99
                if ($pending) {
×
100
                        for ($i = 0; $i < $pending; $i++) {
×
101
                                $output['d'][] = $output['d'][0];
×
102
                        }
103
                }
104
                return $output;
×
105
        }
106

107
        private function getPageDimensionsWithPdfInfo(): array {
108
                if (shell_exec('which pdfinfo') === null) {
16✔
109
                        return [];
×
110
                }
111
                $content = $this->getContent();
16✔
112
                $filename = $this->tempManager->getTemporaryFile('.pdf');
15✔
113
                file_put_contents($filename, $content);
15✔
114

115
                // The output of this command go to STDERR and shell_exec get the STDOUT
116
                // With 2>&1 the STRERR is redirected to STDOUT
117
                $pdfinfo = shell_exec('pdfinfo ' . $filename . ' -l -1 2>&1');
15✔
118
                if (!$pdfinfo) {
15✔
119
                        return [];
×
120
                }
121
                if (!preg_match_all('/Page +\d+ +size: +(\d+\.?\d*) x (\d+\.?\d*)/', (string)$pdfinfo, $pages)) {
15✔
122
                        return [];
×
123
                }
124
                $output = [
15✔
125
                        'p' => count($pages[1]),
15✔
126
                ];
15✔
127
                foreach ($pages[1] as $page => $width) {
15✔
128
                        $output['d'][] = [
15✔
129
                                'w' => (float)$width,
15✔
130
                                'h' => (float)$pages[2][$page],
15✔
131
                        ];
15✔
132
                }
133
                return $output;
15✔
134
        }
135

136
        public function getPdfVersion(): string {
137
                preg_match('/^%PDF-(?<version>\d+(\.\d+)?)/', $this->getContent(), $match);
19✔
138
                return $match['version'];
19✔
139
        }
140
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc