upgrade bootstrap and js
This commit is contained in:
72
vendor/Shapefile/Geometry/Geometry.php
vendored
72
vendor/Shapefile/Geometry/Geometry.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -473,44 +473,58 @@ abstract class Geometry
|
||||
* Return sanitized GeoJSON, keeping just the geometry part.
|
||||
* It attempts to sanitize user-provided GeoJSON and throws an exception if it appears to be invalid.
|
||||
*
|
||||
* If a GeoJSON Feature is provided, properties data will be stored within the Geometry.
|
||||
*
|
||||
* @param string $geojson The GeoJSON to sanitize.
|
||||
*
|
||||
* @return string
|
||||
* @return array [
|
||||
* "coordinates" => []
|
||||
* "flag_m" => bool
|
||||
* ]
|
||||
*/
|
||||
protected function geojsonSanitize($geojson)
|
||||
{
|
||||
$geojson = json_decode($geojson, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Cannot parse JSON input');
|
||||
}
|
||||
|
||||
// If it is null it means "an empty Geometry"
|
||||
if ($geojson === null) {
|
||||
// Treat any value other than a GeoJSON object as null (empty Geometry)
|
||||
if (!is_array($geojson)) {
|
||||
return null;
|
||||
}
|
||||
// If it is a Feature just keep the Geometry part
|
||||
if (isset($geojson['geometry'])) {
|
||||
$geojson = $geojson['geometry'];
|
||||
}
|
||||
// Check if "type" and "coordinates" are defined
|
||||
if (!isset($geojson['type'], $geojson['coordinates'])) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID);
|
||||
}
|
||||
// Check if "type" is consistent with current Geometry
|
||||
if (substr(strtoupper(trim($geojson['type'])), 0, strlen($this->getGeoJSONBasetype())) != strtoupper($this->getGeoJSONBasetype())) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID);
|
||||
|
||||
// Handle Feature
|
||||
$geojson = array_change_key_case($geojson, CASE_LOWER);
|
||||
if (isset($geojson['type']) && strtolower(trim($geojson['type'])) === 'feature') {
|
||||
if (!isset($geojson['properties']) || !is_array($geojson['properties'])) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Feature "properties" not defined');
|
||||
}
|
||||
$this->setDataArray($geojson['properties']);
|
||||
$geometry = !empty($geojson['geometry']) ? array_change_key_case($geojson['geometry'], CASE_LOWER) : null;
|
||||
} else {
|
||||
$geometry = $geojson;
|
||||
}
|
||||
|
||||
return $geojson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if GeoJSON type represents a Geometry that has a M dimension.
|
||||
*
|
||||
* @param string $type The type speficied in the GeoJSON.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function geojsonIsM($type)
|
||||
{
|
||||
return substr($type, -1) == 'M';
|
||||
// If geometry is null it means "an empty Geometry"
|
||||
if ($geometry === null) {
|
||||
return null;
|
||||
}
|
||||
// Check if "type" and "coordinates" are defined and in correct format
|
||||
if (!isset($geometry['type'], $geometry['coordinates']) || !is_string($geometry['type']) || !is_array($geometry['coordinates'])) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Geometry "type" or "coordinates" not correctly defined');
|
||||
}
|
||||
// Check if "type" is consistent with current Geometry
|
||||
$type = strtoupper(trim($geometry['type']));
|
||||
if (substr($type, 0, strlen($this->getGeoJSONBasetype())) != strtoupper($this->getGeoJSONBasetype())) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Wrong Geometry type - ' . $geometry['type']);
|
||||
}
|
||||
|
||||
// Empty "coordinates" array means empty Geometry
|
||||
return empty($geometry['coordinates']) ? null : [
|
||||
'coordinates' => $geometry['coordinates'],
|
||||
'flag_m' => substr($type, -1) == 'M',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,7 +617,7 @@ abstract class Geometry
|
||||
($force_z && $force_m && $count < 4) ||
|
||||
$count > 4
|
||||
) {
|
||||
throw new ShapefileException($err_code);
|
||||
throw new ShapefileException($err_code, 'Wrong coordinates format');
|
||||
}
|
||||
|
||||
$ret = [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
|
||||
6
vendor/Shapefile/Geometry/Linestring.php
vendored
6
vendor/Shapefile/Geometry/Linestring.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -188,8 +188,8 @@ class Linestring extends MultiPoint
|
||||
*/
|
||||
private function computeGaussArea($points, $exp = 0)
|
||||
{
|
||||
// If a coefficient of 10^9 is not enough, give up!
|
||||
if ($exp > 9) {
|
||||
// If a coefficient of 10^12 is not enough, give up!
|
||||
if ($exp > 12) {
|
||||
return 0;
|
||||
}
|
||||
$coef = pow(10, $exp);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -105,11 +105,13 @@ class MultiLinestring extends GeometryCollection
|
||||
$this->checkInit();
|
||||
$geojson = $this->geojsonSanitize($geojson);
|
||||
if ($geojson !== null) {
|
||||
$force_m = $this->geojsonIsM($geojson['type']);
|
||||
foreach ($geojson['coordinates'] as $part) {
|
||||
if (!is_array($part)) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Wrong coordinates format');
|
||||
}
|
||||
$Linestring = new Linestring();
|
||||
foreach ($part as $geojson_coordinates) {
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $force_m);
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $geojson['flag_m']);
|
||||
$Point = new Point($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
|
||||
$Linestring->addPoint($Point);
|
||||
}
|
||||
|
||||
5
vendor/Shapefile/Geometry/MultiPoint.php
vendored
5
vendor/Shapefile/Geometry/MultiPoint.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -88,9 +88,8 @@ class MultiPoint extends GeometryCollection
|
||||
$this->checkInit();
|
||||
$geojson = $this->geojsonSanitize($geojson);
|
||||
if ($geojson !== null) {
|
||||
$force_m = $this->geojsonIsM($geojson['type']);
|
||||
foreach ($geojson['coordinates'] as $geojson_coordinates) {
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $force_m);
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $geojson['flag_m']);
|
||||
$Point = new Point($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
|
||||
$this->addPoint($Point);
|
||||
}
|
||||
|
||||
11
vendor/Shapefile/Geometry/MultiPolygon.php
vendored
11
vendor/Shapefile/Geometry/MultiPolygon.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -156,13 +156,18 @@ class MultiPolygon extends GeometryCollection
|
||||
$this->checkInit();
|
||||
$geojson = $this->geojsonSanitize($geojson);
|
||||
if ($geojson !== null) {
|
||||
$force_m = $this->geojsonIsM($geojson['type']);
|
||||
foreach ($geojson['coordinates'] as $part) {
|
||||
if (!is_array($part)) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Wrong coordinates format');
|
||||
}
|
||||
$Polygon = new Polygon(null, $this->closed_rings, $this->force_orientation);
|
||||
foreach ($part as $ring) {
|
||||
if (!is_array($ring)) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_GEOJSON_NOT_VALID, 'Wrong coordinates format');
|
||||
}
|
||||
$Linestring = new Linestring();
|
||||
foreach ($ring as $geojson_coordinates) {
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $force_m);
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson_coordinates, $geojson['flag_m']);
|
||||
$Point = new Point($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
|
||||
$Linestring->addPoint($Point);
|
||||
}
|
||||
|
||||
4
vendor/Shapefile/Geometry/Point.php
vendored
4
vendor/Shapefile/Geometry/Point.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -110,7 +110,7 @@ class Point extends Geometry
|
||||
$this->checkInit();
|
||||
$geojson = $this->geojsonSanitize($geojson);
|
||||
if ($geojson !== null) {
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson['coordinates'], $this->geojsonIsM($geojson['type']));
|
||||
$coordinates = $this->geojsonParseCoordinates($geojson['coordinates'], $geojson['flag_m']);
|
||||
$this->init($coordinates['x'], $coordinates['y'], $coordinates['z'], $coordinates['m']);
|
||||
}
|
||||
return $this;
|
||||
|
||||
2
vendor/Shapefile/Geometry/Polygon.php
vendored
2
vendor/Shapefile/Geometry/Polygon.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
|
||||
234
vendor/Shapefile/Shapefile.php
vendored
234
vendor/Shapefile/Shapefile.php
vendored
@@ -5,13 +5,16 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
|
||||
namespace Shapefile;
|
||||
|
||||
use Shapefile\File\FileInterface;
|
||||
use Shapefile\File\StreamResourceFile;
|
||||
|
||||
/**
|
||||
* Abstract base class for ShapefileReader and ShapefileWriter.
|
||||
* It provides some common public methods to both of them and exposes package-wide constants.
|
||||
@@ -75,6 +78,7 @@ abstract class Shapefile
|
||||
/** Misc */
|
||||
const EOF = 0;
|
||||
const UNDEFINED = null;
|
||||
const UNKNOWN = -1;
|
||||
|
||||
|
||||
|
||||
@@ -154,7 +158,8 @@ abstract class Shapefile
|
||||
const OPTION_DBF_RETURN_DATES_AS_OBJECTS_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Deletes empty files after closing them (only if they were passed as resource handles).
|
||||
* Deletes empty files after closing them.
|
||||
* This makes sense only when they were passed as resource handles or FileInterface instances.
|
||||
* ShapefileWriter
|
||||
* @var bool
|
||||
*/
|
||||
@@ -189,6 +194,26 @@ abstract class Shapefile
|
||||
const OPTION_FORCE_MULTIPART_GEOMETRIES = 'OPTION_FORCE_MULTIPART_GEOMETRIES';
|
||||
const OPTION_FORCE_MULTIPART_GEOMETRIES_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Ignores DBF file (useful to recover corrupted Shapefiles).
|
||||
* Data will not be available for geometries.
|
||||
* ShapefileReader
|
||||
* @var bool
|
||||
*/
|
||||
const OPTION_IGNORE_FILE_DBF = 'OPTION_IGNORE_FILE_DBF';
|
||||
const OPTION_IGNORE_FILE_DBF_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Ignores SHX file (useful to recover corrupted Shapefiles).
|
||||
* This might not always work as it relies on SHP record headers content lengths
|
||||
* and assumes there are no unused bytes between records in SHP file.
|
||||
* Random access to specific records will not be possible.
|
||||
* ShapefileReader
|
||||
* @var bool
|
||||
*/
|
||||
const OPTION_IGNORE_FILE_SHX = 'OPTION_IGNORE_FILE_SHX';
|
||||
const OPTION_IGNORE_FILE_SHX_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Ignores Geometries bounding box found in Shapefile.
|
||||
* ShapefileReader
|
||||
@@ -207,7 +232,7 @@ abstract class Shapefile
|
||||
|
||||
/**
|
||||
* Defines action to perform on Polygons rings.
|
||||
* They should be closed but some software don't enforce that, creating uncompliant Shapefiles.
|
||||
* They should be closed but some software do not enforce that, creating uncompliant Shapefiles.
|
||||
* Possible values:
|
||||
* Shapefile::ACTION_IGNORE : No action taken
|
||||
* Shapefile::ACTION_CHECK : Checks for open rings and eventually throws Shapefile::ERR_GEOM_POLYGON_OPEN_RING
|
||||
@@ -271,8 +296,14 @@ abstract class Shapefile
|
||||
const ERR_FILE_EXISTS = 'ERR_FILE_EXISTS';
|
||||
const ERR_FILE_EXISTS_MESSAGE = "Check if the file exists and is readable and/or writable";
|
||||
|
||||
const ERR_FILE_INVALID_RESOURCE = 'ERR_FILE_INVALID_RESOURCE';
|
||||
const ERR_FILE_INVALID_RESOURCE_MESSAGE = "File pointer resource not valid";
|
||||
const ERR_FILE_PERMISSIONS = 'ERR_FILE_PERMISSIONS';
|
||||
const ERR_FILE_PERMISSIONS_MESSAGE = "Check if the file is readable and/or writable in binary mode";
|
||||
|
||||
const ERR_FILE_PATH_NOT_VALID = 'ERR_FILE_PATH_NOT_VALID';
|
||||
const ERR_FILE_PATH_NOT_VALID_MESSAGE = "File path not valid";
|
||||
|
||||
const ERR_FILE_RESOURCE_NOT_VALID = 'ERR_FILE_RESOURCE_NOT_VALID';
|
||||
const ERR_FILE_RESOURCE_NOT_VALID_MESSAGE = "File pointer resource not valid. It must be a seekable stream";
|
||||
|
||||
const ERR_FILE_OPEN = 'ERR_FILE_OPEN';
|
||||
const ERR_FILE_OPEN_MESSAGE = "Unable to open file";
|
||||
@@ -364,6 +395,9 @@ abstract class Shapefile
|
||||
const ERR_GEOM_RING_NOT_ENOUGH_VERTICES = 'ERR_GEOM_RING_NOT_ENOUGH_VERTICES';
|
||||
const ERR_GEOM_RING_NOT_ENOUGH_VERTICES_MESSAGE = "Not enough vertices. Cannot determine ring orientation";
|
||||
|
||||
const ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE = 'ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE';
|
||||
const ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE_MESSAGE = "Cannot change current record without a valid SHX file";
|
||||
|
||||
const ERR_INPUT_RECORD_NOT_FOUND = 'ERR_INPUT_RECORD_NOT_FOUND';
|
||||
const ERR_INPUT_RECORD_NOT_FOUND_MESSAGE = "Record index not found (check the total number of records in the SHP file)";
|
||||
|
||||
@@ -403,6 +437,12 @@ abstract class Shapefile
|
||||
*/
|
||||
const OPTION_INVERT_POLYGONS_ORIENTATION = 'OPTION_INVERT_POLYGONS_ORIENTATION';
|
||||
|
||||
/**
|
||||
* @deprecated This constant was deprecated with v3.5.0 and will disappear in the next releases.
|
||||
* Use ERR_FILE_RESOURCE_NOT_VALID instead.
|
||||
*/
|
||||
const ERR_FILE_INVALID_RESOURCE = 'ERR_FILE_RESOURCE_NOT_VALID';
|
||||
|
||||
/**
|
||||
* @deprecated This constant was deprecated with v3.3.0 and will disappear in the next releases.
|
||||
* Use ERR_GEOM_RING_AREA_TOO_SMALL instead.
|
||||
@@ -423,6 +463,7 @@ abstract class Shapefile
|
||||
const SHP_HEADER_SIZE = 100;
|
||||
const SHP_NO_DATA_THRESHOLD = -1e38;
|
||||
const SHP_NO_DATA_VALUE = -1e40;
|
||||
const SHP_REC_HEADER_SIZE = 8;
|
||||
const SHP_VERSION = 1000;
|
||||
/** SHX files constants */
|
||||
const SHX_HEADER_SIZE = 100;
|
||||
@@ -434,7 +475,8 @@ abstract class Shapefile
|
||||
const DBF_EOF_MARKER = 0x1a;
|
||||
const DBF_FIELD_TERMINATOR = 0x0d;
|
||||
const DBF_MAX_FIELD_COUNT = 255;
|
||||
const DBF_VALUE_MASK_TRUE = 'TtYy';
|
||||
const DBF_VALUE_MASK_FALSE = 'FfNn0';
|
||||
const DBF_VALUE_MASK_TRUE = 'TtYy1';
|
||||
const DBF_VALUE_FALSE = 'F';
|
||||
const DBF_VALUE_NULL = '?';
|
||||
const DBF_VALUE_TRUE = 'T';
|
||||
@@ -501,7 +543,7 @@ abstract class Shapefile
|
||||
private $fields = [];
|
||||
|
||||
/**
|
||||
* @var array Array of file pointer resource handles.
|
||||
* @var array Array of FileInterface instances.
|
||||
*/
|
||||
private $files = [];
|
||||
|
||||
@@ -721,16 +763,17 @@ abstract class Shapefile
|
||||
|
||||
/////////////////////////////// PROTECTED ///////////////////////////////
|
||||
/**
|
||||
* Opens file pointer resource handles to specified files with binary read or write access.
|
||||
* Opens files with binary read or write access.
|
||||
*
|
||||
* (Filenames are mapped here because files are closed in destructors and working directory may be different!)
|
||||
* Filenames are mapped here because files are closed in destructors and working directory might be different!
|
||||
*
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of resource handles of individual files.
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of resource handles / Array of FileInterface instances.
|
||||
* @param bool $write_access Access type: false = read; true = write.
|
||||
* @param array $ignored_files Optional map of files to ignore [filetype => bool].
|
||||
*
|
||||
* @return self Returns $this to provide a fluent interface.
|
||||
*/
|
||||
protected function openFiles($files, $write_access)
|
||||
protected function openFiles($files, $write_access, $ignored_files = [])
|
||||
{
|
||||
// Create $files array from single string (SHP filename)
|
||||
if (is_string($files)) {
|
||||
@@ -745,86 +788,107 @@ abstract class Shapefile
|
||||
];
|
||||
}
|
||||
|
||||
// Ignored files
|
||||
$ignored_files = $ignored_files + [
|
||||
Shapefile::FILE_SHX => false,
|
||||
Shapefile::FILE_DBF => false,
|
||||
];
|
||||
|
||||
// Make sure required files are specified
|
||||
if (!is_array($files) || !isset($files[Shapefile::FILE_SHP])) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_MISSING, strtoupper(Shapefile::FILE_SHP));
|
||||
}
|
||||
if (!is_array($files) || !isset($files[Shapefile::FILE_SHX])) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_MISSING, strtoupper(Shapefile::FILE_SHX));
|
||||
}
|
||||
if (!is_array($files) || !isset($files[Shapefile::FILE_DBF])) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_MISSING, strtoupper(Shapefile::FILE_DBF));
|
||||
foreach (
|
||||
[
|
||||
Shapefile::FILE_SHP,
|
||||
Shapefile::FILE_SHX,
|
||||
Shapefile::FILE_DBF,
|
||||
] as $type
|
||||
) {
|
||||
if (!is_array($files) || (!isset($files[$type]) && (!isset($ignored_files[$type]) || !$ignored_files[$type]))) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_MISSING, strtoupper($type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$mode = $write_access ? 'c+b' : 'rb';
|
||||
if ($files === array_filter($files, 'is_resource')) {
|
||||
$this->filenames = [];
|
||||
if (array_reduce($files, function($ret, $item) {
|
||||
return $ret && $item instanceof FileInterface;
|
||||
}, true)) {
|
||||
// FileInterface instances
|
||||
foreach ($files as $type => $File) {
|
||||
if (!isset($ignored_files[$type]) || !$ignored_files[$type]) {
|
||||
if ((!$write_access && !$File->isReadable()) || ($write_access && !$File->isWritable())) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_PERMISSIONS, strtoupper($type));
|
||||
}
|
||||
$this->files[$type] = $File;
|
||||
}
|
||||
}
|
||||
} elseif ($files === array_filter($files, 'is_resource')) {
|
||||
// Resource handles
|
||||
foreach ($files as $type => $file) {
|
||||
$file_mode = stream_get_meta_data($file)['mode'];
|
||||
if (
|
||||
get_resource_type($file) != 'stream'
|
||||
|| (!$write_access && !in_array($file_mode, array('rb', 'r+b', 'w+b', 'x+b', 'c+b')))
|
||||
|| ($write_access && !in_array($file_mode, array('r+b', 'wb', 'w+b', 'xb', 'x+b', 'cb', 'c+b')))
|
||||
) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_INVALID_RESOURCE, strtoupper($type));
|
||||
if (!isset($ignored_files[$type]) || !$ignored_files[$type]) {
|
||||
try {
|
||||
$this->files[$type] = new StreamResourceFile($file, $write_access);
|
||||
} catch (ShapefileException $e) {
|
||||
throw new ShapefileException($e->getErrorType(), strtoupper($type));
|
||||
}
|
||||
}
|
||||
$this->files[$type] = $file;
|
||||
}
|
||||
$this->filenames = [];
|
||||
} else {
|
||||
// Filenames
|
||||
foreach (
|
||||
[
|
||||
Shapefile::FILE_SHP => true,
|
||||
Shapefile::FILE_SHX => true,
|
||||
Shapefile::FILE_DBF => true,
|
||||
Shapefile::FILE_SHX => !$ignored_files[Shapefile::FILE_SHX],
|
||||
Shapefile::FILE_DBF => !$ignored_files[Shapefile::FILE_DBF],
|
||||
Shapefile::FILE_DBT => false,
|
||||
Shapefile::FILE_PRJ => false,
|
||||
Shapefile::FILE_CPG => false,
|
||||
] as $type => $required
|
||||
) {
|
||||
if (isset($files[$type])) {
|
||||
if (isset($files[$type]) && (!isset($ignored_files[$type]) || !$ignored_files[$type])) {
|
||||
if (!is_string($files[$type])){
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_PATH_NOT_VALID, strtoupper($type));
|
||||
}
|
||||
if (
|
||||
(!$write_access && is_string($files[$type]) && is_readable($files[$type]) && is_file($files[$type]))
|
||||
|| ($write_access && is_string($files[$type]) && is_writable(dirname($files[$type])) && (!file_exists($files[$type]) || ($this->getOption(Shapefile::OPTION_EXISTING_FILES_MODE) != Shapefile::MODE_PRESERVE && is_readable($files[$type]) && is_file($files[$type]))))
|
||||
(!$write_access && is_readable($files[$type]) && is_file($files[$type]))
|
||||
|| ($write_access && is_writable(dirname($files[$type])) && (!file_exists($files[$type]) || (is_file($files[$type]) && is_writable($files[$type]) && (($this->getOption(Shapefile::OPTION_EXISTING_FILES_MODE) === Shapefile::MODE_APPEND && is_readable($files[$type])) || ($this->getOption(Shapefile::OPTION_EXISTING_FILES_MODE) === Shapefile::MODE_OVERWRITE)))))
|
||||
) {
|
||||
$handle = fopen($files[$type], $mode);
|
||||
if ($handle === false) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_OPEN, $files[$type]);
|
||||
try {
|
||||
$this->files[$type] = new StreamResourceFile($files[$type], $write_access);
|
||||
$this->filenames[$type] = $this->files[$type]->getFilepath();
|
||||
} catch (ShapefileException $e) {
|
||||
throw new ShapefileException($e->getErrorType(), $files[$type]);
|
||||
}
|
||||
$this->files[$type] = $handle;
|
||||
$this->filenames[$type] = realpath(stream_get_meta_data($handle)['uri']);
|
||||
} elseif ($required) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_EXISTS, $files[$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (array_keys($this->files) as $file_type) {
|
||||
$this->setFilePointer($file_type, 0);
|
||||
|
||||
// Set files pointers to start
|
||||
foreach ($this->files as $File) {
|
||||
$File->setPointer(0);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all open resource handles.
|
||||
* Closes all open files.
|
||||
* Actually, this just destroys the reference to FileInterface instance, letting it handle the situation.
|
||||
*
|
||||
* @return self Returns $this to provide a fluent interface.
|
||||
*/
|
||||
protected function closeFiles()
|
||||
{
|
||||
if (count($this->filenames) > 0) {
|
||||
foreach ($this->files as $handle) {
|
||||
fclose($handle);
|
||||
}
|
||||
foreach (array_keys($this->files) as $type) {
|
||||
$this->files[$type] = null;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates an open resource handle to a given length.
|
||||
* Truncates file to given length.
|
||||
*
|
||||
* @param string $file_type File type.
|
||||
* @param int $size Optional size to truncate to.
|
||||
@@ -833,14 +897,14 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function fileTruncate($file_type, $size = 0)
|
||||
{
|
||||
ftruncate($this->files[$file_type], $size);
|
||||
$this->files[$file_type]->truncate($size);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if file type has been opened.
|
||||
*
|
||||
* @param string $file_type File type.
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@@ -850,7 +914,7 @@ abstract class Shapefile
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of the open resource handles.
|
||||
* Gets an array of the open files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -860,7 +924,8 @@ abstract class Shapefile
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of canonicalized absolute pathnames if files were NOT passed as stream resources, or an empty array if they were.
|
||||
* Gets an array of canonicalized absolute pathnames.
|
||||
* If files were passed as stream resource handles or FileInterface instances, an empty array is returned.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
@@ -870,7 +935,7 @@ abstract class Shapefile
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets size of an open a resource handle.
|
||||
* Gets file size.
|
||||
*
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
*
|
||||
@@ -878,11 +943,11 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function getFileSize($file_type)
|
||||
{
|
||||
return fstat($this->files[$file_type])['size'];
|
||||
return $this->files[$file_type]->getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current pointer position of a resource handle.
|
||||
* Gets file current pointer position.
|
||||
*
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
*
|
||||
@@ -890,11 +955,11 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function getFilePointer($file_type)
|
||||
{
|
||||
return ftell($this->files[$file_type]);
|
||||
return $this->files[$file_type]->getPointer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pointer position of a resource handle to specified value.
|
||||
* Sets file pointer to specified position.
|
||||
*
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
* @param int $position The position to set the pointer to.
|
||||
@@ -903,12 +968,12 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function setFilePointer($file_type, $position)
|
||||
{
|
||||
fseek($this->files[$file_type], $position, SEEK_SET);
|
||||
$this->files[$file_type]->setPointer($position);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the pointer position of a resource handle to its end.
|
||||
* Resets file pointer position to its end.
|
||||
*
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
*
|
||||
@@ -916,12 +981,12 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function resetFilePointer($file_type)
|
||||
{
|
||||
fseek($this->files[$file_type], 0, SEEK_END);
|
||||
$this->files[$file_type]->resetPointer();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the pointer position of a resource handle of specified value.
|
||||
* Increases file pointer position of specified offset.
|
||||
*
|
||||
* @param string $file_type File type (member of $this->files array).
|
||||
* @param int $offset The offset to move the pointer for.
|
||||
@@ -930,12 +995,12 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function setFileOffset($file_type, $offset)
|
||||
{
|
||||
fseek($this->files[$file_type], $offset, SEEK_CUR);
|
||||
$this->files[$file_type]->setOffset($offset);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from an open resource handle.
|
||||
* Reads data from file.
|
||||
*
|
||||
* @param string $file_type File type.
|
||||
* @param int $length Number of bytes to read.
|
||||
@@ -944,7 +1009,7 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function readData($file_type, $length)
|
||||
{
|
||||
$ret = @fread($this->files[$file_type], $length);
|
||||
$ret = $this->files[$file_type]->read($length);
|
||||
if ($ret === false) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_READING);
|
||||
}
|
||||
@@ -952,7 +1017,7 @@ abstract class Shapefile
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes binary string packed data to an open resource handle.
|
||||
* Writes binary string packed data to file.
|
||||
*
|
||||
* @param string $file_type File type.
|
||||
* @param string $data Binary string packed data to write.
|
||||
@@ -961,7 +1026,7 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function writeData($file_type, $data)
|
||||
{
|
||||
if (@fwrite($this->files[$file_type], $data) === false) {
|
||||
if ($this->files[$file_type]->write($data) === false) {
|
||||
throw new ShapefileException(Shapefile::ERR_FILE_WRITING);
|
||||
}
|
||||
return $this;
|
||||
@@ -984,15 +1049,15 @@ abstract class Shapefile
|
||||
/**
|
||||
* Initializes options with default and user-provided values.
|
||||
*
|
||||
* @param array $options Array of options to initialize.
|
||||
* @param array $custom User-provided options
|
||||
* @param array $options_list Array of options to initialize.
|
||||
* @param array $user_values User-provided options values.
|
||||
*
|
||||
* @return self Returns $this to provide a fluent interface.
|
||||
*/
|
||||
protected function initOptions($options, $custom)
|
||||
protected function initOptions($options_list, $user_values)
|
||||
{
|
||||
// Make sure compulsory options used in this abstract class are defined
|
||||
$options = array_unique(array_merge($options, [
|
||||
$options_list = array_unique(array_merge($options_list, [
|
||||
Shapefile::OPTION_DBF_ALLOW_FIELD_SIZE_255,
|
||||
Shapefile::OPTION_DBF_FORCE_ALL_CAPS,
|
||||
Shapefile::OPTION_SUPPRESS_M,
|
||||
@@ -1001,15 +1066,15 @@ abstract class Shapefile
|
||||
|
||||
// Defaults
|
||||
$defaults = [];
|
||||
foreach ($options as $option) {
|
||||
foreach ($options_list as $option) {
|
||||
$defaults[$option] = constant('Shapefile\Shapefile::' . $option . '_DEFAULT');
|
||||
}
|
||||
|
||||
// Filter custom options
|
||||
$custom = array_intersect_key(array_change_key_case($custom, CASE_UPPER), $defaults);
|
||||
$user_values = array_intersect_key(array_change_key_case($user_values, CASE_UPPER), $defaults);
|
||||
|
||||
// Initialize option array
|
||||
$this->options = $custom + $defaults;
|
||||
$this->options = $user_values + $defaults;
|
||||
|
||||
// Use only the first character of OPTION_DBF_NULL_PADDING_CHAR if it's set and is not false or empty
|
||||
$k = Shapefile::OPTION_DBF_NULL_PADDING_CHAR;
|
||||
@@ -1038,19 +1103,6 @@ abstract class Shapefile
|
||||
return $this->options[$option];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets option value.
|
||||
*
|
||||
* @param string $option Name of the option.
|
||||
* @param mixed $value Value of the option.
|
||||
*
|
||||
* @return self Returns $this to provide a fluent interface.
|
||||
*/
|
||||
protected function setOption($option, $value)
|
||||
{
|
||||
$this->options[$option] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets shape type.
|
||||
@@ -1106,7 +1158,9 @@ abstract class Shapefile
|
||||
*/
|
||||
protected function overwriteComputedBoundingBox($bounding_box)
|
||||
{
|
||||
$this->computed_bounding_box = $this->sanitizeBoundingBox($bounding_box);
|
||||
if ($bounding_box) {
|
||||
$this->computed_bounding_box = $this->sanitizeBoundingBox($bounding_box);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1230,7 +1284,7 @@ abstract class Shapefile
|
||||
&& $type !== Shapefile::DBF_TYPE_NUMERIC
|
||||
&& $type !== Shapefile::DBF_TYPE_FLOAT
|
||||
) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_TYPE_NOT_VALID, $type);
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_TYPE_NOT_VALID, "$name - $type");
|
||||
}
|
||||
|
||||
// Check size
|
||||
@@ -1245,7 +1299,7 @@ abstract class Shapefile
|
||||
|| ($type == Shapefile::DBF_TYPE_NUMERIC && $size > $max_size)
|
||||
|| ($type == Shapefile::DBF_TYPE_FLOAT && $size > $max_size)
|
||||
) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_SIZE_NOT_VALID, $size);
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_SIZE_NOT_VALID, "$name - $type - $size");
|
||||
}
|
||||
|
||||
// Minimal decimal formal check
|
||||
@@ -1256,7 +1310,7 @@ abstract class Shapefile
|
||||
|| ($decimals < 0)
|
||||
|| ($decimals > 0 && $size - 1 <= $decimals)
|
||||
) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_DECIMALS_NOT_VALID, $type . ' - ' . $decimals);
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_FIELD_DECIMALS_NOT_VALID, "$name - $type - $decimals");
|
||||
}
|
||||
|
||||
// Add field
|
||||
|
||||
2
vendor/Shapefile/ShapefileAutoloader.php
vendored
2
vendor/Shapefile/ShapefileAutoloader.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
|
||||
2
vendor/Shapefile/ShapefileException.php
vendored
2
vendor/Shapefile/ShapefileException.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
|
||||
146
vendor/Shapefile/ShapefileReader.php
vendored
146
vendor/Shapefile/ShapefileReader.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -67,6 +67,11 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
*/
|
||||
private $dbt_file_size;
|
||||
|
||||
/**
|
||||
* @var int SHP file size in bytes (used when SHX file is not available).
|
||||
*/
|
||||
private $shp_file_size;
|
||||
|
||||
/**
|
||||
* @var int Pointer to current SHP and DBF files record.
|
||||
*/
|
||||
@@ -78,7 +83,7 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of handles of individual files.
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of resource handles / Array of FileInterface instances.
|
||||
* @param array $options Optional associative array of options.
|
||||
*/
|
||||
public function __construct($files, $options = [])
|
||||
@@ -105,26 +110,39 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES,
|
||||
Shapefile::OPTION_DBF_RETURN_DATES_AS_OBJECTS,
|
||||
Shapefile::OPTION_FORCE_MULTIPART_GEOMETRIES,
|
||||
Shapefile::OPTION_IGNORE_FILE_DBF,
|
||||
Shapefile::OPTION_IGNORE_FILE_SHX,
|
||||
Shapefile::OPTION_IGNORE_GEOMETRIES_BBOXES,
|
||||
Shapefile::OPTION_IGNORE_SHAPEFILE_BBOX,
|
||||
Shapefile::OPTION_POLYGON_CLOSED_RINGS_ACTION,
|
||||
Shapefile::OPTION_POLYGON_ORIENTATION_READING_AUTOSENSE,
|
||||
Shapefile::OPTION_POLYGON_OUTPUT_ORIENTATION,
|
||||
Shapefile::OPTION_IGNORE_GEOMETRIES_BBOXES,
|
||||
Shapefile::OPTION_IGNORE_SHAPEFILE_BBOX,
|
||||
Shapefile::OPTION_SUPPRESS_M,
|
||||
Shapefile::OPTION_SUPPRESS_Z,
|
||||
], $options);
|
||||
|
||||
// Open files
|
||||
$this->openFiles($files, false);
|
||||
$this->openFiles($files, false, [
|
||||
Shapefile::FILE_DBF => $this->getOption(Shapefile::OPTION_IGNORE_FILE_DBF),
|
||||
Shapefile::FILE_SHX => $this->getOption(Shapefile::OPTION_IGNORE_FILE_SHX),
|
||||
]);
|
||||
|
||||
// Gets number of records from SHX file size.
|
||||
$this->setTotRecords(($this->getFileSize(Shapefile::FILE_SHX) - Shapefile::SHX_HEADER_SIZE) / Shapefile::SHX_RECORD_SIZE);
|
||||
// SHX
|
||||
$this->setTotRecords($this->getOption(Shapefile::OPTION_IGNORE_FILE_SHX) ? Shapefile::UNKNOWN : ($this->getFileSize(Shapefile::FILE_SHX) - Shapefile::SHX_HEADER_SIZE) / Shapefile::SHX_RECORD_SIZE);
|
||||
|
||||
// DBF file size
|
||||
$this->dbf_file_size = $this->getFileSize(Shapefile::FILE_DBF);
|
||||
// DBT file size
|
||||
$this->dbt_file_size = ($this->isFileOpen(Shapefile::FILE_DBT) && $this->getFileSize(Shapefile::FILE_DBT) > 0) ? $this->getFileSize(Shapefile::FILE_DBT) : null;
|
||||
// SHP
|
||||
$this->shp_file_size = $this->getFileSize(Shapefile::FILE_SHP);
|
||||
$this->readSHPHeader();
|
||||
|
||||
// DBF and DBT
|
||||
if (!$this->getOption(Shapefile::OPTION_IGNORE_FILE_DBF)) {
|
||||
// DBF file size
|
||||
$this->dbf_file_size = $this->getFileSize(Shapefile::FILE_DBF);
|
||||
// DBT file size
|
||||
$this->dbt_file_size = ($this->isFileOpen(Shapefile::FILE_DBT) && $this->getFileSize(Shapefile::FILE_DBT) > 0) ? $this->getFileSize(Shapefile::FILE_DBT) : null;
|
||||
// Read DBF header
|
||||
$this->readDBFHeader();
|
||||
}
|
||||
// PRJ
|
||||
if ($this->isFileOpen(Shapefile::FILE_PRJ) && $this->getFileSize(Shapefile::FILE_PRJ) > 0) {
|
||||
$this->setPRJ($this->readString(Shapefile::FILE_PRJ, $this->getFileSize(Shapefile::FILE_PRJ)));
|
||||
@@ -134,9 +152,6 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
if ($this->isFileOpen(Shapefile::FILE_CPG) && $this->getFileSize(Shapefile::FILE_CPG) > 0) {
|
||||
$this->setCharset($this->readString(Shapefile::FILE_CPG, $this->getFileSize(Shapefile::FILE_CPG)));
|
||||
}
|
||||
// Read headers
|
||||
$this->readSHPHeader();
|
||||
$this->readDBFHeader();
|
||||
|
||||
// Init record pointer
|
||||
$this->rewind();
|
||||
@@ -156,13 +171,14 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
public function rewind()
|
||||
{
|
||||
$this->current_record = 0;
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, Shapefile::SHP_HEADER_SIZE);
|
||||
$this->next();
|
||||
}
|
||||
|
||||
public function next()
|
||||
{
|
||||
++$this->current_record;
|
||||
if (!$this->checkRecordIndex($this->current_record)) {
|
||||
if (($this->getTotRecords() !== Shapefile::UNKNOWN && !$this->checkRecordIndex($this->current_record)) || $this->getFilePointer(Shapefile::FILE_SHP) >= $this->shp_file_size) {
|
||||
$this->current_record = Shapefile::EOF;
|
||||
}
|
||||
}
|
||||
@@ -205,6 +221,9 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
*/
|
||||
public function setCurrentRecord($index)
|
||||
{
|
||||
if ($this->getTotRecords() === Shapefile::UNKNOWN) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_RANDOM_ACCESS_UNAVAILABLE);
|
||||
}
|
||||
if (!$this->checkRecordIndex($index)) {
|
||||
throw new ShapefileException(Shapefile::ERR_INPUT_RECORD_NOT_FOUND, $index);
|
||||
}
|
||||
@@ -339,8 +358,9 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, 32);
|
||||
$this->setShapeType($this->readInt32L(Shapefile::FILE_SHP));
|
||||
|
||||
// Bounding Box (Z and M ranges are always present in the Shapefile, although with a 0 value if not used)
|
||||
if (!$this->getOption(Shapefile::OPTION_IGNORE_SHAPEFILE_BBOX)) {
|
||||
// Read Bounding Box if there are any records in the file.
|
||||
// Z and M ranges are always present in the Shapefile, although with value 0 if not used.
|
||||
if (!$this->getOption(Shapefile::OPTION_IGNORE_SHAPEFILE_BBOX) && ($this->getTotRecords() === Shapefile::UNKNOWN || $this->getTotRecords() > 0)) {
|
||||
$bounding_box = $this->readXYBoundingBox() + $this->readZRange() + $this->readMRange();
|
||||
if (!$this->isZ()) {
|
||||
unset($bounding_box['zmin']);
|
||||
@@ -353,6 +373,8 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
$this->setCustomBoundingBox($bounding_box);
|
||||
}
|
||||
|
||||
// Set SHP file pointer to first record
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, Shapefile::SHP_HEADER_SIZE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -365,7 +387,7 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
{
|
||||
// Number of records
|
||||
$this->setFilePointer(Shapefile::FILE_DBF, 4);
|
||||
if ($this->readInt32L(Shapefile::FILE_DBF) !== $this->getTotRecords()) {
|
||||
if ($this->readInt32L(Shapefile::FILE_DBF) !== $this->getTotRecords() && $this->getTotRecords() !== Shapefile::UNKNOWN) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_MISMATCHED_FILE);
|
||||
}
|
||||
|
||||
@@ -416,13 +438,20 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
}
|
||||
|
||||
// === SHX ===
|
||||
$this->setFilePointer(Shapefile::FILE_SHX, Shapefile::SHX_HEADER_SIZE + (($this->current_record - 1) * Shapefile::SHX_RECORD_SIZE));
|
||||
// Offset (stored as 16-bit words)
|
||||
$shp_offset = $this->readInt32B(Shapefile::FILE_SHX) * 2;
|
||||
if (!$this->getOption(Shapefile::OPTION_IGNORE_FILE_SHX)) {
|
||||
$this->setFilePointer(Shapefile::FILE_SHX, Shapefile::SHX_HEADER_SIZE + (($this->current_record - 1) * Shapefile::SHX_RECORD_SIZE));
|
||||
// Offset (stored as 16-bit words)
|
||||
$shp_offset = $this->readInt32B(Shapefile::FILE_SHX) * 2;
|
||||
} else {
|
||||
$shp_offset = $this->getFilePointer(Shapefile::FILE_SHP);
|
||||
}
|
||||
|
||||
// === SHP ===
|
||||
// Set file pointer position skipping the 8-bytes record header
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, $shp_offset + 8);
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, $shp_offset);
|
||||
// Skip Record Number
|
||||
$this->setFileOffset(Shapefile::FILE_SHP, 4);
|
||||
// Content length (stored as 16-bit words and missing the record header size)
|
||||
$content_length = ($this->readInt32B(Shapefile::FILE_SHP) * 2) + Shapefile::SHP_REC_HEADER_SIZE;
|
||||
// Shape type
|
||||
$shape_type = $this->readInt32L(Shapefile::FILE_SHP);
|
||||
if ($shape_type != Shapefile::SHAPE_TYPE_NULL && $shape_type != $this->getShapeType()) {
|
||||
@@ -430,39 +459,46 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
}
|
||||
// Read Geometry
|
||||
$Geometry = $this->{self::$shp_read_methods[$shape_type]}();
|
||||
// Set SHP file pointer position to next record if there is no SHX file available
|
||||
if ($this->getOption(Shapefile::OPTION_IGNORE_FILE_SHX)) {
|
||||
$this->setFilePointer(Shapefile::FILE_SHP, $shp_offset + $content_length);
|
||||
}
|
||||
|
||||
// === DBF ===
|
||||
$dbf_file_position = $this->dbf_header_size + (($this->current_record - 1) * $this->dbf_record_size);
|
||||
// Check if DBF is not corrupted (some "naive" users try to edit the DBF separately...)
|
||||
// Some GIS do not include the last Shapefile::DBF_EOF_MARKER (0x1a) byte in the DBF file, hence the "- 1" in the following line
|
||||
if ($dbf_file_position - 1 >= $this->dbf_file_size - $this->dbf_record_size) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_EOF_REACHED);
|
||||
}
|
||||
$this->setFilePointer(Shapefile::FILE_DBF, $dbf_file_position);
|
||||
$Geometry->setFlagDeleted($this->readChar(Shapefile::FILE_DBF) === Shapefile::DBF_DELETED_MARKER);
|
||||
foreach ($this->dbf_fields as $i => $f) {
|
||||
if ($f['ignored']) {
|
||||
$this->setFileOffset(Shapefile::FILE_DBF, $f['size']);
|
||||
} else {
|
||||
$type = $this->getField($f['name'])['type'];
|
||||
$value = $this->decodeFieldValue($f['name'], $type, $this->readString(Shapefile::FILE_DBF, $f['size'], true));
|
||||
// Memo (DBT)
|
||||
if ($type === Shapefile::DBF_TYPE_MEMO && $value) {
|
||||
$this->setFilePointer(Shapefile::FILE_DBT, intval($value) * Shapefile::DBT_BLOCK_SIZE);
|
||||
$value = '';
|
||||
do {
|
||||
if ($this->getFilePointer(Shapefile::FILE_DBT) >= $this->dbt_file_size) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBT_EOF_REACHED);
|
||||
}
|
||||
$value .= $this->readString(Shapefile::FILE_DBT, Shapefile::DBT_BLOCK_SIZE, true);
|
||||
// Some software only sets ONE field terminator instead of TWO, hence the weird loop condition check:
|
||||
} while (ord(substr($value, -1)) != Shapefile::DBT_FIELD_TERMINATOR && ord(substr($value, -2, 1)) != Shapefile::DBT_FIELD_TERMINATOR);
|
||||
$value = substr($value, 0, -2);
|
||||
if (!$this->getOption(Shapefile::OPTION_IGNORE_FILE_DBF)) {
|
||||
$dbf_file_position = $this->dbf_header_size + (($this->current_record - 1) * $this->dbf_record_size);
|
||||
// Check if DBF is not corrupted (some "naive" users try to edit the DBF separately...)
|
||||
// Some GIS do not include the last Shapefile::DBF_EOF_MARKER (0x1a) byte in the DBF file, hence the "- 1" in the following line
|
||||
if ($dbf_file_position - 1 >= $this->dbf_file_size - $this->dbf_record_size) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBF_EOF_REACHED);
|
||||
}
|
||||
$this->setFilePointer(Shapefile::FILE_DBF, $dbf_file_position);
|
||||
$Geometry->setFlagDeleted($this->readChar(Shapefile::FILE_DBF) === Shapefile::DBF_DELETED_MARKER);
|
||||
foreach ($this->dbf_fields as $i => $f) {
|
||||
if ($f['ignored']) {
|
||||
$this->setFileOffset(Shapefile::FILE_DBF, $f['size']);
|
||||
} else {
|
||||
$type = $this->getField($f['name'])['type'];
|
||||
$value = $this->decodeFieldValue($f['name'], $type, $this->readString(Shapefile::FILE_DBF, $f['size'], true));
|
||||
// Memo (DBT)
|
||||
if ($type === Shapefile::DBF_TYPE_MEMO && $value) {
|
||||
$this->setFilePointer(Shapefile::FILE_DBT, intval($value) * Shapefile::DBT_BLOCK_SIZE);
|
||||
$value = '';
|
||||
do {
|
||||
if ($this->getFilePointer(Shapefile::FILE_DBT) >= $this->dbt_file_size) {
|
||||
throw new ShapefileException(Shapefile::ERR_DBT_EOF_REACHED);
|
||||
}
|
||||
$value .= $this->readString(Shapefile::FILE_DBT, Shapefile::DBT_BLOCK_SIZE, true);
|
||||
// Some software only sets ONE field terminator instead of TWO, hence the weird loop condition check:
|
||||
} while (ord(substr($value, -1)) != Shapefile::DBT_FIELD_TERMINATOR && ord(substr($value, -2, 1)) != Shapefile::DBT_FIELD_TERMINATOR);
|
||||
$value = substr($value, 0, -2);
|
||||
}
|
||||
$Geometry->setData($f['name'], $value);
|
||||
}
|
||||
$Geometry->setData($f['name'], $value);
|
||||
}
|
||||
}
|
||||
|
||||
// Pair Geometry with Shapefile and return it
|
||||
$this->pairGeometry($Geometry);
|
||||
return $Geometry;
|
||||
}
|
||||
@@ -486,7 +522,7 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
case Shapefile::DBF_TYPE_DATE:
|
||||
$DateTime = \DateTime::createFromFormat('Ymd', $value);
|
||||
$errors = \DateTime::getLastErrors();
|
||||
if ($errors['warning_count'] || $errors['error_count']) {
|
||||
if (is_array($errors) && ($errors['warning_count'] || $errors['error_count'])) {
|
||||
$value = $this->getOption(Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES) ? null : $value;
|
||||
} elseif ($this->getOption(Shapefile::OPTION_DBF_RETURN_DATES_AS_OBJECTS)) {
|
||||
$DateTime->setTime(0, 0, 0);
|
||||
@@ -497,7 +533,13 @@ class ShapefileReader extends Shapefile implements \Iterator
|
||||
break;
|
||||
|
||||
case Shapefile::DBF_TYPE_LOGICAL:
|
||||
$value = ($value === Shapefile::DBF_VALUE_NULL) ? null : strpos(Shapefile::DBF_VALUE_MASK_TRUE, $value) !== false;
|
||||
if (strpos(Shapefile::DBF_VALUE_MASK_TRUE, $value) !== false) {
|
||||
$value = true;
|
||||
} elseif (strpos(Shapefile::DBF_VALUE_MASK_FALSE, $value) !== false) {
|
||||
$value = false;
|
||||
} else {
|
||||
$value = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
113
vendor/Shapefile/ShapefileWriter.php
vendored
113
vendor/Shapefile/ShapefileWriter.php
vendored
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* @package Shapefile
|
||||
* @author Gaspare Sganga
|
||||
* @version 3.3.0
|
||||
* @version 4.0.0dev
|
||||
* @license MIT
|
||||
* @link https://gasparesganga.com/labs/php-shapefile/
|
||||
*/
|
||||
@@ -67,7 +67,7 @@ class ShapefileWriter extends Shapefile
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of handles of individual files.
|
||||
* @param string|array $files Path to SHP file / Array of paths / Array of resource handles / Array of FileInterface instances.
|
||||
* @param array $options Optional associative array of options.
|
||||
*/
|
||||
public function __construct($files, $options = [])
|
||||
@@ -95,12 +95,7 @@ class ShapefileWriter extends Shapefile
|
||||
|
||||
// Mode overwrite
|
||||
if ($this->getOption(Shapefile::OPTION_EXISTING_FILES_MODE) === Shapefile::MODE_OVERWRITE) {
|
||||
foreach (array_keys($this->getFiles()) as $file_type) {
|
||||
if ($this->getFileSize($file_type) > 0) {
|
||||
$this->fileTruncate($file_type);
|
||||
$this->setFilePointer($file_type, 0);
|
||||
}
|
||||
}
|
||||
$this->truncateFiles();
|
||||
}
|
||||
|
||||
// Mode append
|
||||
@@ -133,23 +128,25 @@ class ShapefileWriter extends Shapefile
|
||||
// Close Shapefile in reading mode
|
||||
$ShapefileReader = null;
|
||||
|
||||
// Mark Shapefile as initialized if there are any records
|
||||
if ($this->getTotRecords() > 0) {
|
||||
// Mark Shapefile as initialized
|
||||
$this->setFlagInitialized(true);
|
||||
}
|
||||
// Flag init headers
|
||||
$this->flag_init_headers = true;
|
||||
// SHP current offset (in 16-bit words)
|
||||
$this->shp_current_offset = $this->getFileSize(Shapefile::FILE_SHP) / 2;
|
||||
// Remove DBF EOF marker
|
||||
$dbf_size_without_eof = $this->getFileSize(Shapefile::FILE_DBF) - 1;
|
||||
$this->setFilePointer(Shapefile::FILE_DBF, $dbf_size_without_eof);
|
||||
if ($this->readData(Shapefile::FILE_DBF, 1) === $this->packChar(Shapefile::DBF_EOF_MARKER)) {
|
||||
$this->fileTruncate(Shapefile::FILE_DBF, $dbf_size_without_eof);
|
||||
}
|
||||
// Reset pointers
|
||||
foreach (array_keys($this->getFiles()) as $file_type) {
|
||||
$this->resetFilePointer($file_type);
|
||||
// Set flag init headers
|
||||
$this->flag_init_headers = true;
|
||||
// SHP current offset (in 16-bit words)
|
||||
$this->shp_current_offset = $this->getFileSize(Shapefile::FILE_SHP) / 2;
|
||||
// Remove DBF EOF marker
|
||||
$dbf_size_without_eof = $this->getFileSize(Shapefile::FILE_DBF) - 1;
|
||||
$this->setFilePointer(Shapefile::FILE_DBF, $dbf_size_without_eof);
|
||||
if ($this->readData(Shapefile::FILE_DBF, 1) === $this->packChar(Shapefile::DBF_EOF_MARKER)) {
|
||||
$this->fileTruncate(Shapefile::FILE_DBF, $dbf_size_without_eof);
|
||||
}
|
||||
// Reset pointers
|
||||
foreach (array_keys($this->getFiles()) as $file_type) {
|
||||
$this->resetFilePointer($file_type);
|
||||
}
|
||||
} else {
|
||||
$this->truncateFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,14 +155,12 @@ class ShapefileWriter extends Shapefile
|
||||
* Destructor.
|
||||
*
|
||||
* Finalizes open files.
|
||||
* If files were NOT passed as stream resources, empty useless files will be removed.
|
||||
* Empty useless files will be removed if they were NOT passed as stream resources or FileInterface instances.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// Flush buffers
|
||||
$this->writeBuffers();
|
||||
// Write DBF EOF marker to buffer
|
||||
$this->writeData(Shapefile::FILE_DBF, $this->packChar(Shapefile::DBF_EOF_MARKER));
|
||||
|
||||
// Try setting Shapefile as NULL SHAPE if it hasn't been initialized yet (no records written)
|
||||
if (!$this->isInitialized()) {
|
||||
@@ -194,6 +189,9 @@ class ShapefileWriter extends Shapefile
|
||||
$this->resetFilePointer($file_type);
|
||||
}
|
||||
|
||||
// Write DBF EOF marker
|
||||
$this->writeData(Shapefile::FILE_DBF, $this->packChar(Shapefile::DBF_EOF_MARKER));
|
||||
|
||||
// Write PRJ file
|
||||
if ($this->isFileOpen(Shapefile::FILE_PRJ)) {
|
||||
$this->fileTruncate(Shapefile::FILE_PRJ);
|
||||
@@ -403,6 +401,20 @@ class ShapefileWriter extends Shapefile
|
||||
|
||||
|
||||
/////////////////////////////// PRIVATE ///////////////////////////////
|
||||
/**
|
||||
* Truncates open files.
|
||||
*/
|
||||
private function truncateFiles()
|
||||
{
|
||||
foreach (array_keys($this->getFiles()) as $file_type) {
|
||||
if ($this->getFileSize($file_type) > 0) {
|
||||
$this->fileTruncate($file_type);
|
||||
$this->setFilePointer($file_type, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores binary string packed data into a buffer.
|
||||
*
|
||||
@@ -638,11 +650,10 @@ class ShapefileWriter extends Shapefile
|
||||
*/
|
||||
private function packPoint(Geometry\Geometry $Geometry)
|
||||
{
|
||||
$array = $Geometry->getArray();
|
||||
$bounding_box = $Geometry->getBoundingBox();
|
||||
$is_m = $this->isM();
|
||||
$is_z = $this->isZ();
|
||||
$shape_type = $is_z ? Shapefile::SHAPE_TYPE_POINTZ : ($is_m ? Shapefile::SHAPE_TYPE_POINTM : Shapefile::SHAPE_TYPE_POINT);
|
||||
$array = $Geometry->getArray();
|
||||
$is_m = $this->isM();
|
||||
$is_z = $this->isZ();
|
||||
$shape_type = $is_z ? Shapefile::SHAPE_TYPE_POINTZ : ($is_m ? Shapefile::SHAPE_TYPE_POINTM : Shapefile::SHAPE_TYPE_POINT);
|
||||
|
||||
// Shape type
|
||||
$ret = $this->packInt32L($shape_type);
|
||||
@@ -651,12 +662,12 @@ class ShapefileWriter extends Shapefile
|
||||
|
||||
if ($is_z) {
|
||||
// Z Coordinate
|
||||
$ret .= $this->packZ($coordinates);
|
||||
$ret .= $this->packZ($array);
|
||||
}
|
||||
|
||||
if ($is_m) {
|
||||
// M Coordinate
|
||||
$ret .= $this->packM($coordinates);
|
||||
$ret .= $this->packM($array);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -840,7 +851,7 @@ class ShapefileWriter extends Shapefile
|
||||
}
|
||||
|
||||
/**
|
||||
* Packs DBF and DBT data from a Geometry object into binary strings and returns an array with SHP, DBT and "dbt_next_available_block" members.
|
||||
* Packs DBF and DBT data from a Geometry object into binary strings and returns an array with DBF, DBT and "dbt_next_available_block" members.
|
||||
*
|
||||
* @param \Shapefile\Geometry\Geometry $Geometry Input Geometry.
|
||||
*
|
||||
@@ -949,12 +960,12 @@ class ShapefileWriter extends Shapefile
|
||||
// Try YYYY-MM-DD format
|
||||
$DateTime = \DateTime::createFromFormat('Y-m-d', $value);
|
||||
$errors = \DateTime::getLastErrors();
|
||||
if ($errors['warning_count'] || $errors['error_count']) {
|
||||
if (is_array($errors) && ($errors['warning_count'] || $errors['error_count'])) {
|
||||
// Try YYYYMMDD format
|
||||
$DateTime = \DateTime::createFromFormat('Ymd', $value);
|
||||
$errors = \DateTime::getLastErrors();
|
||||
}
|
||||
if ($errors['warning_count'] || $errors['error_count']) {
|
||||
if (is_array($errors) && ($errors['warning_count'] || $errors['error_count'])) {
|
||||
$value = $this->getOption(Shapefile::OPTION_DBF_NULLIFY_INVALID_DATES) ? null : $this->truncateOrPadString($this->sanitizeNumber($value), $size);
|
||||
} else {
|
||||
$value = $DateTime->format('Ymd');
|
||||
@@ -963,12 +974,19 @@ class ShapefileWriter extends Shapefile
|
||||
break;
|
||||
|
||||
case Shapefile::DBF_TYPE_LOGICAL:
|
||||
if ($value === null) {
|
||||
$value = Shapefile::DBF_VALUE_NULL;
|
||||
} elseif ($value === true || strpos(Shapefile::DBF_VALUE_MASK_TRUE, substr(trim($value), 0, 1)) !== false) {
|
||||
$value = Shapefile::DBF_VALUE_TRUE;
|
||||
if (is_string($value)) {
|
||||
$value = substr(trim($value), 0, 1);
|
||||
if (strpos(Shapefile::DBF_VALUE_MASK_TRUE, $value) !== false) {
|
||||
$value = Shapefile::DBF_VALUE_TRUE;
|
||||
} elseif (strpos(Shapefile::DBF_VALUE_MASK_FALSE, $value) !== false) {
|
||||
$value = Shapefile::DBF_VALUE_FALSE;
|
||||
} else {
|
||||
$value = Shapefile::DBF_VALUE_NULL;
|
||||
}
|
||||
} elseif (is_bool($value) || is_int($value) || is_float($value)) {
|
||||
$value = $value ? Shapefile::DBF_VALUE_TRUE : Shapefile::DBF_VALUE_FALSE;
|
||||
} else {
|
||||
$value = Shapefile::DBF_VALUE_FALSE;
|
||||
$value = Shapefile::DBF_VALUE_NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1054,8 +1072,17 @@ class ShapefileWriter extends Shapefile
|
||||
// Shape Type
|
||||
$ret .= $this->packInt32L($this->getShapeType(Shapefile::FORMAT_INT));
|
||||
|
||||
//Bounding Box
|
||||
$bounding_box = $this->getBoundingBox();
|
||||
//Bounding Box (Defaults to all zeros for empty Shapefile)
|
||||
$bounding_box = $this->getBoundingBox() ?: [
|
||||
'xmin' => -Shapefile::SHP_NO_DATA_VALUE,
|
||||
'ymin' => -Shapefile::SHP_NO_DATA_VALUE,
|
||||
'xmax' => Shapefile::SHP_NO_DATA_VALUE,
|
||||
'ymax' => Shapefile::SHP_NO_DATA_VALUE,
|
||||
'zmin' => -Shapefile::SHP_NO_DATA_VALUE,
|
||||
'zmax' => Shapefile::SHP_NO_DATA_VALUE,
|
||||
'mmin' => -Shapefile::SHP_NO_DATA_VALUE,
|
||||
'mmax' => Shapefile::SHP_NO_DATA_VALUE,
|
||||
];
|
||||
$ret .= $this->packXYBoundingBox($bounding_box);
|
||||
$ret .= $this->packZRange($this->isZ() ? $bounding_box : ['zmin' => 0, 'zmax' => 0]);
|
||||
$ret .= $this->packMRange($this->isM() ? $bounding_box : ['mmin' => 0, 'mmax' => 0]);
|
||||
|
||||
Reference in New Issue
Block a user