upgrade bootstrap and js

This commit is contained in:
Walter Hupfeld
2024-03-13 12:03:56 +01:00
parent 2ac9d01257
commit 0df358251a
93 changed files with 17858 additions and 33259 deletions

View File

@@ -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