Passed
Push — master ( 228075...1455af )
by Maurício
13:04 queued 05:18
created

ShapeFile::saveBBoxRecord()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 PhpMyAdmin\ShapeFile;
27
28
use function array_push;
29
use function chr;
30
use function count;
31
use function extension_loaded;
32
use function fclose;
33
use function feof;
34
use function file_exists;
35
use function fopen;
36
use function fread;
37
use function fwrite;
38
use function in_array;
39
use function is_array;
40
use function is_readable;
41
use function ord;
42
use function pack;
43
use function sprintf;
44
use function str_replace;
45
use function strpos;
46
use function strtoupper;
47
use function substr;
48
use function trim;
49
use function unlink;
50
51
/**
52
 * ShapeFile class.
53
 */
54
class ShapeFile
55
{
56
    public const MAGIC = 0x270a;
57
58
    /** @var string|null */
59
    public $fileName;
60
61
    /** @var resource|null */
62
    private $shpFile = null;
63
    /** @var resource|null */
64
    private $shxFile = null;
65
    /** @var resource|null */
66
    private $dbfFile = null;
67
68
    /** @var array|null */
69
    private $dbfHeader;
70
71
    /** @var string */
72
    public $lastError = '';
73
74
    /** @var array */
75
    public $boundingBox = [
76
        'xmin' => 0.0,
77
        'ymin' => 0.0,
78
        'xmax' => 0.0,
79
        'ymax' => 0.0,
80
    ];
81
    /** @var int */
82
    private $fileLength = 0;
83
84
    /** @var int|false */
85
    public $shapeType = 0;
86
87
    /** @var array */
88
    public $records = [];
89
90
    /**
91
     * Checks whether dbase manipulations are supported.
92
     */
93 201
    public static function supportsDbase(): bool
94
    {
95 201
        return extension_loaded('dbase');
96
    }
97
98
    /**
99
     * @param int         $shapeType   File shape type, should be same as all records
100
     * @param array       $boundingBox File bounding box
101
     * @param string|null $fileName    File name
102
     */
103 233
    public function __construct(
104
        int $shapeType,
105
        array $boundingBox = [
106
            'xmin' => 0.0,
107
            'ymin' => 0.0,
108
            'xmax' => 0.0,
109
            'ymax' => 0.0,
110
        ],
111
        ?string $fileName = null
112
    ) {
113 233
        $this->shapeType = $shapeType;
114 233
        $this->boundingBox = $boundingBox;
115 233
        $this->fileName = $fileName;
116
117
        /**
118
         * The value for file length is the total length of the file in 16-bit words
119
         * (including the fifty 16-bit words that make up the header).
120
         */
121 233
        $this->fileLength = 50;
122
    }
123
124
    /**
125
     * Loads shapefile and dbase (if supported).
126
     *
127
     * @param string $fileName File mask to load (eg. example.*)
128
     */
129 209
    public function loadFromFile(string $fileName): bool
130
    {
131 209
        if (! empty($fileName)) {
132 201
            $this->fileName = $fileName;
133 201
            $result = $this->openSHPFile();
134
        } else {
135
            /* We operate on buffer emulated by readSHP / eofSHP */
136 8
            $result = true;
137
        }
138
139 209
        if ($result && ($this->openDBFFile())) {
140 173
            if (! $this->loadHeaders()) {
141 6
                $this->closeSHPFile();
142 6
                $this->closeDBFFile();
143
144 6
                return false;
145
            }
146
147 167
            if (! $this->loadRecords()) {
148
                $this->closeSHPFile();
149
                $this->closeDBFFile();
150
151
                return false;
152
            }
153
154 167
            $this->closeSHPFile();
155 167
            $this->closeDBFFile();
156
157 167
            return true;
158
        }
159
160 36
        return false;
161
    }
162
163
    /**
164
     * Saves shapefile.
165
     *
166
     * @param string|null $fileName Name of file, otherwise existing is used
167
     */
168 119
    public function saveToFile(?string $fileName = null): bool
169
    {
170 119
        if ($fileName !== null) {
171 119
            $this->fileName = $fileName;
172
        }
173
174 119
        if (! $this->openSHPFile(true) || (! $this->openSHXFile(true)) || (! $this->createDBFFile())) {
175
            return false;
176
        }
177
178 119
        $this->saveHeaders();
179 119
        $this->saveRecords();
180 119
        $this->closeSHPFile();
181 119
        $this->closeSHXFile();
182 119
        $this->closeDBFFile();
183
184 119
        return true;
185
    }
186
187
    /**
188
     * Generates filename with given extension.
189
     *
190
     * @param string $extension Extension to use (including dot)
191
     */
192 214
    private function getFilename(string $extension): string
193
    {
194 214
        return str_replace('.*', $extension, (string) $this->fileName);
195
    }
196
197
    /**
198
     * Updates bounding box based on shpData.
199
     *
200
     * @param string $type Type of box
201
     * @param array  $data ShapeRecord shpData
202
     */
203 111
    private function updateBBox(string $type, array $data): void
204
    {
205 111
        $min = $type . 'min';
206 111
        $max = $type . 'max';
207
208
        if (
209 111
            ! isset($this->boundingBox[$min])
210 111
            || $this->boundingBox[$min] == 0.0 // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators
211 111
            || ($this->boundingBox[$min] > $data[$min])
212
        ) {
213 111
            $this->boundingBox[$min] = $data[$min];
214
        }
215
216
        if (
217 111
            isset($this->boundingBox[$max])
218 111
            && $this->boundingBox[$max] != 0.0 // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators
219 111
            && ($this->boundingBox[$max] >= $data[$max])
220
        ) {
221 15
            return;
222
        }
223
224 111
        $this->boundingBox[$max] = $data[$max];
225
    }
226
227
    /**
228
     * Adds record to shape file.
229
     *
230
     * @return int Number of added record
231
     */
232 111
    public function addRecord(ShapeRecord $record): int
233
    {
234 111
        if (isset($this->dbfHeader) && (is_array($this->dbfHeader))) {
235 101
            $record->updateDBFInfo($this->dbfHeader);
236
        }
237
238 111
        $this->fileLength += $record->getContentLength() + 4;
239 111
        $this->records[] = $record;
240 111
        $this->records[count($this->records) - 1]->recordNumber = count($this->records);
241
242 111
        $this->updateBBox('x', $record->shpData);
243 111
        $this->updateBBox('y', $record->shpData);
244
245 111
        if (in_array($this->shapeType, [11, 13, 15, 18, 21, 23, 25, 28])) {
246 64
            $this->updateBBox('m', $record->shpData);
247
        }
248
249 111
        if (in_array($this->shapeType, [11, 13, 15, 18])) {
250 32
            $this->updateBBox('z', $record->shpData);
251
        }
252
253 111
        return count($this->records) - 1;
254
    }
255
256
    /**
257
     * Deletes record from shapefile.
258
     */
259 5
    public function deleteRecord(int $index): void
260
    {
261 5
        if (! isset($this->records[$index])) {
262
            return;
263
        }
264
265 5
        $this->fileLength -= $this->records[$index]->getContentLength() + 4;
266 5
        $count = count($this->records) - 1;
267 5
        for ($i = $index; $i < $count; ++$i) {
268 5
            $this->records[$i] = $this->records[$i + 1];
269
        }
270
271 5
        unset($this->records[count($this->records) - 1]);
272 5
        $this->deleteRecordFromDBF($index);
273
    }
274
275
    /**
276
     * Returns array defining fields in DBF file.
277
     *
278
     * @return array|null see setDBFHeader for more information
279
     */
280 8
    public function getDBFHeader(): ?array
281
    {
282 8
        return $this->dbfHeader;
283
    }
284
285
    /**
286
     * Changes array defining fields in DBF file, used in dbase_create call.
287
     *
288
     * @param array $header An array of arrays, each array describing the
289
     *                      format of one field of the database. Each
290
     *                      field consists of a name, a character indicating
291
     *                      the field type, and optionally, a length,
292
     *                      a precision and a nullable flag.
293
     */
294 111
    public function setDBFHeader(array $header): void
295
    {
296 111
        $this->dbfHeader = $header;
297
298 111
        $count = count($this->records);
299 111
        for ($i = 0; $i < $count; ++$i) {
300 15
            $this->records[$i]->updateDBFInfo($header);
301
        }
302
    }
303
304
    /**
305
     * Lookups value in the DBF file and returns index.
306
     *
307
     * @param string $field Field to match
308
     * @param mixed  $value Value to match
309
     */
310 8
    public function getIndexFromDBFData(string $field, $value): int
311
    {
312 8
        foreach ($this->records as $index => $record) {
313
            if (
314 8
                isset($record->dbfData[$field]) &&
315 8
                (trim(strtoupper($record->dbfData[$field])) === strtoupper($value))
316
            ) {
317 5
                return $index;
318
            }
319
        }
320
321 8
        return -1;
322
    }
323
324
    /**
325
     * Loads DBF metadata.
326
     */
327 110
    private function loadDBFHeader(): array
328
    {
329 110
        $DBFFile = fopen($this->getFilename('.dbf'), 'r');
330
331 110
        $result = [];
332 110
        $i = 1;
333 110
        $inHeader = true;
334
335 110
        while ($inHeader) {
336 110
            if (! feof($DBFFile)) {
337 110
                $buff32 = fread($DBFFile, 32);
338 110
                if ($i > 1) {
339 110
                    if (substr($buff32, 0, 1) === chr(13)) {
340 110
                        $inHeader = false;
341
                    } else {
342 110
                        $pos = strpos(substr($buff32, 0, 10), chr(0));
343 110
                        $pos = ($pos === false ? 10 : $pos);
344
345 110
                        $fieldName = substr($buff32, 0, $pos);
346 110
                        $fieldType = substr($buff32, 11, 1);
347 110
                        $fieldLen = ord(substr($buff32, 16, 1));
348 110
                        $fieldDec = ord(substr($buff32, 17, 1));
349
350 110
                        array_push($result, [$fieldName, $fieldType, $fieldLen, $fieldDec]);
351
                    }
352
                }
353
354 110
                ++$i;
355
            } else {
356
                $inHeader = false;
357
            }
358
        }
359
360 110
        fclose($DBFFile);
361
362 110
        return $result;
363
    }
364
365
    /**
366
     * Deletes record from the DBF file.
367
     */
368 5
    private function deleteRecordFromDBF(int $index): void
369
    {
370 5
        if ($this->dbfFile === null || ! @dbase_delete_record($this->dbfFile, $index)) {
0 ignored issues
show
introduced by
Function dbase_delete_record() should not be referenced via a fallback global name, but via a use statement.
Loading history...
Bug introduced by
The function dbase_delete_record was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

370
        if ($this->dbfFile === null || ! @/** @scrutinizer ignore-call */ dbase_delete_record($this->dbfFile, $index)) {
Loading history...
371 5
            return;
372
        }
373
374
        dbase_pack($this->dbfFile);
0 ignored issues
show
introduced by
Function dbase_pack() should not be referenced via a fallback global name, but via a use statement.
Loading history...
Bug introduced by
The function dbase_pack was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

374
        /** @scrutinizer ignore-call */ 
375
        dbase_pack($this->dbfFile);
Loading history...
375
    }
376
377
    /**
378
     * Loads SHP file metadata.
379
     */
380 173
    private function loadHeaders(): bool
381
    {
382 173
        if (Util::loadData('N', $this->readSHP(4)) !== self::MAGIC) {
383 6
            $this->setError('Not a SHP file (file code mismatch)');
384
385 6
            return false;
386
        }
387
388
        /* Skip 20 unused bytes */
389 167
        $this->readSHP(20);
390
391 167
        $this->fileLength = Util::loadData('N', $this->readSHP(4));
0 ignored issues
show
Documentation Bug introduced by
It seems like PhpMyAdmin\ShapeFile\Uti...'N', $this->readSHP(4)) can also be of type false. However, the property $fileLength is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
392
393
        /* We currently ignore version */
394 167
        $this->readSHP(4);
395
396 167
        $this->shapeType = Util::loadData('V', $this->readSHP(4));
397
398 167
        $this->boundingBox = [];
399 167
        $this->boundingBox['xmin'] = Util::loadData('d', $this->readSHP(8));
400 167
        $this->boundingBox['ymin'] = Util::loadData('d', $this->readSHP(8));
401 167
        $this->boundingBox['xmax'] = Util::loadData('d', $this->readSHP(8));
402 167
        $this->boundingBox['ymax'] = Util::loadData('d', $this->readSHP(8));
403 167
        $this->boundingBox['zmin'] = Util::loadData('d', $this->readSHP(8));
404 167
        $this->boundingBox['zmax'] = Util::loadData('d', $this->readSHP(8));
405 167
        $this->boundingBox['mmin'] = Util::loadData('d', $this->readSHP(8));
406 167
        $this->boundingBox['mmax'] = Util::loadData('d', $this->readSHP(8));
407
408 167
        if (self::supportsDbase()) {
409 110
            $this->dbfHeader = $this->loadDBFHeader();
410
        }
411
412 167
        return true;
413
    }
414
415
    /**
416
     * Saves bounding box record, possibly using 0 instead of not set values.
417
     *
418
     * @param resource $file File object
419
     * @param string   $type Bounding box dimension (eg. xmax, mmin...)
420
     */
421 119
    private function saveBBoxRecord($file, string $type): void
422
    {
423 119
        fwrite($file, Util::packDouble(
424 119
            $this->boundingBox[$type] ?? 0
425
        ));
426
    }
427
428
    /**
429
     * Saves bounding box to a file.
430
     *
431
     * @param resource $file File object
432
     */
433 119
    private function saveBBox($file): void
434
    {
435 119
        $this->saveBBoxRecord($file, 'xmin');
436 119
        $this->saveBBoxRecord($file, 'ymin');
437 119
        $this->saveBBoxRecord($file, 'xmax');
438 119
        $this->saveBBoxRecord($file, 'ymax');
439 119
        $this->saveBBoxRecord($file, 'zmin');
440 119
        $this->saveBBoxRecord($file, 'zmax');
441 119
        $this->saveBBoxRecord($file, 'mmin');
442 119
        $this->saveBBoxRecord($file, 'mmax');
443
    }
444
445
    /**
446
     * Saves SHP and SHX file metadata.
447
     */
448 119
    private function saveHeaders(): void
449
    {
450 119
        fwrite($this->shpFile, pack('NNNNNN', self::MAGIC, 0, 0, 0, 0, 0));
451 119
        fwrite($this->shpFile, pack('N', $this->fileLength));
452 119
        fwrite($this->shpFile, pack('V', 1000));
453 119
        fwrite($this->shpFile, pack('V', $this->shapeType));
454 119
        $this->saveBBox($this->shpFile);
455
456 119
        fwrite($this->shxFile, pack('NNNNNN', self::MAGIC, 0, 0, 0, 0, 0));
457 119
        fwrite($this->shxFile, pack('N', 50 + 4 * count($this->records)));
458 119
        fwrite($this->shxFile, pack('V', 1000));
459 119
        fwrite($this->shxFile, pack('V', $this->shapeType));
460 119
        $this->saveBBox($this->shxFile);
461
    }
462
463
    /**
464
     * Loads records from SHP file (and DBF).
465
     */
466 167
    private function loadRecords(): bool
467
    {
468
        /* Need to start at offset 100 */
469 167
        while (! $this->eofSHP()) {
470 167
            $record = new ShapeRecord(-1);
471 167
            $record->loadFromFile($this, $this->shpFile, $this->dbfFile);
472 167
            if ($record->lastError !== '') {
473
                $this->setError($record->lastError);
474
475
                return false;
476
            }
477
478 167
            if (($record->shapeType === false || $record->shapeType === '') && $this->eofSHP()) {
479 167
                break;
480
            }
481
482 167
            $this->records[] = $record;
483
        }
484
485 167
        return true;
486
    }
487
488
    /**
489
     * Saves records to SHP and SHX files.
490
     */
491 119
    private function saveRecords(): void
492
    {
493 119
        $offset = 50;
494 119
        if (! is_array($this->records) || (count($this->records) <= 0)) {
0 ignored issues
show
introduced by
The condition is_array($this->records) is always true.
Loading history...
495 8
            return;
496
        }
497
498 111
        foreach ($this->records as $index => $record) {
499
            //Save the record to the .shp file
500 111
            $record->saveToFile($this->shpFile, $this->dbfFile, $index + 1);
501
502
            //Save the record to the .shx file
503 111
            fwrite($this->shxFile, pack('N', $offset));
504 111
            fwrite($this->shxFile, pack('N', $record->getContentLength()));
505 111
            $offset += 4 + $record->getContentLength();
506
        }
507
    }
508
509
    /**
510
     * Generic interface to open files.
511
     *
512
     * @param bool   $toWrite   Whether file should be opened for writing
513
     * @param string $extension File extension
514
     * @param string $name      Verbose file name to report errors
515
     *
516
     * @return resource|false File handle
517
     */
518 209
    private function openFile(bool $toWrite, string $extension, string $name)
519
    {
520 209
        $shpName = $this->getFilename($extension);
521 209
        $result = @fopen($shpName, ($toWrite ? 'wb+' : 'rb'));
522 209
        if (! $result) {
0 ignored issues
show
introduced by
$result is of type false|resource, thus it always evaluated to false.
Loading history...
523 16
            $this->setError(sprintf('It wasn\'t possible to open the %s file "%s"', $name, $shpName));
524
525 16
            return false;
526
        }
527
528 193
        return $result;
529
    }
530
531
    /**
532
     * Opens SHP file.
533
     *
534
     * @param bool $toWrite Whether file should be opened for writing
535
     */
536 209
    private function openSHPFile(bool $toWrite = false): bool
537
    {
538 209
        $this->shpFile = $this->openFile($toWrite, '.shp', 'Shape');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->openFile($toWrite, '.shp', 'Shape') of type false is incompatible with the declared type null|resource of property $shpFile.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
539
540 209
        return (bool) $this->shpFile;
541
    }
542
543
    /**
544
     * Closes SHP file.
545
     */
546 181
    private function closeSHPFile(): void
547
    {
548 181
        if (! $this->shpFile) {
549 3
            return;
550
        }
551
552 178
        fclose($this->shpFile);
553 178
        $this->shpFile = null;
554
    }
555
556
    /**
557
     * Opens SHX file.
558
     *
559
     * @param bool $toWrite Whether file should be opened for writing
560
     */
561 119
    private function openSHXFile(bool $toWrite = false): bool
562
    {
563 119
        $this->shxFile = $this->openFile($toWrite, '.shx', 'Index');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->openFile($toWrite, '.shx', 'Index') of type false is incompatible with the declared type null|resource of property $shxFile.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
564
565 119
        return (bool) $this->shxFile;
566
    }
567
568
    /**
569
     * Closes SHX file.
570
     */
571 119
    private function closeSHXFile(): void
572
    {
573 119
        if (! $this->shxFile) {
574
            return;
575
        }
576
577 119
        fclose($this->shxFile);
578 119
        $this->shxFile = null;
579
    }
580
581
    /**
582
     * Creates DBF file.
583
     */
584 119
    private function createDBFFile(): bool
585
    {
586 119
        if (! self::supportsDbase() || ! is_array($this->dbfHeader) || count($this->dbfHeader) === 0) {
587 44
            $this->dbfFile = null;
588
589 44
            return true;
590
        }
591
592 75
        $dbfName = $this->getFilename('.dbf');
593
594
        /* Unlink existing file */
595 75
        if (file_exists($dbfName)) {
596 10
            unlink($dbfName);
597
        }
598
599
        /* Create new file */
600 75
        $this->dbfFile = @dbase_create($dbfName, $this->dbfHeader);
0 ignored issues
show
introduced by
Function dbase_create() should not be referenced via a fallback global name, but via a use statement.
Loading history...
Bug introduced by
The function dbase_create was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

600
        $this->dbfFile = @/** @scrutinizer ignore-call */ dbase_create($dbfName, $this->dbfHeader);
Loading history...
601 75
        if ($this->dbfFile === false) {
602
            $this->setError(sprintf('It wasn\'t possible to create the DBase file "%s"', $dbfName));
603
604
            return false;
605
        }
606
607 75
        return true;
608
    }
609
610
    /**
611
     * Loads DBF file if supported.
612
     */
613 193
    private function openDBFFile(): bool
614
    {
615 193
        if (! self::supportsDbase()) {
616 63
            $this->dbfFile = null;
617
618 63
            return true;
619
        }
620
621 130
        $dbfName = $this->getFilename('.dbf');
622 130
        if (! is_readable($dbfName)) {
623 15
            $this->setError(sprintf('It wasn\'t possible to find the DBase file "%s"', $dbfName));
624
625 15
            return false;
626
        }
627
628 115
        $this->dbfFile = @dbase_open($dbfName, 0);
0 ignored issues
show
Bug introduced by
The function dbase_open was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

628
        $this->dbfFile = @/** @scrutinizer ignore-call */ dbase_open($dbfName, 0);
Loading history...
introduced by
Function dbase_open() should not be referenced via a fallback global name, but via a use statement.
Loading history...
629 115
        if (! $this->dbfFile) {
630 5
            $this->setError(sprintf('It wasn\'t possible to open the DBase file "%s"', $dbfName));
631
632 5
            return false;
633
        }
634
635 110
        return true;
636
    }
637
638
    /**
639
     * Closes DBF file.
640
     */
641 181
    private function closeDBFFile(): void
642
    {
643 181
        if (! $this->dbfFile) {
644 71
            return;
645
        }
646
647 110
        dbase_close($this->dbfFile);
0 ignored issues
show
Bug introduced by
The function dbase_close was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

647
        /** @scrutinizer ignore-call */ 
648
        dbase_close($this->dbfFile);
Loading history...
introduced by
Function dbase_close() should not be referenced via a fallback global name, but via a use statement.
Loading history...
648 110
        $this->dbfFile = null;
649
    }
650
651
    /**
652
     * Sets error message.
653
     */
654 42
    public function setError(string $error): void
655
    {
656 42
        $this->lastError = $error;
657
    }
658
659
    /**
660
     * Reads given number of bytes from SHP file.
661
     *
662
     * @return string|false
663
     */
664 173
    public function readSHP(int $bytes)
665
    {
666 173
        if ($this->shpFile === null) {
667 3
            return false;
668
        }
669
670 170
        return fread($this->shpFile, $bytes);
671
    }
672
673
    /**
674
     * Checks whether file is at EOF.
675
     */
676 167
    public function eofSHP(): bool
677
    {
678 167
        return feof($this->shpFile);
679
    }
680
681
    /**
682
     * Returns shape name.
683
     */
684 8
    public function getShapeName(): string
685
    {
686 8
        return Util::nameShape($this->shapeType);
0 ignored issues
show
Bug introduced by
It seems like $this->shapeType can also be of type boolean; however, parameter $type of PhpMyAdmin\ShapeFile\Util::nameShape() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

686
        return Util::nameShape(/** @scrutinizer ignore-type */ $this->shapeType);
Loading history...
687
    }
688
689
    /**
690
     * Check whether file contains measure data.
691
     *
692
     * For some reason this is distinguished by zero bounding box in the
693
     * specification.
694
     */
695 64
    public function hasMeasure(): bool
696
    {
697
        // phpcs:ignore SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
698 64
        return $this->boundingBox['mmin'] != 0 || $this->boundingBox['mmax'] != 0;
699
    }
700
}
701