Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
InfoObject
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
5 / 5
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 parse
100.00% covered (success)
100.00%
61 / 61
100.00% covered (success)
100.00%
1 / 1
8
 setMetadata
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getMetadata
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 __toString
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
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\Build\PdfObject;
16
17use Pop\Pdf\Document\Metadata;
18
19/**
20 * Pdf info object class
21 *
22 * @category   Pop
23 * @package    Pop\Pdf
24 * @author     Nick Sagona, III <nick@popphp.org>
25 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
26 * @license    https://www.popphp.org/license     New BSD License
27 * @version    6.0.0
28 */
29class InfoObject extends AbstractObject
30{
31
32    /**
33     * PDF info object index
34     * @var ?int
35     */
36    protected ?int $index = 3;
37
38    /**
39     * PDF metadata for the info object
40     * @var ?Metadata
41     */
42    protected ?Metadata $metadata = null;
43
44    /**
45     * Constructor
46     *
47     * Instantiate a PDF info object.
48     *
49     * @param  int       $index
50     * @param  ?Metadata $metadata
51     */
52    public function __construct(int $index = 3, ?Metadata $metadata = null)
53    {
54        $this->setIndex($index);
55        $this->setData("[{info_index}] 0 obj\n<</Creator([{creator}])/CreationDate([{creation_date}])/ModDate" .
56            "([{mod_date}])/Author([{author}])/Title([{title}])/Subject([{subject}])/Producer([{producer}])>>\nendobj\n");
57
58        if ($metadata !== null) {
59            $this->setMetadata($metadata);
60        }
61    }
62
63    /**
64     * Parse a info object from a string
65     *
66     * @param  string $stream
67     * @return InfoObject
68     */
69    public static function parse(string $stream): InfoObject
70    {
71        $info = new self();
72        $info->setIndex((int)substr($stream, 0, strpos($stream, ' ')));
73        $stream = str_replace($info->getIndex() . ' 0 obj', '[{info_index}] 0 obj', $stream);
74
75        // Determine the Creator
76        if (str_contains($stream, '/Creator')) {
77            $creator = substr($stream, strpos($stream, '/Creator'));
78            $creator = substr($creator, strpos($creator, '('));
79            $creator = substr($creator, 0, strpos($creator, ')'));
80            $creator =  str_replace('(', '', $creator);
81            $stream =  str_replace('Creator(' . $creator . ')', 'Creator([{creator}])', $stream);
82            $info->getMetadata()->setCreator($creator);
83        } else {
84            $stream =  str_replace('>>', '/Creator([{creator}])>>', $stream);
85        }
86
87        // Determine the CreationDate
88        if (str_contains($stream, '/CreationDate')) {
89            $creationDate = substr($stream, strpos($stream, '/CreationDate'));
90            $creationDate = substr($creationDate, strpos($creationDate, '('));
91            $creationDate = substr($creationDate, 0, strpos($creationDate, ')'));
92            $creationDate =  str_replace('(', '', $creationDate);
93            $stream =  str_replace('CreationDate(' . $creationDate . ')', 'CreationDate([{creation_date}])', $stream);
94            $info->getMetadata()->setCreationDate($creationDate);
95        } else {
96            $stream =  str_replace('>>', '/CreationDate([{creation_date}])>>', $stream);
97        }
98
99        // Determine the ModDate
100        if (str_contains($stream, '/ModDate')) {
101            $modDate = substr($stream, strpos($stream, '/ModDate'));
102            $modDate = substr($modDate, strpos($modDate, '('));
103            $modDate = substr($modDate, 0, strpos($modDate, ')'));
104            $modDate =  str_replace('(', '', $modDate);
105            $stream =  str_replace('ModDate(' . $modDate . ')', 'ModDate([{mod_date}])', $stream);
106            $info->getMetadata()->setModDate($modDate);
107        } else {
108            $stream =  str_replace('>>', '/ModDate([{mod_date}])>>', $stream);
109        }
110
111        // Determine the Author
112        if (str_contains($stream, '/Author')) {
113            $author = substr($stream, strpos($stream, '/Author'));
114            $author = substr($author, strpos($author, '('));
115            $author = substr($author, 0, strpos($author, ')'));
116            $author =  str_replace('(', '', $author);
117            $stream =  str_replace('Author(' . $author . ')', 'Author([{author}])', $stream);
118            $info->getMetadata()->setAuthor($author);
119        } else {
120            $stream =  str_replace('>>', '/Author([{author}])>>', $stream);
121        }
122
123        // Determine the Title
124        if (str_contains($stream, '/Title')) {
125            $title = substr($stream, strpos($stream, '/Title'));
126            $title = substr($title, strpos($title, '('));
127            $title = substr($title, 0, strpos($title, ')'));
128            $title =  str_replace('(', '', $title);
129            $stream =  str_replace('Title(' . $title . ')', 'Title([{title}])', $stream);
130            $info->getMetadata()->setTitle($title);
131        } else {
132            $stream =  str_replace('>>', '/Title([{title}])>>', $stream);
133        }
134
135        // Determine the Subject
136        if (str_contains($stream, '/Subject')) {
137            $subject = substr($stream, strpos($stream, '/Subject'));
138            $subject = substr($subject, strpos($subject, '('));
139            $subject = substr($subject, 0, strpos($subject, ')'));
140            $subject =  str_replace('(', '', $subject);
141            $stream =  str_replace('Subject(' . $subject . ')', 'Subject([{subject}])', $stream);
142            $info->getMetadata()->setSubject($subject);
143        } else {
144            $stream =  str_replace('>>', '/Subject([{subject}])>>', $stream);
145        }
146
147        // Determine the Producer
148        if (str_contains($stream, '/Producer')) {
149            $producer = substr($stream, strpos($stream, '/Producer'));
150            $producer = substr($producer, strpos($producer, '('));
151            $producer = substr($producer, 0, strpos($producer, ')'));
152            $producer =  str_replace('(', '', $producer);
153            $stream =  str_replace('Producer(' . $producer . ')', 'Producer([{producer}])', $stream);
154            $info->getMetadata()->setProducer($producer);
155        } else {
156            $stream =  str_replace('>>', '/Producer([{producer}])>>', $stream);
157        }
158
159        $info->setData($stream);
160        return $info;
161    }
162
163    /**
164     * Set the info object metadata
165     *
166     * @param  Metadata $metadata
167     * @return InfoObject
168     */
169    public function setMetadata(Metadata $metadata): InfoObject
170    {
171        $this->metadata = $metadata;
172        return $this;
173    }
174
175    /**
176     * Get the info object metadata
177     *
178     * @return ?Metadata
179     */
180    public function getMetadata(): ?Metadata
181    {
182        if ($this->metadata === null) {
183            $this->metadata = new Metadata();
184        }
185        return $this->metadata;
186    }
187
188    /**
189     * Method to print the PDF info object.
190     *
191     * @return string
192     */
193    public function __toString(): string
194    {
195        if ($this->metadata === null) {
196            $this->metadata = new \Pop\Pdf\Document\Metadata();
197        }
198
199        // Set the CreationDate and the ModDate if they are null.
200        if ($this->metadata->getCreationDate() === null) {
201            $this->metadata->setCreationDate(date('D, M j, Y h:i A'));
202        }
203        if ($this->metadata->getModDate() === null) {
204            $this->metadata->setModDate(date('D, M j, Y h:i A'));
205        }
206
207        return str_replace(
208            [
209                '[{info_index}]', '[{title}]', '[{subject}]', '[{author}]',
210                '[{creator}]', '[{producer}]', '[{mod_date}]', '[{creation_date}]'
211            ],
212            [
213                (string)$this->index, (string)$this->metadata->getTitle(), (string)$this->metadata->getSubject(), (string)$this->metadata->getAuthor(),
214                (string)$this->metadata->getCreator(), (string)$this->metadata->getProducer(), (string)$this->metadata->getModDate(), (string)$this->metadata->getCreationDate()
215            ],
216            $this->data
217        );
218    }
219
220}