diff --git a/composer.lock b/composer.lock index e323dfd0..c5e88041 100644 --- a/composer.lock +++ b/composer.lock @@ -88,16 +88,16 @@ }, { "name": "composer/semver", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { @@ -149,7 +149,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" + "source": "https://github.com/composer/semver/tree/3.4.4" }, "funding": [ { @@ -159,13 +159,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2025-08-20T19:15:30+00:00" }, { "name": "composer/xdebug-handler", @@ -283,30 +279,29 @@ }, { "name": "doctrine/instantiator", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/23da848e1a2308728fe5fdddabf4be17ff9720c7", + "reference": "23da848e1a2308728fe5fdddabf4be17ff9720c7", "shasum": "" }, "require": { - "php": "^8.1" + "php": "^8.4" }, "require-dev": { - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^14", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -333,7 +328,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "source": "https://github.com/doctrine/instantiator/tree/2.1.0" }, "funding": [ { @@ -349,7 +344,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2026-01-05T06:47:08+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -443,16 +438,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -491,7 +486,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -499,7 +494,7 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "netresearch/jsonmapper", @@ -554,16 +549,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.5.0", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -582,7 +577,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -606,22 +601,22 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-05-31T08:24:38+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phan/phan", - "version": "5.4.5", + "version": "5.5.2", "source": { "type": "git", "url": "https://github.com/phan/phan.git", - "reference": "2b15302175931a0629a85c57d0c1f91d68b26a4d" + "reference": "25d7e8d185a4c78e7423c188fb28bba5dbde20c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phan/phan/zipball/2b15302175931a0629a85c57d0c1f91d68b26a4d", - "reference": "2b15302175931a0629a85c57d0c1f91d68b26a4d", + "url": "https://api.github.com/repos/phan/phan/zipball/25d7e8d185a4c78e7423c188fb28bba5dbde20c1", + "reference": "25d7e8d185a4c78e7423c188fb28bba5dbde20c1", "shasum": "" }, "require": { @@ -632,7 +627,7 @@ "ext-tokenizer": "*", "felixfbecker/advanced-json-rpc": "^3.0.4", "microsoft/tolerant-php-parser": "0.1.2", - "netresearch/jsonmapper": "^1.6.0|^2.0|^3.0|^4.0", + "netresearch/jsonmapper": "^1.6.0|^2.0|^3.0|^4.0|^5.0", "php": "^7.2.0|^8.0.0", "sabre/event": "^5.1.3", "symfony/console": "^3.2|^4.0|^5.0|^6.0|^7.0", @@ -686,9 +681,9 @@ ], "support": { "issues": "https://github.com/phan/phan/issues", - "source": "https://github.com/phan/phan/tree/5.4.5" + "source": "https://github.com/phan/phan/tree/5.5.2" }, - "time": "2024-08-13T21:41:35+00:00" + "time": "2025-10-04T18:04:38+00:00" }, { "name": "phar-io/manifest", @@ -863,16 +858,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.2", + "version": "5.6.6", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", "shasum": "" }, "require": { @@ -882,7 +877,7 @@ "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", "phpstan/phpdoc-parser": "^1.7|^2.0", - "webmozart/assert": "^1.9.1" + "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { "mockery/mockery": "~1.3.5 || ~1.6.0", @@ -921,22 +916,22 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" }, - "time": "2025-04-13T19:20:35+00:00" + "time": "2025-12-22T21:13:58+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.10.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", "shasum": "" }, "require": { @@ -979,22 +974,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" }, - "time": "2024-11-09T15:12:26+00:00" + "time": "2025-11-21T15:09:14+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.1.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68" + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", - "reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", + "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", "shasum": "" }, "require": { @@ -1026,22 +1021,17 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" }, - "time": "2025-02-19T13:28:12+00:00" + "time": "2025-08-30T15:50:23+00:00" }, { "name": "phpstan/phpstan", - "version": "2.1.17", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" - }, + "version": "2.1.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", - "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", + "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", "shasum": "" }, "require": { @@ -1086,7 +1076,7 @@ "type": "github" } ], - "time": "2025-05-21T20:55:28+00:00" + "time": "2025-12-05T10:24:31+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -1456,16 +1446,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.23", + "version": "9.6.31", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + "reference": "945d0b7f346a084ce5549e95289962972c4272e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/945d0b7f346a084ce5549e95289962972c4272e5", + "reference": "945d0b7f346a084ce5549e95289962972c4272e5", "shasum": "" }, "require": { @@ -1476,7 +1466,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -1487,11 +1477,11 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", + "sebastian/comparator": "^4.0.9", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", "sebastian/type": "^3.2.1", @@ -1539,7 +1529,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.31" }, "funding": [ { @@ -1563,7 +1553,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T06:40:34+00:00" + "time": "2025-12-06T07:45:52+00:00" }, { "name": "psr/container", @@ -1903,16 +1893,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", "shasum": "" }, "require": { @@ -1965,15 +1955,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2025-08-10T06:51:50+00:00" }, { "name": "sebastian/complexity", @@ -2163,16 +2165,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -2228,28 +2230,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", "shasum": "" }, "require": { @@ -2292,15 +2306,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-08-10T07:10:35+00:00" }, { "name": "sebastian/lines-of-code", @@ -2473,16 +2499,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", "shasum": "" }, "require": { @@ -2524,15 +2550,27 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2025-08-10T06:57:39+00:00" }, { "name": "sebastian/resource-operations", @@ -2699,16 +2737,16 @@ }, { "name": "symfony/console", - "version": "v7.3.0", + "version": "v7.4.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" + "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", - "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", + "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6", + "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6", "shasum": "" }, "require": { @@ -2716,7 +2754,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" + "symfony/string": "^7.2|^8.0" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -2730,16 +2768,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -2773,7 +2811,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.0" + "source": "https://github.com/symfony/console/tree/v7.4.3" }, "funding": [ { @@ -2784,12 +2822,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-05-24T10:34:04+00:00" + "time": "2025-12-23T14:50:43+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2860,7 +2902,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -2919,7 +2961,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -2930,6 +2972,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -2939,16 +2985,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -2997,7 +3043,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -3008,16 +3054,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -3078,7 +3128,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -3089,6 +3139,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3098,7 +3152,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -3159,7 +3213,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -3170,6 +3224,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3179,7 +3237,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -3239,7 +3297,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -3250,6 +3308,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -3259,16 +3321,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -3322,7 +3384,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -3333,44 +3395,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/string", - "version": "v7.3.0", + "version": "v8.0.1", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", - "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "url": "https://api.github.com/repos/symfony/string/zipball/ba65a969ac918ce0cc3edfac6cdde847eba231dc", + "reference": "ba65a969ac918ce0cc3edfac6cdde847eba231dc", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/error-handler": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3409,7 +3474,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.0" + "source": "https://github.com/symfony/string/tree/v8.0.1" }, "funding": [ { @@ -3420,25 +3485,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-20T20:19:01+00:00" + "time": "2025-12-01T09:13:36+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -3467,7 +3536,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -3475,7 +3544,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "tysonandre/var_representation_polyfill", @@ -3541,33 +3610,33 @@ }, { "name": "webmozart/assert", - "version": "1.11.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "reference": "1b34b004e35a164bc5bb6ebd33c844b2d8069a54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/1b34b004e35a164bc5bb6ebd33c844b2d8069a54", + "reference": "1b34b004e35a164bc5bb6ebd33c844b2d8069a54", "shasum": "" }, "require": { "ext-ctype": "*", - "php": "^7.2 || ^8.0" + "ext-date": "*", + "ext-filter": "*", + "php": "^8.2" }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.10-dev" + "dev-feature/2-0": "2.0-dev" } }, "autoload": { @@ -3583,6 +3652,10 @@ { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" + }, + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com" } ], "description": "Assertions to validate method input/output with nice error messages.", @@ -3593,9 +3666,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" + "source": "https://github.com/webmozarts/assert/tree/2.0.0" }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2025-12-16T21:36:00+00:00" } ], "aliases": [], @@ -3605,5 +3678,5 @@ "prefer-lowest": false, "platform": {}, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/www/admin/UrlRequests.target.php b/www/admin/UrlRequests.target.php new file mode 100644 index 00000000..d74e32e8 --- /dev/null +++ b/www/admin/UrlRequests.target.php @@ -0,0 +1,79 @@ + BASE . LOG, + 'log_file_id' => $LOG_FILE_ID, + 'log_per_date' => true, +]); + +/** + * build return json + * + * @param array $http_headers + * @param ?string $body + * @return string + */ +function buildContent(array $http_headers, ?string $body): string +{ + if (is_string($body) && !empty($body)) { + $_body = Json::jsonConvertToArray($body); + if (Json::jsonGetLastError()) { + $body = [$body]; + } else { + $body = $_body; + } + } elseif (is_string($body)) { + $body = []; + } + return Json::jsonConvertArrayTo([ + 'HEADERS' => $http_headers, + "REQUEST_TYPE" => $_SERVER['REQUEST_METHOD'], + "PARAMS" => $_GET, + "BODY" => $body, + // "STRING_BODY" => $body, + ]); +} + +$http_headers = array_filter($_SERVER, function ($value, $key) { + if (str_starts_with($key, 'HTTP_')) { + return true; + } +}, ARRAY_FILTER_USE_BOTH); + +header("Content-Type: application/json; charset=UTF-8"); + +// if the header has Authorization and RunAuthTest then exit with 401 +if (!empty($http_headers['HTTP_AUTHORIZATION']) && !empty($http_headers['HTTP_RUNAUTHTEST'])) { + header("HTTP/1.1 401 Unauthorized"); + print buildContent($http_headers, '{"code": 401, "content": {"Error": "Not Authorized"}}'); + exit(1); +} + +// if server request type is get set file_get to null -> no body +if ($_SERVER['REQUEST_METHOD'] == "GET") { + $file_get = null; +} elseif (($file_get = file_get_contents('php://input')) === false) { + header("HTTP/1.1 404 Not Found"); + print buildContent($http_headers, '{"code": 404, "content": {"Error": "file_get_contents failed"}}'); + exit(1); +} +// str_replace('\"', '"', trim($file_get, '"')); + +$log->debug('SERVER', $log->prAr($_SERVER)); +$log->debug('HEADERS', $log->prAr($http_headers)); +$log->debug('REQUEST TYPE', $_SERVER['REQUEST_METHOD']); +$log->debug('GET', $log->prAr($_GET)); +$log->debug('POST', $log->prAr($_POST)); +$log->debug('PHP-INPUT', $log->prAr($file_get)); + +print buildContent($http_headers, $file_get); + +$log->debug('[END]', '=========================================>'); + +// __END__ diff --git a/www/admin/class_test.array.php b/www/admin/class_test.array.php index 439252f3..9424889b 100644 --- a/www/admin/class_test.array.php +++ b/www/admin/class_test.array.php @@ -332,7 +332,7 @@ print "(kosrt, lower case, reverse): " print "
"; $nested = [ - 'B' => 'foo', 'a', '0', 9, + 'B' => 'foo', 'a', '0', 9, /** @phpstan-ignore-line This is a test for wrong index */ '1' => ['z', 'b', 'a'], 'd' => ['zaip', 'bar', 'baz'] ]; diff --git a/www/admin/class_test.byte.php b/www/admin/class_test.byte.php index cc17ce2f..81577703 100644 --- a/www/admin/class_test.byte.php +++ b/www/admin/class_test.byte.php @@ -74,9 +74,21 @@ foreach ($bytes as $byte) { print '
'; print "(" . number_format($byte) . "/" . $byte . ") bytes :"; $_bytes = Byte::humanReadableByteFormat($byte); - print '
' . $_bytes; - print '
'; - print Byte::stringByteFormat($_bytes); + print '
'; + print '
' . $_bytes . '
'; + print '
'; + try { + print Byte::stringByteFormat($_bytes); + } catch (\LengthException $e) { + print "LengthException 1: " . $e->getMessage(); + try { + print "
S: " . Byte::stringByteFormat($_bytes, Byte::RETURN_AS_STRING); + } catch (\LengthException $e) { + print "LengthException 2: " . $e->getMessage(); + } catch (\RuntimeException $e) { + print "RuntimeException 1: " . $e->getMessage(); + } + } print "
"; // print ""; @@ -87,13 +99,85 @@ foreach ($bytes as $byte) { print "bytes [si]:"; $_bytes = Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_SI); print '
' . $_bytes; - print '
'; - print Byte::stringByteFormat($_bytes); + print '
'; + try { + print Byte::stringByteFormat($_bytes); + } catch (\LengthException $e) { + print "LengthException A: " . $e->getMessage(); + try { + print "
Ssi: " . Byte::stringByteFormat($_bytes, Byte::RETURN_AS_STRING | Byte::BYTE_FORMAT_SI); + } catch (\LengthException $e) { + print "LengthException B: " . $e->getMessage(); + } catch (\RuntimeException $e) { + print "RuntimeException A: " . $e->getMessage(); + } + } print "
"; // print ""; } +$string_bytes = [ + '-117.42 MB', + '242.98 MB', + '254.78 MiB', + '1 EiB', + '8 EB', + '867.36EB', + '1000EB', + '10000EB', +]; +print "BYTE STRING TO BYTES TESTS
"; +foreach ($string_bytes as $string) { + print '
'; + // + print '
'; + print "string byte ($string) to bytes :"; + try { + $_bytes = Byte::stringByteFormat($string); + } catch (\LengthException $e) { + print "
LengthException A: " . $e->getMessage(); + $_bytes = 0; + } + try { + $_bytes_string = Byte::stringByteFormat($string, Byte::RETURN_AS_STRING); + } catch (\LengthException $e) { + print "
LengthException B: " . $e->getMessage(); + $_bytes_string = ''; + } catch (\RuntimeException $e) { + print "
RuntimeException: " . $e->getMessage(); + $_bytes_string = ''; + } + try { + $_bytes_si = Byte::stringByteFormat($string, Byte::BYTE_FORMAT_SI); + } catch (\LengthException $e) { + print "
LengthException A: " . $e->getMessage(); + $_bytes_si = 0; + } + try { + $_bytes_string_si = Byte::stringByteFormat($string, Byte::RETURN_AS_STRING | Byte::BYTE_FORMAT_SI); + } catch (\LengthException $e) { + print "
LengthException B: " . $e->getMessage(); + $_bytes_string_si = ''; + } catch (\RuntimeException $e) { + print "
RuntimeException: " . $e->getMessage(); + $_bytes_string_si = ''; + } + print '
'; + print '
' + . "F:" . number_format((int)$_bytes) + . '
B: ' . $_bytes + . '
S: ' . $_bytes_string + . "
Fsi:" . number_format((int)$_bytes_si) + . '
Bsi: ' . $_bytes_si + . '
Ssi: ' . $_bytes_string_si; + print '
'; + print '
'; + print "B: " . Byte::humanReadableByteFormat($_bytes) . "
"; + print "Bsi: " . Byte::humanReadableByteFormat($_bytes_si, Byte::BYTE_FORMAT_SI); + print "
"; + print "
"; +} print ""; // __END__ diff --git a/www/admin/class_test.debug.php b/www/admin/class_test.debug.php index 25427152..c50ba3ff 100644 --- a/www/admin/class_test.debug.php +++ b/www/admin/class_test.debug.php @@ -68,6 +68,14 @@ function test2(): array return DebugSupport::getCallerMethodList(1); } +// date stueff +print "printTime(-1): " . DebugSupport::printTime() . "
"; +print "printTime(2): " . DebugSupport::printTime(2) . "
"; +print "printTime(3): " . DebugSupport::printTime(3) . "
"; +print "printTime(5): " . DebugSupport::printTime(5) . "
"; +print "printIsoTime(): " . DebugSupport::printIsoTime() . "
"; +print "printIsoTime(false): " . DebugSupport::printIsoTime(false) . "
"; + print "S::GETCALLERMETHOD: " . DebugSupport::getCallerMethod(0) . "
"; print "S::GETCALLERMETHOD: " . test() . "
"; print "S::GETCALLERMETHODLIST:
" . print_r(test2(), true) . "

"; @@ -146,7 +154,7 @@ print "LOG LEVEL: " . DebugSupport::printAr(\CoreLibs\Convert\SetVarType::setAr $new_log->getLogLevel('debug', 'on') )) . "
"; -echo "CLASS DEBUG CALL
"; +echo "CLASS DEBUG CALL LEGACY
"; // @codingStandardsIgnoreLine class TestL diff --git a/www/admin/class_test.error_msg.php b/www/admin/class_test.error_msg.php index e174003d..3ce5173d 100644 --- a/www/admin/class_test.error_msg.php +++ b/www/admin/class_test.error_msg.php @@ -40,6 +40,8 @@ print "Log ERROR: " . $log->prAr($em->getFlagLogError()) . "
"; print "FN: " . ml::fromName('Affe')->name . "
"; print "NU: " . ml::fromValue(100)->name . "
"; print "NU: " . ml::fromValue(1000)->name . "
"; +print "OK.: " . ml::ok->name . "
"; +print "OK^: " . ml::fromName('OK')->name . "
"; $em->setErrorMsg('123', 'error', 'msg this is bad, auto logged if debug'); $em->setErrorMsg('123', 'error', 'msg this is bad, auto logged if debug', 'target-id', 'other-style'); @@ -56,6 +58,14 @@ $em->setErrorMsg('100-2', 'error', 'Input wring', jump_target:['target' => 'foo- $em->setMessage('error', 'I have no id set', jump_target:['target' => 'bar-123', 'info' => 'Jump Bar']); $em->setMessage('error', 'Jump empty', jump_target:['target' => 'bar-empty']); +function inLine(\CoreLibs\Logging\ErrorMessage $em): void +{ + $em->log->error('Direct log before from ', context:['function' => __FUNCTION__]); + $em->setMessage('error', 'Inline call', context:['test' => 'inLine Function']); + $em->log->error('Direct log from ', context:['function' => __FUNCTION__]); +} +inLine($em); + print "ErrorsLast:
" . $log->prAr($em->getLastErrorMsg()) . "
"; print "ErrorsIds:
" . $log->prAr($em->getErrorIds()) . "
"; print "Errors:
" . $log->prAr($em->getErrorMsg()) . "
"; diff --git a/www/admin/class_test.logging.php b/www/admin/class_test.logging.php index 77a47426..f5a2d852 100644 --- a/www/admin/class_test.logging.php +++ b/www/admin/class_test.logging.php @@ -121,6 +121,12 @@ Class TestP public function test(): void { $this->log->info('TestL::test call'); + $this->subCall(); + } + + public function subCall(): void + { + $this->log->info('TestL::sub_call call'); } } diff --git a/www/admin/class_test.uids.php b/www/admin/class_test.uids.php index d01598d5..bf194b57 100644 --- a/www/admin/class_test.uids.php +++ b/www/admin/class_test.uids.php @@ -56,6 +56,8 @@ print "UNIQU ID LONG : " . Uids::uniqIdLong() . "
"; $uuidv4 = Uids::uuidv4(); if (!Uids::validateUuuidv4($uuidv4)) { print "Invalid UUIDv4: " . $uuidv4 . "
"; +} else { + print "Valid UUIDv4: " . $uuidv4 . "
"; } if (!Uids::validateUuuidv4("foobar")) { print "Invalid UUIDv4: hard coded
"; diff --git a/www/admin/edit_base_page_test.php b/www/admin/edit_base_page_test.php new file mode 100644 index 00000000..0ecc3bb3 --- /dev/null +++ b/www/admin/edit_base_page_test.php @@ -0,0 +1,5 @@ +name == 'Debug') { error_reporting(E_ALL); } diff --git a/www/admin/subfolder/class_test.config.direct.php b/www/admin/subfolder/class_test.config.direct.php index de6d32de..43d27810 100644 --- a/www/admin/subfolder/class_test.config.direct.php +++ b/www/admin/subfolder/class_test.config.direct.php @@ -6,7 +6,7 @@ declare(strict_types=1); -error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR); +error_reporting(E_ALL | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR); ob_start(); diff --git a/www/admin/test.env b/www/admin/test.env index 4988714a..d5318911 120000 --- a/www/admin/test.env +++ b/www/admin/test.env @@ -1 +1 @@ -../../4dev/tests/dotenv/test.env \ No newline at end of file +../../4dev/tests/Get/dotenv/test.env \ No newline at end of file diff --git a/www/admin/test.javascript.html b/www/admin/test.javascript.html new file mode 100644 index 00000000..e76020f7 --- /dev/null +++ b/www/admin/test.javascript.html @@ -0,0 +1,37 @@ + + + JavaScript Test + + + + + +
+

JavaScript tests

+
+
+
+ + diff --git a/www/admin/test_edit_base.php b/www/admin/test_edit_base.php index eb429e6d..ebda77ee 100644 --- a/www/admin/test_edit_base.php +++ b/www/admin/test_edit_base.php @@ -4,12 +4,7 @@ declare(strict_types=1); -$DEBUG_ALL_OVERRIDE = false; // set to 1 to debug on live/remote server locations -$DEBUG_ALL = true; -$PRINT_ALL = true; -$DB_DEBUG = true; - -error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR); +error_reporting(E_ALL | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR); ob_start(); @@ -23,15 +18,10 @@ $SET_SESSION_NAME = EDIT_SESSION_NAME; // init login & backend class $session = new CoreLibs\Create\Session($SET_SESSION_NAME); -$log = new CoreLibs\Debug\Logging([ +$log = new CoreLibs\Logging\Logging([ 'log_folder' => BASE . LOG, - 'file_id' => $LOG_FILE_ID, - // add file date - 'print_file_date' => true, - // set debug and print flags - 'debug_all' => $DEBUG_ALL, - 'echo_all' => $ECHO_ALL ?? false, - 'print_all' => $PRINT_ALL, + 'log_file_id' => $LOG_FILE_ID, + 'log_per_date' => true, ]); $db = new CoreLibs\DB\IO(DB_CONFIG, $log); $login = new CoreLibs\ACL\Login( @@ -57,7 +47,7 @@ $l10n = new \CoreLibs\Language\L10n( ); print ""; -print "GROUP TESTER"; +print "GROUP TESTER"; print ""; print '
'; diff --git a/www/composer.lock b/www/composer.lock index ec0b5d56..8111f786 100644 --- a/www/composer.lock +++ b/www/composer.lock @@ -12,7 +12,7 @@ "dist": { "type": "path", "url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All", - "reference": "ec1fb72ba95699907605ac1507fe4c4dd7349896" + "reference": "f765f50350a6364ba36d832ed5acfdb4b3c78143" }, "require": { "php": ">=8.2", @@ -58,6 +58,11 @@ { "name": "egrajp/smarty-extended", "version": "4.5.2", + "source": { + "type": "git", + "url": "https://git.egplusww.jp/Composer/Smarty-Extended", + "reference": "4.5.2" + }, "dist": { "type": "zip", "url": "https://git.egplusww.jp/api/packages/Composer/composer/files/egrajp%2Fsmarty-extended/4.5.2/egrajp-smarty-extended.4.5.2.zip", @@ -209,5 +214,5 @@ "prefer-lowest": false, "platform": {}, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/www/vendor/autoload.php b/www/vendor/autoload.php index e03aa0f8..89c25879 100644 --- a/www/vendor/autoload.php +++ b/www/vendor/autoload.php @@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) { echo $err; } } - trigger_error( - $err, - E_USER_ERROR - ); + throw new RuntimeException($err); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/www/vendor/composer/InstalledVersions.php b/www/vendor/composer/InstalledVersions.php index 07b32ed6..2052022f 100644 --- a/www/vendor/composer/InstalledVersions.php +++ b/www/vendor/composer/InstalledVersions.php @@ -26,12 +26,23 @@ use Composer\Semver\VersionParser; */ class InstalledVersions { + /** + * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to + * @internal + */ + private static $selfDir = null; + /** * @var mixed[]|null * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null */ private static $installed; + /** + * @var bool + */ + private static $installedIsLocalDir; + /** * @var bool|null */ @@ -309,6 +320,24 @@ class InstalledVersions { self::$installed = $data; self::$installedByVendor = array(); + + // when using reload, we disable the duplicate protection to ensure that self::$installed data is + // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, + // so we have to assume it does not, and that may result in duplicate data being returned when listing + // all installed packages for example + self::$installedIsLocalDir = false; + } + + /** + * @return string + */ + private static function getSelfDir() + { + if (self::$selfDir === null) { + self::$selfDir = strtr(__DIR__, '\\', '/'); + } + + return self::$selfDir; } /** @@ -325,7 +354,9 @@ class InstalledVersions $copiedLocalDir = false; if (self::$canGetVendors) { + $selfDir = self::getSelfDir(); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + $vendorDir = strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { @@ -333,11 +364,14 @@ class InstalledVersions $required = require $vendorDir.'/composer/installed.php'; self::$installedByVendor[$vendorDir] = $required; $installed[] = $required; - if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { self::$installed = $required; - $copiedLocalDir = true; + self::$installedIsLocalDir = true; } } + if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { + $copiedLocalDir = true; + } } } diff --git a/www/vendor/composer/autoload_static.php b/www/vendor/composer/autoload_static.php index c48199bf..f9a122d0 100644 --- a/www/vendor/composer/autoload_static.php +++ b/www/vendor/composer/autoload_static.php @@ -7,35 +7,35 @@ namespace Composer\Autoload; class ComposerStaticInit1b7cd5bacf2590b458d7a94400b505d4 { public static $prefixLengthsPsr4 = array ( - 'g' => + 'g' => array ( 'gullevek\\dotenv\\' => 16, 'gullevek\\dotEnv\\' => 16, ), - 'P' => + 'P' => array ( 'Psr\\Log\\' => 8, ), - 'C' => + 'C' => array ( 'CoreLibs\\' => 9, ), ); public static $prefixDirsPsr4 = array ( - 'gullevek\\dotenv\\' => + 'gullevek\\dotenv\\' => array ( 0 => __DIR__ . '/..' . '/gullevek/dotenv/src', ), - 'gullevek\\dotEnv\\' => + 'gullevek\\dotEnv\\' => array ( 0 => __DIR__ . '/..' . '/gullevek/dotenv/src', ), - 'Psr\\Log\\' => + 'Psr\\Log\\' => array ( 0 => __DIR__ . '/..' . '/psr/log/src', ), - 'CoreLibs\\' => + 'CoreLibs\\' => array ( 0 => __DIR__ . '/..' . '/egrajp/corelibs-composer-all/src', ), diff --git a/www/vendor/composer/installed.json b/www/vendor/composer/installed.json index ad51dcee..c2d084a4 100644 --- a/www/vendor/composer/installed.json +++ b/www/vendor/composer/installed.json @@ -7,7 +7,7 @@ "dist": { "type": "path", "url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All", - "reference": "ec1fb72ba95699907605ac1507fe4c4dd7349896" + "reference": "f765f50350a6364ba36d832ed5acfdb4b3c78143" }, "require": { "php": ">=8.2", @@ -56,11 +56,23 @@ "name": "egrajp/smarty-extended", "version": "4.5.2", "version_normalized": "4.5.2.0", + "source": { + "type": "git", + "url": "https://git.egplusww.jp/Composer/Smarty-Extended", + "reference": "4.5.2" + }, "dist": { "type": "zip", "url": "https://git.egplusww.jp/api/packages/Composer/composer/files/egrajp%2Fsmarty-extended/4.5.2/egrajp-smarty-extended.4.5.2.zip", "shasum": "a2c67a5047aad349a2cfa54240a44da449df9c4c" }, + "require": { + "ext-mbstring": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "egrajp/corelibs-composer-all": "^9" + }, "time": "2024-04-16T18:25:27+09:00", "type": "library", "installation-source": "dist", diff --git a/www/vendor/composer/installed.php b/www/vendor/composer/installed.php index 53a77c90..1ddbead2 100644 --- a/www/vendor/composer/installed.php +++ b/www/vendor/composer/installed.php @@ -13,7 +13,7 @@ 'egrajp/corelibs-composer-all' => array( 'pretty_version' => 'dev-development', 'version' => 'dev-development', - 'reference' => 'ec1fb72ba95699907605ac1507fe4c4dd7349896', + 'reference' => 'f765f50350a6364ba36d832ed5acfdb4b3c78143', 'type' => 'library', 'install_path' => __DIR__ . '/../egrajp/corelibs-composer-all', 'aliases' => array(), @@ -31,7 +31,7 @@ 'egrajp/smarty-extended' => array( 'pretty_version' => '4.5.2', 'version' => '4.5.2.0', - 'reference' => null, + 'reference' => '4.5.2', 'type' => 'library', 'install_path' => __DIR__ . '/../egrajp/smarty-extended', 'aliases' => array(), diff --git a/www/vendor/composer/platform_check.php b/www/vendor/composer/platform_check.php index d32d90c6..14bf88da 100644 --- a/www/vendor/composer/platform_check.php +++ b/www/vendor/composer/platform_check.php @@ -19,8 +19,7 @@ if ($issues) { echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; } } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR + throw new \RuntimeException( + 'Composer detected issues in your platform: ' . implode(' ', $issues) ); } diff --git a/www/vendor/egrajp/corelibs-composer-all/publish/last.published b/www/vendor/egrajp/corelibs-composer-all/publish/last.published index d95eff75..05fd0722 100644 --- a/www/vendor/egrajp/corelibs-composer-all/publish/last.published +++ b/www/vendor/egrajp/corelibs-composer-all/publish/last.published @@ -1 +1 @@ -9.33.0 +9.36.0 diff --git a/www/vendor/egrajp/corelibs-composer-all/publish/publish.sh b/www/vendor/egrajp/corelibs-composer-all/publish/publish.sh index c56ac3eb..569b09da 100755 --- a/www/vendor/egrajp/corelibs-composer-all/publish/publish.sh +++ b/www/vendor/egrajp/corelibs-composer-all/publish/publish.sh @@ -9,16 +9,85 @@ VERSION=$(git tag --list | sort -V | tail -n1 | sed -e "s/^v//"); file_last_published="${BASE_FOLDER}last.published"; go_flag="$1"; +function gitea_publish +{ + _GITEA_PUBLISH="${1}" + _GITEA_UPLOAD_FILENAME="${2}" + _GITEA_URL_DL="${3}" + _GITEA_URL_PUSH="${4}" + _GITEA_USER="${5}" + _GITEA_TOKEN="${6}" + _PACKAGE_DOWNLOAD="${7}" + _VERSION="${8}" + _file_last_published="${9}" + + if [ -z "${_GITEA_PUBLISH}" ]; then + return + fi; + if [ -n "${_GITEA_UPLOAD_FILENAME}" ] && + [ -n "${_GITEA_URL_DL}" ] && [ -n "${_GITEA_URL_PUSH}" ] && + [ -n "${_GITEA_USER}" ] && [ -n "${_GITEA_TOKEN}" ]; then + echo "> Publish ${_GITEA_UPLOAD_FILENAME} with ${_VERSION} to: ${_GITEA_URL_PUSH}"; + if [ ! -f "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" ]; then + echo "> Download: ${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip"; + curl -LJO \ + --output-dir "${_PACKAGE_DOWNLOAD}" \ + "${_GITEA_URL_DL}"/v"${_VERSION}".zip; + fi; + if [ ! -f "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" ]; then + echo "[!] Package file does not exist for version: ${_VERSION}"; + else + response=$(curl --user "${_GITEA_USER}":"${_GITEA_TOKEN}" \ + --upload-file "${_PACKAGE_DOWNLOAD}${_GITEA_UPLOAD_FILENAME}-v${_VERSION}.zip" \ + "${_GITEA_URL_PUSH}"?version="${_VERSION}"); + status=$(echo "${response}" | jq .errors[].status); + message=$(echo "${response}" | jq .errors[].message); + if [ -n "${status}" ]; then + echo "[!] Error ${status}: ${message}"; + else + echo "> Publish completed"; + fi; + echo "${_VERSION}" > "${_file_last_published}"; + fi; + else + echo "[!] Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable"; + fi; +} + +function gitlab_publish +{ + _GITLAB_PUBLISH="${1}"; + _GITLAB_URL="${2}"; + _GITLAB_DEPLOY_TOKEN="${3}"; + _PACKAGE_DOWNLOAD="${4}" + _VERSION="${5}" + _file_last_published="${6}" + if [ -z "${GITLAB_PUBLISH}" ]; then + return; + fi; + if [ -n "${_GITLAB_URL}" ] && [ -n "${_GITLAB_DEPLOY_TOKEN}" ]; then + curl --data tag=v"${_VERSION}" \ + --header "Deploy-Token: ${_GITLAB_DEPLOY_TOKEN}" \ + "${_GITLAB_URL}"; + curl --data branch=master \ + --header "Deploy-Token: ${_GITLAB_DEPLOY_TOKEN}" \ + "${_GITLAB_URL}"; + echo "${_VERSION}" > "${_file_last_published}"; + else + echo "[!] Missing GITLAB_URL or GITLAB_DEPLOY_TOKEN environment variable"; + fi; +} + + if [ -z "${VERSION}" ]; then - echo "Version must be set in the form x.y.z without any leading characters"; + echo "[!] Version must be set in the form x.y.z without any leading characters"; exit; fi; # compare version, if different or newer, deploy if [ -f "${file_last_published}" ]; then LAST_PUBLISHED_VERSION=$(cat "${file_last_published}"); if dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"; then - echo "git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}"; - exit; + echo "[!] git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}"; fi; fi; @@ -36,62 +105,30 @@ fi; # GITLAB_TOKEN # GITLAB_URL if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then - echo "Deploy enviroment file .env.deploy is missing"; + echo "[!] Deploy enviroment file .env.deploy is missing"; exit; fi; set -o allexport; -cd "${BASE_FOLDER}" || exit; +cd "${BASE_FOLDER}" || exit # shellcheck source=.env.deploy source .env.deploy; -cd - || exit; +cd - >/dev/null 2>&1 || exit; set +o allexport; if [ "${go_flag}" != "go" ]; then - echo "No go flag given"; - echo "Would publish ${VERSION}"; + echo "[!] No go flag given"; + echo "> Would publish ${VERSION}"; echo "[END]"; exit; fi; echo "[START]"; # gitea -# skip iof -if [ -n "${GITEA_PUBLISH}" ]; then - if [ -n "${GITEA_UPLOAD_FILENAME}" ] && - [ -n "${GITEA_URL_DL}" ] && [ -n "${GITEA_URL_PUSH}" ] && - [ -n "${GITEA_USER}" ] && [ -n "${GITEA_TOKEN}" ]; then - if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then - curl -LJO \ - --output-dir "${PACKAGE_DOWNLOAD}" \ - "${GITEA_URL_DL}"/v"${VERSION}".zip; - fi; - if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then - echo "Version file does not exist for ${VERSION}"; - else - curl --user "${GITEA_USER}":"${GITEA_TOKEN}" \ - --upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \ - "${GITEA_URL_PUSH}"?version="${VERSION}"; - echo "${VERSION}" > "${file_last_published}"; - fi; - else - echo "Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable"; - fi; -fi; +gitea_publish "${GITEA_PUBLISH}" "${GITEA_UPLOAD_FILENAME}" "${GITEA_URL_DL}" "${GITEA_URL_PUSH}" "${GITEA_USER}" "${GITEA_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}"; +gitea_publish "${PR_GITEA_PUBLISH}" "${PR_GITEA_UPLOAD_FILENAME}" "${PR_GITEA_URL_DL}" "${PR_GITEA_URL_PUSH}" "${PR_GITEA_USER}" "${PR_GITEA_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}"; # gitlab -if [ -n "${GITLAB_PUBLISH}" ]; then - if [ -n "${GITLAB_URL}" ] && [ -n "${GITLAB_DEPLOY_TOKEN}" ]; then - curl --data tag=v"${VERSION}" \ - --header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \ - "${GITLAB_URL}"; - curl --data branch=master \ - --header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \ - "${GITLAB_URL}"; - echo "${VERSION}" > "${file_last_published}"; - else - echo "Missing GITLAB_URL or GITLAB_DEPLOY_TOKEN environment variable"; - fi; -fi; +# gitlab_publish "${GITLAB_PUBLISH}" "${GITLAB_URL}" "${GITLAB_DEPLOY_TOKEN}" "${PACKAGE_DOWNLOAD}" "${VERSION}" "${file_last_published}"; echo ""; echo "[DONE]"; diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Basic.php b/www/vendor/egrajp/corelibs-composer-all/src/Basic.php index 1eb3410f..ef93875a 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Basic.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Basic.php @@ -383,7 +383,8 @@ class Basic public function initRandomKeyLength(int $key_length): bool { trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Create\RandomKey::setRandomKeyLength()', E_USER_DEPRECATED); - return \CoreLibs\Create\RandomKey::setRandomKeyLength($key_length); + // no op, we do no longer pre set the random key length + return true; } /** @@ -988,10 +989,10 @@ class Basic * @param bool $auto_check default true, if source encoding is set * check that the source is actually matching * to what we sav the source is - * @return string encoding converted string + * @return string|false encoding converted string * @deprecated use \CoreLibs\Convert\Encoding::convertEncoding() instead */ - public static function convertEncoding(string $string, string $to_encoding, string $source_encoding = '', bool $auto_check = true): string + public static function convertEncoding(string $string, string $to_encoding, string $source_encoding = '', bool $auto_check = true): string|false { trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Convert\Encoding::convertEncoding()', E_USER_DEPRECATED); return \CoreLibs\Convert\Encoding::convertEncoding($string, $to_encoding, $source_encoding, $auto_check); diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Check/Email.php b/www/vendor/egrajp/corelibs-composer-all/src/Check/Email.php index 455a7d24..34b18ef5 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Check/Email.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Check/Email.php @@ -10,12 +10,16 @@ class Email /** @var array */ private static array $email_regex_check = [ 0 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" - . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER + // . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$", // MASTER + // fixed pattern matching for domain + . "(?!-)[A-Za-z0-9-]{1,63}(? "@(.*)@(.*)", // double @ 2 => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@", // wrong part before @ - 3 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$", // wrong part after @ - 4 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.", // wrong domain name part - 5 => "\.([a-zA-Z]{2,6}){1}$", // wrong top level part + // 3 => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$", // wrong part after @ + 3 => "@(?!-)[A-Za-z0-9-]{1,63}(? "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.", // wrong domain name part + 4 => "@(?!-)[A-Za-z0-9-]{1,63}(? "\.[a-zA-Z]{2,6}$", // wrong top level part 6 => "@(.*)\.{2,}", // double .. in domain name part 7 => "@.*\.$" // ends with a dot, top level, domain missing ]; diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Check/Encoding.php b/www/vendor/egrajp/corelibs-composer-all/src/Check/Encoding.php index 577cf9b9..b690c04d 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Check/Encoding.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Check/Encoding.php @@ -56,7 +56,11 @@ class Encoding { // return mb_substitute_character(); if ($return_substitute_func === true) { - return mb_substitute_character(); + // if false abort with error + if (($return = mb_substitute_character()) === false) { + return self::$mb_error_char; + } + return $return; } else { return self::$mb_error_char; } @@ -88,7 +92,13 @@ class Encoding ): array|false { // convert to target encoding and convert back $temp = mb_convert_encoding($string, $to_encoding, $from_encoding); + if ($temp === false) { + return false; + } $compare = mb_convert_encoding($temp, $from_encoding, $to_encoding); + if ($compare === false) { + return false; + } // if string does not match anymore we have a convert problem if ($string == $compare) { return false; @@ -104,7 +114,7 @@ class Encoding (($char != $r_char && (!self::$mb_error_char || in_array(self::$mb_error_char, ['none', 'long', 'entity']))) || ($char != $r_char && $r_char == self::$mb_error_char && self::$mb_error_char)) && - ord($char) != 194 + ord($char[0]) != 194 ) { $failed[] = $char; } diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php b/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php index dae3e1e9..d7e789bb 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Combined/ArrayHandler.php @@ -10,6 +10,8 @@ namespace CoreLibs\Combined; class ArrayHandler { + public const string DATA_SEPARATOR = ':'; + /** * searches key = value in an array / array * only returns the first one found @@ -148,28 +150,32 @@ class ArrayHandler * array search simple. looks for key, value combination, if found, returns true * on default does not strict check, so string '4' will match int 4 and vica versa * - * @param array $array search in as array - * @param string|int $key key (key to search in) - * @param string|int|bool $value value (what to find) - * @param bool $strict [false], if set to true, will strict check key/value - * @return bool true on found, false on not found + * @param array $in_array search in as array + * @param string|int $key key (key to search in) + * @param string|int|bool|array $value values list (what to find) + * @param bool $strict [false], if set to true, will strict check key/value + * @return bool true on found, false on not found */ public static function arraySearchSimple( - array $array, + array $in_array, string|int $key, - string|int|bool $value, + string|int|bool|array $value, bool $strict = false ): bool { - foreach ($array as $_key => $_value) { + // convert to array + if (!is_array($value)) { + $value = [$value]; + } + foreach ($in_array as $_key => $_value) { // if value is an array, we search if (is_array($_value)) { // call recursive, and return result if it is true, else continue if (($result = self::arraySearchSimple($_value, $key, $value, $strict)) !== false) { return $result; } - } elseif ($strict === false && $_key == $key && $_value == $value) { + } elseif ($strict === false && $_key == $key && in_array($_value, $value)) { return true; - } elseif ($strict === true && $_key === $key && $_value === $value) { + } elseif ($strict === true && $_key === $key && in_array($_value, $value, true)) { return true; } } @@ -183,19 +189,19 @@ class ArrayHandler * If prefix is turned on each found group will be prefixed with the * search key * - * @param array $array array to search in + * @param array $in_array array to search in * @param array $needles keys to find in array * @param bool $flat [false] Turn on flat output * @param bool $prefix [false] Prefix found with needle key * @return array Found values */ public static function arraySearchKey( - array $array, + array $in_array, array $needles, bool $flat = false, bool $prefix = false ): array { - $iterator = new \RecursiveArrayIterator($array); + $iterator = new \RecursiveArrayIterator($in_array); $recursive = new \RecursiveIteratorIterator( $iterator, \RecursiveIteratorIterator::SELF_FIRST @@ -236,17 +242,171 @@ class ArrayHandler return $hit_list; } + /** + * Search in an array for value with or without key and + * check in the same array block for the required key + * If not found return an array with the array block there the required key is missing, + * the path as string with seperator block set and the missing key entry + * + * @param array $in_array + * @param string|int|float|bool $search_value + * @param string|array $required_key + * @param ?string $search_key [null] + * @param string $path_separator [DATA_SEPARATOR] + * @param string $current_path + * @return array,path?:string,missing_key?:array}> + */ + public static function findArraysMissingKey( + array $in_array, + string|int|float|bool $search_value, + string|array $required_key, + ?string $search_key = null, + string $path_separator = self::DATA_SEPARATOR, + string $current_path = '' + ): array { + $results = []; + foreach ($in_array as $key => $value) { + $path = $current_path ? $current_path . $path_separator . $key : $key; + + if (is_array($value)) { + // Check if this array contains the search value + // either any value match or with key + if ($search_key === null) { + $containsValue = in_array($search_value, $value, true); + } else { + $containsValue = array_key_exists($search_key, $value) && $value[$search_key] === $search_value; + } + + // If it contains the value but doesn't have the required key + if ( + $containsValue && + ( + ( + is_string($required_key) && + !array_key_exists($required_key, $value) + ) || ( + is_array($required_key) && + count(array_intersect($required_key, array_keys($value))) !== count($required_key) + ) + ) + ) { + $results[] = [ + 'content' => $value, + 'path' => $path, + 'missing_key' => is_array($required_key) ? + array_values(array_diff($required_key, array_keys($value))) : + [$required_key] + ]; + } + + // Recursively search nested arrays + $results = array_merge( + $results, + self::findArraysMissingKey( + $value, + $search_value, + $required_key, + $search_key, + $path_separator, + $path + ) + ); + } + } + + return $results; + } + + /** + * Find key => value entry and return set with key for all matching + * Can search recursively through nested arrays if recursive flag is set + * + * @param array $in_array + * @param string $lookup + * @param int|string|float|bool $search + * @param bool $strict [false] + * @param bool $case_insensitive [false] + * @param bool $recursive [false] + * @param bool $flat_result [true] If set to false and recursive is on the result is a nested array + * @param string $flat_separator [DATA_SEPARATOR] if flat result is true, can be any string + * @return array + */ + public static function selectArrayFromOption( + array $in_array, + string $lookup, + int|string|float|bool $search, + bool $strict = false, + bool $case_insensitive = false, + bool $recursive = false, + bool $flat_result = true, + string $flat_separator = self::DATA_SEPARATOR + ): array { + // skip on empty + if ($in_array == []) { + return []; + } + // init return result + $result = []; + // case sensitive convert if string + if ($case_insensitive && is_string($search)) { + $search = strtolower($search); + } + + foreach ($in_array as $key => $value) { + // Handle current level search + if (isset($value[$lookup])) { + $compareValue = $value[$lookup]; + + if ($case_insensitive && is_string($compareValue)) { + $compareValue = strtolower($compareValue); + } + + if ( + ($strict && $search === $compareValue) || + (!$strict && $search == $compareValue) + ) { + $result[$key] = $value; + } + } + // Handle recursive search if flag is set + if ($recursive && is_array($value)) { + $recursiveResults = self::selectArrayFromOption( + $value, + $lookup, + $search, + $strict, + $case_insensitive, + true, + $flat_result, + $flat_separator + ); + + // Merge recursive results with current results + // Preserve keys by using array_merge with string keys or + operator + foreach ($recursiveResults as $recKey => $recValue) { + if ($flat_result) { + $result[$key . $flat_separator . $recKey] = $recValue; + } else { + $result[$key][$recKey] = $recValue; + } + } + } + } + + return $result; + } + /** * main wrapper function for next/prev key * - * @param array $array array to search in + * @param array $in_array array to search in * @param int|string $key key for next/prev * @param bool $next [=true] if to search next or prev * @return int|string|null Next/prev key or null for end/first */ - private static function arrayGetKey(array $array, int|string $key, bool $next = true): int|string|null + private static function arrayGetKey(array $in_array, int|string $key, bool $next = true): int|string|null { - $keys = array_keys($array); + $keys = array_keys($in_array); if (($position = array_search($key, $keys, true)) === false) { return null; } @@ -262,26 +422,26 @@ class ArrayHandler * Get previous array key from an array * null on not found * - * @param array $array + * @param array $in_array * @param int|string $key * @return int|string|null Next key, or null for not found */ - public static function arrayGetPrevKey(array $array, int|string $key): int|string|null + public static function arrayGetPrevKey(array $in_array, int|string $key): int|string|null { - return self::arrayGetKey($array, $key, false); + return self::arrayGetKey($in_array, $key, false); } /** * Get next array key from an array * null on not found * - * @param array $array + * @param array $in_array * @param int|string $key * @return int|string|null Next key, or null for not found */ - public static function arrayGetNextKey(array $array, int|string $key): int|string|null + public static function arrayGetNextKey(array $in_array, int|string $key): int|string|null { - return self::arrayGetKey($array, $key, true); + return self::arrayGetKey($in_array, $key, true); } /** @@ -303,27 +463,27 @@ class ArrayHandler } // default key is not string $key_is_string = false; - $arrays = func_get_args(); + $in_arrays = func_get_args(); // if last is not array, then assume it is trigger for key is always string - if (!is_array(end($arrays))) { - if (array_pop($arrays)) { + if (!is_array(end($in_arrays))) { + if (array_pop($in_arrays)) { $key_is_string = true; } } // check that arrays count is at least two, else we don't have enough to do anything - if (count($arrays) < 2) { + if (count($in_arrays) < 2) { throw new \ArgumentCountError(__FUNCTION__ . ' needs two or more array arguments'); } $merged = []; - while ($arrays) { - $array = array_shift($arrays); - if (!is_array($array)) { + while ($in_arrays) { + $in_array = array_shift($in_arrays); + if (!is_array($in_array)) { throw new \TypeError(__FUNCTION__ . ' encountered a non array argument'); } - if (!$array) { + if (!$in_array) { continue; } - foreach ($array as $key => $value) { + foreach ($in_array as $key => $value) { // if string or if key is assumed to be string do key match // else add new entry if (is_string($key) || $key_is_string === false) { @@ -429,14 +589,14 @@ class ArrayHandler * converts multi dimensional array to a flat array * does NOT preserve keys * - * @param array $array multi dimensionial array + * @param array $in_array multi dimensionial array * @return array flattened array */ - public static function flattenArray(array $array): array + public static function flattenArray(array $in_array): array { $return = []; array_walk_recursive( - $array, + $in_array, function ($value) use (&$return) { $return[] = $value; } @@ -447,13 +607,13 @@ class ArrayHandler /** * will loop through an array recursivly and write the array keys back * - * @param array $array multidemnsional array to flatten + * @param array $in_array multidemnsional array to flatten * @param array $return recoursive pass on array of keys * @return array flattened keys array */ - public static function flattenArrayKey(array $array, array $return = []): array + public static function flattenArrayKey(array $in_array, array $return = []): array { - foreach ($array as $key => $sub) { + foreach ($in_array as $key => $sub) { $return[] = $key; if (is_array($sub) && count($sub) > 0) { $return = self::flattenArrayKey($sub, $return); @@ -466,14 +626,14 @@ class ArrayHandler * as above will flatten an array, but in this case only the outmost * leave nodes, all other keyswill be skipped * - * @param array $array multidemnsional array to flatten + * @param array $in_array multidemnsional array to flatten * @return array flattened keys array */ - public static function flattenArrayKeyLeavesOnly(array $array): array + public static function flattenArrayKeyLeavesOnly(array $in_array): array { $return = []; array_walk_recursive( - $array, + $in_array, function ($value, $key) use (&$return) { $return[] = $key; } @@ -485,14 +645,14 @@ class ArrayHandler * searches for key -> value in an array tree and writes the value one level up * this will remove this leaf will all other values * - * @param array $array nested array + * @param array $in_array nested array * @param string|int $search key to find that has no sub leaf * and will be pushed up * @return array modified, flattened array */ - public static function arrayFlatForKey(array $array, string|int $search): array + public static function arrayFlatForKey(array $in_array, string|int $search): array { - foreach ($array as $key => $value) { + foreach ($in_array as $key => $value) { // if it is not an array do just nothing if (!is_array($value)) { continue; @@ -500,14 +660,14 @@ class ArrayHandler // probe it has search key if (isset($value[$search])) { // set as current - $array[$key] = $value[$search]; + $in_array[$key] = $value[$search]; } else { // call up next node down - // $array[$key] = call_user_func(__METHOD__, $value, $search); - $array[$key] = self::arrayFlatForKey($value, $search); + // $in_array[$key] = call_user_func(__METHOD__, $value, $search); + $in_array[$key] = self::arrayFlatForKey($value, $search); } } - return $array; + return $in_array; } /** @@ -517,13 +677,13 @@ class ArrayHandler * * https://stackoverflow.com/a/369608 * - * @param array $array Array where elements are located + * @param array $in_array Array where elements are located * @param array $remove Elements to remove * @return array Array with $remove elements removed */ - public static function arrayRemoveEntry(array $array, array $remove): array + public static function arrayRemoveEntry(array $in_array, array $remove): array { - return array_diff($array, $remove); + return array_diff($in_array, $remove); } /** @@ -533,32 +693,33 @@ class ArrayHandler * key list is a list[string] * if key list is empty, return array as is * - * @param array $array + * @param array $in_array * @param array $key_list * @return array */ public static function arrayReturnMatchingKeyOnly( - array $array, + array $in_array, array $key_list ): array { // on empty return as is if (empty($key_list)) { - return $array; + return $in_array; } return array_filter( - $array, + $in_array, fn($key) => in_array($key, $key_list), ARRAY_FILTER_USE_KEY ); } /** - * Modifieds the key of an array with a prefix and/or suffix and returns it with the original value + * Modifieds the key of an array with a prefix and/or suffix and + * returns it with the original value * does not change order in array * * @param array $in_array - * @param string $key_mod_prefix [default=''] key prefix string - * @param string $key_mod_suffix [default=''] key suffix string + * @param string $key_mod_prefix [''] key prefix string + * @param string $key_mod_suffix [''] key suffix string * @return array */ public static function arrayModifyKey( @@ -581,6 +742,75 @@ class ArrayHandler array_values($in_array) ); } + + /** + * sort array and return in same call + * sort ascending or descending with or without lower case convert + * value only, will loose key connections unless preserve_keys is set to true + * + * @param array $in_array Array to sort by values + * @param bool $case_insensitive [false] Sort case insensitive + * @param bool $reverse [false] Reverse sort + * @param bool $maintain_keys [false] Maintain keys + * @param int $flag [SORT_REGULAR] Sort flags + * @return array + */ + public static function sortArray( + array $in_array, + bool $case_insensitive = false, + bool $reverse = false, + bool $maintain_keys = false, + int $flag = SORT_REGULAR + ): array { + $fk_sort_lower_case = function (string $a, string $b): int { + return strtolower($a) <=> strtolower($b); + }; + $fk_sort_lower_case_reverse = function (string $a, string $b): int { + return strtolower($b) <=> strtolower($a); + }; + $case_insensitive ? ( + $maintain_keys ? + (uasort($in_array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) : + (usort($in_array, $reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case)) + ) : + ( + $maintain_keys ? + ($reverse ? arsort($in_array, $flag) : asort($in_array, $flag)) : + ($reverse ? rsort($in_array, $flag) : sort($in_array, $flag)) + ); + return $in_array; + } + + /** + * sort by key ascending or descending and return + * + * @param array $in_array Array to srt + * @param bool $case_insensitive [false] Sort keys case insenstive + * @param bool $reverse [false] Reverse key sort + * @return array + */ + public static function ksortArray(array $in_array, bool $case_insensitive = false, bool $reverse = false): array + { + $fk_sort_lower_case = function (string $a, string $b): int { + return strtolower($a) <=> strtolower($b); + }; + $fk_sort_lower_case_reverse = function (string $a, string $b): int { + return strtolower($b) <=> strtolower($a); + }; + $fk_sort = function (string $a, string $b): int { + return $a <=> $b; + }; + $fk_sort_reverse = function (string $a, string $b): int { + return $b <=> $a; + }; + uksort( + $in_array, + $case_insensitive ? + ($reverse ? $fk_sort_lower_case_reverse : $fk_sort_lower_case) : + ($reverse ? $fk_sort_reverse : $fk_sort) + ); + return $in_array; + } } // __END__ diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php index b0d05ece..a9ddbd99 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Byte.php @@ -14,6 +14,7 @@ class Byte public const BYTE_FORMAT_NOSPACE = 1; public const BYTE_FORMAT_ADJUST = 2; public const BYTE_FORMAT_SI = 4; + public const RETURN_AS_STRING = 8; /** * This function replaces the old byteStringFormat @@ -77,7 +78,7 @@ class Byte // labels in order of size [Y, Z] $labels = ['', 'K', 'M', 'G', 'T', 'P', 'E']; // exp position calculation - $exp = floor(log($abs_bytes, $unit)); + $exp = (int)floor(log($abs_bytes, $unit)); // avoid printing out anything larger than max labels if ($exp >= count($labels)) { $exp = count($labels) - 1; @@ -119,7 +120,9 @@ class Byte * @param int $flags bitwise flag with use space turned on * BYTE_FORMAT_SI: use 1000 instead of 1024 * @return string|int|float converted value or original value - * @throws \InvalidArgumentException 1: no valid flag set + * @throws \InvalidArgumentException no valid flag set + * @throws \LengthException number too large to convert to int + * @throws \RuntimeException BCMath extension not loaded if flag is set to string */ public static function stringByteFormat(string|int|float $number, int $flags = 0): string|int|float { @@ -129,7 +132,12 @@ class Byte } else { $si = false; } - if ($flags != 0 && $flags != 4) { + if ($flags & self::RETURN_AS_STRING) { + $return_as_string = true; + } else { + $return_as_string = false; + } + if ($flags != 0 && $flags != 4 && $flags != 8 && $flags != 12) { throw new \InvalidArgumentException("Invalid flags parameter: $flags", 1); } // matches in regex @@ -142,6 +150,10 @@ class Byte strtolower((string)$number), $matches ); + $number_negative = false; + if (!empty($matches[1])) { + $number_negative = true; + } if (isset($matches[2]) && isset($matches[3])) { // remove all non valid characters from the number $number = preg_replace('/[^0-9\.]/', '', $matches[2]); @@ -152,12 +164,48 @@ class Byte if ($unit) { $number = $number * pow($si ? 1000 : 1024, stripos($valid_units_, $unit[0]) ?: 0); } + // if the number is too large, we cannot convert to int directly + if ($number <= PHP_INT_MIN || $number >= PHP_INT_MAX) { + // if we do not want to convert to string + if (!$return_as_string) { + throw new \LengthException( + 'Number too large be converted to int: ' . (string)$number + ); + } + // for string, check if bcmath is loaded, if not this will not work + if (!extension_loaded('bcmath')) { + throw new \RuntimeException( + 'Number too large be converted to int and BCMath extension not loaded: ' . (string)$number + ); + } + } + // string return + if ($return_as_string) { + // return as string to avoid overflow + // $number = (string)round($number); + $number = bcmul(number_format( + $number, + 12, + '.', + '' + ), "1"); + if ($number_negative) { + $number = '-' . $number; + } + return $number; + } // convert to INT to avoid +E output $number = (int)round($number); // if negative input, keep nnegative - if (!empty($matches[1])) { + if ($number_negative) { $number *= -1; } + // check if number is negative but should be, this is Lenght overflow + if (!$number_negative && $number < 0) { + throw new \LengthException( + 'Number too large be converted to int: ' . (string)$number + ); + } } // if not matching return as is return $number; diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Encoding.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Encoding.php index 26e1a9de..a0a80bf9 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Encoding.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Encoding.php @@ -23,14 +23,14 @@ class Encoding * @param bool $auto_check default true, if source encoding is set * check that the source is actually matching * to what we sav the source is - * @return string encoding converted string + * @return string|false encoding converted string or false on error */ public static function convertEncoding( string $string, string $to_encoding, string $source_encoding = '', bool $auto_check = true - ): string { + ): string|false { // set if not given if (!$source_encoding) { $source_encoding = mb_detect_encoding($string); diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Json.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Json.php index 7f885df4..91626a18 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Json.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Json.php @@ -55,10 +55,10 @@ class Json * Deos not throw errors * * @param array $data - * @param int $flags json_encode flags as is + * @param int $flags [JSON_UNESCAPED_UNICODE] json_encode flags as is * @return string JSON string or '{}' if false */ - public static function jsonConvertArrayTo(array $data, int $flags = 0): string + public static function jsonConvertArrayTo(array $data, int $flags = JSON_UNESCAPED_UNICODE): string { $json_string = json_encode($data, $flags) ?: '{}'; self::$json_last_error = json_last_error(); @@ -119,6 +119,23 @@ class Json } return $return_string === true ? $json_error_string : self::$json_last_error; } + + /** + * wrapper to call convert array to json with pretty print + * + * @param array $data + * @return string + */ + public static function jsonPrettyPrint(array $data): string + { + return self::jsonConvertArrayTo( + $data, + JSON_PRETTY_PRINT | + JSON_UNESCAPED_LINE_TERMINATORS | + JSON_UNESCAPED_SLASHES | + JSON_UNESCAPED_UNICODE + ); + } } // __END__ diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Math.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Math.php index daf4bf07..6aba6f4b 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Math.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Math.php @@ -62,10 +62,15 @@ class Math * * @param float $number Number to cubic root * @return float Calculated value + * @throws \InvalidArgumentException if $number is negative */ public static function cbrt(float|int $number): float { - return pow((float)$number, 1.0 / 3); + $value = pow((float)$number, 1.0 / 3); + if (is_nan($value)) { + throw new \InvalidArgumentException('cube root from this number is not supported: ' . $number); + } + return $value; } /** @@ -199,15 +204,17 @@ class Math callback: fn ($col) => is_array($row) ? array_reduce( array: $row, - callback: fn ($a, $v, $i = null) => $a + $v * ( + // TODO check that v is not an array + callback: fn ($a, $v, $i = null) => $a + $v * ( /** @phpstan-ignore-line Possible array + int */ // if last entry missing for full copy add a 0 to it - $col[$i ?? array_search($v, $row, true)] ?? 0 /** @phpstan-ignore-line */ + $col[$i ?? array_search($v, $row, true)] ?? 0 ), initial: 0, ) : array_reduce( array: $col, - callback: fn ($a, $v) => $a + $v * $row, + // TODO check that v is not an array + callback: fn ($a, $v) => $a + $v * $row, /** @phpstan-ignore-line Possible array + int */ initial: 0, ), array: $bCols, diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php index 81632392..30d4ad44 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Convert/Strings.php @@ -8,8 +8,20 @@ declare(strict_types=1); namespace CoreLibs\Convert; +use CoreLibs\Combined\ArrayHandler; + class Strings { + /** @var array all the preg error messages */ + public const array PREG_ERROR_MESSAGES = [ + PREG_NO_ERROR => 'No error', + PREG_INTERNAL_ERROR => 'Internal PCRE error', + PREG_BACKTRACK_LIMIT_ERROR => 'Backtrack limit exhausted', + PREG_RECURSION_LIMIT_ERROR => 'Recursion limit exhausted', + PREG_BAD_UTF8_ERROR => 'Malformed UTF-8 data', + PREG_BAD_UTF8_OFFSET_ERROR => 'Bad UTF-8 offset', + PREG_JIT_STACKLIMIT_ERROR => 'JIT stack limit exhausted' + ]; /** * return the number of elements in the split list * 0 if nothing / invalid split @@ -52,29 +64,42 @@ class Strings * Note a string LONGER then the maxium will be attached with the LAST * split character. In above exmaple * ABCD1234EFGHTOOLONG will be ABCD-1234-EFGH-TOOLONG + * If the characters are NOT ASCII it will return the string as is * - * @param string $value string value to split + * @param string $string string value to split * @param string $split_format split format - * @param string $split_characters list of charcters with which we split - * if not set uses dash ('-') * @return string split formatted string or original value if not chnaged + * @throws \InvalidArgumentException for empty split format, invalid values, split characters or split format */ public static function splitFormatString( - string $value, + string $string, string $split_format, - string $split_characters = '-' ): string { - if ( - // abort if split format is empty - empty($split_format) || - // if not in the valid ASCII character range for any of the strings - preg_match('/[^\x20-\x7e]/', $value) || - // preg_match('/[^\x20-\x7e]/', $split_format) || - preg_match('/[^\x20-\x7e]/', $split_characters) || - // only numbers and split characters in split_format - !preg_match("/[0-9" . $split_characters . "]/", $split_format) - ) { - return $value; + // skip if string or split format is empty is empty + if (empty($string) || empty($split_format)) { + return $string; + } + if (preg_match('/[^\x20-\x7e]/', $string)) { + throw new \InvalidArgumentException( + "The string to split can only be ascii characters: " . $string + ); + } + // get the split characters that are not numerical and check they are ascii + $split_characters = self::removeDuplicates(preg_replace('/[0-9]/', '', $split_format) ?: ''); + if (empty($split_characters)) { + throw new \InvalidArgumentException( + "A split character must exist in the format string: " . $split_format + ); + } + if (preg_match('/[^\x20-\x7e]/', $split_characters)) { + throw new \InvalidArgumentException( + "The split character has to be a valid ascii character: " . $split_characters + ); + } + if (!preg_match("/^[0-9" . $split_characters . "]+$/", $split_format)) { + throw new \InvalidArgumentException( + "The split format can only be numbers and the split characters: " . $split_format + ); } // split format list $split_list = preg_split( @@ -86,14 +111,14 @@ class Strings ); // if this is false, or only one array, abort split if (!is_array($split_list) || count($split_list) == 1) { - return $value; + return $string; } $out = ''; $pos = 0; $last_split = ''; foreach ($split_list as $offset) { if (is_numeric($offset)) { - $_part = substr($value, $pos, (int)$offset); + $_part = substr($string, $pos, (int)$offset); if (empty($_part)) { break; } @@ -104,8 +129,8 @@ class Strings $last_split = $offset; } } - if (!empty($out) && $pos < strlen($value)) { - $out .= $last_split . substr($value, $pos); + if (!empty($out) && $pos < strlen($string)) { + $out .= $last_split . substr($string, $pos); } // if last is not alphanumeric remove, remove if (!strcspn(substr($out, -1, 1), $split_characters)) { @@ -115,10 +140,49 @@ class Strings if (!empty($out)) { return $out; } else { - return $value; + return $string; } } + /** + * Split a string into n-length blocks with a split character inbetween + * This is simplified version from splitFormatString that uses + * fixed split length with a characters, this evenly splits the string out into the + * given length + * This works with non ASCII characters too + * + * @param string $string string to split + * @param int $split_length split length, must be smaller than string and larger than 0 + * @param string $split_characters [default=-] the character to split, can be more than one + * @return string + * @throws \InvalidArgumentException Thrown if split length style is invalid + */ + public static function splitFormatStringFixed( + string $string, + int $split_length, + string $split_characters = '-' + ): string { + // if empty string or if split lenght is 0 or empty split characters + // then we skip any splitting + if (empty($string) || $split_length == 0 || empty($split_characters)) { + return $string; + } + $return_string = ''; + $string_length = mb_strlen($string); + // check that the length is not too short + if ($split_length < 1 || $split_length >= $string_length) { + throw new \InvalidArgumentException( + "The split length must be at least 1 character and less than the string length to split. " + . "Split length: " . $split_length . ", string length: " . $string_length + ); + } + for ($i = 0; $i < $string_length; $i += $split_length) { + $return_string .= mb_substr($string, $i, $split_length) . $split_characters; + } + // remove last trailing character which is always the split char length + return mb_substr($return_string, 0, -1 * mb_strlen($split_characters)); + } + /** * Strip any duplicated slahes from a path * eg: //foo///bar/foo.inc -> /foo/bar/foo.inc @@ -146,6 +210,116 @@ class Strings { return trim($text, pack('H*', 'EFBBBF')); } + + /** + * Make as string of characters unique + * + * @param string $string + * @return string + */ + public static function removeDuplicates(string $string): string + { + // combine again + $result = implode( + '', + // unique list + array_unique( + // split into array + mb_str_split($string) + ) + ); + + return $result; + } + + /** + * check if all characters are in set + * + * @param string $needle Needle to search + * @param string $haystack Haystack to search in + * @return bool True on found, False if not in haystack + */ + public static function allCharsInSet(string $needle, string $haystack): bool + { + $input_length = strlen($needle); + + for ($i = 0; $i < $input_length; $i++) { + if (strpos($haystack, $needle[$i]) === false) { + return false; + } + } + + return true; + } + + /** + * converts a list of arrays of strings into a string of unique entries + * input arrays can be nested, only values are used + * + * @param array ...$char_lists + * @return string + */ + public static function buildCharStringFromLists(array ...$char_lists): string + { + return implode('', array_unique( + ArrayHandler::flattenArray( + array_merge(...$char_lists) + ) + )); + } + + /** + * Check if a regex is valid. Does not return the detail regex parser error + * + * @param string $pattern Any regex string + * @return bool False on invalid regex + */ + public static function isValidRegex(string $pattern): bool + { + preg_last_error(); + try { + $var = ''; + @preg_match($pattern, $var); + return preg_last_error() === PREG_NO_ERROR; + } catch (\Error $e) { + return false; + } + } + + /** + * Returns the last preg error messages as string + * all messages are defined in PREG_ERROR_MESSAGES + * + * @return string + */ + public static function getLastRegexErrorString(): string + { + return self::PREG_ERROR_MESSAGES[preg_last_error()] ?? 'Unknown error'; + } + + /** + * check if a regex is invalid, returns array with flag and error string + * + * @param string $pattern + * @return array{valid:bool,preg_error:int,error:null|string,pcre_error:null|string} + */ + public static function validateRegex(string $pattern): array + { + // Clear any previous PCRE errors + preg_last_error(); + $var = ''; + if (@preg_match($pattern, $var) === false) { + $error = preg_last_error(); + return [ + 'valid' => false, + 'preg_error' => $error, + 'error' => self::PREG_ERROR_MESSAGES[$error] ?? 'Unknown error', + 'pcre_error' => preg_last_error_msg(), + ]; + } + + return ['valid' => true, 'preg_error' => PREG_NO_ERROR, 'error' => null, 'pcre_error' => null]; + } } // __END__ diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Create/Email.php b/www/vendor/egrajp/corelibs-composer-all/src/Create/Email.php index 5e0c6f72..2f549bbf 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Create/Email.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Create/Email.php @@ -38,6 +38,7 @@ class Email * @param string $encoding Encoding, if not set UTF-8 * @param bool $kv_folding If set to true and a valid encoding, do KV folding * @return string Correctly encoded and build email string + * @throws \IntlException if email name cannot be converted to UTF-8 */ public static function encodeEmailName( string $email, @@ -52,6 +53,10 @@ class Email if ($encoding != 'UTF-8') { $email_name = mb_convert_encoding($email_name, $encoding, 'UTF-8'); } + // if we cannot transcode the name, return just the email + if ($email_name === false) { + throw new \IntlException('Cannot convert email_name to UTF-8'); + } $email_name = mb_encode_mimeheader( in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ? @@ -77,6 +82,8 @@ class Email * @param bool $kv_folding If set to true and a valid encoding, * do KV folding * @return array Pos 0: Subject, Pos 1: Body + * @throws \IntlException if subject cannot be converted to UTF-8 + * @throws \IntlException if body cannot be converted to UTF-8 */ private static function replaceContent( string $subject, @@ -102,6 +109,12 @@ class Email $subject = mb_convert_encoding($subject, $encoding, 'UTF-8'); $body = mb_convert_encoding($body, $encoding, 'UTF-8'); } + if ($subject === false) { + throw new \IntlException('Cannot convert subject to UTF-8'); + } + if ($body === false) { + throw new \IntlException('Cannot convert body to UTF-8'); + } // we need to encodde the subject $subject = mb_encode_mimeheader( in_array($encoding, self::$encoding_kv_allowed) && $kv_folding ? diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Create/RandomKey.php b/www/vendor/egrajp/corelibs-composer-all/src/Create/RandomKey.php index 6d57f754..31a5c5b8 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Create/RandomKey.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Create/RandomKey.php @@ -8,39 +8,97 @@ declare(strict_types=1); namespace CoreLibs\Create; +use CoreLibs\Convert\Strings; + class RandomKey { + /** @var int set the default key length it nothing else is set */ + public const int KEY_LENGTH_DEFAULT = 4; + /** @var int the maximum key length allowed */ + public const int KEY_LENGTH_MAX = 256; + /** @var string the default characters in the key range */ + public const string KEY_CHARACTER_RANGE_DEFAULT = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + . 'abcdefghijklmnopqrstuvwxyz' + . '0123456789'; // key generation - /** @var string */ - private static string $key_range = ''; - /** @var int */ - private static int $one_key_length; - /** @var int */ - private static int $key_length = 4; // default key length - /** @var int */ - private static int $max_key_length = 256; // max allowed length + /** @var string all the characters that are int he current radnom key range */ + private static string $key_character_range = ''; + /** @var int character count in they key character range */ + private static int $key_character_range_length = 0; + /** @var int default key lenghth */ + /** @deprecated Will be removed */ + private static int $key_length = 4; /** * if launched as class, init random key data first + * + * @param array ...$key_range */ - public function __construct() + public function __construct(array ...$key_range) { - $this->initRandomKeyData(); + $this->setRandomKeyData(...$key_range); } + + /** + * internal key range validation + * + * @param array ...$key_range + * @return string + */ + private static function validateRandomKeyData(array ...$key_range): string + { + $key_character_range = Strings::buildCharStringFromLists(...$key_range); + if (strlen(self::$key_character_range) <= 1) { + return ''; + } + return $key_character_range; + } + /** * sets the random key range with the default values * + * @param array $key_range a list of key ranges as array * @return void has no return + * @throws \LengthException If the string length is only 1 abort */ - private static function initRandomKeyData(): void + public static function setRandomKeyData(array ...$key_range): void { - // random key generation base string - self::$key_range = join('', array_merge( - range('A', 'Z'), - range('a', 'z'), - range('0', '9') - )); - self::$one_key_length = strlen(self::$key_range); + // if key range is not set + if (!count($key_range)) { + self::$key_character_range = self::KEY_CHARACTER_RANGE_DEFAULT; + } else { + self::$key_character_range = self::validateRandomKeyData(...$key_range); + // random key generation base string + } + self::$key_character_range_length = strlen(self::$key_character_range); + if (self::$key_character_range_length <= 1) { + throw new \LengthException( + "The given key character range '" . self::$key_character_range . "' " + . "is too small, must be at lest two characters: " + . self::$key_character_range_length + ); + } + } + + /** + * get the characters for the current key characters + * + * @return string + */ + public static function getRandomKeyData(): string + { + return self::$key_character_range; + } + + /** + * get the length of all random characters + * + * @return int + */ + public static function getRandomKeyDataLength(): int + { + return self::$key_character_range_length; } /** @@ -53,7 +111,7 @@ class RandomKey { if ( $key_length > 0 && - $key_length <= self::$max_key_length + $key_length <= self::KEY_LENGTH_MAX ) { return true; } else { @@ -67,6 +125,7 @@ class RandomKey * * @param int $key_length key length * @return bool true/false for set status + * @deprecated This function does no longer set the key length, the randomKeyGen parameter has to b used */ public static function setRandomKeyLength(int $key_length): bool { @@ -83,6 +142,7 @@ class RandomKey * get the current set random key length * * @return int Current set key length + * @deprecated Key length is set during randomKeyGen call, this nethid is deprecated */ public static function getRandomKeyLength(): int { @@ -94,28 +154,37 @@ class RandomKey * if override key length is set, it will check on valid key and use this * this will not set the class key length variable * - * @param int $key_length key length override, -1 for use default - * @return string random key + * @param int $key_length [default=-1] key length override, + * if not set use default [LEGACY] + * @param array $key_range a list of key ranges as array, + * if not set use previous set data + * @return string random key */ - public static function randomKeyGen(int $key_length = -1): string - { - // init random key strings if not set - if ( - !isset(self::$one_key_length) - ) { - self::initRandomKeyData(); - } - $use_key_length = 0; - // only if valid int key with valid length - if (self::validateRandomKeyLenght($key_length) === true) { - $use_key_length = $key_length; + public static function randomKeyGen( + int $key_length = self::KEY_LENGTH_DEFAULT, + array ...$key_range + ): string { + $key_character_range = ''; + if (count($key_range)) { + $key_character_range = self::validateRandomKeyData(...$key_range); + $key_character_range_length = strlen($key_character_range); } else { - $use_key_length = self::$key_length; + if (!self::$key_character_range_length) { + self::setRandomKeyData(); + } + $key_character_range = self::getRandomKeyData(); + $key_character_range_length = self::getRandomKeyDataLength(); + } + // if not valid key length, fallback to default + if (!self::validateRandomKeyLenght($key_length)) { + $key_length = self::KEY_LENGTH_DEFAULT; } // create random string $random_string = ''; - for ($i = 1; $i <= $use_key_length; $i++) { - $random_string .= self::$key_range[random_int(0, self::$one_key_length - 1)]; + for ($i = 1; $i <= $key_length; $i++) { + $random_string .= $key_character_range[ + random_int(0, $key_character_range_length - 1) + ]; } return $random_string; } diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Create/Uids.php b/www/vendor/egrajp/corelibs-composer-all/src/Create/Uids.php index 09bdc86b..d82ed36b 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Create/Uids.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Create/Uids.php @@ -81,7 +81,7 @@ class Uids */ public static function validateUuuidv4(string $uuidv4): bool { - if (!preg_match("/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/", $uuidv4)) { + if (!preg_match("/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i", $uuidv4)) { return false; } return true; diff --git a/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php b/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php index 9fbbf876..9640a5be 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/DB/Support/ConvertPlaceholder.php @@ -263,11 +263,11 @@ class ConvertPlaceholder } } // add the connectors back (1), and the data sets only if no replacement will be done - return $params_lookup[$match] ?? + return $params_lookup[$match]/* ?? throw new \RuntimeException( 'Cannot lookup ' . $match . ' in params lookup list', 211 - ); + )*/; }, $converted_placeholders['original']['query'] ); @@ -327,11 +327,11 @@ class ConvertPlaceholder } } // add the connectors back (1), and the data sets only if no replacement will be done - return $params_lookup[$match] ?? + return $params_lookup[$match]/* ?? throw new \RuntimeException( 'Cannot lookup ' . $match . ' in params lookup list', 231 - ); + )*/; }, $converted_placeholders['original']['query'] ); diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php b/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php index affec0f7..beabd0a8 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Debug/Support.php @@ -33,6 +33,36 @@ class Support return $string; } + /** + * print ISO type datetime with microseconds and timezone + * Y-m-dTH:i:s.uP + * if no micro time the ".u" part is omitted + * + * @param bool $set_micro_time + * @return string + */ + public static function printIsoTime(bool $set_micro_time = true): string + { + $datetime = new \DateTime(); + + // Format the DateTime object to ISO 8601 with microseconds + // 'Y-m-d\TH:i:s.uP' is the format string: + // Y: Full year (e.g., 2025) + // m: Month (01-12) + // d: Day of the month (01-31) + // T: Literal 'T' to separate date and time (escaped with a backslash) + // H: Hour (00-23) + // i: Minute (00-59) + // s: Second (00-59) + // u: Microseconds (e.g., 654321) + // P: Difference to Greenwich time (GMT) with colon (e.g., +09:00) + if ($set_micro_time) { + return $datetime->format('Y-m-d\TH:i:s.uP'); + } else { + return $datetime->format('Y-m-d\TH:i:sP'); + } + } + /** * prints a html formatted (pre) data * diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Logging/ErrorMessage.php b/www/vendor/egrajp/corelibs-composer-all/src/Logging/ErrorMessage.php index c952c69e..153faf2c 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Logging/ErrorMessage.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Logging/ErrorMessage.php @@ -131,6 +131,7 @@ class ErrorMessage // set a jump target $this->setJumpTarget($jump_target['target'] ?? null, $jump_target['info'] ?? null, $level); // write to log for abort/crash + $this->log->setErrorMessageCallSetErrorMsg(); switch ($level) { case 'notice': $this->log->notice($message ?? $str, array_merge([ @@ -210,6 +211,7 @@ class ErrorMessage ?bool $log_error = null, ?bool $log_warning = null, ): void { + $this->log->setErrorMessageCallSetMessage(); $this->setErrorMsg( $error_id ?? '', $level, @@ -289,7 +291,7 @@ class ErrorMessage */ public function getLastErrorMsg(): array { - return $this->error_str[array_key_last($this->error_str)] ?? [ + return $this->error_str[array_key_last($this->error_str) ?? -1] ?? [ 'level' => '', 'str' => '', 'id' => '', diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/Level.php b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/Level.php index ba497f70..dd59bfa6 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/Level.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/Level.php @@ -112,7 +112,7 @@ enum Level: int } /** - * Returns true if the passed $level is higher or equal to $this + * Returns true if the passed $level is included in set level * * @param Level $level * @return bool diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/MessageLevel.php b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/MessageLevel.php index 60bb2717..3b74bf52 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/MessageLevel.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logger/MessageLevel.php @@ -13,6 +13,7 @@ namespace CoreLibs\Logging\Logger; enum MessageLevel: int { + case noset = 0; case ok = 100; case success = 150; // special for file uploads case info = 200; diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logging.php b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logging.php index 7476ef56..5bedf4bc 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logging.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Logging/Logging.php @@ -29,12 +29,21 @@ use Stringable; class Logging { /** @var int minimum size for a max file size, so we don't set 1 byte, 10kb */ - public const MIN_LOG_MAX_FILESIZE = 10 * 1024; + public const int MIN_LOG_MAX_FILESIZE = 10 * 1024; /** @var string log file extension, not changeable */ - private const LOG_FILE_NAME_EXT = "log"; + private const string LOG_FILE_NAME_EXT = "log"; /** @var string log file block separator, not changeable */ - private const LOG_FILE_BLOCK_SEPARATOR = '.'; + private const string LOG_FILE_BLOCK_SEPARATOR = '.'; + /** @var int the base stack trace level for the line number */ + private const int DEFAULT_STACK_TRACE_LEVEL_LINE = 1; + /** @var array */ + private const array STACK_OVERRIDE_CHECK = [ + 'setErrorMsg' => 2, + 'setMessage' => 3, + ]; + + // MARK: OPTION array // NOTE: the second party array{} hs some errors /** @var array>|array{string:array{type:string,type_info?:string,mandatory:true,alias?:string,default:string|bool|Level,deprecated:bool,use?:string}} */ private const OPTIONS = [ @@ -50,6 +59,7 @@ class Logging 'type' => 'string', 'mandatory' => false, 'default' => '', 'deprecated' => true, 'use' => 'log_file_id' ], + // log level 'log_level' => [ 'type' => 'instance', 'type_info' => '\CoreLibs\Logging\Logger\Level', @@ -57,6 +67,14 @@ class Logging 'default' => Level::Debug, 'deprecated' => false ], + // level to trigger write to error_log + 'error_log_write_level' => [ + 'type' => 'instance', + 'type_info' => '\CoreLibs\Logging\Logger\Level', + 'mandatory' => false, + 'default' => Level::Emergency, + 'deprecated' => false, + ], // options 'log_per_run' => [ 'type' => 'bool', 'mandatory' => false, @@ -86,14 +104,21 @@ class Logging 'type' => 'bool', 'mandatory' => false, 'default' => false, 'deprecated' => true, 'use' => 'log_per_date' ], + // if turned off uses old time format without time zone + 'log_time_format_iso' => [ + 'type' => 'bool', 'mandatory' => false, + 'default' => true, 'deprecated' => false + ] ]; // options /** @var array */ private array $options = []; - /** @var Level set level */ + /** @var Level set logging level */ private Level $log_level; + /** @var Level set level for writing to error_log, will not write if log level lower than error log write level */ + private Level $error_log_write_level; // page and host name /** @var string */ @@ -121,6 +146,12 @@ class Logging /** @var string Y-m-d file in file name */ private string $log_file_date = ''; + // speical flags for ErrorMessage calls + /** @var bool Flag to set if called from ErrorMessage::setErrorMsg */ + private bool $error_message_call_set_error_msg = false; + /** @var bool Flag to set if called from ErrorMessage::setMessage */ + private bool $error_message_call_set_message = false; + /** * 1: create a new log file per run (time stamp + unique ID) * 2: add Y-m-d and do automatic daily rotation @@ -145,12 +176,13 @@ class Logging ]; /** - * Init logger + * MARK: Init logger * * options array layout * - log_folder: * - log_file_id / file_id (will be deprecated): * - log_level: + * - error_log_write_level: at what level we write to error_log * * - log_per_run: * - log_per_date: (was print_file_date) @@ -172,6 +204,8 @@ class Logging // set log level $this->initLogLevel(); + // set error log write level + $this->initErrorLogWriteLevel(); // set log folder from options $this->initLogFolder(); // set per run UID for logging @@ -190,8 +224,10 @@ class Logging // PRIVATE METHODS // ********************************************************************* + // MARK: options check + /** - * Undocumented function + * validate options * * @param array $options * @return bool @@ -263,6 +299,8 @@ class Logging return true; } + // MARK: init log elvels + /** * init log level, just a wrapper to auto set from options * @@ -280,6 +318,24 @@ class Logging $this->setLoggingLevel($this->options['log_level']); } + /** + * init error log write level + * + * @return void + */ + private function initErrorLogWriteLevel() + { + if ( + empty($this->options['error_log_write_level']) || + !$this->options['error_log_write_level'] instanceof Level + ) { + $this->options['error_log_write_level'] = Level::Emergency; + } + $this->setErrorLogWriteLevel($this->options['error_log_write_level']); + } + + // MARK: set log folder + /** * Set the log folder * If folder is not writeable the script will throw an E_USER_ERROR @@ -321,6 +377,8 @@ class Logging return $status; } + // MARK: set host name + /** * Set the hostname and port * If port is not defaul 80 it will be added to the host name @@ -337,6 +395,8 @@ class Logging } } + // MARK: set log file id (file) + /** * set log file prefix id * @@ -395,6 +455,8 @@ class Logging return $status; } + // MARK init log flags and levels + /** * set flags from options and option flags connection internal settings * @@ -423,6 +485,19 @@ class Logging return $this->log_level->includes($level); } + /** + * Checks that given level is matchins error_log write level + * + * @param Level $level + * @return bool + */ + private function checkErrorLogWriteLevel(Level $level): bool + { + return $this->error_log_write_level->includes($level); + } + + // MARK: build log ifle name + /** * Build the file name for writing * @@ -490,6 +565,8 @@ class Logging return $fn; } + // MARK: master write log to file + /** * writes error msg data to file for current level * @@ -507,6 +584,10 @@ class Logging if (!$this->checkLogLevel($level)) { return false; } + // if we match level then write to error_log + if ($this->checkErrorLogWriteLevel($level)) { + error_log((string)$message); + } // build logging file name // fn is log folder + file name @@ -531,6 +612,8 @@ class Logging return true; } + // MARK: master prepare log + /** * Prepare the log message with all needed info blocks: * [timestamp] [host name] [file path + file::row number] [running uid] {class::/->method} @@ -558,31 +641,65 @@ class Logging $file_line = ''; $caller_class_method = '-'; $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - // print "[" . $level->getName() . "] [$message] prepareLog:
" . Support::printAr($traces); - // file + line: call not this but one before (the one that calls this) - // start from this level, if unset fall down until we are at null - $start_trace_level = 2; - for ($trace_level = $start_trace_level; $trace_level >= 0; $trace_level--) { - if (isset($traces[$trace_level])) { - $file_line = ($traces[$trace_level]['file'] ?? $traces[$trace_level]['function']) - . ':' . ($traces[$trace_level]['line'] ?? '-'); - // as namespace\class->method - $caller_class_method = - // get the last call before we are in the Logging class - ($traces[$trace_level]['class'] ?? '') - // connector, if unkown use == - . ($traces[$trace_level]['type'] ?? '') - // method/function: prepareLog->(debug|info|...)->[THIS] - . $traces[$trace_level]['function']; - break; + $stack_trace_start_level_line = self::DEFAULT_STACK_TRACE_LEVEL_LINE; + // set stack trace level +1 if called from ErrorMessage::setMessage + if ($this->error_message_call_set_message) { + $stack_trace_start_level_line = 3; + } elseif ($this->error_message_call_set_error_msg) { + $stack_trace_start_level_line = 2; + } + // if we have line > default, then check if valid, else reset to default + if ($stack_trace_start_level_line > self::DEFAULT_STACK_TRACE_LEVEL_LINE) { + // check if function at level is one of the override checks + $fn_check = $traces[$stack_trace_start_level_line]['function'] ?? ''; + if ( + !isset(self::STACK_OVERRIDE_CHECK[$fn_check]) || + self::STACK_OVERRIDE_CHECK[$fn_check] != $stack_trace_start_level_line + ) { + $stack_trace_start_level_line = self::DEFAULT_STACK_TRACE_LEVEL_LINE; } } + $this->error_message_call_set_message = false; + $this->error_message_call_set_error_msg = false; + // set stack trace level +1 if called from ErrorMessage::setMessage + // print "[" . $level->getName() . "] [$message] [" . $stack_trace_start_level_line . "] " + // . "prepareLog:
" . Support::printAr($traces); + // file + line: call not this but one before (the one that calls this) + // start from this level, if unset fall down until we are at null + // NOTE this has to be pushed to 3 for setMessage wrap calls + for ($trace_level = $stack_trace_start_level_line; $trace_level >= 0; $trace_level--) { + if (!isset($traces[$trace_level])) { + continue; + } + $file_line = ($traces[$trace_level]['file'] ?? $traces[$trace_level]['function']) + . ':' . ($traces[$trace_level]['line'] ?? '-'); + // call function is one stack level above + $trace_level++; + // skip setting if we are in the top level already + if (!isset($traces[$trace_level])) { + break; + } + // as namespace\class->method + $caller_class_method = + // get the last call before we are in the Logging class + ($traces[$trace_level]['class'] ?? '') + // connector, if unkown use == + . ($traces[$trace_level]['type'] ?? '') + // method/function: prepareLog->(debug|info|...)->[THIS] + . $traces[$trace_level]['function']; + break; + } + // if not line is set if (empty($file_line)) { $file_line = System::getPageName(System::FULL_PATH); } // print "CLASS: " . $class . "
"; // get timestamp - $timestamp = Support::printTime(); + if (!empty($this->options['log_time_format_iso'])) { + $timestamp = Support::printIsoTime(); + } else { + $timestamp = Support::printTime(); + } // if group id is empty replace it with current level $group_str = $level->getName(); @@ -610,6 +727,7 @@ class Logging // PUBLIC STATIC METHJODS // ********************************************************************* + // MARK: set log level /** * set the log level * @@ -670,7 +788,7 @@ class Logging // **** GET/SETTER - // log level set and get + // MARK: log level /** * set new log level @@ -705,7 +823,30 @@ class Logging ); } - // log file id set (file name prefix) + // MARK: error log write level + + /** + * set the error_log write level + * + * @param string|int|Level $level + * @return void + */ + public function setErrorLogWriteLevel(string|int|Level $level): void + { + $this->error_log_write_level = $this->processLogLevel($level); + } + + /** + * get the current level for error_log write + * + * @return Level + */ + public function getErrorLogWriteLevel(): Level + { + return $this->error_log_write_level; + } + + // MARK: log file id set (file name prefix) /** * sets the internal log file prefix id @@ -733,7 +874,7 @@ class Logging return $this->log_file_id; } - // log unique id set (for per run) + // MARK: log unique id set (for per run) /** * Sets a unique id based on current date (y/m/d, h:i:s) and a unique id (8 chars) @@ -768,7 +909,7 @@ class Logging return $this->log_file_unique_id; } - // general log date + // MARK: general log date /** * set the log file date to Y-m-d @@ -791,7 +932,7 @@ class Logging return $this->log_file_date; } - // general flag set + // MARK: general flag set /** * set one of the basic flags @@ -846,7 +987,7 @@ class Logging return $this->log_flags; } - // log folder/file + // MARK: log folder/file /** * set new log folder, check that folder is writeable @@ -890,7 +1031,7 @@ class Logging return $this->log_file_name; } - // max log file size + // MARK: max log file size /** * set mag log file size @@ -921,7 +1062,31 @@ class Logging } // ********************************************************************* - // OPTIONS CALLS + // MARK: ErrorMessage class overrides + // ********************************************************************* + + /** + * call if called from Error Message setMessage wrapper + * + * @return void + */ + public function setErrorMessageCallSetMessage(): void + { + $this->error_message_call_set_message = true; + } + + /** + * call if called from Error Message setMessage wrapper + * + * @return void + */ + public function setErrorMessageCallSetErrorMsg(): void + { + $this->error_message_call_set_error_msg = true; + } + + // ********************************************************************* + // MARK: OPTIONS CALLS // ********************************************************************* /** @@ -939,6 +1104,8 @@ class Logging // MAIN CALLS // ********************************************************************* + // MARK: main log call + /** * Commong log interface * @@ -976,7 +1143,7 @@ class Logging } /** - * DEBUG: 100 + * MARK: DEBUG: 100 * * write debug data to error_msg array * @@ -1008,7 +1175,7 @@ class Logging } /** - * INFO: 200 + * MARK: INFO: 200 * * @param string|Stringable $message * @param mixed[] $context @@ -1027,7 +1194,7 @@ class Logging } /** - * NOTICE: 250 + * MARK: NOTICE: 250 * * @param string|Stringable $message * @param mixed[] $context @@ -1046,7 +1213,7 @@ class Logging } /** - * WARNING: 300 + * MARK: WARNING: 300 * * @param string|Stringable $message * @param mixed[] $context @@ -1065,7 +1232,7 @@ class Logging } /** - * ERROR: 400 + * MARK: ERROR: 400 * * @param string|Stringable $message * @param mixed[] $context @@ -1084,7 +1251,7 @@ class Logging } /** - * CTRITICAL: 500 + * MARK: CTRITICAL: 500 * * @param string|Stringable $message * @param mixed[] $context @@ -1103,7 +1270,7 @@ class Logging } /** - * ALERT: 550 + * MARK: ALERT: 550 * * @param string|Stringable $message * @param mixed[] $context @@ -1122,7 +1289,7 @@ class Logging } /** - * EMERGENCY: 600 + * MARK: EMERGENCY: 600 * * @param string|Stringable $message * @param mixed[] $context @@ -1141,7 +1308,7 @@ class Logging } // ********************************************************************* - // DEPRECATED SUPPORT CALLS + // MARK: DEPRECATED SUPPORT CALLS // ********************************************************************* // legacy, but there are too many implemented @@ -1199,7 +1366,7 @@ class Logging } // ********************************************************************* - // DEPRECATED METHODS + // MARK: DEPRECATED METHODS // ********************************************************************* /** @@ -1365,7 +1532,7 @@ class Logging } // ********************************************************************* - // DEBUG METHODS + // MARK: DEBUG METHODS // ********************************************************************* /** @@ -1385,19 +1552,21 @@ class Logging Level::Error, Level::Critical, Level::Alert, Level::Emergency ] as $l ) { + print "Check: " . $this->log_level->getName() . " | " . $l->getName() . "
"; if ($this->log_level->isHigherThan($l)) { - print "L: " . $this->log_level->getName() . " > " . $l->getName() . "
"; + print "L(gt): " . $this->log_level->getName() . " > " . $l->getName() . "
"; } if ($this->log_level->includes($l)) { - print "L: " . $this->log_level->getName() . " <= " . $l->getName() . "
"; + print "L(le): " . $this->log_level->getName() . " <= " . $l->getName() . "
"; } if ($this->log_level->isLowerThan($l)) { - print "L: " . $this->log_level->getName() . " < " . $l->getName() . "
"; + print "L(lt): " . $this->log_level->getName() . " < " . $l->getName() . "
"; } echo "
"; } // back to options level $this->initLogLevel(); + $this->initErrorLogWriteLevel(); print "OPT set level: " . $this->getLoggingLevel()->getName() . "
"; } } diff --git a/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php b/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php index aa449602..94d7f181 100644 --- a/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php +++ b/www/vendor/egrajp/corelibs-composer-all/src/Output/Image.php @@ -365,9 +365,6 @@ class Image imagepng($thumb, $thumbnail_write_path . $thumbnail); break; } - // free up resources (in case we are called in a loop) - imagedestroy($source); - imagedestroy($thumb); } else { throw new \RuntimeException( 'Invalid source image file. Only JPEG/PNG are allowed: ' . $filename, @@ -543,8 +540,6 @@ class Image imagepng($img, $filename); break; } - // clean up image if we have an image - imagedestroy($img); } } diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckEmailTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckEmailTest.php index 81aeceb7..eaebfa0d 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckEmailTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Check/CoreLibsCheckEmailTest.php @@ -24,12 +24,12 @@ final class CoreLibsCheckEmailTest extends TestCase 'get email regex invalid -1, will be 0' => [ -1, "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" - . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" + . "(?!-)[A-Za-z0-9-]{1,63}(? [ 10, "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" - . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" + . "(?!-)[A-Za-z0-9-]{1,63}(? [ 1, @@ -157,7 +157,7 @@ final class CoreLibsCheckEmailTest extends TestCase 'error' => 0, 'message' => 'Invalid email address', 'regex' => "^[A-Za-z0-9!#$%&'*+\-\/=?^_`{|}~][A-Za-z0-9!#$%:\(\)&'*+\-\/=?^_`{|}~\.]{0,63}@" - . "[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]{1,})*\.([a-zA-Z]{2,}){1}$" + . "(?!-)[A-Za-z0-9-]{1,63}(? [ @@ -181,7 +181,7 @@ final class CoreLibsCheckEmailTest extends TestCase [ 'error' => 3, 'message' => 'Invalid domain part after @ sign', - 'regex' => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\.([a-zA-Z]{2,}){1}$" + 'regex' => "@(?!-)[A-Za-z0-9-]{1,63}(? [ @@ -189,7 +189,7 @@ final class CoreLibsCheckEmailTest extends TestCase [ 'error' => 4, 'message' => 'Invalid domain name part', - 'regex' => "@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]{1,})*\." + 'regex' => "@(?!-)[A-Za-z0-9-]{1,63}(? [ @@ -197,7 +197,7 @@ final class CoreLibsCheckEmailTest extends TestCase [ 'error' => 5, 'message' => 'Wrong domain top level part', - 'regex' => "\.([a-zA-Z]{2,6}){1}$" + 'regex' => "\.[a-zA-Z]{2,6}$" ] ], 'error 6 will be domain double dot' => [ diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php index e11aab8e..8843393c 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Combined/CoreLibsCombinedArrayHandlerTest.php @@ -7,7 +7,6 @@ declare(strict_types=1); namespace tests; -use Exception; use PHPUnit\Framework\TestCase; /** @@ -25,7 +24,11 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase 'same' => 'same', 3 => 'foobar', 'foobar' => 4, + 'barbaz' => 5, + 'zapzap' => '6', + 'zipzip' => 7, 'true' => true, + 'more' => 'other', ], 'd', 4, @@ -37,7 +40,10 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase 'sub' => [ 'nested' => 'bar', 'same' => 'same', - 'more' => 'test' + 'more' => 'test', + 'barbaz' => '5', + 'zapzap' => '6', + 'zipzip' => 7, ] ] ]; @@ -184,7 +190,7 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase 0: array $input, 1: $key, 2: $value, - 3: bool $flag, + 3: bool $strict, 4: bool $expected */ return [ @@ -286,6 +292,91 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase 3 => true, 4 => false, ], + // array tyep search + 'array type, both exist' => [ + 0 => self::$array, + 1 => 'more', + 2 => ['other', 'test'], + 3 => false, + 4 => true, + ], + 'array type, one exist' => [ + 0 => self::$array, + 1 => 'more', + 2 => ['other', 'not'], + 3 => false, + 4 => true, + ], + 'array type, none exist' => [ + 0 => self::$array, + 1 => 'more', + 2 => ['never', 'not'], + 3 => false, + 4 => false, + ], + 'array type, both exist, not strict, int and string' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => [5, '5'], + 3 => false, + 4 => true, + ], + 'array type, both exist, not strict, both string' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => ['5', '5'], + 3 => false, + 4 => true, + ], + 'array type, both exist, not strict, int and int' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => [5, 5], + 3 => false, + 4 => true, + ], + 'array type, both exist, strict, int and string' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => [5, '5'], + 3 => true, + 4 => true, + ], + 'array type, both exist, strict, both string' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => ['5', '5'], + 3 => true, + 4 => true, + ], + 'array type, both exist, strict, int and int' => [ + 0 => self::$array, + 1 => 'barbaz', + 2 => [5, 5], + 3 => true, + 4 => true, + ], + 'array type, both exist, strict, int and int to string and string' => [ + 0 => self::$array, + 1 => 'zapzap', + 2 => [6, 6], + 3 => true, + 4 => false, + ], + 'array type, both exist, strict, string and string to string and string' => [ + 0 => self::$array, + 1 => 'zapzap', + 2 => ['6', '6'], + 3 => true, + 4 => true, + ], + 'array type, both exist, not strict, int and int to string and string' => [ + 0 => self::$array, + 1 => 'zapzap', + 2 => [6, 6], + 3 => false, + 4 => true, + ], ]; } @@ -842,13 +933,13 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase * @dataProvider arraySearchRecursiveAllProvider * @testdox arraySearchRecursiveAll $needle (key $key_search_for) in $input and will be $expected (old: $flag) [$_dataName] * - * @param string|null $needle + * @param string|int|null $needle * @param array $input - * @param string|null $key_search_for + * @param string|int|null $key_search_for * @param bool $flag * @return void */ - public function testArraySearchRecursiveAll($needle, array $input, ?string $key_search_for, bool $flag, array $expected): void + public function testArraySearchRecursiveAll(string|int|null $needle, array $input, string|int|null $key_search_for, bool $flag, array $expected): void { $this->assertEquals( $expected, @@ -865,15 +956,16 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase * * @param array $input * @param string|int $key - * @param string|int|bool $value + * @param string|int|bool|array $value + * @param bool $strict * @param bool $expected * @return void */ - public function testArraySearchSimple(array $input, $key, $value, bool $flag, bool $expected): void + public function testArraySearchSimple(array $input, string|int $key, string|int|bool|array $value, bool $strict, bool $expected): void { $this->assertEquals( $expected, - \CoreLibs\Combined\ArrayHandler::arraySearchSimple($input, $key, $value, $flag) + \CoreLibs\Combined\ArrayHandler::arraySearchSimple($input, $key, $value, $strict) ); } @@ -1394,8 +1486,896 @@ final class CoreLibsCombinedArrayHandlerTest extends TestCase array $expected ): void { $this->assertEquals( - \CoreLibs\Combined\ArrayHandler::arrayModifyKey($in_array, $key_mod_prefix, $key_mod_suffix), - $expected + $expected, + \CoreLibs\Combined\ArrayHandler::arrayModifyKey($in_array, $key_mod_prefix, $key_mod_suffix) + ); + } + + /** + * sort + * + * @return array + */ + public function providerSortArray(): array + { + $unsorted = [9, 5, 'A', 4, 'B', 6, 'c', 'C', 'a']; + // for lower case the initial order of the elmenet is important: + // A, a => A, a + // d, D => d, D + $unsorted_keys = ['A' => 9, 'B' => 5, 'C' => 'A', 'D' => 4, 'E' => 'B', 'F' => 6, 'G' => 'c', 'H' => 'C', 'I' => 'a']; + return [ + // sort default + 'sort default' => [ + $unsorted, + null, + null, + null, + [4, 5, 6, 9, 'A', 'B', 'C', 'a', 'c'], + ], + // sort param set + 'sort param set' => [ + $unsorted, + false, + false, + false, + [4, 5, 6, 9, 'A', 'B', 'C', 'a', 'c'], + ], + // sort lower case + 'sort lower case' => [ + $unsorted, + true, + false, + false, + [4, 5, 6, 9, 'A', 'a', 'B', 'c', 'C'], + ], + // sort reverse + 'sort reverse' => [ + $unsorted, + false, + true, + false, + ['c', 'a', 'C', 'B', 'A', 9, 6, 5, 4], + ], + // sort lower case + reverse + 'sort lower case + reverse' => [ + $unsorted, + true, + true, + false, + ['c', 'C', 'B', 'A', 'a', 9, 6, 5, 4], + ], + // keys, do not maintain, default + 'keys, do not maintain, default' => [ + $unsorted_keys, + false, + false, + false, + [4, 5, 6, 9, 'A', 'B', 'C', 'a', 'c'], + ], + // sort maintain keys + 'sort maintain keys' => [ + $unsorted_keys, + false, + false, + true, + [ + 'D' => 4, + 'B' => 5, + 'F' => 6, + 'A' => 9, + 'C' => 'A', + 'E' => 'B', + 'H' => 'C', + 'I' => 'a', + 'G' => 'c' + ], + ], + // sort maintain keys + lower case + 'sort maintain keys + lower case' => [ + $unsorted_keys, + true, + false, + true, + [ + 'D' => 4, + 'B' => 5, + 'F' => 6, + 'A' => 9, + 'C' => 'A', + 'I' => 'a', + 'E' => 'B', + 'H' => 'C', + 'G' => 'c' + ], + ], + // sort maintain keys + reverse + 'sort maintain keys + reverse' => [ + $unsorted_keys, + false, + true, + true, + [ + 'G' => 'c', + 'H' => 'C', + 'E' => 'B', + 'I' => 'a', + 'C' => 'A', + 'A' => 9, + 'F' => 6, + 'B' => 5, + 'D' => 4, + ], + ], + // sort maintain keys + lower case + reverse + 'sort maintain keys + lower case + reverse' => [ + $unsorted_keys, + true, + true, + true, + [ + 'G' => 'c', + 'H' => 'C', + 'E' => 'B', + 'I' => 'a', + 'C' => 'A', + 'A' => 9, + 'F' => 6, + 'B' => 5, + 'D' => 4, + ], + ], + // emtpy + 'empty' => [ + [], + false, + false, + false, + [] + ], + // with nulls + 'null entries' => [ + ['d', null, 'a', null, 1], + false, + false, + false, + [null, null, 1, 'a', 'd'], + ], + // double entries + 'double entries' => [ + [1, 2, 2, 1, 'B', 'A', 'a', 'b', 'A', 'B', 'b', 'a'], + false, + false, + false, + [1, 1, 2, 2, 'A', 'A', 'B', 'B', 'a', 'a', 'b', 'b'], + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::sortArray + * @dataProvider providerSortArray + * @testdox sortArray sort $input with lower case $lower_case, reverse $reverse, maintain keys $maintain_keys with expeted $expected [$_dataName] + * + * @param array $input + * @param ?bool $lower_case + * @param ?bool $reverse + * @param ?bool $maintain_keys + * @param array $expected + * @return void + */ + public function testSortArray(array $input, ?bool $lower_case, ?bool $reverse, ?bool $maintain_keys, array $expected): void + { + $original = $input; + if ($lower_case === null && $reverse === null && $maintain_keys === null) { + $sorted_array = \CoreLibs\Combined\ArrayHandler::sortArray($input); + } else { + $sorted_array = \CoreLibs\Combined\ArrayHandler::sortArray($input, $lower_case, $reverse, $maintain_keys); + } + $expected_count = count($expected); + $this->assertIsArray( + $sorted_array, + 'sortArray: result not array' + ); + $this->assertCount( + $expected_count, + $sorted_array, + 'sortArray: count not matching' + ); + $this->assertEquals( + $expected, + $sorted_array, + 'sortArray: result not matching' + ); + $this->assertEquals( + $original, + $input, + 'sortArray: original - input was modified' + ); + if ($maintain_keys) { + $this->assertEqualsCanonicalizing( + array_keys($input), + array_keys($sorted_array), + 'sortArray: keys are not modified', + ); + } + if ($input != []) { + // we only care about array values + $this->assertNotEquals( + array_values($input), + array_values($sorted_array), + 'sortArray: output - input was modified' + ); + } + } + +/** + * sort + * + * @return array + */ + public function providerKsortArray(): array + { + // for lower case the initial order of the elmenet is important: + // A, a => A, a + // d, D => d, D + $unsorted_keys = [ + 9 => 'A', + 5 => 'B', + 'A' => 'C', + 4 => 'D', + 'B' => 'E', + 6 => 'F', + 'c' => 'G', + 'C' => 'H', + 'a' => 'I', + ]; + return [ + // sort keys + 'sort keys' => [ + $unsorted_keys, + false, + false, + [ + 4 => 'D', + 5 => 'B', + 6 => 'F', + 9 => 'A', + 'A' => 'C', + 'B' => 'E', + 'C' => 'H', + 'a' => 'I', + 'c' => 'G', + ], + ], + // sort keys + lower case + 'sort keys + lower case' => [ + $unsorted_keys, + true, + false, + [ + 4 => 'D', + 5 => 'B', + 6 => 'F', + 9 => 'A', + 'A' => 'C', + 'a' => 'I', + 'B' => 'E', + 'c' => 'G', + 'C' => 'H', + ], + ], + // sort keys + reverse + 'sort keys + reverse' => [ + $unsorted_keys, + false, + true, + [ + 'c' => 'G', + 'a' => 'I', + 'C' => 'H', + 'B' => 'E', + 'A' => 'C', + 9 => 'A', + 6 => 'F', + 5 => 'B', + 4 => 'D', + ], + ], + // sort keys + lower case + reverse + 'sort keys + lower case + reverse' => [ + $unsorted_keys, + true, + true, + [ + 'C' => 'H', + 'c' => 'G', + 'B' => 'E', + 'a' => 'I', + 'A' => 'C', + 9 => 'A', + 6 => 'F', + 5 => 'B', + 4 => 'D', + ], + ], + // emtpy + 'empty' => [ + [], + false, + false, + [] + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::ksortArray + * @dataProvider providerKsortArray + * @testdox ksortArray sort $input with lower case $lower_case, reverse $reverse with expeted $expected [$_dataName] + * + * @param array $input + * @param ?bool $lower_case + * @param ?bool $reverse + * @param array $expected + * @return void + */ + public function testKsortArray(array $input, ?bool $lower_case, ?bool $reverse, array $expected): void + { + $original = $input; + if ($lower_case === null && $reverse === null) { + $sorted_array = \CoreLibs\Combined\ArrayHandler::ksortArray($input); + } else { + $sorted_array = \CoreLibs\Combined\ArrayHandler::ksortArray($input, $lower_case, $reverse); + } + $expected_count = count($expected); + $this->assertIsArray( + $sorted_array, + 'ksortArray: result not array' + ); + $this->assertCount( + $expected_count, + $sorted_array, + 'ksortArray: count not matching' + ); + $this->assertEquals( + $expected, + $sorted_array, + 'ksortArray: result not matching' + ); + $this->assertEquals( + $original, + $input, + 'ksortArray: original - input was modified' + ); + $this->assertEqualsCanonicalizing( + array_values($original), + array_values($sorted_array), + 'ksortArray: values are not modified' + ); + if ($input != []) { + // we only care about array keys + $this->assertNotEquals( + array_keys($input), + array_keys($sorted_array), + 'sortArray: output - input was modified' + ); + } + } + + /** + * Undocumented function + * + * @return array + */ + public function providerFindArraysMissingKey(): array + { + $search_array = [ + 'table_lookup' => [ + 'match' => [ + ['param' => 'access_d_cd', 'data' => 'a_cd', 'time_validation' => 'on_load',], + ['param' => 'other_block', 'data' => 'b_cd'], + ['pflaume' => 'other_block', 'data' => 'c_cd'], + ['param' => 'third_block', 'data' => 'd_cd', 'time_validation' => 'cool'], + ['special' => 'other_block', 'data' => 'e_cd', 'time_validation' => 'other'], + ] + ] + ]; + return [ + 'find, no key set' => [ + $search_array, + 'other_block', + 'time_validation', + null, + null, + [ + [ + 'content' => [ + 'param' => 'other_block', + 'data' => 'b_cd', + ], + 'path' => 'table_lookup:match:1', + 'missing_key' => ['time_validation'], + ], + [ + 'content' => [ + 'data' => 'c_cd', + 'pflaume' => 'other_block', + ], + 'path' => 'table_lookup:match:2', + 'missing_key' => ['time_validation'], + ], + ] + ], + 'find, key set' => [ + $search_array, + 'other_block', + 'time_validation', + 'pflaume', + null, + [ + [ + 'content' => [ + 'data' => 'c_cd', + 'pflaume' => 'other_block', + ], + 'path' => 'table_lookup:match:2', + 'missing_key' => ['time_validation'], + ], + ] + ], + 'find, key set, different separator' => [ + $search_array, + 'other_block', + 'time_validation', + 'pflaume', + '#', + [ + [ + 'content' => [ + 'data' => 'c_cd', + 'pflaume' => 'other_block', + ], + 'path' => 'table_lookup#match#2', + 'missing_key' => ['time_validation'], + ], + ] + ], + 'find, key set, multiple check' => [ + $search_array, + 'other_block', + ['data', 'time_validation'], + 'pflaume', + null, + [ + [ + 'content' => [ + 'data' => 'c_cd', + 'pflaume' => 'other_block', + ], + 'path' => 'table_lookup:match:2', + 'missing_key' => ['time_validation'], + ], + ] + ], + 'has set' => [ + $search_array, + 'access_d_cd', + 'time_validation', + null, + null, + [] + ], + 'not found' => [ + $search_array, + 'not_found', + 'value', + null, + null, + [] + ], + 'empty' => [ + [], + 'something', + 'other', + null, + null, + [] + ] + ]; + } + + /** + * Undocumented function + * + * @covers ::findArraysMissingKey + * @dataProvider providerFindArraysMissingKey + * @testdox findArraysMissingKey $input find $search_value with $search_key and missing $required_key [$_dataName] + * + * @param array $input + * @param string|int|float|bool $search_value + * @param string|array $required_key + * @param string|null $search_key + * @param string|null $path_separator + * @param array $expected + * @return void + */ + public function testFindArraysMissingKey( + array $input, + string|int|float|bool $search_value, + string|array $required_key, + ?string $search_key, + ?string $path_separator, + array $expected + ): void { + if ($path_separator === null) { + $result = \CoreLibs\Combined\ArrayHandler::findArraysMissingKey( + $input, + $search_value, + $required_key, + $search_key + ); + } else { + $result = \CoreLibs\Combined\ArrayHandler::findArraysMissingKey( + $input, + $search_value, + $required_key, + $search_key, + $path_separator + ); + } + $this->assertEquals( + $expected, + $result + ); + } + + /** + * Undocumented function + * + * @return array + */ + public function providerSelectArrayFromOption(): array + { + $search_array = [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + 'c' => [ + 'lookup' => 0, + 'value' => 'CCC', + 'other' => 'OTHER', + ], + 'd' => [ + 'd-1' => [ + 'lookup' => 1, + 'value' => 'D SUB 1', + 'other' => 'Other B', + ], + 'd-2' => [ + 'lookup' => 0, + 'value' => 'D SUB 2', + 'other' => 'Other B', + ], + 'more' => [ + 'd-more-1' => [ + 'lookup' => 1, + 'value' => 'D MORE SUB 1', + 'other' => 'Other C', + ], + 'd-more-2' => [ + 'lookup' => 0, + 'value' => 'D MORE SUB 0', + 'other' => 'Other C', + ], + ] + ] + ]; + /* + 0: input + 1: lookup + 2: search + 3: strict [false] + 4: case insensitive [false] + 5: recursive [false] + 6: flat_result [true] + 7: flat_separator [:] + 8: expected + */ + return [ + 'search, flat with found' => [ + $search_array, + 'lookup' => 'lookup', + 'search' => 1, + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => false, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + ] + ], + 'search, recusrive with found' => [ + $search_array, + 'lookup' => 'lookup', + 'search' => 1, + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => true, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + 'd:d-1' => [ + 'lookup' => 1, + 'value' => 'D SUB 1', + 'other' => 'Other B', + ], + 'd:more:d-more-1' => [ + 'lookup' => 1, + 'value' => 'D MORE SUB 1', + 'other' => 'Other C', + ], + ] + ], + 'search, recusrive with found, other separator' => [ + $search_array, + 'lookup' => 'lookup', + 'search' => 1, + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => true, + 'flat_result' => true, + 'flag_separator' => '+', + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + 'd+d-1' => [ + 'lookup' => 1, + 'value' => 'D SUB 1', + 'other' => 'Other B', + ], + 'd+more+d-more-1' => [ + 'lookup' => 1, + 'value' => 'D MORE SUB 1', + 'other' => 'Other C', + ], + ] + ], + 'search, recusrive with found, not flat result' => [ + $search_array, + 'lookup' => 'lookup', + 'search' => 1, + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => true, + 'flat_result' => false, + 'flag_separator' => null, + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + 'd' => [ + 'd-1' => [ + 'lookup' => 1, + 'value' => 'D SUB 1', + 'other' => 'Other B', + ], + 'more' => [ + 'd-more-1' => [ + 'lookup' => 1, + 'value' => 'D MORE SUB 1', + 'other' => 'Other C', + ], + ], + ], + ], + ], + 'search case insensitive' => [ + $search_array, + 'lookup' => 'other', + 'search' => 'Other', + 'strict' => false, + 'case_insenstivie' => true, + 'recursive' => false, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + 'c' => [ + 'lookup' => 0, + 'value' => 'CCC', + 'other' => 'OTHER', + ], + ] + ], + 'search case sensitiv' => [ + $search_array, + 'lookup' => 'other', + 'search' => 'Other', + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => false, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + ] + ], + 'search strict' => [ + $search_array, + 'lookup' => 'strict', + 'search' => '2', + 'strict' => true, + 'case_insenstivie' => false, + 'recursive' => false, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + ] + ], + 'search not strict' => [ + $search_array, + 'lookup' => 'strict', + 'search' => '2', + 'strict' => false, + 'case_insenstivie' => false, + 'recursive' => false, + 'flat_result' => true, + 'flag_separator' => null, + [ + 'a' => [ + 'lookup' => 1, + 'value' => 'Foo', + 'other' => 'Bar', + 'strict' => '2', + ], + 'b' => [ + 'lookup' => 1, + 'value' => 'AAA', + 'other' => 'Other', + 'strict' => 2, + ], + ] + ], + 'empty' => [ + [], + 'something', + 'NOT_SET_AT_ALL', + false, + false, + false, + true, + null, + [] + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::selectArrayFromOption + * @dataProvider providerSelectArrayFromOption + * @testdox selectArrayFromOption $input find $lookup with $search, strict: $strict, case sensitive: $case_sensitive, recursive: $recursive, flag result: $flag_result, flag separator: $flat_separator amd expected $expected [$_dataName] + * + * @param array $input + * @param string $lookup + * @param int|string|float|bool $search + * @param bool $strict + * @param bool $case_sensitive + * @param bool $recursive + * @param bool $flat_result + * @param string|null $flat_separator + * @param array $expected + * @return void + */ + public function testSelectArrayFromOption( + array $input, + string $lookup, + int|string|float|bool $search, + bool $strict, + bool $case_sensitive, + bool $recursive, + bool $flat_result, + ?string $flat_separator, + array $expected + ): void { + if ($flat_separator === null) { + $result = \CoreLibs\Combined\ArrayHandler::selectArrayFromOption( + $input, + $lookup, + $search, + $strict, + $case_sensitive, + $recursive, + $flat_result + ); + } else { + $result = \CoreLibs\Combined\ArrayHandler::selectArrayFromOption( + $input, + $lookup, + $search, + $strict, + $case_sensitive, + $recursive, + $flat_result, + $flat_separator + ); + } + $this->assertEquals( + $expected, + $result ); } } diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php index 0cd1682f..a80b0911 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertByteTest.php @@ -123,47 +123,6 @@ final class CoreLibsConvertByteTest extends TestCase ]; } - /** - * Undocumented function - * - * @return array - */ - public function byteStringProvider(): array - { - return [ - 'negative number' => [ - 0 => '-117.42 MB', - 1 => -123123794, - 2 => -117420000, - ], - 'megabyte' => [ - 0 => '242.98 MB', - 1 => 254782996, - 2 => 242980000 - ], - 'megabyte si' => [ - 0 => '254.78 MiB', - 1 => 267156193, - 2 => 254780000 - ], - 'petabyte' => [ - 0 => '1 EiB', - 1 => 1152921504606846976, - 2 => 1000000000000000000, - ], - 'max int' => [ - 0 => '8 EB', - 1 => -9223372036854775807 - 1, - 2 => 8000000000000000000, - ], - 'exabyte, overflow' => [ - 0 => '867.36EB', - 1 => 3873816255479021568, - 2 => 363028535651074048, - ] - ]; - } - /** * Undocumented function * @@ -180,7 +139,7 @@ final class CoreLibsConvertByteTest extends TestCase * @return void */ public function testHumanReadableByteFormat( - $input, + string|int|float $input, string $expected, string $expected_si, string $expected_no_space, @@ -217,6 +176,73 @@ final class CoreLibsConvertByteTest extends TestCase ); } + /** + * Undocumented function + * + * @return array + */ + public function byteStringProvider(): array + { + return [ + 'negative number' => [ + 0 => '-117.42 MB', + 1 => -123123794, + 2 => -117420000, + 3 => "-123123793", + 4 => "-117420000", + 5 => null, + ], + 'megabyte' => [ + 0 => '242.98 MB', + 1 => 254782996, + 2 => 242980000, + 3 => "254782996", + 4 => "242980000", + 5 => null, + ], + 'megabyte si' => [ + 0 => '254.78 MiB', + 1 => 267156193, + 2 => 254780000, + 3 => "267156193", + 4 => "254780000", + 5 => null, + ], + 'petabyte' => [ + 0 => '1 EiB', + 1 => 1152921504606846976, + 2 => 1000000000000000000, + 3 => "1152921504606846976", + 4 => "1000000000000000000", + 5 => null, + ], + 'max int' => [ + 0 => '8 EB', + 1 => 0, + 2 => 0, + 3 => "9223372036854775808", + 4 => "8000000000000000000", + 5 => \LengthException::class, + ], + 'exabyte, overflow' => [ + 0 => '867.36EB', + 1 => 0, + 2 => 0, + 3 => "999997996235794808832", + 4 => "867360000000000000000", + 5 => \LengthException::class, + ], + 'huge exabyte, overflow' => [ + 0 => '1000EB', + 1 => 0, + 2 => 0, + 3 => "1152921504606846976000", + 4 => "1000000000000000000000", + 5 => \LengthException::class, + ], + ]; + } + /** * Undocumented function * @@ -227,10 +253,22 @@ final class CoreLibsConvertByteTest extends TestCase * @param string|int|float $input * @param string|int|float $expected * @param string|int|float $expected_si + * @param string|int|float $expected_string + * @param string|int|float $expected_string_si + * @param ?string $exception * @return void */ - public function testStringByteFormat($input, $expected, $expected_si): void - { + public function testStringByteFormat( + string|int|float $input, + string|int|float $expected, + string|int|float $expected_si, + string|int|float $expected_string, + string|int|float $expected_string_si, + ?string $exception + ): void { + if ($exception !== null) { + $this->expectException($exception); + } $this->assertEquals( $expected, \CoreLibs\Convert\Byte::stringByteFormat($input) @@ -239,6 +277,17 @@ final class CoreLibsConvertByteTest extends TestCase $expected_si, \CoreLibs\Convert\Byte::stringByteFormat($input, \CoreLibs\Convert\Byte::BYTE_FORMAT_SI) ); + $this->assertEquals( + $expected_string, + \CoreLibs\Convert\Byte::stringByteFormat($input, \CoreLibs\Convert\Byte::RETURN_AS_STRING) + ); + $this->assertEquals( + $expected_string_si, + \CoreLibs\Convert\Byte::stringByteFormat( + $input, + \CoreLibs\Convert\Byte::BYTE_FORMAT_SI | \CoreLibs\Convert\Byte::RETURN_AS_STRING + ) + ); } /** diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertMathTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertMathTest.php index 5df06aa0..c3aa145b 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertMathTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertMathTest.php @@ -122,9 +122,9 @@ final class CoreLibsConvertMathTest extends TestCase public function providerCbrt(): array { return [ - 'cube root of 2' => [2, 1.25992, 5], - 'cube root of 3' => [3, 1.44225, 5], - 'cube root of -1' => [-1, 'NAN', 0], + 'cube root of 2' => [2, 1.25992, 5, null], + 'cube root of 3' => [3, 1.44225, 5, null], + 'cube root of -1' => [-1, 'NAN', 0, \InvalidArgumentException::class], ]; } @@ -138,10 +138,14 @@ final class CoreLibsConvertMathTest extends TestCase * @param float|int $number * @param float $expected * @param int $round_to + * @param ?string $exception * @return void */ - public function testCbrt(float|int $number, float|string $expected, int $round_to): void + public function testCbrt(float|int $number, float|string $expected, int $round_to, ?string $exception): void { + if ($exception !== null) { + $this->expectException($exception); + } $this->assertEquals( $expected, round(\CoreLibs\Convert\Math::cbrt($number), $round_to) diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php index c6c92251..ed4bbc97 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Convert/CoreLibsConvertStringsTest.php @@ -24,117 +24,83 @@ final class CoreLibsConvertStringsTest extends TestCase { // 0: input // 1: format - // 2: split characters as string, null for default // 3: expected return [ 'all empty string' => [ '', '', - null, '' ], 'empty input string' => [ '', '2-2', - null, '' ], 'empty format string string' => [ '1234', '', - null, '1234' ], 'string format match' => [ '1234', '2-2', - null, '12-34' ], 'string format trailing match' => [ '1234', '2-2-', - null, '12-34' ], 'string format leading match' => [ '1234', '-2-2', - null, '12-34' ], 'string format double inside match' => [ '1234', '2--2', - null, '12--34', ], 'string format short first' => [ '1', '2-2', - null, '1' ], 'string format match first' => [ '12', '2-2', - null, '12' ], 'string format short second' => [ '123', '2-2', - null, '12-3' ], 'string format too long' => [ '1234567', '2-2', - null, '12-34-567' ], - 'string format invalid format string' => [ - '1234', - '2_2', - null, - '1234' - ], 'different split character' => [ '1234', '2_2', - '_', '12_34' ], 'mixed split characters' => [ '123456', '2-2_2', - '-_', '12-34_56' ], 'length mixed' => [ 'ABCD12345568ABC13', '2-4_5-2#4', - '-_#', 'AB-CD12_34556-8A#BC13' ], 'split with split chars in string' => [ '12-34', '2-2', - null, '12--3-4' ], - 'mutltibyte string' => [ - 'あいうえ', - '2-2', - null, - 'あいうえ' - ], - 'mutltibyte split string' => [ - '1234', - '2-2', - null, - '1234' - ], ]; } @@ -143,29 +109,137 @@ final class CoreLibsConvertStringsTest extends TestCase * * @covers ::splitFormatString * @dataProvider splitFormatStringProvider - * @testdox splitFormatString $input with format $format and splitters $split_characters will be $expected [$_dataName] + * @testdox splitFormatString $input with format $format will be $expected [$_dataName] * * @param string $input * @param string $format - * @param string|null $split_characters * @param string $expected * @return void */ public function testSplitFormatString( string $input, string $format, + string $expected + ): void { + $output = \CoreLibs\Convert\Strings::splitFormatString( + $input, + $format, + ); + $this->assertEquals( + $expected, + $output + ); + } + + /** check exceptions */ + public function splitFormatStringExceptionProvider(): array + { + return [ + 'string format with no splitter match' => [ + '1234', + '22', + '12-34' + ], + 'invalid format string' => [ + '1234', + '2あ2', + ], + 'mutltibyte string' => [ + 'あいうえ', + '2-2', + ], + 'mutltibyte split string' => [ + '1234', + '2-2', + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::splitFormatStringFixed + * @dataProvider splitFormatStringExceptionProvider + * @testdox splitFormatString Exception catch checks for $input with $format[$_dataName] + * + * @return void + */ + public function testSplitFormatStringExceptions(string $input, string $format): void + { + // catch exception + $this->expectException(\InvalidArgumentException::class); + \CoreLibs\Convert\Strings::splitFormatString($input, $format); + } + + /** + * test for split Format string fixed length + * + * @return array + */ + public function splitFormatStringFixedProvider(): array + { + return [ + 'normal split, default split char' => [ + 'abcdefg', + 4, + null, + 'abcd-efg' + ], + 'noraml split, other single split char' => [ + 'abcdefg', + 4, + "=", + 'abcd=efg' + ], + 'noraml split, other multiple split char' => [ + 'abcdefg', + 4, + "-=-", + 'abcd-=-efg' + ], + 'non ascii characters' => [ + 'あいうえお', + 2, + "-", + 'あい-うえ-お' + ], + 'empty string' => [ + '', + 4, + "-", + '' + ] + ]; + } + + /** + * Undocumented function + * + * @covers ::splitFormatStringFixed + * @dataProvider splitFormatStringFixedProvider + * @testdox splitFormatStringFixed $input with length $split_length and split chars $split_characters will be $expected [$_dataName] + * + * @param string $input + * @param int $split_length + * @param string|null $split_characters + * @param string $expected + * @return void + */ + public function testSplitFormatStringFixed( + string $input, + int $split_length, ?string $split_characters, string $expected ): void { if ($split_characters === null) { - $output = \CoreLibs\Convert\Strings::splitFormatString( + $output = \CoreLibs\Convert\Strings::splitFormatStringFixed( $input, - $format + $split_length ); } else { - $output = \CoreLibs\Convert\Strings::splitFormatString( + $output = \CoreLibs\Convert\Strings::splitFormatStringFixed( $input, - $format, + $split_length, $split_characters ); } @@ -175,6 +249,36 @@ final class CoreLibsConvertStringsTest extends TestCase ); } + public function splitFormatStringFixedExceptionProvider(): array + { + return [ + 'split length too short' => [ + 'abcdefg', + -1, + ], + 'split length longer than string' => [ + 'abcdefg', + 20, + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::splitFormatStringFixed + * @dataProvider splitFormatStringFixedExceptionProvider + * @testdox splitFormatStringFixed Exception catch checks for $input with $length [$_dataName] + * + * @return void + */ + public function testSplitFormatStringFixedExceptions(string $input, int $length): void + { + // catch exception + $this->expectException(\InvalidArgumentException::class); + \CoreLibs\Convert\Strings::splitFormatStringFixed($input, $length); + } + /** * Undocumented function * @@ -378,6 +482,222 @@ final class CoreLibsConvertStringsTest extends TestCase \CoreLibs\Convert\Strings::stripUTF8BomBytes($file) ); } + + /** + * Undocumented function + * + * @return array + */ + public function allCharsInSetProvider(): array + { + return [ + 'find' => [ + 'abc', + 'abcdef', + true + ], + 'not found' => [ + 'abcz', + 'abcdef', + false + ] + ]; + } + + /** + * Undocumented function + * + * @covers ::allCharsInSet + * @dataProvider allCharsInSetProvider + * @testdox allCharsInSet $input in $haystack with expected $expected [$_dataName] + * + * @param string $needle + * @param string $haystack + * @param bool $expected + * @return void + */ + public function testAllCharsInSet(string $needle, string $haystack, bool $expected): void + { + $this->assertEquals( + $expected, + \CoreLibs\Convert\Strings::allCharsInSet($needle, $haystack) + ); + } + + public function buildCharStringFromListsProvider(): array + { + return [ + 'test a' => [ + 'abc', + ['a', 'b', 'c'], + ], + 'test b' => [ + 'abc123', + ['a', 'b', 'c'], + ['1', '2', '3'], + ], + 'test c: no params' => [ + '', + ], + 'test c: empty 1' => [ + '', + [] + ], + 'test nested' => [ + 'abc', + [['a'], ['b'], ['c']], + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::buildCharStringFromLists + * @dataProvider buildCharStringFromListsProvider + * @testdox buildCharStringFromLists all $input convert to $expected [$_dataName] + * + * @param string $expected + * @param array ...$input + * @return void + */ + public function testBuildCharStringFromLists(string $expected, array ...$input): void + { + $this->assertEquals( + $expected, + \CoreLibs\Convert\Strings::buildCharStringFromLists(...$input) + ); + } + + /** + * Undocumented function + * + * @return array + */ + public function removeDuplicatesProvider(): array + { + return [ + 'test no change' => [ + 'ABCDEFG', + 'ABCDEFG', + ], + 'test simple' => [ + 'aa', + 'a' + ], + 'test keep lower and uppwer case' => [ + 'AaBbCc', + 'AaBbCc' + ], + 'test unqiue' => [ + 'aabbcc', + 'abc' + ], + 'test multibyte no change' => [ + 'あいうえお', + 'あいうえお', + ], + 'test multibyte' => [ + 'ああいいううええおお', + 'あいうえお', + ], + 'test multibyte special' => [ + 'あぁいぃうぅえぇおぉ', + 'あぁいぃうぅえぇおぉ', + ] + ]; + } + + /** + * Undocumented function + * + * @covers ::removeDuplicates + * @dataProvider removeDuplicatesProvider + * @testdox removeDuplicates make $input unqiue to $expected [$_dataName] + * + * @param string $input + * @param string $expected + * @return void + */ + public function testRemoveDuplicates(string $input, string $expected): void + { + $this->assertEquals( + $expected, + \CoreLibs\Convert\Strings::removeDuplicates($input) + ); + } + + /** + * Undocumented function + * + * @return array + */ + public function isValidRegexSimpleProvider(): array + { + return [ + 'valid regex' => [ + '/^[A-z]$/', + true, + [ + 'valid' => true, + 'preg_error' => 0, + 'error' => null, + 'pcre_error' => null + ], + ], + 'invalid regex A' => [ + '/^[A-z]$', + false, + [ + 'valid' => false, + 'preg_error' => 1, + 'error' => 'Internal PCRE error', + 'pcre_error' => 'Internal error' + ], + ], + 'invalid regex B' => [ + '/^[A-z$', + false, + [ + 'valid' => false, + 'preg_error' => 1, + 'error' => 'Internal PCRE error', + 'pcre_error' => 'Internal error' + ], + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::isValidRegexSimple + * @dataProvider isValidRegexSimpleProvider + * @testdox isValidRegexSimple make $input unqiue to $expected [$_dataName] + * + * @param string $input + * @param bool $expected + * @return void + */ + public function testIsValidRegexSimple(string $input, bool $expected, array $expected_extended): void + { + $this->assertEquals( + $expected, + \CoreLibs\Convert\Strings::isValidRegex($input), + 'Regex is not valid' + ); + $this->assertEquals( + $expected_extended, + \CoreLibs\Convert\Strings::validateRegex($input), + 'Validation of regex failed' + ); + $this->assertEquals( + // for true null is set, so we get here No Error + $expected_extended['error'] ?? \CoreLibs\Convert\Strings::PREG_ERROR_MESSAGES[0], + \CoreLibs\Convert\Strings::getLastRegexErrorString(), + 'Cannot match last preg error string' + ); + } } // __END__ diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Create/CoreLibsCreateRandomKeyTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Create/CoreLibsCreateRandomKeyTest.php index 3662aa65..353ec25b 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Create/CoreLibsCreateRandomKeyTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Create/CoreLibsCreateRandomKeyTest.php @@ -13,32 +13,6 @@ use PHPUnit\Framework\TestCase; */ final class CoreLibsCreateRandomKeyTest extends TestCase { - /** - * Undocumented function - * - * @return array - */ - public function keyLenghtProvider(): array - { - return [ - 'valid key length' => [ - 0 => 6, - 1 => true, - 2 => 6, - ], - 'negative key length' => [ - 0 => -1, - 1 => false, - 2 => 4, - ], - 'tpp big key length' => [ - 0 => 300, - 1 => false, - 2 => 4, - ], - ]; - } - /** * Undocumented function * @@ -47,109 +21,67 @@ final class CoreLibsCreateRandomKeyTest extends TestCase public function randomKeyGenProvider(): array { return [ - 'default key length' => [ + // just key length + 'default key length, default char set' => [ 0 => null, - 1 => 4 + 1 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT ], - 'set -1 key length default' => [ + 'set -1 key length, default char set' => [ 0 => -1, - 1 => 4, + 1 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT, ], - 'set too large key length' => [ + 'set 0 key length, default char set' => [ + 0 => -1, + 1 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT, + ], + 'set too large key length, default char set' => [ 0 => 300, - 1 => 4, + 1 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT, ], - 'set override key lenght' => [ + 'set override key lenght, default char set' => [ 0 => 6, 1 => 6, ], + // just character set + 'default key length, different char set A' => [ + 0 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT, + 1 => \CoreLibs\Create\RandomKey::KEY_LENGTH_DEFAULT, + 2 => [ + 'A', 'B', 'C' + ], + ], + 'different key length, different char set B' => [ + 0 => 16, + 1 => 16, + 2 => [ + 'A', 'B', 'C' + ], + 3 => [ + '1', '2', '3' + ] + ], ]; } + // Alternative more efficient version using strpos /** - * 1 + * check if all characters are in set * - * @return array + * @param string $input + * @param string $allowed_chars + * @return bool */ - public function keepKeyLengthProvider(): array + private function allCharsInSet(string $input, string $allowed_chars): bool { - return [ - 'set too large' => [ - 0 => 6, - 1 => 300, - 2 => 6, - ], - 'set too small' => [ - 0 => 8, - 1 => -2, - 2 => 8, - ], - 'change valid' => [ - 0 => 10, - 1 => 6, - 2 => 6, - ] - ]; - } + $inputLength = strlen($input); - /** - * run before each test and reset to default 4 - * - * @before - * - * @return void - */ - public function resetKeyLength(): void - { - \CoreLibs\Create\RandomKey::setRandomKeyLength(4); - } - - /** - * check that first length is 4 - * - * @covers ::getRandomKeyLength - * @testWith [4] - * @testdox getRandomKeyLength on init will be $expected [$_dataName] - * - * @param integer $expected - * @return void - */ - public function testGetRandomKeyLengthInit(int $expected): void - { - $this->assertEquals( - $expected, - \CoreLibs\Create\RandomKey::getRandomKeyLength() - ); - } - - /** - * Undocumented function - * - * @covers ::setRandomKeyLength - * @covers ::getRandomKeyLength - * @dataProvider keyLenghtProvider - * @testdox setRandomKeyLength $input will be $expected, compare to $compare [$_dataName] - * - * @param integer $input - * @param boolean $expected - * @param integer $compare - * @return void - */ - public function testSetRandomKeyLength(int $input, bool $expected, int $compare): void - { - // set - $this->assertEquals( - $expected, - \CoreLibs\Create\RandomKey::setRandomKeyLength($input) - ); - // read test, if false, use compare check - if ($expected === false) { - $input = $compare; + for ($i = 0; $i < $inputLength; $i++) { + if (strpos($allowed_chars, $input[$i]) === false) { + return false; + } } - $this->assertEquals( - $input, - \CoreLibs\Create\RandomKey::getRandomKeyLength() - ); + + return true; } /** @@ -163,43 +95,41 @@ final class CoreLibsCreateRandomKeyTest extends TestCase * @param integer $expected * @return void */ - public function testRandomKeyGen(?int $input, int $expected): void + public function testRandomKeyGen(?int $input, int $expected, array ...$key_range): void { + $__key_data = \CoreLibs\Create\RandomKey::KEY_CHARACTER_RANGE_DEFAULT; + if (count($key_range)) { + $__key_data = join('', array_unique(array_merge(...$key_range))); + } if ($input === null) { $this->assertEquals( $expected, strlen(\CoreLibs\Create\RandomKey::randomKeyGen()) ); - } else { + } elseif ($input !== null && !count($key_range)) { + $random_key = \CoreLibs\Create\RandomKey::randomKeyGen($input); + $this->assertTrue( + $this->allCharsInSet($random_key, $__key_data), + 'Characters not valid' + ); $this->assertEquals( $expected, - strlen(\CoreLibs\Create\RandomKey::randomKeyGen($input)) + strlen($random_key), + 'String length not matching' + ); + } elseif (count($key_range)) { + $random_key = \CoreLibs\Create\RandomKey::randomKeyGen($input, ...$key_range); + $this->assertTrue( + $this->allCharsInSet($random_key, $__key_data), + 'Characters not valid' + ); + $this->assertEquals( + $expected, + strlen($random_key), + 'String length not matching' ); } } - - /** - * Check that if set to n and then invalid, it keeps the previous one - * or if second change valid, second will be shown - * - * @covers ::setRandomKeyLength - * @dataProvider keepKeyLengthProvider - * @testdox keep setRandomKeyLength set with $input_valid and then $input_invalid will be $expected [$_dataName] - * - * @param integer $input_valid - * @param integer $input_invalid - * @param integer $expected - * @return void - */ - public function testKeepKeyLength(int $input_valid, int $input_invalid, int $expected): void - { - \CoreLibs\Create\RandomKey::setRandomKeyLength($input_valid); - \CoreLibs\Create\RandomKey::setRandomKeyLength($input_invalid); - $this->assertEquals( - $expected, - \CoreLibs\Create\RandomKey::getRandomKeyLength() - ); - } } // __END__ diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingErrorMessagesTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingErrorMessagesTest.php index 5e9c3ac6..ba343533 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingErrorMessagesTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingErrorMessagesTest.php @@ -105,11 +105,15 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase 'log_folder' => self::LOG_FOLDER, 'log_level' => Level::Error, ]); + $errorLogTmpfile = tmpfile(); + $errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']); $em = new \CoreLibs\Logging\ErrorMessage($log); $em->setMessage( $level, $str ); + // for exceptions if log level is set to catch them + $error_log_content = stream_get_contents($errorLogTmpfile); $this->assertEquals( [ 'level' => $expected, @@ -377,6 +381,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase ?bool $log_warning, string $expected ): void { + $errorLogTmpfile = tmpfile(); + $errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']); $log = new \CoreLibs\Logging\Logging([ 'log_file_id' => 'testErrorMessagesLogError', 'log_folder' => self::LOG_FOLDER, @@ -392,6 +398,9 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase log_error: $log_error, log_warning: $log_warning ); + ini_set('error_log', $errorLogLocationBackup); + // for exceptions if log level is set to catch them + $error_log_content = stream_get_contents($errorLogTmpfile); $file_content = ''; if (is_file($log->getLogFolder() . $log->getLogFile())) { $file_content = file_get_contents( @@ -447,6 +456,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase 'log_level' => Level::Debug, 'log_per_run' => true ]); + $errorLogTmpfile = tmpfile(); + $errorLogLocationBackup = ini_set('error_log', stream_get_meta_data($errorLogTmpfile)['uri']); $em = new \CoreLibs\Logging\ErrorMessage($log); $em->setErrorMsg( $id, @@ -456,6 +467,9 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase log_error: $log_error, log_warning: $log_warning ); + ini_set('error_log', $errorLogLocationBackup); + // for exceptions if log level is set to catch them + $error_log_content = stream_get_contents($errorLogTmpfile); $file_content = ''; if (is_file($log->getLogFolder() . $log->getLogFile())) { $file_content = file_get_contents( diff --git a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingLoggingTest.php b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingLoggingTest.php index 3d2b3894..d1792d6d 100644 --- a/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingLoggingTest.php +++ b/www/vendor/egrajp/corelibs-composer-all/test/phpunit/Logging/CoreLibsLoggingLoggingTest.php @@ -18,7 +18,7 @@ use CoreLibs\Logging\Logger\Flag; final class CoreLibsLoggingLoggingTest extends TestCase { private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR; - private const REGEX_BASE = "\[[\d\-\s\.:]+\]\s{1}" // date + private const REGEX_BASE = "\[[\d\-\s\.:+T]+\]\s{1}" // date, just basic checks . "\[[\w\.]+(:\d+)?\]\s{1}" // host:port . "\[(phar:\/\/)?[\w\-\.\/]+:\d+\]\s{1}" // folder/file [note phar:// is for phpunit] . "\[\w+\]\s{1}" // run id @@ -249,7 +249,7 @@ final class CoreLibsLoggingLoggingTest extends TestCase $this->assertFalse( $log->loggingLevelIsDebug() ); - // not set, should be debug] + // not set, should be debug $log = new \CoreLibs\Logging\Logging([ 'log_file_id' => 'testSetLoggingLevel', 'log_folder' => self::LOG_FOLDER, @@ -297,6 +297,71 @@ final class CoreLibsLoggingLoggingTest extends TestCase $log->setLoggingLevel('NotGood'); } + /** + * Undocumented function + * + * @covers ::setErrorLogWriteLevel + * @covers ::getErrorLogWriteLevel + * @testdox setErrorLogWriteLevel set/get checks + * + * @return void + */ + public function testSetErrorLogWriteLevel(): void + { + // valid that is not Debug + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => Level::Error + ]); + $this->assertEquals( + Level::Error, + $log->getErrorLogWriteLevel() + ); + // not set on init + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + ]); + $this->assertEquals( + Level::Emergency, + $log->getErrorLogWriteLevel() + ); + // invalid, should be Emergency, will throw excpetion too + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage( + 'Option: "error_log_write_level" is not of instance \CoreLibs\Logging\Logger\Level' + ); + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetLoggingLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => 'I' + ]); + $this->assertEquals( + Level::Emergency, + $log->getErrorLogWriteLevel() + ); + // set valid then change + $log = new \CoreLibs\Logging\Logging([ + 'log_file_id' => 'testSetErrorLogWriteLevel', + 'log_folder' => self::LOG_FOLDER, + 'error_log_write_level' => Level::Error + ]); + $this->assertEquals( + Level::Error, + $log->getErrorLogWriteLevel() + ); + $log->setErrorLogWriteLevel(Level::Notice); + $this->assertEquals( + Level::Notice, + $log->getErrorLogWriteLevel() + ); + // illegal logging level + $this->expectException(\Psr\Log\InvalidArgumentException::class); + $this->expectExceptionMessageMatches("/^Level \"NotGood\" is not defined, use one of: /"); + $log->setErrorLogWriteLevel('NotGood'); + } + // setLogFileId // getLogFileId