Test Failed
Pull Request — master (#510)
by Jeremy
04:34 queued 02:12
created

Header::init()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 3
c 0
b 0
f 0
nc 3
nop 0
dl 0
loc 5
rs 10
ccs 4
cts 4
cp 1
crap 3
1
<?php
2
3
/**
4
 * @file
5
 *          This file is part of the PdfParser library.
6
 *
7
 * @author  Sébastien MALOT <[email protected]>
8
 * @date    2017-01-03
9
 *
10
 * @license LGPLv3
11
 * @url     <https://github.com/smalot/pdfparser>
12
 *
13
 *  PdfParser is a pdf library written in PHP, extraction oriented.
14
 *  Copyright (C) 2017 - Sébastien MALOT <[email protected]>
15
 *
16
 *  This program is free software: you can redistribute it and/or modify
17
 *  it under the terms of the GNU Lesser General Public License as published by
18
 *  the Free Software Foundation, either version 3 of the License, or
19
 *  (at your option) any later version.
20
 *
21
 *  This program is distributed in the hope that it will be useful,
22
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 *  GNU Lesser General Public License for more details.
25
 *
26
 *  You should have received a copy of the GNU Lesser General Public License
27
 *  along with this program.
28
 *  If not, see <http://www.pdfparser.org/sites/default/LICENSE.txt>.
29
 */
30
31
namespace Smalot\PdfParser;
32
33
use Smalot\PdfParser\Element\ElementArray;
34
use Smalot\PdfParser\Element\ElementMissing;
35
use Smalot\PdfParser\Element\ElementStruct;
36
use Smalot\PdfParser\Element\ElementXRef;
37
38
/**
39
 * Class Header
40
 */
41
class Header
42
{
43
    /**
44
     * @var Document
45
     */
46
    protected $document = null;
47
48
    /**
49
     * @var Element[]
50
     */
51
    protected $elements = null;
52
53
    /**
54
     * @param Element[] $elements list of elements
55
     * @param Document  $document document
56
     */
57 65
    public function __construct(array $elements = [], ?Document $document = null)
58
    {
59 65
        $this->elements = $elements;
60 65
        $this->document = $document;
61 65
    }
62
63 43
    public function init()
64
    {
65 43
        foreach ($this->elements as $element) {
66 43
            if ($element instanceof Element) {
67 43
                $element->init();
68
            }
69
        }
70 43
    }
71
72
    /**
73
     * Returns all elements.
74
     */
75 36
    public function getElements()
76
    {
77 36
        foreach ($this->elements as $name => $element) {
78 36
            $this->resolveXRef($name);
79
        }
80
81 36
        return $this->elements;
82
    }
83
84
    /**
85
     * Used only for debug.
86
     */
87 1
    public function getElementTypes(): array
88
    {
89 1
        $types = [];
90
91 1
        foreach ($this->elements as $key => $element) {
92 1
            $types[$key] = \get_class($element);
93
        }
94
95 1
        return $types;
96
    }
97
98 34
    public function getDetails(bool $deep = true): array
99
    {
100 34
        $values = [];
101 34
        $elements = $this->getElements();
102
103 34
        foreach ($elements as $key => $element) {
104 34
            if ($element instanceof self && $deep) {
105
                $values[$key] = $element->getDetails($deep);
106 34
            } elseif ($element instanceof PDFObject && $deep) {
107
                $values[$key] = $element->getDetails(false);
108 34
            } elseif ($element instanceof ElementArray) {
109
                if ($deep) {
110
                    $values[$key] = $element->getDetails();
111
                }
112 34
            } elseif ($element instanceof Element) {
113 34
                $values[$key] = (string) $element;
114
            }
115
        }
116
117
        // ensure detail information aren't badly encoded
118 34
        foreach ($values as $key => $value) {
119 34
            if (false === preg_match('!!u', $value)) {
120 4
                $font = $this->document->getFirstFont();
121 4
                if ($font) {
122 4
                    $newValue = $font->decodeContent($value);
123
                } else {
124
                    $newValue = mb_convert_encoding($value, 'UTF-8', 'Windows-1252');
125
                }
126
127 4
                $values[$key] = $newValue;
128
            }
129
        }
130
131 34
        return $values;
132
    }
133
134
    /**
135
     * Indicate if an element name is available in header.
136
     *
137
     * @param string $name the name of the element
138
     */
139 47
    public function has(string $name): bool
140
    {
141 47
        return \array_key_exists($name, $this->elements);
142
    }
143
144
    /**
145
     * @return Element|PDFObject
146
     */
147 50
    public function get(string $name)
148
    {
149 50
        if (\array_key_exists($name, $this->elements)) {
150 49
            return $this->resolveXRef($name);
151
        }
152
153 47
        return new ElementMissing();
154
    }
155
156
    /**
157
     * Resolve XRef to object.
158
     *
159
     * @return Element|PDFObject
160
     *
161
     * @throws \Exception
162
     */
163 50
    protected function resolveXRef(string $name)
164
    {
165 50
        if (($obj = $this->elements[$name]) instanceof ElementXRef && null !== $this->document) {
166
            /** @var ElementXRef $obj */
167 38
            $object = $this->document->getObjectById($obj->getId());
168
169 38
            if (null === $object) {
170 2
                return new ElementMissing();
171
            }
172
173
            // Update elements list for future calls.
174 38
            $this->elements[$name] = $object;
175
        }
176
177 50
        return $this->elements[$name];
178
    }
179
180
    /**
181
     * @param string   $content  The content to parse
182
     * @param Document $document The document
183
     * @param int      $position The new position of the cursor after parsing
184
     */
185 21
    public static function parse(string $content, Document $document, int &$position = 0): self
186
    {
187
        /* @var Header $header */
188 21
        if ('<<' == substr(trim($content), 0, 2)) {
189 20
            $header = ElementStruct::parse($content, $document, $position);
190
        } else {
191 8
            $elements = ElementArray::parse($content, $document, $position);
192 8
            $header = new self([], $document);
193
194 8
            if ($elements) {
195 7
                $header = new self($elements->getRawContent(), null);
196
            }
197
        }
198
199 21
        if ($header) {
200 21
            return $header;
201
        }
202
203
        // Build an empty header.
204
        return new self([], $document);
205
    }
206
}
207