Completed
Push — master ( e60e65...b26a42 )
by Michal
03:07
created

ShapeRecord   D

Complexity

Total Complexity 184

Size/Duplication

Total Lines 723
Duplicated Lines 3.6 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 89.51%

Importance

Changes 37
Bugs 0 Features 0
Metric Value
dl 26
loc 723
ccs 478
cts 534
cp 0.8951
rs 4.4444
c 37
b 0
f 0
wmc 184
lcom 1
cbo 2

51 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
C loadFromFile() 0 70 19
C saveToFile() 0 54 16
A updateDBFInfo() 0 8 3
A _loadData() 0 9 2
A _loadHeaders() 0 14 3
A _saveHeaders() 0 5 1
A _loadPoint() 0 8 1
A _loadPointM() 0 7 1
A _loadPointZ() 0 8 1
A _savePoint() 0 4 1
A _savePointM() 0 5 1
A _savePointZ() 0 6 1
A _loadNullRecord() 0 3 1
A _loadPointRecord() 0 3 1
A _loadPointMRecord() 0 3 1
A _loadPointZRecord() 0 3 1
A _savePointRecord() 0 3 1
A _savePointMRecord() 0 3 1
A _savePointZRecord() 0 3 1
A _loadBBox() 0 7 1
A _loadMultiPointRecord() 0 10 2
A _loadMultiPointMZRecord() 0 14 4
A _loadMultiPointMRecord() 0 5 1
A _loadMultiPointZRecord() 0 6 1
A _saveMultiPointRecord() 0 9 2
A _saveMultiPointMZRecord() 0 8 2
A _saveMultiPointMRecord() 0 5 1
A _saveMultiPointZRecord() 0 6 1
C _loadPolyLineRecord() 3 25 7
B _loadPolyLineMZRecord() 3 20 6
A _loadPolyLineMRecord() 0 5 1
A _loadPolyLineZRecord() 0 6 1
A _savePolyLineRecord() 0 17 4
A _savePolyLineMZRecord() 0 9 3
A _savePolyLineMRecord() 0 5 1
A _savePolyLineZRecord() 0 6 1
A _loadPolygonRecord() 0 3 1
A _loadPolygonMRecord() 0 3 1
A _loadPolygonZRecord() 0 3 1
A _savePolygonRecord() 0 3 1
A _savePolygonMRecord() 0 3 1
A _savePolygonZRecord() 0 3 1
B _adjustBBox() 0 17 7
C addPoint() 0 61 28
C deletePoint() 0 55 21
C getContentLength() 20 56 17
A _loadDBFData() 0 4 1
B _saveDBFData() 0 15 5
A setError() 0 3 1
A getShapeName() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ShapeRecord often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ShapeRecord, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * phpMyAdmin ShapeFile library
4
 * <https://github.com/phpmyadmin/shapefile/>
5
 *
6
 * Copyright 2006-2007 Ovidio <ovidio AT users.sourceforge.net>
7
 * Copyright 2016 Michal Čihař <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, you can download one from
20
 * https://www.gnu.org/copyleft/gpl.html.
21
 */
22
namespace ShapeFile;
23
24
class ShapeRecord {
25
    private $SHPFile = null;
26
    private $DBFFile = null;
27
    private $ShapeFile = null;
28
29
    private $size = 0;
30
    private $read = 0;
31
32
    public $recordNumber = null;
33
    public $shapeType = null;
34
35
    public $lastError = '';
36
37
    public $SHPData = array();
38
    public $DBFData = array();
39
40
    /**
41
     * @param integer $shapeType
42
     */
43 19
    public function __construct($shapeType) {
44 19
        $this->shapeType = $shapeType;
45 19
    }
46
47
    /**
48
     * @param ShapeFile $ShapeFile
49
     */
50 18
    public function loadFromFile(&$ShapeFile, &$SHPFile, &$DBFFile) {
51 18
        $this->ShapeFile = $ShapeFile;
52 18
        $this->SHPFile = $SHPFile;
53 18
        $this->DBFFile = $DBFFile;
54 18
        $this->_loadHeaders();
55
56
        /* No header read */
57 18
        if ($this->read == 0) {
58 18
            return;
59
        }
60
61 18
        switch ($this->shapeType) {
62 18
            case 0:
63
                $this->_loadNullRecord();
64
                break;
65 18
            case 1:
66 3
                $this->_loadPointRecord();
67 3
                break;
68 15
            case 21:
69 1
                $this->_loadPointMRecord();
70 1
                break;
71 14
            case 11:
72 1
                $this->_loadPointZRecord();
73 1
                break;
74 13
            case 3:
75 1
                $this->_loadPolyLineRecord();
76 1
                break;
77 12
            case 23:
78 1
                $this->_loadPolyLineMRecord();
79 1
                break;
80 11
            case 13:
81 1
                $this->_loadPolyLineZRecord();
82 1
                break;
83 10
            case 5:
84 3
                $this->_loadPolygonRecord();
85 3
                break;
86 7
            case 25:
87 1
                $this->_loadPolygonMRecord();
88 1
                break;
89 6
            case 15:
90 2
                $this->_loadPolygonZRecord();
91 2
                break;
92 4
            case 8:
93 1
                $this->_loadMultiPointRecord();
94 1
                break;
95 3
            case 28:
96 1
                $this->_loadMultiPointMRecord();
97 1
                break;
98 2
            case 18:
99 2
                $this->_loadMultiPointZRecord();
100 2
                break;
101
            default:
102
                $this->setError(sprintf('The Shape Type "%s" is not supported.', $this->shapeType));
103
                break;
104 18
        }
105
106
        /* We need to skip rest of the record */
107 18
        while ($this->read < $this->size) {
108 6
            $this->_loadData('V', 4);
109 6
        }
110
111
        /* Check if we didn't read too much */
112 18
        if ($this->read != $this->size) {
113
            $this->setError(sprintf('Failed to parse record, read=%d, size=%d', $this->read, $this->size));
114
        }
115
116 18
        if (ShapeFile::supports_dbase() && isset($this->DBFFile)) {
117
            $this->_loadDBFData();
118
        }
119 18
    }
120
121 12
    public function saveToFile(&$SHPFile, &$DBFFile, $recordNumber) {
122 12
        $this->SHPFile = $SHPFile;
123 12
        $this->DBFFile = $DBFFile;
124 12
        $this->recordNumber = $recordNumber;
125 12
        $this->_saveHeaders();
126
127 12
        switch ($this->shapeType) {
128 12
            case 0:
129
                // Nothing to save
130
                break;
131 12
            case 1:
132 1
                $this->_savePointRecord();
133 1
                break;
134 11
            case 21:
135 1
                $this->_savePointMRecord();
136 1
                break;
137 10
            case 11:
138 1
                $this->_savePointZRecord();
139 1
                break;
140 9
            case 3:
141 1
                $this->_savePolyLineRecord();
142 1
                break;
143 8
            case 23:
144 1
                $this->_savePolyLineMRecord();
145 1
                break;
146 7
            case 13:
147 1
                $this->_savePolyLineZRecord();
148 1
                break;
149 6
            case 5:
150 1
                $this->_savePolygonRecord();
151 1
                break;
152 5
            case 25:
153 1
                $this->_savePolygonMRecord();
154 1
                break;
155 4
            case 15:
156 1
                $this->_savePolygonZRecord();
157 1
                break;
158 3
            case 8:
159 1
                $this->_saveMultiPointRecord();
160 1
                break;
161 2
            case 28:
162 1
                $this->_saveMultiPointMRecord();
163 1
                break;
164 1
            case 18:
165 1
                $this->_saveMultiPointZRecord();
166 1
                break;
167
            default:
168
                $this->setError(sprintf('The Shape Type "%s" is not supported.', $this->shapeType));
169
                break;
170 12
        }
171 12
        if (ShapeFile::supports_dbase() && isset($this->DBFFile)) {
172
            $this->_saveDBFData();
173
        }
174 12
    }
175
176 12
    public function updateDBFInfo($header) {
177 12
        $tmp = $this->DBFData;
178 12
        unset($this->DBFData);
179 12
        $this->DBFData = array();
180 12
        foreach ($header as $value) {
181 12
            $this->DBFData[$value[0]] = (isset($tmp[$value[0]])) ? $tmp[$value[0]] : '';
182 12
        }
183 12
    }
184
185
    /**
186
     * Reads data
187
     *
188
     * @param string $type type for unpack()
189
     * @param int    $count number of bytes
190
     *
191
     * @return mixed
192
     */
193 18
    private function _loadData($type, $count)
194
    {
195 18
        $data = $this->ShapeFile->readSHP($count);
196 18
        if ($data === false) {
197
            return false;
198
        }
199 18
        $this->read += strlen($data);
200 18
        return Util::loadData($type, $data);
201
    }
202
203 18
    private function _loadHeaders() {
204 18
        $this->shapeType = false;
205 18
        $this->recordNumber = $this->_loadData('N', 4);
206 18
        if ($this->recordNumber === false) {
207 18
            return;
208
        }
209
        // We read the length of the record
210 18
        $this->size = $this->_loadData('N', 4);
211 18
        if ($this->size === false) {
212
            return;
213
        }
214 18
        $this->size = $this->size * 2 + 8;
215 18
        $this->shapeType = $this->_loadData('V', 4);
216 18
    }
217
218 12
    private function _saveHeaders() {
219 12
        fwrite($this->SHPFile, pack('N', $this->recordNumber));
220 12
        fwrite($this->SHPFile, pack('N', $this->getContentLength()));
221 12
        fwrite($this->SHPFile, pack('V', $this->shapeType));
222 12
    }
223
224 18
    private function _loadPoint() {
225 18
        $data = array();
226
227 18
        $data['x'] = $this->_loadData('d', 8);
228 18
        $data['y'] = $this->_loadData('d', 8);
229
230 18
        return $data;
231
    }
232
233 1
    private function _loadPointM() {
234 1
        $data = $this->_loadPoint();
235
236 1
        $data['m'] = $this->_loadData('d', 8);
237
238 1
        return $data;
239
    }
240
241 1
    private function _loadPointZ() {
242 1
        $data = $this->_loadPoint();
243
244 1
        $data['z'] = $this->_loadData('d', 8);
245 1
        $data['m'] = $this->_loadData('d', 8);
246
247 1
        return $data;
248
    }
249
250 10
    private function _savePoint($data) {
251 10
        fwrite($this->SHPFile, Util::packDouble($data['x']));
252 10
        fwrite($this->SHPFile, Util::packDouble($data['y']));
253 10
    }
254
255 1
    private function _savePointM($data) {
256 1
        fwrite($this->SHPFile, Util::packDouble($data['x']));
257 1
        fwrite($this->SHPFile, Util::packDouble($data['y']));
258 1
        fwrite($this->SHPFile, Util::packDouble($data['m']));
259 1
    }
260
261 1
    private function _savePointZ($data) {
262 1
        fwrite($this->SHPFile, Util::packDouble($data['x']));
263 1
        fwrite($this->SHPFile, Util::packDouble($data['y']));
264 1
        fwrite($this->SHPFile, Util::packDouble($data['z']));
265 1
        fwrite($this->SHPFile, Util::packDouble($data['m']));
266 1
    }
267
268
    private function _loadNullRecord() {
269
        $this->SHPData = array();
270
    }
271
272 3
    private function _loadPointRecord() {
273 3
        $this->SHPData = $this->_loadPoint();
274 3
    }
275
276 1
    private function _loadPointMRecord() {
277 1
        $this->SHPData = $this->_loadPointM();
278 1
    }
279
280 1
    private function _loadPointZRecord() {
281 1
        $this->SHPData = $this->_loadPointZ();
282 1
    }
283
284 1
    private function _savePointRecord() {
285 1
        $this->_savePoint($this->SHPData);
286 1
    }
287
288 1
    private function _savePointMRecord() {
289 1
        $this->_savePointM($this->SHPData);
290 1
    }
291
292 1
    private function _savePointZRecord() {
293 1
        $this->_savePointZ($this->SHPData);
294 1
    }
295
296 13
    private function _loadBBox()
297
    {
298 13
        $this->SHPData['xmin'] = $this->_loadData('d', 8);
299 13
        $this->SHPData['ymin'] = $this->_loadData('d', 8);
300 13
        $this->SHPData['xmax'] = $this->_loadData('d', 8);
301 13
        $this->SHPData['ymax'] = $this->_loadData('d', 8);
302 13
    }
303
304 4
    private function _loadMultiPointRecord() {
305 4
        $this->SHPData = array();
306 4
        $this->_loadBBox();
307
308 4
        $this->SHPData['numpoints'] = $this->_loadData('V', 4);
309
310 4
        for ($i = 0; $i < $this->SHPData['numpoints']; $i++) {
311 4
            $this->SHPData['points'][] = $this->_loadPoint();
312 4
        }
313 4
    }
314
315
    /**
316
     * @param string $type
317
     */
318 3
    private function _loadMultiPointMZRecord($type)
319
    {
320
        /* The m dimension is optional, depends on bounding box data */
321 3
        if ($type == 'm' && !$this->ShapeFile->hasMeasure()) {
322 3
            return;
323
        }
324
325 2
        $this->SHPData[$type.'min'] = $this->_loadData('d', 8);
326 2
        $this->SHPData[$type.'max'] = $this->_loadData('d', 8);
327
328 2
        for ($i = 0; $i < $this->SHPData['numpoints']; $i++) {
329 2
            $this->SHPData['points'][$i][$type] = $this->_loadData('d', 8);
330 2
        }
331 2
    }
332
333 1
    private function _loadMultiPointMRecord() {
334 1
        $this->_loadMultiPointRecord();
335
336 1
        $this->_loadMultiPointMZRecord('m');
337 1
    }
338
339 2
    private function _loadMultiPointZRecord() {
340 2
        $this->_loadMultiPointRecord();
341
342 2
        $this->_loadMultiPointMZRecord('z');
343 2
        $this->_loadMultiPointMZRecord('m');
344 2
    }
345
346 3
    private function _saveMultiPointRecord() {
347 3
        fwrite($this->SHPFile, pack('dddd', $this->SHPData['xmin'], $this->SHPData['ymin'], $this->SHPData['xmax'], $this->SHPData['ymax']));
348
349 3
        fwrite($this->SHPFile, pack('V', $this->SHPData['numpoints']));
350
351 3
        for ($i = 0; $i < $this->SHPData['numpoints']; $i++) {
352 3
            $this->_savePoint($this->SHPData['points'][$i]);
353 3
        }
354 3
    }
355
356
    /**
357
     * @param string $type
358
     */
359 2
    private function _saveMultiPointMZRecord($type) {
360
361 2
        fwrite($this->SHPFile, pack('dd', $this->SHPData[$type.'min'], $this->SHPData[$type.'max']));
362
363 2
        for ($i = 0; $i < $this->SHPData['numpoints']; $i++) {
364 2
            fwrite($this->SHPFile, Util::packDouble($this->SHPData['points'][$i][$type]));
365 2
        }
366 2
    }
367
368 1
    private function _saveMultiPointMRecord() {
369 1
        $this->_saveMultiPointRecord();
370
371 1
        $this->_saveMultiPointMZRecord('m');
372 1
    }
373
374 1
    private function _saveMultiPointZRecord() {
375 1
        $this->_saveMultiPointRecord();
376
377 1
        $this->_saveMultiPointMZRecord('z');
378 1
        $this->_saveMultiPointMZRecord('m');
379 1
    }
380
381 9
    private function _loadPolyLineRecord() {
382 9
        $this->SHPData = array();
383 9
        $this->_loadBBox();
384
385 9
        $this->SHPData['numparts']  = $this->_loadData('V', 4);
386 9
        $this->SHPData['numpoints'] = $this->_loadData('V', 4);
387
388 9
        $numparts = $this->SHPData['numparts'];
389 9
        $numpoints = $this->SHPData['numpoints'];
390
391 9
        for ($i = 0; $i < $numparts; $i++) {
392 9
            $this->SHPData['parts'][$i] = $this->_loadData('V', 4);
393 9
        }
394
395 9
        $part = 0;
396 9
        for ($i = 0; $i < $numpoints; $i++) {
397 9 View Code Duplication
            if ($part + 1 < $numparts && $this->SHPData['parts'][$part + 1] == $i) {
398 8
                $part++;
399 8
            }
400 9
            if (!isset($this->SHPData['parts'][$part]['points']) || !is_array($this->SHPData['parts'][$part]['points'])) {
401 9
                $this->SHPData['parts'][$part] = array('points' => array());
402 9
            }
403 9
            $this->SHPData['parts'][$part]['points'][] = $this->_loadPoint();
404 9
        }
405 9
    }
406
407
    /**
408
     * @param string $type
409
     */
410 5
    private function _loadPolyLineMZRecord($type) {
411
        /* The m dimension is optional, depends on bounding box data */
412 5
        if ($type == 'm' && !$this->ShapeFile->hasMeasure()) {
413 5
            return;
414
        }
415
416 3
        $this->SHPData[$type.'min'] = $this->_loadData('d', 8);
417 3
        $this->SHPData[$type.'max'] = $this->_loadData('d', 8);
418
419 3
        $numparts = $this->SHPData['numparts'];
420 3
        $numpoints = $this->SHPData['numpoints'];
421
422 3
        $part = 0;
423 3
        for ($i = 0; $i < $numpoints; $i++) {
424 3 View Code Duplication
            if ($part + 1 < $numparts && $this->SHPData['parts'][$part + 1] == $i) {
425
                $part++;
426
            }
427 3
            $this->SHPData['parts'][$part]['points'][$i][$type] = $this->_loadData('d', 8);
428 3
        }
429 3
    }
430
431 2
    private function _loadPolyLineMRecord() {
432 2
        $this->_loadPolyLineRecord();
433
434 2
        $this->_loadPolyLineMZRecord('m');
435 2
    }
436
437 3
    private function _loadPolyLineZRecord() {
438 3
        $this->_loadPolyLineRecord();
439
440 3
        $this->_loadPolyLineMZRecord('z');
441 3
        $this->_loadPolyLineMZRecord('m');
442 3
    }
443
444 6
    private function _savePolyLineRecord() {
445 6
        fwrite($this->SHPFile, pack('dddd', $this->SHPData['xmin'], $this->SHPData['ymin'], $this->SHPData['xmax'], $this->SHPData['ymax']));
446
447 6
        fwrite($this->SHPFile, pack('VV', $this->SHPData['numparts'], $this->SHPData['numpoints']));
448
449 6
        $part_index = 0;
450 6
        for ($i = 0; $i < $this->SHPData['numparts']; $i++) {
451 6
            fwrite($this->SHPFile, pack('V', $part_index));
452 6
            $part_index += count($this->SHPData['parts'][$i]['points']);
453 6
        }
454
455 6
        foreach ($this->SHPData['parts'] as $partData) {
456 6
            foreach ($partData['points'] as $pointData) {
457 6
                $this->_savePoint($pointData);
458 6
            }
459 6
        }
460 6
    }
461
462
    /**
463
     * @param string $type
464
     */
465 4
    private function _savePolyLineMZRecord($type) {
466 4
        fwrite($this->SHPFile, pack('dd', $this->SHPData[$type.'min'], $this->SHPData[$type.'max']));
467
468 4
        foreach ($this->SHPData['parts'] as $partData) {
469 4
            foreach ($partData['points'] as $pointData) {
470 4
                fwrite($this->SHPFile, Util::packDouble($pointData[$type]));
471 4
            }
472 4
        }
473 4
    }
474
475 2
    private function _savePolyLineMRecord() {
476 2
        $this->_savePolyLineRecord();
477
478 2
        $this->_savePolyLineMZRecord('m');
479 2
    }
480
481 2
    private function _savePolyLineZRecord() {
482 2
        $this->_savePolyLineRecord();
483
484 2
        $this->_savePolyLineMZRecord('z');
485 2
        $this->_savePolyLineMZRecord('m');
486 2
    }
487
488 3
    private function _loadPolygonRecord() {
489 3
        $this->_loadPolyLineRecord();
490 3
    }
491
492 1
    private function _loadPolygonMRecord() {
493 1
        $this->_loadPolyLineMRecord();
494 1
    }
495
496 2
    private function _loadPolygonZRecord() {
497 2
        $this->_loadPolyLineZRecord();
498 2
    }
499
500 1
    private function _savePolygonRecord() {
501 1
        $this->_savePolyLineRecord();
502 1
    }
503
504 1
    private function _savePolygonMRecord() {
505 1
        $this->_savePolyLineMRecord();
506 1
    }
507
508 1
    private function _savePolygonZRecord() {
509 1
        $this->_savePolyLineZRecord();
510 1
    }
511
512 12
    private function _adjustBBox($point) {
513
        // Adjusts bounding box based on point
514 12
        $directions = array('x', 'y', 'z', 'm');
515 12
        foreach ($directions as $direction) {
516 12
            if (!isset($point[$direction])) {
517 8
                continue;
518
            }
519 12
            $min = $direction.'min';
520 12
            $max = $direction.'max';
521 12
            if (!isset($this->SHPData[$min]) || ($this->SHPData[$min] > $point[$direction])) {
522 12
                $this->SHPData[$min] = $point[$direction];
523 12
            }
524 12
            if (!isset($this->SHPData[$max]) || ($this->SHPData[$max] < $point[$direction])) {
525 12
                $this->SHPData[$max] = $point[$direction];
526 12
            }
527 12
        }
528 12
    }
529
530 12
    public function addPoint($point, $partIndex = 0) {
531 12
        switch ($this->shapeType) {
532 12
            case 0:
533
                //Don't add anything
534
                break;
535 12
            case 1:
536 12
            case 11:
537 12
            case 21:
538 3
                if (in_array($this->shapeType, array(11, 21)) && !isset($point['m'])) {
539 2
                    $point['m'] = 0.0; // no_value
540 2
                }
541 3
                if (in_array($this->shapeType, array(11)) && !isset($point['z'])) {
542 1
                    $point['z'] = 0.0; // no_value
543 1
                }
544
545
                //Substitutes the value of the current point
546 3
                $this->SHPData = $point;
547 3
                $this->_adjustBBox($point);
548 3
                break;
549 9
            case 3:
550 9
            case 5:
551 9
            case 13:
552 9
            case 15:
553 9
            case 23:
554 9
            case 25:
555 6
                if (in_array($this->shapeType, array(13, 15, 23, 25)) && !isset($point['m'])) {
556 4
                    $point['m'] = 0.0; // no_value
557 4
                }
558 6
                if (in_array($this->shapeType, array(13, 15)) && !isset($point['z'])) {
559 2
                    $point['z'] = 0.0; // no_value
560 2
                }
561
562 6
                $this->_adjustBBox($point);
563
564
                //Adds a new point to the selected part
565 6
                $this->SHPData['parts'][$partIndex]['points'][] = $point;
566
567 6
                $this->SHPData['numparts'] = count($this->SHPData['parts']);
568 6
                $this->SHPData['numpoints'] = 1 + (isset($this->SHPData['numpoints']) ? $this->SHPData['numpoints'] : 0);
569 6
                break;
570 3
            case 8:
571 3
            case 18:
572 3
            case 28:
573 3
                if (in_array($this->shapeType, array(18, 28)) && !isset($point['m'])) {
574 2
                    $point['m'] = 0.0; // no_value
575 2
                }
576 3
                if (in_array($this->shapeType, array(18)) && !isset($point['z'])) {
577 1
                    $point['z'] = 0.0; // no_value
578 1
                }
579
580 3
                $this->_adjustBBox($point);
581
582
                //Adds a new point
583 3
                $this->SHPData['points'][] = $point;
584 3
                $this->SHPData['numpoints'] = 1 + (isset($this->SHPData['numpoints']) ? $this->SHPData['numpoints'] : 0);
585 3
                break;
586
            default:
587
                $this->setError(sprintf('The Shape Type "%s" is not supported.', $this->shapeType));
588
                break;
589 12
        }
590 12
    }
591
592 12
    public function deletePoint($pointIndex = 0, $partIndex = 0) {
593 12
        switch ($this->shapeType) {
594 12
            case 0:
595
                //Don't delete anything
596
                break;
597 12
            case 1:
598 12
            case 11:
599 12
            case 21:
600
                //Sets the value of the point to zero
601 3
                $this->SHPData['x'] = 0.0;
602 3
                $this->SHPData['y'] = 0.0;
603 3
                if (in_array($this->shapeType, array(11, 21))) {
604 2
                    $this->SHPData['m'] = 0.0;
605 2
                }
606 3
                if (in_array($this->shapeType, array(11))) {
607 1
                    $this->SHPData['z'] = 0.0;
608 1
                }
609 3
                break;
610 9
            case 3:
611 9
            case 5:
612 9
            case 13:
613 9
            case 15:
614 9
            case 23:
615 9
            case 25:
616
                //Deletes the point from the selected part, if exists
617 6
                if (isset($this->SHPData['parts'][$partIndex]) && isset($this->SHPData['parts'][$partIndex]['points'][$pointIndex])) {
618 6
                    $count = count($this->SHPData['parts'][$partIndex]['points']) - 1;
619 6
                    for ($i = $pointIndex; $i < $count; $i++) {
620 6
                        $this->SHPData['parts'][$partIndex]['points'][$i] = $this->SHPData['parts'][$partIndex]['points'][$i + 1];
621 6
                    }
622 6
                    unset($this->SHPData['parts'][$partIndex]['points'][count($this->SHPData['parts'][$partIndex]['points']) - 1]);
623
624 6
                    $this->SHPData['numparts'] = count($this->SHPData['parts']);
625 6
                    $this->SHPData['numpoints']--;
626 6
                }
627 6
                break;
628 3
            case 8:
629 3
            case 18:
630 3
            case 28:
631
                //Deletes the point, if exists
632 3
                if (isset($this->SHPData['points'][$pointIndex])) {
633 3
                    $count = count($this->SHPData['points']) - 1;
634 3
                    for ($i = $pointIndex; $i < $count; $i++) {
635 3
                        $this->SHPData['points'][$i] = $this->SHPData['points'][$i + 1];
636 3
                    }
637 3
                    unset($this->SHPData['points'][count($this->SHPData['points']) - 1]);
638
639 3
                    $this->SHPData['numpoints']--;
640 3
                }
641 3
                break;
642
            default:
643
                $this->setError(sprintf('The Shape Type "%s" is not supported.', $this->shapeType));
644
                break;
645 12
        }
646 12
    }
647
648 12
    public function getContentLength() {
649
        // The content length for a record is the length of the record contents section measured in 16-bit words.
650
        // one coordinate makes 4 16-bit words (64 bit double)
651 12
        switch ($this->shapeType) {
652 12
            case 0:
653
                $result = 0;
654
                break;
655 12
            case 1:
656 1
                $result = 10;
657 1
                break;
658 11
            case 21:
659 1
                $result = 10 + 4;
660 1
                break;
661 10
            case 11:
662 1
                $result = 10 + 8;
663 1
                break;
664 9
            case 3:
665 9
            case 5:
666 2
                $count = count($this->SHPData['parts']);
667 2
                $result = 22 + 2 * $count;
668 2
                for ($i = 0; $i < $count; $i++) {
669 2
                    $result += 8 * count($this->SHPData['parts'][$i]['points']);
670 2
                }
671 2
                break;
672 7
            case 23:
673 7 View Code Duplication
            case 25:
674 2
                $count = count($this->SHPData['parts']);
675 2
                $result = 22 + (2 * 4) + 2 * $count;
676 2
                for ($i = 0; $i < $count; $i++) {
677 2
                    $result += (8 + 4) * count($this->SHPData['parts'][$i]['points']);
678 2
                }
679 2
                break;
680 5
            case 13:
681 5 View Code Duplication
            case 15:
682 2
                $count = count($this->SHPData['parts']);
683 2
                $result = 22 + (4 * 4) + 2 * $count;
684 2
                for ($i = 0; $i < $count; $i++) {
685 2
                    $result += (8 + 8) * count($this->SHPData['parts'][$i]['points']);
686 2
                }
687 2
                break;
688 3
            case 8:
689 1
                $result = 20 + 8 * count($this->SHPData['points']);
690 1
                break;
691 2 View Code Duplication
            case 28:
692 1
                $result = 20 + (2 * 4) + (8 + 4) * count($this->SHPData['points']);
693 1
                break;
694 1 View Code Duplication
            case 18:
695 1
                $result = 20 + (4 * 4) + (8 + 8) * count($this->SHPData['points']);
696 1
                break;
697
            default:
698
                $result = false;
699
                $this->setError(sprintf('The Shape Type "%s" is not supported.', $this->shapeType));
700
                break;
701 12
        }
702 12
        return $result;
703
    }
704
705
    private function _loadDBFData() {
706
        $this->DBFData = @dbase_get_record_with_names($this->DBFFile, $this->recordNumber);
707
        unset($this->DBFData['deleted']);
708
    }
709
710
    private function _saveDBFData() {
711
        if (count($this->DBFData) == 0) {
712
            return;
713
        }
714
        unset($this->DBFData['deleted']);
715
        if ($this->recordNumber <= dbase_numrecords($this->DBFFile)) {
716
            if (!dbase_replace_record($this->DBFFile, array_values($this->DBFData), $this->recordNumber)) {
717
                $this->setError('I wasn\'t possible to update the information in the DBF file.');
718
            }
719
        } else {
720
            if (!dbase_add_record($this->DBFFile, array_values($this->DBFData))) {
721
                $this->setError('I wasn\'t possible to add the information to the DBF file.');
722
            }
723
        }
724
    }
725
726
    /**
727
     * Sets error message
728
     *
729
     * @param string $error
730
     *
731
     * @return void
732
     */
733
    public function setError($error) {
734
        $this->lastError = $error;
735
    }
736
737
    /**
738
     * Returns shape name
739
     *
740
     * @return string
741
     */
742 1
    public function getShapeName()
743
    {
744 1
        return ShapeFile::nameShape($this->shapeType);
745
    }
746
}
747