Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
78.31% |
65 / 83 |
|
58.82% |
10 / 17 |
CRAP | |
0.00% |
0 / 1 |
StreamObject | |
78.31% |
65 / 83 |
|
58.82% |
10 / 17 |
67.58 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
parse | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
2 | |||
setDefinition | |
66.67% |
16 / 24 |
|
0.00% |
0 / 1 |
17.33 | |||
setStream | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
appendStream | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getDefinition | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStream | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
encode | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
5 | |||
decode | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
isEncoded | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getEncoding | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setPalette | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isPalette | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isXObject | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getByteLength | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
calculateByteLength | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__toString | |
100.00% |
22 / 22 |
|
100.00% |
1 / 1 |
12 |
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-2023 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\Build\PdfObject; |
15 | |
16 | /** |
17 | * Pdf stream object class |
18 | * |
19 | * @category Pop |
20 | * @package Pop\Pdf |
21 | * @author Nick Sagona, III <dev@nolainteractive.com> |
22 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
23 | * @license http://www.popphp.org/license New BSD License |
24 | * @version 4.2.0 |
25 | */ |
26 | class StreamObject extends AbstractObject |
27 | { |
28 | |
29 | /** |
30 | * PDF stream object index |
31 | * @var int |
32 | */ |
33 | protected $index = 5; |
34 | |
35 | /** |
36 | * PDF stream object definition |
37 | * @var string |
38 | */ |
39 | protected $definition = null; |
40 | |
41 | /** |
42 | * PDF stream object stream |
43 | * @var string |
44 | */ |
45 | protected $stream = null; |
46 | |
47 | /** |
48 | * Encoding filter |
49 | * @var boolean |
50 | */ |
51 | protected $encoding = null; |
52 | |
53 | /** |
54 | * Palette object flag |
55 | * @var boolean |
56 | */ |
57 | protected $isPalette = false; |
58 | |
59 | /** |
60 | * XObject object flag |
61 | * @var boolean |
62 | */ |
63 | protected $isXObject = false; |
64 | |
65 | /** |
66 | * Constructor |
67 | * |
68 | * Instantiate a PDF stream object. |
69 | * |
70 | * @param int $index |
71 | */ |
72 | public function __construct($index = 5) |
73 | { |
74 | $this->setIndex($index); |
75 | $this->setData("\n[{object_index}] 0 obj\n[{definition}]\n[{stream}]\nendobj\n\n"); |
76 | } |
77 | |
78 | /** |
79 | * Parse a stream object from a string |
80 | * |
81 | * @param string $stream |
82 | * @return StreamObject |
83 | */ |
84 | public static function parse($stream) |
85 | { |
86 | $object = new self(); |
87 | $object->setIndex(substr($stream, 0, strpos($stream, ' '))); |
88 | $stream = str_replace($object->getIndex() . ' 0 obj', '[{object_index}] 0 obj', $stream); |
89 | |
90 | // Determine the objects definition and stream, if applicable. |
91 | $s = substr($stream, (strpos($stream, ' obj') + 4)); |
92 | $s = substr($s, 0, strpos($s, 'endobj')); |
93 | if (strpos($s, 'stream') !== false) { |
94 | $def = substr($s, 0, strpos($s, 'stream')); |
95 | $str = substr($s, (strpos($s, 'stream') + 6)); |
96 | $str = substr($str, 0, strpos($str, 'endstream')); |
97 | $object->setDefinition($def); |
98 | $object->appendStream($str); |
99 | } else { |
100 | $object->setDefinition($s); |
101 | } |
102 | |
103 | $object->setData("\n[{object_index}] 0 obj\n[{definition}]\n[{stream}]\nendobj\n\n"); |
104 | return $object; |
105 | } |
106 | |
107 | /** |
108 | * Set the stream object definition |
109 | * |
110 | * @param string $definition |
111 | * @return StreamObject |
112 | */ |
113 | public function setDefinition($definition) |
114 | { |
115 | $this->definition = (string)$definition; |
116 | |
117 | if (strpos($this->definition, '/ASCIIHexDecode') !== false) { |
118 | $this->encoding = 'ASCIIHexDecode'; |
119 | } else if (strpos($this->definition, '/ASCII85Decode') !== false) { |
120 | $this->encoding = 'ASCII85Decode'; |
121 | } else if (strpos($this->definition, '/LZWDecode') !== false) { |
122 | $this->encoding = 'LZWDecode'; |
123 | } else if (strpos($this->definition, '/FlateDecode') !== false) { |
124 | $this->encoding = 'FlateDecode'; |
125 | } else if (strpos($this->definition, '/RunLengthDecode') !== false) { |
126 | $this->encoding = 'RunLengthDecode'; |
127 | } else if (strpos($this->definition, '/CCITTFaxDecode') !== false) { |
128 | $this->encoding = 'CCITTFaxDecode'; |
129 | } else if (strpos($this->definition, '/JBIG2Decode') !== false) { |
130 | $this->encoding = 'JBIG2Decode'; |
131 | } else if (strpos($this->definition, '/DCTDecode') !== false) { |
132 | $this->encoding = 'DCTDecode'; |
133 | } else if (strpos($this->definition, '/JPXDecode') !== false) { |
134 | $this->encoding = 'JPXDecode'; |
135 | } else if (strpos($this->definition, '/Crypt') !== false) { |
136 | $this->encoding = 'Crypt'; |
137 | } |
138 | |
139 | if (stripos($this->definition, '/xobject') !== false) { |
140 | $this->isXObject = true; |
141 | } |
142 | |
143 | return $this; |
144 | } |
145 | |
146 | /** |
147 | * Set the stream object stream |
148 | * |
149 | * @param string $stream |
150 | * @return StreamObject |
151 | */ |
152 | public function setStream($stream) |
153 | { |
154 | $this->stream = $stream; |
155 | return $this; |
156 | } |
157 | |
158 | /** |
159 | * Append to the stream the PDF stream object |
160 | * |
161 | * @param string $stream |
162 | * @return StreamObject |
163 | */ |
164 | public function appendStream($stream) |
165 | { |
166 | $this->stream .= $stream; |
167 | return $this; |
168 | } |
169 | |
170 | /** |
171 | * Get the stream object definition |
172 | * |
173 | * @return string |
174 | */ |
175 | public function getDefinition() |
176 | { |
177 | return $this->definition; |
178 | } |
179 | |
180 | /** |
181 | * Get the PDF stream object stream |
182 | * |
183 | * @return string |
184 | */ |
185 | public function getStream() |
186 | { |
187 | return $this->stream; |
188 | } |
189 | |
190 | /** |
191 | * Method to encode the PDF stream object with FlateDecode (gzcompress) |
192 | * |
193 | * @return void |
194 | */ |
195 | public function encode() |
196 | { |
197 | if (($this->stream != '') && (function_exists('gzcompress')) && |
198 | (strpos((string)$this->definition, ' /Image') === false) && (strpos((string)$this->definition, '/FlateDecode') === false)) { |
199 | $this->stream = "\n" . gzcompress($this->stream, 9) . "\n"; |
200 | $this->encoding = 'FlateDecode'; |
201 | } |
202 | } |
203 | |
204 | /** |
205 | * Method to decode the PDF stream contents with FlateDecode (gzuncompress) |
206 | * |
207 | * @return boolean|string |
208 | */ |
209 | public function decode() |
210 | { |
211 | $decoded = false; |
212 | if (($this->stream != '') && function_exists('gzuncompress')) { |
213 | $decoded = @gzuncompress(trim($this->stream)); |
214 | } |
215 | return $decoded; |
216 | } |
217 | |
218 | /** |
219 | * Determine whether or not the PDF stream object is encoded |
220 | * |
221 | * @return boolean |
222 | */ |
223 | public function isEncoded() |
224 | { |
225 | return (null !== $this->encoding); |
226 | } |
227 | |
228 | /** |
229 | * Get the encoding filter |
230 | * |
231 | * @return string |
232 | */ |
233 | public function getEncoding() |
234 | { |
235 | return $this->encoding; |
236 | } |
237 | |
238 | /** |
239 | * Set whether the PDF stream object is a palette object |
240 | * |
241 | * @param boolean $isPalette |
242 | * @return void |
243 | */ |
244 | public function setPalette($isPalette) |
245 | { |
246 | $this->isPalette = (bool)$isPalette; |
247 | } |
248 | |
249 | /** |
250 | * Get whether the PDF stream object is a palette object |
251 | * |
252 | * @return boolean |
253 | */ |
254 | public function isPalette() |
255 | { |
256 | return $this->isPalette; |
257 | } |
258 | |
259 | /** |
260 | * Get whether the PDF stream object is an XObject |
261 | * |
262 | * @return boolean |
263 | */ |
264 | public function isXObject() |
265 | { |
266 | return $this->isXObject; |
267 | } |
268 | |
269 | /** |
270 | * Get the PDF stream object byte length |
271 | * |
272 | * @return int |
273 | */ |
274 | public function getByteLength() |
275 | { |
276 | return $this->calculateByteLength($this); |
277 | } |
278 | |
279 | /** |
280 | * Calculate the byte length of a string |
281 | * |
282 | * @param string $string |
283 | * @return int |
284 | */ |
285 | protected function calculateByteLength($string) |
286 | { |
287 | return strlen((string)$string); |
288 | } |
289 | |
290 | /** |
291 | * Method to print the PDF stream object. |
292 | * |
293 | * @return string |
294 | */ |
295 | public function __toString() |
296 | { |
297 | // Set the stream. |
298 | $stream = (null !== $this->stream) ? "stream" . $this->stream . "endstream\n" : ''; |
299 | |
300 | // Set up the Length definition. |
301 | if ((strpos((string)$this->definition, '/Length ') !== false) && (strpos((string)$this->definition, '/Length1') === false) && |
302 | (strpos((string)$this->definition, '/Image') === false)) { |
303 | $matches = []; |
304 | preg_match('/\/Length\s\d*/', $this->definition, $matches); |
305 | if (isset($matches[0])) { |
306 | $len = $matches[0]; |
307 | $len = str_replace('/Length', '', $len); |
308 | $len = str_replace(' ', '', $len); |
309 | $this->definition = str_replace($len, '[{byte_length}]', $this->definition); |
310 | } |
311 | } else if (strpos((string)$this->definition, '/Length') === false) { |
312 | $this->definition .= "<</Length [{byte_length}]>>\n"; |
313 | } |
314 | |
315 | // Calculate the byte length of the stream and swap out the placeholders. |
316 | $byteLength = (($this->encoding == 'FlateDecode') && (function_exists('gzcompress')) && |
317 | (strpos((string)$this->definition, ' /Image') === false) && (strpos((string)$this->definition, '/FlateDecode') === false)) ? |
318 | $this->calculateByteLength($this->stream) . " /Filter /FlateDecode" : $this->calculateByteLength($this->stream); |
319 | |
320 | $data = str_replace( |
321 | ['[{object_index}]', '[{stream}]', '[{definition}]', '[{byte_length}]'], |
322 | [$this->index, $stream, $this->definition, $byteLength], |
323 | $this->data |
324 | ); |
325 | |
326 | // Clear Length definition if it is zero. |
327 | if (strpos((string)$data, '<</Length 0>>') !== false) { |
328 | $data = str_replace('<</Length 0>>', '', $data); |
329 | } |
330 | |
331 | return $data; |
332 | } |
333 | |
334 | } |