Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
31 / 31
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractDocument
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
31 / 31
36
100.00% covered (success)
100.00%
1 / 1
 setVersion
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setMetadata
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setOrigin
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getVersion
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOrigin
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMetadata
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPage
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasPages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFonts
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFont
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasFonts
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAvailableFonts
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isFontAvailable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasFont
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStyles
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStyle
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 hasStyles
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAvailableStyles
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isStyleAvailable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasStyle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentPage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNumberOfPages
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentFont
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNumberOfFonts
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getForms
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getForm
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 hasForms
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addForm
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setCompression
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isCompressed
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __construct
n/a
0 / 0
n/a
0 / 0
0
 addPage
n/a
0 / 0
n/a
0 / 0
0
 addPages
n/a
0 / 0
n/a
0 / 0
0
 createPage
n/a
0 / 0
n/a
0 / 0
0
 copyPage
n/a
0 / 0
n/a
0 / 0
0
 orderPages
n/a
0 / 0
n/a
0 / 0
0
 deletePage
n/a
0 / 0
n/a
0 / 0
0
 addFont
n/a
0 / 0
n/a
0 / 0
0
 addFonts
n/a
0 / 0
n/a
0 / 0
0
 embedFont
n/a
0 / 0
n/a
0 / 0
0
 embedFonts
n/a
0 / 0
n/a
0 / 0
0
 createStyle
n/a
0 / 0
n/a
0 / 0
0
 addStyle
n/a
0 / 0
n/a
0 / 0
0
 addStyles
n/a
0 / 0
n/a
0 / 0
0
 setCurrentPage
n/a
0 / 0
n/a
0 / 0
0
 setCurrentFont
n/a
0 / 0
n/a
0 / 0
0
 __toString
n/a
0 / 0
n/a
0 / 0
0
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Pdf\Document;
16
17/**
18 * Abstract Pdf document class
19 *
20 * @category   Pop
21 * @package    Pop\Pdf
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    6.0.0
26 */
27abstract class AbstractDocument implements DocumentInterface
28{
29
30    /**
31     * Document origin constants
32     */
33    const ORIGIN_TOP_LEFT     = 'ORIGIN_TOP_LEFT';
34    const ORIGIN_TOP_RIGHT    = 'ORIGIN_TOP_RIGHT';
35    const ORIGIN_BOTTOM_LEFT  = 'ORIGIN_BOTTOM_LEFT';
36    const ORIGIN_BOTTOM_RIGHT = 'ORIGIN_BOTTOM_RIGHT';
37    const ORIGIN_CENTER       = 'ORIGIN_CENTER';
38
39    /**
40     * PDF version
41     * @var float
42     */
43    protected float $version = 1.7;
44
45    /**
46     * PDF metadata for the info object
47     * @var ?Metadata
48     */
49    protected ?Metadata $metadata = null;
50
51    /**
52     * Pages array
53     * @var array
54     */
55    protected array $pages = [];
56
57    /**
58     * Fonts array
59     * @var array
60     */
61    protected array $fonts = [];
62
63    /**
64     * Styles array
65     * @var array
66     */
67    protected array $styles = [];
68
69    /**
70     * Forms array
71     * @var array
72     */
73    protected array $forms = [];
74
75    /**
76     * Current page
77     * @var ?int
78     */
79    protected ?int $currentPage = null;
80
81    /**
82     * Current font
83     * @var ?string
84     */
85    protected ?string $currentFont = null;
86
87    /**
88     * Compression property
89     * @var bool
90     */
91    protected bool$compression = false;
92
93    /**
94     * Document origin
95     * @var string
96     */
97    protected string $origin = 'ORIGIN_BOTTOM_LEFT';
98
99    /**
100     * Set the document version
101     *
102     * @param  float $version
103     * @return AbstractDocument
104     */
105    public function setVersion(float $version): AbstractDocument
106    {
107        $this->version = $version;
108        return $this;
109    }
110
111    /**
112     * Set the document metadata
113     *
114     * @param  Metadata $metadata
115     * @return AbstractDocument
116     */
117    public function setMetadata(Metadata $metadata): AbstractDocument
118    {
119        $this->metadata = $metadata;
120        return $this;
121    }
122
123    /**
124     * Set the document origin
125     *
126     * @param  string $origin
127     * @return AbstractDocument
128     */
129    public function setOrigin(string $origin): AbstractDocument
130    {
131        if (defined('Pop\Pdf\Document\AbstractDocument::' . $origin)) {
132            $this->origin = $origin;
133        }
134        return $this;
135    }
136
137    /**
138     * Get the document version
139     *
140     * @return float
141     */
142    public function getVersion(): float
143    {
144        return $this->version;
145    }
146
147    /**
148     * Get the document origin
149     *
150     * @return string
151     */
152    public function getOrigin(): string
153    {
154        return $this->origin;
155    }
156
157    /**
158     * Get the document metadata
159     *
160     * @return ?Metadata
161     */
162    public function getMetadata(): ?Metadata
163    {
164        return $this->metadata;
165    }
166
167    /**
168     * Get the PDF page objects array
169     *
170     * @return array
171     */
172    public function getPages(): array
173    {
174        return $this->pages;
175    }
176
177    /**
178     * Get a PDF page object
179     *
180     * @param  int $p
181     * @throws \Pop\Pdf\Exception
182     * @return Page
183     */
184    public function getPage(int $p): Page
185    {
186        if (!isset($this->pages[$p - 1])) {
187            throw new \Pop\Pdf\Exception('Error: That page (' . $p . ') does not exist.');
188        }
189        return $this->pages[$p - 1];
190    }
191
192    /**
193     * Determine if the document has page objects
194     *
195     * @return bool
196     */
197    public function hasPages(): bool
198    {
199        return (count($this->pages) > 0);
200    }
201
202    /**
203     * Get the PDF font objects array
204     *
205     * @return array
206     */
207    public function getFonts(): array
208    {
209        return $this->fonts;
210    }
211
212    /**
213     * Get a PDF font object
214     *
215     * @param  string $name
216     * @throws \Pop\Pdf\Exception
217     * @return Font
218     */
219    public function getFont(string $name): Font
220    {
221        if (!isset($this->fonts[$name])) {
222            throw new \Pop\Pdf\Exception("Error: The font '" . $name . "' has not been added to the PDF document.");
223        }
224        return $this->fonts[$name];
225    }
226
227    /**
228     * Determine if the document has font objects
229     *
230     * @return bool
231     */
232    public function hasFonts(): bool
233    {
234        return (count($this->fonts) > 0);
235    }
236
237    /**
238     * Get available fonts that have been added to the PDF document
239     *
240     * @return array
241     */
242    public function getAvailableFonts(): array
243    {
244        return array_keys($this->fonts);
245    }
246
247    /**
248     * Determine if a font has been added to the PDF document
249     *
250     * @param  string $font
251     * @return bool
252     */
253    public function isFontAvailable(string $font): bool
254    {
255        return array_key_exists($font, $this->fonts);
256    }
257
258    /**
259     * Determine if a font has been added to the PDF document (alias)
260     *
261     * @param  string $font
262     * @return bool
263     */
264    public function hasFont(string $font): bool
265    {
266        return array_key_exists($font, $this->fonts);
267    }
268
269    /**
270     * Get the PDF style objects array
271     *
272     * @return array
273     */
274    public function getStyles(): array
275    {
276        return $this->styles;
277    }
278
279    /**
280     * Get a PDF style object
281     *
282     * @param  string $name
283     * @throws \Pop\Pdf\Exception
284     * @return Style
285     */
286    public function getStyle(string $name): Style
287    {
288        if (!isset($this->styles[$name])) {
289            throw new \Pop\Pdf\Exception("Error: The style '" . $name . "' has not been added to the PDF document.");
290        }
291        return $this->styles[$name];
292    }
293
294    /**
295     * Determine if the document has style objects
296     *
297     * @return bool
298     */
299    public function hasStyles(): bool
300    {
301        return (count($this->styles) > 0);
302    }
303
304    /**
305     * Get available styles that have been added to the PDF document
306     *
307     * @return array
308     */
309    public function getAvailableStyles(): array
310    {
311        return array_keys($this->styles);
312    }
313
314    /**
315     * Determine if a style has been added to the PDF document
316     *
317     * @param  string $style
318     * @return bool
319     */
320    public function isStyleAvailable(string $style): bool
321    {
322        return array_key_exists($style, $this->styles);
323    }
324
325    /**
326     * Determine if a style has been added to the PDF document (alias)
327     *
328     * @param  string $style
329     * @return bool
330     */
331    public function hasStyle(string $style): bool
332    {
333        return array_key_exists($style, $this->styles);
334    }
335
336    /**
337     * Get the current page number
338     *
339     * @return ?int
340     */
341    public function getCurrentPage(): ?int
342    {
343        return $this->currentPage;
344    }
345
346    /**
347     * Get the current number of pages
348     *
349     * @return int
350     */
351    public function getNumberOfPages(): int
352    {
353        return count($this->pages);
354    }
355
356    /**
357     * Get the current font
358     *
359     * @return ?string
360     */
361    public function getCurrentFont(): ?string
362    {
363        return $this->currentFont;
364    }
365
366    /**
367     * Get the current number of fonts
368     *
369     * @return int
370     */
371    public function getNumberOfFonts(): int
372    {
373        return count($this->fonts);
374    }
375
376    /**
377     * Get form objects
378     *
379     * @return array
380     */
381    public function getForms(): array
382    {
383        return $this->forms;
384    }
385
386    /**
387     * Get form objects
388     *
389     * @param  string $name
390     * @return ?Form
391     */
392    public function getForm(string $name): ?Form
393    {
394        return (isset($this->forms[$name])) ? $this->forms[$name] : null;
395    }
396
397    /**
398     * Determine if the document has form objects
399     *
400     * @return bool
401     */
402    public function hasForms(): bool
403    {
404        return (count($this->forms) > 0);
405    }
406
407    /**
408     * Add form
409     *
410     * @param  Form $form
411     * @return AbstractDocument
412     */
413    public function addForm(Form $form): AbstractDocument
414    {
415        $this->forms[$form->getName()] = $form;
416        return $this;
417    }
418
419    /**
420     * Set the compression
421     *
422     * @param  bool $compression
423     * @return AbstractDocument
424     */
425    public function setCompression(bool $compression): AbstractDocument
426    {
427        $this->compression = $compression;
428        return $this;
429    }
430
431    /**
432     * Determine whether the PDF is compressed or not
433     *
434     * @return bool
435     */
436    public function isCompressed(): bool
437    {
438        return $this->compression;
439    }
440
441    /**
442     * Constructor
443     *
444     * Instantiate a PDF document
445     *
446     * @param  ?Page     $page
447     * @param  ?Metadata $metadata
448     * @return AbstractDocument
449     */
450    abstract public function __construct(?Page $page = null, ?Metadata $metadata = null);
451
452    /**
453     * Add a page to the PDF document
454     *
455     * @param  Page $page
456     * @return AbstractDocument
457     */
458    abstract public function addPage(Page $page): AbstractDocument;
459
460    /**
461     * Add pages to the PDF document
462     *
463     * @param  array $pages
464     * @return AbstractDocument
465     */
466    abstract public function addPages(array $pages): AbstractDocument;
467
468    /**
469     * Create and return a new page object, adding it to the PDF document
470     *
471     * @param  mixed $size
472     * @param  mixed $height
473     * @return Page
474     */
475    abstract public function createPage(mixed $size, mixed $height = null): Page;
476
477    /**
478     * Copy and return a page of the PDF, adding it to the PDF document
479     *
480     * @param  int $p
481     * @throws Exception
482     * @return Page
483     */
484    abstract public function copyPage(int $p): Page;
485
486    /**
487     * Order the pages
488     *
489     * @param  array $pages
490     * @throws Exception
491     * @return AbstractDocument
492     */
493    abstract public function orderPages(array $pages): AbstractDocument;
494
495    /**
496     * Delete a page from the PDF document
497     *
498     * @param  int $p
499     * @throws Exception
500     * @return AbstractDocument
501     */
502    abstract public function deletePage(int $p): AbstractDocument;
503
504    /**
505     * Add a font
506     *
507     * @param  Font $font
508     * @throws Exception
509     * @return AbstractDocument
510     */
511    abstract public function addFont(Font $font): AbstractDocument;
512
513    /**
514     * Add fonts
515     *
516     * @param  array $fonts
517     * @throws Exception
518     * @return AbstractDocument
519     */
520    abstract public function addFonts(array $fonts): AbstractDocument;
521
522    /**
523     * Embed a font
524     *
525     * @param  Font $font
526     * @param  bool $embedOverride
527     * @throws Exception
528     * @return AbstractDocument
529     */
530    abstract public function embedFont(Font $font, bool $embedOverride = false): AbstractDocument;
531
532    /**
533     * Embed fonts
534     *
535     * @param  array $fonts
536     * @param  bool $embedOverride
537     * @throws Exception
538     * @return AbstractDocument
539     */
540    abstract public function embedFonts(array $fonts, bool $embedOverride = false): AbstractDocument;
541
542    /**
543     * Create style
544     *
545     * @param  Style|string $style
546     * @return AbstractDocument
547     */
548    abstract public function createStyle(Style|string $style, ?string $font = null, int|float|null $size = null): AbstractDocument;
549
550    /**
551     * Add a style
552     *
553     * @param  Style|string $style
554     * @return AbstractDocument
555     */
556    abstract public function addStyle(Style|string $style): AbstractDocument;
557
558    /**
559     * Add styles
560     *
561     * @param  array $styles
562     * @return AbstractDocument
563     */
564    abstract public function addStyles(array $styles): AbstractDocument;
565
566    /**
567     * Set the current page of the PDF document
568     *
569     * @param  int $p
570     * @throws Exception
571     * @return AbstractDocument
572     */
573    abstract public function setCurrentPage(int $p): AbstractDocument;
574
575    /**
576     * Set the current font of the PDF document
577     *
578     * @param  string $name
579     * @throws Exception
580     * @return AbstractDocument
581     */
582    abstract public function setCurrentFont(string $name): AbstractDocument;
583
584    /**
585     * Output the PDF document to string
586     *
587     * @return string
588     */
589    abstract public function __toString(): string;
590
591}