Completed
Push — master ( 58d71b...754f44 )
by Michele
06:19
created

Item::getCHM()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace CHMLib\TOCIndex;
4
5
use CHMLib\CHM;
6
use CHMLib\Map;
7
use DOMElement;
8
use Exception;
9
10
/**
11
 * A list of items in the TOC or in the Index of an CHM file.
12
 */
13
class Item
14
{
15
    /**
16
     * The parent CHM instance.
17
     *
18
     * @var CHM
19
     */
20
    protected $chm;
21
22
    /**
23
     * The name of the tree item.
24
     *
25
     * @var string
26
     */
27
    protected $name;
28
29
    /**
30
     * Is this item marked as new?
31
     *
32
     * @var bool
33
     */
34
    protected $isNew;
35
36
    /**
37
     * The comment of the tree item.
38
     *
39
     * @var string
40
     */
41
    protected $comment;
42
43
    /**
44
     * The keyword of the tree item.
45
     *
46
     * @var string
47
     */
48
    protected $keyword;
49
50
    /**
51
     * The value of the "See Also" parameter.
52
     *
53
     * @var string
54
     */
55
    protected $seeAlso;
56
57
    /**
58
     * The local path to the tree item.
59
     *
60
     * @var string
61
     */
62
    protected $local;
63
64
    /**
65
     * The URL to the tree item.
66
     *
67
     * @var string
68
     */
69
    protected $url;
70
71
    /**
72
     * The frame name for this item.
73
     *
74
     * @var string;
75
     */
76
    protected $frameName;
77
78
    /**
79
     * The window name for this item.
80
     *
81
     * @var string;
82
     */
83
    protected $windowName;
84
85
    /**
86
     * The path to an entry in another CHM file.
87
     *
88
     * @var string|array|null If it's an array, it has two keys: 'chm' and 'entry'.
89
     */
90
    protected $merge;
91
92
    /**
93
     * The image number attribute.
94
     *
95
     * @var int|null
96
     */
97
    protected $imageNumber;
98
99
    /**
100
     * The sub-elements of this Item.
101
     *
102
     * @var Tree
103
     */
104
    protected $children;
105
106
    /**
107
     * Initializes the instance.
108
     *
109
     * @param CHM $chm The parent CHM instance.
110
     * @param DOMElement $object The OBJECT element.
111
     *
112
     * @throws Exception Throw an Exception in case of errors.
113
     *
114
     * @return static
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
115
     */
116 1
    public function __construct(CHM $chm, DOMElement $object)
117
    {
118 1
        $this->chm = $chm;
119 1
        $this->name = '';
120 1
        $this->isNew = false;
121 1
        $this->comment = '';
122 1
        $this->keyword = '';
123 1
        $this->seeAlso = '';
124 1
        $this->local = '';
125 1
        $this->url = '';
126 1
        $this->frameName = '';
127 1
        $this->windowName = '';
128 1
        $this->merge = null;
129 1
        $this->imageNumber = null;
130 1
        $this->children = new Tree();
131 1
        foreach ($object->childNodes as $p) {
132 1
            if ($p instanceof DOMElement && strcasecmp($p->tagName, 'param') === 0) {
133 1
                $name = trim((string) $p->getAttribute('name'));
134 1
                $value = trim((string) $p->getAttribute('value'));
135 1
                switch (strtolower($name)) {
136 1
                    case 'name':
137
                        // Multiple values are allowed: we keep only the last one
138 1
                        $this->name = $value;
139 1
                        break;
140 1
                    case 'new':
141
                        $this->isNew = !empty($value);
142
                        break;
143 1
                    case 'comment':
144
                        $this->comment = $value;
145
                        break;
146 1
                    case 'keyword':
147
                        $this->keyword = $value;
148
                        break;
149 1
                    case 'see also':
150
                        $this->seeAlso = $value;
151
                        break;
152 1
                    case 'local':
153 1
                        $this->local = '/'.str_replace('\\', '/', str_replace('%20', ' ', $value));
154 1
                        break;
155 1
                    case 'url':
156
                        $this->url = $value;
157
                        break;
158 1
                    case 'framename':
159
                        $this->frameName = $value;
160
                        break;
161 1
                    case 'windowname':
162
                        $this->windowName = $value;
163
                        break;
164 1
                    case 'merge':
165 1
                        if ($value !== '') {
166 1
                            if (preg_match('%^([^:\\\\/]+.chm)::(.+)$%i', $value, $matches)) {
167 1
                                $this->merge = array('chm' => $matches[1], 'entry' => '/'.ltrim(str_replace('\\', '/', $matches[2]), '/'));
168
                            } else {
169
                                $this->merge = $value;
170
                            }
171
                        }
172 1
                        break;
173
                    case 'imagenumber':
174
                        if (is_numeric($value)) {
175
                            $this->imageNumber = (int) $value;
176
                        } elseif ($value !== '') {
177
                            throw new Exception("Invalid value of the '$name' attribute: $value");
178
                        }
179
                        break;
180
                    default:
181 1
                        throw new Exception("Unknown parameter name '$name' of a tree item (value: '$value')");
182
                }
183
            }
184
        }
185 1
    }
186
187
    /**
188
     * Get the parent CHM instance.
189
     *
190
     * @return CHM
191
     */
192 1
    public function getCHM()
193
    {
194 1
        return $this->chm;
195
    }
196
197
    /**
198
     * Get the name of the tree item.
199
     *
200
     * @return string
201
     */
202
    public function getName()
203
    {
204
        return $this->name;
205
    }
206
207
    /**
208
     * Is this item marked as new?
209
     *
210
     * @return bool
211
     */
212
    public function isNew()
213
    {
214
        return $this->isNew;
215
    }
216
217
    /**
218
     * Get the comment of the tree item.
219
     *
220
     * @return string
221
     */
222
    public function getComment()
223
    {
224
        return $this->comment;
225
    }
226
227
    /**
228
     * Get the keyword of the tree item.
229
     *
230
     * @return string
231
     */
232
    public function getKeyword()
233
    {
234
        return $this->keyword;
235
    }
236
237
    /**
238
     * Get the value of the "See Also" parameter.
239
     *
240
     * @return string
241
     */
242
    public function getSeeAlso()
243
    {
244
        return $this->seeAlso;
245
    }
246
247
    /**
248
     * Get the local path to the tree item.
249
     *
250
     * @return string
251
     */
252 1
    public function getLocal()
253
    {
254 1
        return $this->local;
255
    }
256
257
    /**
258
     * Get the URL to the tree item.
259
     *
260
     * @return string
261
     */
262
    public function getURL()
263
    {
264
        return $this->url;
265
    }
266
267
    /**
268
     * Get the frame name for this item.
269
     *
270
     * @return string
271
     */
272
    public function getFrameName()
273
    {
274
        return $this->frameName;
275
    }
276
277
    /**
278
     * Get the window name for this item.
279
     *
280
     * @return string
281
     */
282 1
    public function getWindowName()
283
    {
284 1
        return $this->frameName;
285
    }
286
287
    /**
288
     * Get the path to an entry in another CHM file.
289
     *
290
     * @var array|null If not null, it's an array with two keys: 'chm' and 'entry'.
291
     */
292
    public function getMerge()
293
    {
294
        return $this->merge;
295
    }
296
297
    /**
298
     * Get the image number attribute.
299
     *
300
     * @return int|null
301
     */
302 1
    public function getImageNumber()
303
    {
304 1
        return $this->imageNumber;
305
    }
306
307
    /**
308
     * Get the sub-elements of this Item.
309
     *
310
     * @return Tree
311
     */
312
    public function getChildren()
313
    {
314
        return $this->children;
315
    }
316
317 1
    /**
318
     * Resolve the items contained in other CHM files.
319 1
     *
320 1
     * @param Map $map
321 1
     * @param bool $ignoreErrors Set to true to ignore missing CHM and/or entries.
322 1
     *
323
     * @throws Exception Throw an Exception in case of errors.
324
     *
325
     * @return static[]
326
     */
327 1
    public function resolve(Map $map, $ignoreErrors = false)
328 1
    {
329
        $result = array($this);
330
        if (is_array($this->merge)) {
331
            $chm = $map->get($this->merge['chm']);
332
            if ($chm === null) {
333 1
                if (!$ignoreErrors) {
334 1
                    throw new Exception("Missing CHM reference from map: {$this->merge['chm']}");
335 1
                }
336
            } else {
337
                $entry = $chm->getEntryByPath($this->merge['entry']);
338
                if ($entry === null) {
339 1
                    if (!$ignoreErrors) {
340 1
                        throw new Exception("Missing entry '{$this->merge['entry']}' in CHM file {$this->merge['chm']}");
341
                    }
342
                } else {
343 1
                    $tree = Tree::fromString($chm, $entry->getContents());
344
                    $tree->resolve($map, $ignoreErrors);
345
                    $result = $tree->getItems();
346
                }
347
            }
348
        }
349
        foreach ($result as $newItem) {
350
            $newItem->children->resolve($map, $ignoreErrors);
351
        }
352
353
        return $result;
354
    }
355
356
    /**
357
     * Search the associated entry in the CHM file.
358
     *
359
     * @return \CHMLib\Entry|null
360
     */
361
    public function findEntry()
362
    {
363
        $result = null;
364
        if ($this->local !== '') {
365
            $path = '/'.ltrim(str_replace('\\', '/', $this->local), '/');
366
            $entry = $this->chm->getEntryByPath($path);
367
            if ($entry === null) {
368
                $p = strpos($path, '#');
369
                if ($p !== false) {
370
                    $path = substr($path, 0, $p);
371
                    $entry = $this->chm->getEntryByPath($path);
372
                }
373
            }
374
            if ($entry !== null && $entry->isFile()) {
375
                $result = $entry;
376
            }
377
        }
378
379
        return $result;
380
    }
381
}
382