Passed
Push — master ( 28fcf3...e27c42 )
by William
02:20
created

ShapeFileTest::testGetDBFHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * phpMyAdmin ShapeFile library
7
 * <https://github.com/phpmyadmin/shapefile/>.
8
 *
9
 * Copyright 2006-2007 Ovidio <ovidio AT users.sourceforge.net>
10
 * Copyright 2016 - 2017 Michal Čihař <[email protected]>
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, you can download one from
23
 * https://www.gnu.org/copyleft/gpl.html.
24
 */
25
26
namespace ShapeFileTest;
27
28
use PhpMyAdmin\ShapeFile\ShapeFile;
29
use PhpMyAdmin\ShapeFile\ShapeRecord;
30
use PHPUnit\Framework\TestCase;
31
use function count;
32
33
class ShapeFileTest extends TestCase
34
{
35
    /**
36
     * Tests loading of a file.
37
     *
38
     * @param string   $filename Name of file
39
     * @param int      $records  Expected number of records
40
     * @param int|null $parts    Expected number of parts in first record
41
     *
42
     * @dataProvider provideFiles
43
     */
44
    public function testLoad(string $filename, int $records, ?int $parts): void
45
    {
46
        $shp = new ShapeFile(1);
47
        $shp->loadFromFile($filename);
48
        $this->assertEquals('', $shp->lastError);
49
        $this->assertEquals($records, count($shp->records));
50
        if ($parts === null) {
51
            return;
52
        }
53
54
        $this->assertEquals($parts, count($shp->records[0]->shpData['parts']));
55
    }
56
57
    /**
58
     * Data provider for file loading tests.
59
     *
60
     * @return array
61
     */
62
    public function provideFiles(): array
63
    {
64
        return [
65
            [
66
                'data/capitals.*',
67
                652,
68
                null,
69
            ],
70
            [
71
                'data/mexico.*',
72
                32,
73
                3,
74
            ],
75
            [
76
                'data/Czech_Republic_AL2.*',
77
                1,
78
                1,
79
            ],
80
            [
81
                'data/w001n05f.*',
82
                16,
83
                1,
84
            ],
85
            [
86
                'data/bc_hospitals.*',
87
                44,
88
                null,
89
            ],
90
            [
91
                'data/multipoint.*',
92
                312,
93
                null,
94
            ],
95
        ];
96
    }
97
98
    /**
99
     * Test error handling in loader.
100
     *
101
     * @param string $filename name to load
102
     *
103
     * @dataProvider provideErrorFiles
104
     */
105
    public function testLoadError(string $filename): void
106
    {
107
        $shp = new ShapeFile(1);
108
        $shp->loadFromFile($filename);
109
        $this->assertNotEquals('', $shp->lastError);
110
    }
111
112
    /**
113
     * Test load an empty file name
114
     */
115
    public function testLoadEmptyFilename(): void
116
    {
117
        $shp = new ShapeFile(1);
118
        $shp->loadFromFile('');
119
        if (ShapeFile::supportsDbase()) {
120
            $this->assertEquals('It wasn\'t possible to find the DBase file ""', $shp->lastError);
121
122
            return;
123
        }
124
        $this->assertEquals('Not a SHP file (file code mismatch)', $shp->lastError);
125
    }
126
127
    /**
128
     * Test to call getDBFHeader on a non loaded file
129
     */
130
    public function testGetDBFHeader(): void
131
    {
132
        $shp = new ShapeFile(1);
133
        $this->assertNull($shp->getDBFHeader());
134
    }
135
136
    /**
137
     * Data provider for file loading error tests.
138
     *
139
     * @return array
140
     */
141
    public function provideErrorFiles(): array
142
    {
143
        $result = [
144
            ['data/no-shp.*'],
145
            ['data/missing.*'],
146
            ['data/invalid-shp.*'],
147
        ];
148
149
        if (ShapeFile::supportsDbase()) {
150
            $result[] = ['data/no-dbf.*'];
151
            $result[] = ['data/invalid-dbf.*'];
152
        }
153
154
        return $result;
155
    }
156
157
    /**
158
     * Creates test data.
159
     */
160
    private function createTestData(): void
161
    {
162
        $shp = new ShapeFile(1);
163
164
        $record0 = new ShapeRecord(1);
165
        $record0->addPoint(['x' => 482131.764567, 'y' => 2143634.39608]);
166
167
        $record1 = new ShapeRecord(11);
168
        $record1->addPoint(['x' => 472131.764567, 'y' => 2143634.39608, 'z' => 220, 'm' => 120]);
169
170
        $record2 = new ShapeRecord(21);
171
        $record2->addPoint(['x' => 492131.764567, 'y' => 2143634.39608, 'z' => 150, 'm' => 80]);
172
173
        $record3 = new ShapeRecord(3);
174
        $record3->addPoint(['x' => 482131.764567, 'y' => 2143634.39608], 0);
175
        $record3->addPoint(['x' => 482132.764567, 'y' => 2143635.39608], 0);
176
        $record3->addPoint(['x' => 482131.764567, 'y' => 2143635.39608], 1);
177
        $record3->addPoint(['x' => 482132.764567, 'y' => 2143636.39608], 1);
178
179
        $shp->addRecord($record0);
180
        $shp->addRecord($record1);
181
        $shp->addRecord($record2);
182
        $shp->addRecord($record3);
183
184
        $shp->setDBFHeader(
185
            [
186
                [
187
                    'ID',
188
                    'N',
189
                    8,
190
                    0,
191
                ],
192
                [
193
                    'DESC',
194
                    'C',
195
                    50,
196
                    0,
197
                ],
198
            ]
199
        );
200
201
        $shp->records[0]->dbfData['ID'] = '1';
202
        $shp->records[0]->dbfData['DESC'] = 'AAAAAAAAA';
203
204
        $shp->records[1]->dbfData['ID'] = '2';
205
        $shp->records[1]->dbfData['DESC'] = 'BBBBBBBBBB';
206
207
        $shp->records[2]->dbfData['ID'] = '3';
208
        $shp->records[2]->dbfData['DESC'] = 'CCCCCCCCCCC';
209
210
        $shp->records[3]->dbfData['ID'] = '4';
211
        $shp->records[3]->dbfData['DESC'] = 'CCCCCCCCCCC';
212
213
        $shp->saveToFile('./data/test_shape.*');
214
    }
215
216
    /**
217
     * Tests creating file.
218
     */
219
    public function testCreate(): void
220
    {
221
        if (! ShapeFile::supportsDbase()) {
222
            $this->markTestSkipped('dbase extension missing');
223
        }
224
225
        $this->createTestData();
226
227
        $shp = new ShapeFile(1);
228
        $shp->loadFromFile('./data/test_shape.*');
229
        $this->assertEquals(4, count($shp->records));
230
    }
231
232
    /**
233
     * Tests removing record from a file.
234
     */
235
    public function testDelete(): void
236
    {
237
        if (! ShapeFile::supportsDbase()) {
238
            $this->markTestSkipped('dbase extension missing');
239
        }
240
241
        $this->createTestData();
242
243
        $shp = new ShapeFile(1);
244
        $shp->loadFromFile('./data/test_shape.*');
245
        $shp->deleteRecord(1);
246
        $shp->saveToFile();
247
        $this->assertEquals(3, count($shp->records));
248
249
        $shp = new ShapeFile(1);
250
        $shp->loadFromFile('./data/test_shape.*');
251
        $this->assertEquals(3, count($shp->records));
252
    }
253
254
    /**
255
     * Test adding record to a file.
256
     */
257
    public function testAdd(): void
258
    {
259
        if (! ShapeFile::supportsDbase()) {
260
            $this->markTestSkipped('dbase extension missing');
261
        }
262
263
        $this->createTestData();
264
265
        $shp = new ShapeFile(1);
266
        $shp->loadFromFile('./data/test_shape.*');
267
268
        $record0 = new ShapeRecord(1);
269
        $record0->addPoint(['x' => 482131.764567, 'y' => 2143634.39608]);
270
271
        $shp->addRecord($record0);
272
        $shp->records[4]->dbfData['ID'] = '4';
273
        $shp->records[4]->dbfData['DESC'] = 'CCCCCCCCCCC';
274
275
        $shp->saveToFile();
276
        $this->assertEquals(5, count($shp->records));
277
278
        $shp = new ShapeFile(1);
279
        $shp->loadFromFile('./data/test_shape.*');
280
        $this->assertEquals(5, count($shp->records));
281
    }
282
283
    /**
284
     * Tests saving without DBF.
285
     */
286
    public function testSaveNoDBF(): void
287
    {
288
        $shp = new ShapeFile(1);
289
        $shp->saveToFile('./data/test_nodbf.*');
290
        $this->assertFileNotExists('./data/test_nodbf.dbf');
291
    }
292
293
    /**
294
     * Test shape naming.
295
     */
296
    public function testShapeName(): void
297
    {
298
        $obj = new ShapeRecord(1);
299
        $this->assertEquals('Point', $obj->getShapeName());
300
        $obj = new ShapeFile(1);
301
        $this->assertEquals('Point', $obj->getShapeName());
302
        $obj = new ShapeRecord(-1);
303
        $this->assertEquals('Shape -1', $obj->getShapeName());
304
    }
305
306
    /**
307
     * Test shapes save/load round robin.
308
     *
309
     * @param int   $type   Shape type
310
     * @param array $points Points
311
     *
312
     * @dataProvider shapes
313
     */
314
    public function testShapeSaveLoad(int $type, array $points): void
315
    {
316
        $filename = './data/test_shape-' . $type . '.*';
317
        $shp = new ShapeFile($type);
318
        $shp->setDBFHeader([
319
            [
320
                'ID',
321
                'N',
322
                19,
323
                0,
324
            ],
325
            [
326
                'DESC',
327
                'C',
328
                14,
329
                0,
330
            ],
331
        ]);
332
333
        $record0 = new ShapeRecord($type);
334
335
        foreach ($points as $point) {
336
            $record0->addPoint($point[0], $point[1]);
337
        }
338
339
        $shp->addRecord($record0);
340
341
        $shp->saveToFile($filename);
342
343
        $shp2 = new ShapeFile($type);
344
        $shp2->loadFromFile($filename);
345
346
        $this->assertEquals(
347
            count($shp->records),
348
            count($shp2->records)
349
        );
350
351
        $record = $shp->records[0];
352
        $record2 = $shp2->records[0];
353
354
        $items = [
355
            'numparts',
356
            'numpoints',
357
        ];
358
        foreach ($items as $item) {
359
            if (! isset($record->shpData[$item])) {
360
                continue;
361
            }
362
363
            $this->assertEquals(
364
                $record->shpData[$item],
365
                $record2->shpData[$item]
366
            );
367
        }
368
369
        /* Test deletion works */
370
        $record->deletePoint();
371
    }
372
373
    /**
374
     * Test shapes save/load round robin with z coordinate.
375
     *
376
     * @param int   $type   Shape type
377
     * @param array $points Points
378
     *
379
     * @dataProvider shapes
380
     */
381
    public function testZetShapeSaveLoad(int $type, array $points): void
382
    {
383
        $this->testShapeSaveLoad($type + 10, $points);
384
    }
385
386
    /**
387
     * Test shapes save/load round robin with measure.
388
     *
389
     * @param int   $type   Shape type
390
     * @param array $points Points
391
     *
392
     * @dataProvider shapes
393
     */
394
    public function testMeasureShapeSaveLoad(int $type, array $points): void
395
    {
396
        $this->testShapeSaveLoad($type + 20, $points);
397
    }
398
399
    /**
400
     * Data provider for save/load testing.
401
     *
402
     * @return array
403
     */
404
    public function shapes(): array
405
    {
406
        return [
407
            [
408
                1,
409
                [
410
                    [
411
                        [
412
                            'x' => 10,
413
                            'y' => 20,
414
                        ],
415
                        0,
416
                    ],
417
                ],
418
            ],
419
            [
420
                3,
421
                [
422
                    [
423
                        [
424
                            'x' => 10,
425
                            'y' => 20,
426
                        ],
427
                        0,
428
                    ],
429
                    [
430
                        [
431
                            'x' => 20,
432
                            'y' => 20,
433
                        ],
434
                        0,
435
                    ],
436
                    [
437
                        [
438
                            'x' => 20,
439
                            'y' => 20,
440
                        ],
441
                        1,
442
                    ],
443
                    [
444
                        [
445
                            'x' => 20,
446
                            'y' => 10,
447
                        ],
448
                        1,
449
                    ],
450
                ],
451
            ],
452
            [
453
                5,
454
                [
455
                    [
456
                        [
457
                            'x' => 10,
458
                            'y' => 20,
459
                        ],
460
                        0,
461
                    ],
462
                    [
463
                        [
464
                            'x' => 20,
465
                            'y' => 20,
466
                        ],
467
                        0,
468
                    ],
469
                    [
470
                        [
471
                            'x' => 20,
472
                            'y' => 20,
473
                        ],
474
                        1,
475
                    ],
476
                    [
477
                        [
478
                            'x' => 20,
479
                            'y' => 10,
480
                        ],
481
                        1,
482
                    ],
483
                    [
484
                        [
485
                            'x' => 20,
486
                            'y' => 10,
487
                        ],
488
                        2,
489
                    ],
490
                    [
491
                        [
492
                            'x' => 10,
493
                            'y' => 20,
494
                        ],
495
                        2,
496
                    ],
497
                ],
498
            ],
499
            [
500
                8,
501
                [
502
                    [
503
                        [
504
                            'x' => 10,
505
                            'y' => 20,
506
                        ],
507
                        0,
508
                    ],
509
                    [
510
                        [
511
                            'x' => 20,
512
                            'y' => 20,
513
                        ],
514
                        0,
515
                    ],
516
                    [
517
                        [
518
                            'x' => 20,
519
                            'y' => 10,
520
                        ],
521
                        0,
522
                    ],
523
                ],
524
            ],
525
        ];
526
    }
527
528
    public function testSearch(): void
529
    {
530
        $shp = new ShapeFile(0);
531
        $shp->loadFromFile('data/capitals.*');
532
        /* Nonexisting entry or no dbase support */
533
        $this->assertEquals(
534
            -1,
535
            $shp->getIndexFromDBFData('CNTRY_NAME', 'nonexisting')
536
        );
537
        if (! ShapeFile::supportsDbase()) {
538
            return;
539
        }
540
541
        $this->assertEquals(
542
            218,
543
            $shp->getIndexFromDBFData('CNTRY_NAME', 'Czech Republic')
544
        );
545
    }
546
}
547