Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
98.65% |
73 / 74 |
|
94.44% |
17 / 18 |
CRAP | |
0.00% |
0 / 1 |
Document | |
98.65% |
73 / 74 |
|
94.44% |
17 / 18 |
40 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
addPage | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
addPages | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
createPage | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
copyPage | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
orderPages | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
5 | |||
deletePage | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
addFont | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
embedFont | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
5.03 | |||
setCurrentPage | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setCurrentFont | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
importObjects | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
importFonts | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
hasImportedObjects | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasImportedFonts | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImportObjects | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImportedFonts | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__toString | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Pdf; |
15 | |
16 | use Pop\Pdf\Document\AbstractDocument; |
17 | use Pop\Pdf\Document\Page; |
18 | use Pop\Pdf\Document\Font; |
19 | use Pop\Pdf\Document\Metadata; |
20 | use Pop\Pdf\Document\Exception; |
21 | |
22 | /** |
23 | * Pdf document class |
24 | * |
25 | * @category Pop |
26 | * @package Pop\Pdf |
27 | * @author Nick Sagona, III <dev@nolainteractive.com> |
28 | * @copyright Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
29 | * @license http://www.popphp.org/license New BSD License |
30 | * @version 5.0.0 |
31 | */ |
32 | class Document extends AbstractDocument |
33 | { |
34 | |
35 | /** |
36 | * Imported objects |
37 | * @var array |
38 | */ |
39 | protected array $importedObjects = []; |
40 | |
41 | /** |
42 | * Imported fonts |
43 | * @var array |
44 | */ |
45 | protected array $importedFonts = []; |
46 | |
47 | /** |
48 | * Constructor |
49 | * |
50 | * Instantiate a PDF document |
51 | * |
52 | * @param ?Page $page |
53 | * @param ?Metadata $metadata |
54 | */ |
55 | public function __construct(?Page $page = null, ?Metadata $metadata = null) |
56 | { |
57 | if ($page !== null) { |
58 | $this->addPage($page); |
59 | } |
60 | $metadata = ($metadata !== null) ? $metadata : new Metadata(); |
61 | $this->setMetadata($metadata); |
62 | } |
63 | |
64 | /** |
65 | * Add a page to the PDF document |
66 | * |
67 | * @param Page $page |
68 | * @return Document |
69 | */ |
70 | public function addPage(Page $page): Document |
71 | { |
72 | $this->pages[] = $page; |
73 | $this->currentPage = count($this->pages); |
74 | return $this; |
75 | } |
76 | |
77 | /** |
78 | * Add pages to the PDF document |
79 | * |
80 | * @param array $pages |
81 | * @return Document |
82 | */ |
83 | public function addPages(array $pages): Document |
84 | { |
85 | foreach ($pages as $page) { |
86 | $this->addPage($page); |
87 | } |
88 | return $this; |
89 | } |
90 | |
91 | /** |
92 | * Create and return a new page object, adding it to the PDF document |
93 | * |
94 | * @param mixed $size |
95 | * @param ?int $height |
96 | * @throws Exception |
97 | * @return Page |
98 | */ |
99 | public function createPage(mixed $size, ?int $height = null): Page |
100 | { |
101 | $page = new Page($size, $height); |
102 | $this->addPage($page); |
103 | return $page; |
104 | } |
105 | |
106 | /** |
107 | * Copy and return a page of the PDF, adding it to the PDF document |
108 | * |
109 | * @param int $p |
110 | * @param bool $preserveContent |
111 | * @throws Exception |
112 | * @return Page |
113 | */ |
114 | public function copyPage(int $p, bool $preserveContent = true): Page |
115 | { |
116 | if (!isset($this->pages[$p - 1])) { |
117 | throw new Exception("Error: That page (" . $p . ") does not exist."); |
118 | } |
119 | |
120 | $page = clone $this->pages[$p - 1]; |
121 | |
122 | if (!$preserveContent) { |
123 | $page->clearContent(); |
124 | } |
125 | |
126 | $this->addPage($page); |
127 | return $page; |
128 | } |
129 | |
130 | /** |
131 | * Order the pages |
132 | * |
133 | * @param array $pages |
134 | * @throws Exception |
135 | * @return Document |
136 | */ |
137 | public function orderPages(array $pages): Document |
138 | { |
139 | $newOrder = []; |
140 | |
141 | // Check if the numbers of pages passed equals the number of pages in the PDF. |
142 | if (count($pages) != count($this->pages)) { |
143 | throw new Exception('Error: The pages array passed does not contain the same number of pages as the PDF.'); |
144 | } |
145 | |
146 | // Make sure each page passed is within the PDF and not out of range. |
147 | foreach ($pages as $value) { |
148 | if (!array_key_exists(($value - 1), $this->pages)) { |
149 | throw new Exception('Error: The pages array passed contains a page that does not exist.'); |
150 | } |
151 | } |
152 | |
153 | // Set the new order of the page objects. |
154 | foreach ($pages as $value) { |
155 | $newOrder[] = $this->pages[$value - 1]; |
156 | } |
157 | |
158 | // Set the pages arrays to the new order. |
159 | $this->pages = $newOrder; |
160 | return $this; |
161 | } |
162 | |
163 | /** |
164 | * Delete a page from the PDF document |
165 | * |
166 | * @param int $p |
167 | * @throws Exception |
168 | * @return Document |
169 | */ |
170 | public function deletePage(int $p): Document |
171 | { |
172 | if (!isset($this->pages[$p - 1])) { |
173 | throw new Exception("Error: That page (" . $p . ") does not exist."); |
174 | } |
175 | |
176 | unset($this->pages[$p - 1]); |
177 | |
178 | // Reset current page if current page was the one deleted |
179 | if ($this->currentPage == $p) { |
180 | $this->currentPage = (count($this->pages) > 0) ? (count($this->pages) - 1) : null; |
181 | } |
182 | |
183 | return $this; |
184 | } |
185 | |
186 | /** |
187 | * Add a font |
188 | * |
189 | * @param Font|string $font |
190 | * @param bool $embedOverride |
191 | * @throws Exception |
192 | * @return Document |
193 | */ |
194 | public function addFont(Font|string $font, bool $embedOverride = false): Document |
195 | { |
196 | if (is_string($font)) { |
197 | $font = new Font($font); |
198 | } |
199 | if (!$font->isStandard()) { |
200 | $this->embedFont($font, $embedOverride); |
201 | } else { |
202 | if (!array_key_exists($font->getName(), $this->fonts)) { |
203 | $this->fonts[$font->getName()] = $font; |
204 | $this->currentFont = $font->getName(); |
205 | } |
206 | } |
207 | |
208 | return $this; |
209 | } |
210 | |
211 | /** |
212 | * Add a font |
213 | * |
214 | * @param Font $font |
215 | * @param bool $embedOverride |
216 | * @throws Exception |
217 | * @return Document |
218 | */ |
219 | public function embedFont(Font $font, bool $embedOverride = false): Document |
220 | { |
221 | if (!$font->isEmbedded()) { |
222 | $this->addFont($font); |
223 | } else { |
224 | if (!$font->parser()->isEmbeddable() && !$embedOverride) { |
225 | throw new Exception('Error: The font license does not allow for it to be embedded.'); |
226 | } |
227 | |
228 | if (!array_key_exists($font->parser()->getFontName(), $this->fonts)) { |
229 | $font->parser()->setCompression($this->compression); |
230 | $this->fonts[$font->parser()->getFontName()] = $font; |
231 | $this->currentFont = $font->parser()->getFontName(); |
232 | } |
233 | } |
234 | |
235 | return $this; |
236 | } |
237 | |
238 | /** |
239 | * Set the current page of the PDF document |
240 | * |
241 | * @param int $p |
242 | * @throws Exception |
243 | * @return Document |
244 | */ |
245 | public function setCurrentPage(int $p): Document |
246 | { |
247 | // Check if the page exists. |
248 | if (!isset($this->pages[$p - 1])) { |
249 | throw new Exception("Error: That page (" . $p . ") does not exist."); |
250 | } |
251 | $this->currentPage = $p; |
252 | |
253 | return $this; |
254 | } |
255 | |
256 | /** |
257 | * Set the current font of the PDF document |
258 | * |
259 | * @param string $name |
260 | * @throws Exception |
261 | * @return Document |
262 | */ |
263 | public function setCurrentFont(string $name): Document |
264 | { |
265 | // Check if the font exists. |
266 | if (!isset($this->fonts[$name])) { |
267 | throw new Exception("Error: The font '" . $name . "' has not been added to the PDF document."); |
268 | } |
269 | $this->currentFont = $name; |
270 | |
271 | return $this; |
272 | } |
273 | |
274 | /** |
275 | * Import objects into document |
276 | * |
277 | * @param array $objects |
278 | * @return Document |
279 | */ |
280 | public function importObjects(array $objects): Document |
281 | { |
282 | $this->importedObjects = $objects; |
283 | return $this; |
284 | } |
285 | |
286 | /** |
287 | * Import fonts into document |
288 | * |
289 | * @param array $fonts |
290 | * @return Document |
291 | */ |
292 | public function importFonts(array $fonts): Document |
293 | { |
294 | foreach ($fonts as $font) { |
295 | $this->fonts[$font['name']] = $font; |
296 | } |
297 | $this->importedFonts = $fonts; |
298 | return $this; |
299 | } |
300 | |
301 | /** |
302 | * Determine if the document has imported objects |
303 | * |
304 | * @return bool |
305 | */ |
306 | public function hasImportedObjects(): bool |
307 | { |
308 | return (count($this->importedObjects) > 0); |
309 | } |
310 | |
311 | /** |
312 | * Determine if the document has imported fonts |
313 | * |
314 | * @return bool |
315 | */ |
316 | public function hasImportedFonts(): bool |
317 | { |
318 | return (count($this->importedFonts) > 0); |
319 | } |
320 | |
321 | /** |
322 | * Get the imported objects |
323 | * |
324 | * @return array |
325 | */ |
326 | public function getImportObjects(): array |
327 | { |
328 | return $this->importedObjects; |
329 | } |
330 | |
331 | /** |
332 | * Get the import fonts |
333 | * |
334 | * @return array |
335 | */ |
336 | public function getImportedFonts(): array |
337 | { |
338 | return $this->importedFonts; |
339 | } |
340 | |
341 | /** |
342 | * Output the PDF document to string |
343 | * |
344 | * @return string |
345 | */ |
346 | public function __toString(): string |
347 | { |
348 | $compiler = new Build\Compiler(); |
349 | $compiler->finalize($this); |
350 | return $compiler->getOutput(); |
351 | } |
352 | |
353 | } |