Completed
Pull Request — master (#139)
by
unknown
01:21
created

Pdf::fetchNumberPages()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 4
nc 3
nop 1
1
<?php
2
3
namespace Spatie\PdfToImage;
4
5
use Imagick;
6
use Spatie\PdfToImage\Exceptions\InvalidFormat;
7
use Spatie\PdfToImage\Exceptions\PageDoesNotExist;
8
use Spatie\PdfToImage\Exceptions\PdfDoesNotExist;
9
10
class Pdf
11
{
12
    protected $pdfFile;
13
14
    protected $resolution = 144;
15
16
    protected $outputFormat = 'jpg';
17
18
    protected $page = 1;
19
20
    public $imagick;
21
22
    protected $numberOfPages;
23
24
    protected $validOutputFormats = ['jpg', 'jpeg', 'png'];
25
26
    protected $layerMethod = Imagick::LAYERMETHOD_FLATTEN;
27
28
    protected $colorspace;
29
30
    protected $compressionQuality;
31
32
    public function __construct(string $pdfFile)
33
    {
34
        if (! file_exists($pdfFile)) {
35
            throw new PdfDoesNotExist("File `{$pdfFile}` does not exist");
36
        }
37
38
        $this->imagick = new Imagick($pdfFile);
39
40
        $this->numberOfPages = $this->fetchNumberPages($pdfFile);
41
42
        $this->pdfFile = $pdfFile;
43
    }
44
45
    public function setResolution(int $resolution)
46
    {
47
        $this->resolution = $resolution;
48
49
        return $this;
50
    }
51
52
    public function setOutputFormat(string $outputFormat)
53
    {
54
        if (! $this->isValidOutputFormat($outputFormat)) {
55
            throw new InvalidFormat("Format {$outputFormat} is not supported");
56
        }
57
58
        $this->outputFormat = $outputFormat;
59
60
        return $this;
61
    }
62
63
    public function getOutputFormat(): string
64
    {
65
        return $this->outputFormat;
66
    }
67
68
    /**
69
     * Sets the layer method for Imagick::mergeImageLayers()
70
     * If int, should correspond to a predefined LAYERMETHOD constant.
71
     * If null, Imagick::mergeImageLayers() will not be called.
72
     *
73
     * @param int|null
74
     *
75
     * @return $this
76
     *
77
     * @throws \Spatie\PdfToImage\Exceptions\InvalidLayerMethod
78
     *
79
     * @see https://secure.php.net/manual/en/imagick.constants.php
80
     * @see Pdf::getImageData()
81
     */
82
    public function setLayerMethod(?int $layerMethod)
83
    {
84
        $this->layerMethod = $layerMethod;
85
86
        return $this;
87
    }
88
89
    public function isValidOutputFormat(string $outputFormat): bool
90
    {
91
        return in_array($outputFormat, $this->validOutputFormats);
92
    }
93
94
    public function setPage(int $page)
95
    {
96
        if ($page > $this->getNumberOfPages() || $page < 1) {
97
            throw new PageDoesNotExist("Page {$page} does not exist");
98
        }
99
100
        $this->page = $page;
101
102
        return $this;
103
    }
104
105
    public function getNumberOfPages(): int
106
    {
107
        return $this->numberOfPages;
108
    }
109
110
    public function saveImage(string $pathToImage): bool
111
    {
112
        if (is_dir($pathToImage)) {
113
            $pathToImage = rtrim($pathToImage, '\/').DIRECTORY_SEPARATOR.$this->page.'.'.$this->outputFormat;
114
        }
115
116
        $imageData = $this->getImageData($pathToImage);
117
118
        return file_put_contents($pathToImage, $imageData) !== false;
119
    }
120
121
    public function saveAllPagesAsImages(string $directory, string $prefix = ''): array
122
    {
123
        $numberOfPages = $this->getNumberOfPages();
124
125
        if ($numberOfPages === 0) {
126
            return [];
127
        }
128
129
        return array_map(function ($pageNumber) use ($directory, $prefix) {
130
            $this->setPage($pageNumber);
131
132
            $destination = "{$directory}/{$prefix}{$pageNumber}.{$this->outputFormat}";
133
134
            $this->saveImage($destination);
135
136
            return $destination;
137
        }, range(1, $numberOfPages));
138
    }
139
140
    public function getImageData(string $pathToImage): Imagick
141
    {
142
        /*
143
         * Reinitialize imagick because the target resolution must be set
144
         * before reading the actual image.
145
         */
146
        $this->imagick = new Imagick();
147
148
        $this->imagick->setResolution($this->resolution, $this->resolution);
149
150
        if ($this->colorspace !== null) {
151
            $this->imagick->setColorspace($this->colorspace);
152
        }
153
154
        if ($this->compressionQuality !== null) {
155
            $this->imagick->setCompressionQuality($this->compressionQuality);
156
        }
157
158
        if (filter_var($this->pdfFile, FILTER_VALIDATE_URL)) {
159
            return $this->getRemoteImageData($pathToImage);
160
        }
161
162
        $this->imagick->readImage(sprintf('%s[%s]', $this->pdfFile, $this->page - 1));
163
164
        if (is_int($this->layerMethod)) {
165
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
166
        }
167
168
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
169
170
        return $this->imagick;
171
    }
172
173
    public function setColorspace(int $colorspace)
174
    {
175
        $this->colorspace = $colorspace;
176
177
        return $this;
178
    }
179
180
    public function setCompressionQuality(int $compressionQuality)
181
    {
182
        $this->compressionQuality = $compressionQuality;
183
184
        return $this;
185
    }
186
187
    protected function getRemoteImageData(string $pathToImage): Imagick
188
    {
189
        $this->imagick->readImage($this->pdfFile);
190
191
        $this->imagick->setIteratorIndex($this->page - 1);
192
193
        if (is_int($this->layerMethod)) {
194
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
195
        }
196
197
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
198
199
        return $this->imagick;
200
    }
201
202
    protected function determineOutputFormat(string $pathToImage): string
203
    {
204
        $outputFormat = pathinfo($pathToImage, PATHINFO_EXTENSION);
205
206
        if ($this->outputFormat != '') {
207
            $outputFormat = $this->outputFormat;
208
        }
209
210
        $outputFormat = strtolower($outputFormat);
211
212
        if (! $this->isValidOutputFormat($outputFormat)) {
213
            $outputFormat = 'jpg';
214
        }
215
216
        return $outputFormat;
217
    }
218
219
    private function fetchNumberPages(string $pdfFile)
220
    {
221
        $stream = fopen($pdfFile, 'r');
222
        $content = fread($stream, filesize($pdfFile));
223
224
        if (! $stream || ! $content) {
225
            throw new PdfDoesNotExist("File `{$pdfFile}` does not exist");
226
        }
227
228
        $count = 0;
0 ignored issues
show
Unused Code introduced by
$count is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
229
230
        $regex = "/\/Count\s+(\d+)/";
231
232
        if (preg_match_all($regex, $content, $matches)) {
233
            $count = max($matches);
234
235
            return $count[0];
236
        } else {
237
            throw new InvalidFormat('Cannot read page count from pdf');
238
        }
239
    }
240
}
241