diff --git a/.phan/config.php b/.phan/config.php
index 68c3202a..65c533f5 100644
--- a/.phan/config.php
+++ b/.phan/config.php
@@ -85,9 +85,7 @@ return [
// to parse, but not analyze
"exclude_analysis_directory_list" => [
'www/vendor',
- // 'www/lib/FileUpload',
- 'www/lib/pChart',
- 'www/lib/pChart2.1.4',
+ 'www/tests',
'www/lib/Smarty',
'www/lib/smarty-3.1.30',
'www/templates_c',
diff --git a/4dev/checking/phan.sh b/4dev/checking/phan.sh
new file mode 100644
index 00000000..6d5ec428
--- /dev/null
+++ b/4dev/checking/phan.sh
@@ -0,0 +1,3 @@
+base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
+# must be run in ${base}www/
+phan --progress-bar -C --analyze-twice
diff --git a/4dev/checking/phpstan.sh b/4dev/checking/phpstan.sh
new file mode 100644
index 00000000..18af6f0f
--- /dev/null
+++ b/4dev/checking/phpstan.sh
@@ -0,0 +1,3 @@
+base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
+# must be run in ${base}www/
+phpstan
diff --git a/4dev/checking/phpunit.sh b/4dev/checking/phpunit.sh
new file mode 100755
index 00000000..ed5b66ed
--- /dev/null
+++ b/4dev/checking/phpunit.sh
@@ -0,0 +1,4 @@
+base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
+# -c phpunit.xml
+# --testdox
+${base}www/vendor/bin/phpunit -c ${base}phpunit.xml ${base}4dev/tests/
diff --git a/4dev/composer/install.txt b/4dev/composer/install.txt
index a7189bac..f441eb22 100644
--- a/4dev/composer/install.txt
+++ b/4dev/composer/install.txt
@@ -1,21 +1,27 @@
Install composer:
-curl -sS https://getcomposer.org/installer | /usr/local/php-7.3-httpd-2.4/bin/php
+# old
+curl -sS https://getcomposer.org/installer | /usr/local/php-8.0-httpd-2.4/bin/php
+# new (4 steps) https://getcomposer.org/download/
+/usr/local/php-8.0-httpd-2.4/bin/php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+/usr/local/php-8.0-httpd-2.4/bin/php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
+/usr/local/php-8.0-httpd-2.4/bin/php composer-setup.php
+/usr/local/php-8.0-httpd-2.4/bin/php -r "unlink('composer-setup.php');
Update composer phar file
-/usr/local/php-7.3-httpd-2.4/bin/php composer.phar selfupdate
+/usr/local/php-8.0-httpd-2.4/bin/php composer.phar selfupdate
Install something:
-/usr/local/php-7.3-httpd-2.4/bin/php composer.phar require something/something
+/usr/local/php-8.0-httpd-2.4/bin/php composer.phar require something/something
Update all installed:
-/usr/local/php-7.3-httpd-2.4/bin/php composer.phar update
+/usr/local/php-8.0-httpd-2.4/bin/php composer.phar update
Or update only one package:
-/usr/local/php-7.3-httpd-2.4/bin/php composer.phar something/something
+/usr/local/php-8.0-httpd-2.4/bin/php composer.phar something/something
Install AWS SDK:
-/usr/local/php-7.3-httpd-2.4/bin/php -d memory_limit=-1 composer.phar require aws/aws-sdk-php
+/usr/local/php-8.0-httpd-2.4/bin/php -d memory_limit=-1 composer.phar require aws/aws-sdk-php
Install zipStream:
-/usr/local/php-7.3-httpd-2.4/bin/php composer.phar require maennchen/zipstream-php
+/usr/local/php-8.0-httpd-2.4/bin/php composer.phar require maennchen/zipstream-php
diff --git a/4dev/static_checker/phan.sh b/4dev/static_checker/phan.sh
deleted file mode 100644
index 1ee1ea25..00000000
--- a/4dev/static_checker/phan.sh
+++ /dev/null
@@ -1 +0,0 @@
-phan --progress-bar -C --analyze-twice
diff --git a/4dev/static_checker/phpstan.sh b/4dev/static_checker/phpstan.sh
deleted file mode 100644
index 14e637bc..00000000
--- a/4dev/static_checker/phpstan.sh
+++ /dev/null
@@ -1 +0,0 @@
-phpstan
diff --git a/4dev/tests/CoreLibsConvertMathTest.php b/4dev/tests/CoreLibsConvertMathTest.php
new file mode 100644
index 00000000..f061f357
--- /dev/null
+++ b/4dev/tests/CoreLibsConvertMathTest.php
@@ -0,0 +1,137 @@
+ [5.5, 6],
+ '5.1234567890 with 5 must be 6' => [5.1234567890, 6],
+ '6 must be 6' => [6, 6]
+ ];
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @dataProvider fceilProvider
+ * @testdox Math::fceil: Input $input must be $expected
+ *
+ * @param int $input
+ * @param int $expected
+ * @return void
+ */
+ public function testMathFceilValue(float $input, int $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Convert\Math::fceil($input)
+ );
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function floorProvider(): array
+ {
+ return [
+ '5123456 with -3 must be 5123000' => [5123456, -3, 5123000],
+ '5123456 with -10 must be 5000000' => [5123456, -10, 5000000]
+ ];
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @dataProvider floorProvider
+ * @testdox Math::floor: Input $input with cutoff $cutoff must be $expected
+ *
+ * @param int $input
+ * @param int $cutoff
+ * @param int $expected
+ * @return void
+ */
+ public function testMathFloorValue(int $input, int $cutoff, int $expected): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Convert\Math::floorp($input, $cutoff)
+ );
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @return array
+ */
+ public function initNumericProvider(): array
+ {
+ return [
+ '5 must be 5' => [5, 5, 'int'],
+ '5.123 must be 5.123' => [5.123, 5.123, 'float'],
+ "'5' must be 5" => ['5', 5, 'string'],
+ "'5.123' must be 5.123" => ['5.123', 5.123, 'string'],
+ ];
+ }
+
+ /**
+ * Undocumented function
+ *
+ * @dataProvider initNumericProvider
+ * @testdox Math::initNumeric: Input $info $input must match $expected [$_dataName]
+ *
+ * @param int|float|string $input
+ * @param float $expected
+ * @return void
+ */
+ public function testMathInitNumericValue($input, float $expected, string $info): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Convert\Math::initNumeric($input)
+ );
+ }
+
+ /**
+ * A testWith sample
+ *
+ * @testdox Math::initNumeric: alternate tests $input => $expected ($info) [$_dataName]
+ * @testWith [123.123, 123.123, "float"]
+ * ["123.123", 123.123, "string"]
+ *
+ * @param [type] $input
+ * @param float $expected
+ * @param string $info
+ * @return void
+ */
+ public function testMathInitNumericValueAlt($input, float $expected, string $info): void
+ {
+ $this->assertEquals(
+ $expected,
+ \CoreLibs\Convert\Math::initNumeric($input)
+ );
+ }
+}
diff --git a/phpstan.neon b/phpstan.neon
index 884b9a15..41080333 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -43,6 +43,8 @@ parameters:
- www/lib/Smarty*
# ignore composer
- www/vendor
+ # ignore tst folder
+ - www/tests
# ignore errores with
ignoreErrors:
# -
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 00000000..917056a9
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,6 @@
+