Compare commits

...

6 Commits

Author SHA1 Message Date
Clemens Schwaighofer
4ab382990e Output\Image Exceptions update 2023-10-12 17:12:15 +09:00
Clemens Schwaighofer
c61a68b131 Release: v9.8.2 2023-10-06 16:53:33 +09:00
Clemens Schwaighofer
c7254c45b7 Update DB\IO with fixed regex for query params detection 2023-10-06 16:52:42 +09:00
Clemens Schwaighofer
4edacc0d13 phpunit tools symlink fix, phpunit boostrap update 2023-10-04 15:01:23 +09:00
Clemens Schwaighofer
128d6533fc Remove composer install phan/phpstan/etc and switch to phive install 2023-10-04 14:49:49 +09:00
Clemens Schwaighofer
c740fb1af1 Release: v9.8.1 2023-10-02 17:34:37 +09:00
20 changed files with 203 additions and 55 deletions

View File

@@ -360,10 +360,7 @@ return [
'directory_list' => [ 'directory_list' => [
'src', 'src',
'vendor/egrajp/smarty-extended/src', 'vendor/egrajp/smarty-extended/src',
'vendor/phan/phan/src/Phan',
'vendor/phpunit/phpunit/src',
'vendor/psr/log/src', 'vendor/psr/log/src',
'vendor/vimeo/psalm/src/Psalm',
'vendor/gullevek/dotenv', 'vendor/gullevek/dotenv',
], ],

9
.phive/phars.xml Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^9.6" installed="9.6.13" location="./tools/phpunit" copy="false"/>
<phar name="phpcs" version="^3.7.2" installed="3.7.2" location="./tools/phpcs" copy="false"/>
<phar name="phpcbf" version="^3.7.2" installed="3.7.2" location="./tools/phpcbf" copy="false"/>
<phar name="psalm" version="^5.15.0" installed="5.15.0" location="./tools/psalm" copy="false"/>
<phar name="phpstan" version="^1.10.37" installed="1.10.37" location="./tools/phpstan" copy="false"/>
<phar name="phan" version="^5.4.2" installed="5.4.2" location="./tools/phan" copy="false"/>
</phive>

View File

@@ -23,3 +23,21 @@ Alternative setup composer local zip file repot:
## Install package ## Install package
`composer require egrajp/corelibs-composer-all:^8.0` `composer require egrajp/corelibs-composer-all:^8.0`
## Tests
All tests must be run from the base folder
### phan
`phan --progress-bar -C --analyze-twic`
### phpstan
`phpstan`
### phpunit
PHP unit is installed via "phiev"
`tools/phpunit test/phpunit`

View File

@@ -20,11 +20,7 @@
"psr/log": "^3.0@dev" "psr/log": "^3.0@dev"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.10",
"phan/phan": "v5.x-dev",
"phpunit/phpunit": "^9",
"egrajp/smarty-extended": "^4.3", "egrajp/smarty-extended": "^4.3",
"vimeo/psalm": "^5.0@dev",
"gullevek/dotenv": "dev-master" "gullevek/dotenv": "dev-master"
}, },
"repositories": { "repositories": {

View File

@@ -2,5 +2,6 @@
cacheResultFile="/tmp/phpunit-corelibs-composer.result.cache" cacheResultFile="/tmp/phpunit-corelibs-composer.result.cache"
colors="true" colors="true"
verbose="true" verbose="true"
bootstrap="test/phpunit/bootstrap.php"
> >
</phpunit> </phpunit>

View File

@@ -1 +1 @@
9.8.0 9.8.2

View File

@@ -281,12 +281,6 @@ class IO
public const NO_CACHE = 3; public const NO_CACHE = 3;
/** @var string default hash type */ /** @var string default hash type */
public const ERROR_HASH_TYPE = 'adler32'; public const ERROR_HASH_TYPE = 'adler32';
/**
* @var string regex for params: only stand alone $number allowed
* never allowed to start with '
* must be after space/tab, =, (
*/
public const REGEX_PARAMS = '/[^\'][\s(=](\$[0-9]{1,})/';
/** @var string regex to get returning with matches at position 1 */ /** @var string regex to get returning with matches at position 1 */
public const REGEX_RETURNING = '/\s+returning\s+(.+\s*(?:.+\s*)+);?$/i'; public const REGEX_RETURNING = '/\s+returning\s+(.+\s*(?:.+\s*)+);?$/i';
// REGEX_SELECT // REGEX_SELECT
@@ -1264,6 +1258,32 @@ class IO
return $return; return $return;
} }
/**
* count $ leading parameters only
*
* @param string $query Query to check
* @return int Number of parameters found
*/
private function __dbCountQueryParams(string $query): int
{
$match = [];
// regex for params: only stand alone $number allowed
// exclude all '' enclosed strings, ignore all numbers [note must start with digit]
// can have space/tab/new line
// must have = , ( [equal, comma, opening round bracket]
// can have space/tab/new line
// $ number with 1-9 for first and 0-9 for further digits
// /s for matching new line in . list
// [disabled, we don't used ^ or $] /m for multi line match
// Matches in 1:, must be array_filtered to remove empty, count with array_unique
preg_match_all(
'/(?:\'.*?\')?\s*(?:\?\?|[(=,])\s*(?:\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s',
$query,
$match
);
return count(array_unique(array_filter($match[1])));
}
/** /**
* Checks if the placeholder count in the query matches the params given * Checks if the placeholder count in the query matches the params given
* on call * on call
@@ -1274,10 +1294,7 @@ class IO
*/ */
private function __dbCheckQueryParams(string $query, int $params_count): bool private function __dbCheckQueryParams(string $query, int $params_count): bool
{ {
// search for $1, $2, in the query and push it into the control array $placeholder_count = $this->__dbCountQueryParams($query);
// skip counts for same eg $1, $1, $2 = 2 and not 3
preg_match_all(self::REGEX_PARAMS, $query, $match);
$placeholder_count = count(array_unique($match[1]));
if ($params_count != $placeholder_count) { if ($params_count != $placeholder_count) {
$this->__dbError( $this->__dbError(
23, 23,
@@ -1384,6 +1401,9 @@ class IO
) { ) {
$this->returning_id = true; $this->returning_id = true;
} }
// import protection, hash needed
$query_hash = $this->dbGetQueryHash($this->query, $this->params);
// $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id); // $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id);
// for DEBUG, only on first time ;) // for DEBUG, only on first time ;)
$this->__dbDebug( $this->__dbDebug(
@@ -1395,8 +1415,6 @@ class IO
'__dbPrepareExec', '__dbPrepareExec',
($this->params === [] ? 'Q' : 'Qp') ($this->params === [] ? 'Q' : 'Qp')
); );
// import protection, hash needed
$query_hash = $this->dbGetQueryHash($this->query, $this->params);
// if the array index does not exists set it 0 // if the array index does not exists set it 0
if (!array_key_exists($query_hash, $this->query_called)) { if (!array_key_exists($query_hash, $this->query_called)) {
$this->query_called[$query_hash] = 0; $this->query_called[$query_hash] = 0;
@@ -2943,11 +2961,8 @@ class IO
$this->prepare_cursor[$stm_name]['pk_name'] = $pk_name; $this->prepare_cursor[$stm_name]['pk_name'] = $pk_name;
} }
} }
$match = []; // check prepared curser parameter count
// search for $1, $2, in the query and push it into the control array $this->prepare_cursor[$stm_name]['count'] = $this->__dbCountQueryParams($query);
// skip counts for same eg $1, $1, $2 = 2 and not 3
preg_match_all(self::REGEX_PARAMS, $query, $match);
$this->prepare_cursor[$stm_name]['count'] = count(array_unique($match[1]));
$this->prepare_cursor[$stm_name]['query'] = $query; $this->prepare_cursor[$stm_name]['query'] = $query;
$result = $this->db_functions->__dbPrepare($stm_name, $query); $result = $this->db_functions->__dbPrepare($stm_name, $query);
if ($result) { if ($result) {

View File

@@ -470,12 +470,20 @@ class Image
* *
* @param string $filename path + filename to rotate. This file must be writeable * @param string $filename path + filename to rotate. This file must be writeable
* @return void * @return void
* @throws \RuntimeException if exit_read_data is not found
* @throws \UnexpectedValueException if file name not writeable or file name not found
*/ */
public static function correctImageOrientation(string $filename): void public static function correctImageOrientation(string $filename): void
{ {
// function exists & file is writeable, else do nothing // function exists & file is writeable, else do nothing
if (!function_exists('exif_read_data') || !is_writeable($filename)) { if (!function_exists('exif_read_data')) {
return; throw new \RuntimeException('Function \'exit_read_data\' does not exist');
}
if (!file_exists($filename) || !is_file($filename)) {
throw new \UnexpectedValueException('Missing image file: ' . $filename);
}
if (!is_writeable($filename)) {
throw new \UnexpectedValueException('File name is not writeable: ' . $filename);
} }
[$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [0, 0, null]; [$inc_width, $inc_height, $img_type] = getimagesize($filename) ?: [0, 0, null];
// add @ to avoid "file not supported error" // add @ to avoid "file not supported error"

View File

@@ -3907,7 +3907,8 @@ final class CoreLibsDBIOTest extends TestCase
'id' => '51', 'id' => '51',
'error' => 'Max query call needs to be set to at least 1', 'error' => 'Max query call needs to be set to at least 1',
// run:: can be +1 if called in set and not direct // run:: can be +1 if called in set and not direct
'source' => "/^include::main::run::run::run::run::run::run::(run::)?runBare::runTest::testDbErrorHandling::dbSetMaxQueryCall$/", // 'main::run::run::run::run::run::run::run::runBare::runTest::testDbErrorHandling::dbSetMaxQueryCall
'source' => "/^(include::)?main::(run::)+runBare::runTest::testDbErrorHandling::dbSetMaxQueryCall$/",
'pg_error' => '', 'pg_error' => '',
'msg' => '', 'msg' => '',
] ]

View File

@@ -460,8 +460,8 @@ final class CoreLibsDebugSupportTest extends TestCase
* Undocumented function * Undocumented function
* *
* @cover ::getCallerFileLine * @cover ::getCallerFileLine
* @testWith ["vendor/phpunit/phpunit/src/Framework/TestCase.php:"] * @testWith ["vendor/phpunit/phpunit/src/Framework/TestCase.php:6434","phar:///home/clemens/.phive/phars/phpunit-9.6.13.phar/phpunit/Framework/TestCase.php:6434"]
* @testdox getCallerFileLine check based on regex /[\w\-\/]/vendor/phpunit/phpunit/src/Framework/TestCase.php:\d+ [$_dataName] * @testdox getCallerFileLine check based on regex .../Framework/TestCase.php:\d+ [$_dataName]
* *
* @param string $expected * @param string $expected
* @return void * @return void
@@ -469,7 +469,14 @@ final class CoreLibsDebugSupportTest extends TestCase
public function testGetCallerFileLine(): void public function testGetCallerFileLine(): void
{ {
// regex prefix with path "/../" and then fixed vendor + \d+ // regex prefix with path "/../" and then fixed vendor + \d+
$regex = "/^\/[\w\-\/]+\/vendor\/phpunit\/phpunit\/src\/Framework\/TestCase.php:\d+$/"; // or phar start if phiev installed
// phar:///home/clemens/.phive/phars/phpunit-9.6.13.phar/phpunit/Framework/TestCase.php
$regex = "/^("
. "\/.*\/vendor\/phpunit\/phpunit\/src"
. "|"
. "phar:\/\/\/.*\.phive\/phars\/phpunit-\d+\.\d+\.\d+\.phar\/phpunit"
. ")"
. "\/Framework\/TestCase.php:\d+$/";
$this->assertMatchesRegularExpression( $this->assertMatchesRegularExpression(
$regex, $regex,
Support::getCallerFileLine() Support::getCallerFileLine()
@@ -514,27 +521,30 @@ final class CoreLibsDebugSupportTest extends TestCase
// add nothing // add nothing
$this->assertEquals( $this->assertEquals(
$expected, $expected,
Support::getCallerMethodList(), $compare,
'assert expected 10' 'assert expected 10'
); );
break; break;
case 11: case 11:
// add one "run" before "runBare" if ($compare[0] == 'include') {
// array_splice( // add include at first
// $expected, array_splice(
// 7, $expected,
// 0, 0,
// ['run'] 0,
// ); ['include']
array_splice( );
$expected, } else {
0, array_splice(
0, $expected,
['include'] 6,
); 0,
['run']
);
}
$this->assertEquals( $this->assertEquals(
$expected, $expected,
Support::getCallerMethodList(), $compare,
'assert expected 11' 'assert expected 11'
); );
break; break;
@@ -554,7 +564,7 @@ final class CoreLibsDebugSupportTest extends TestCase
); );
$this->assertEquals( $this->assertEquals(
$expected, $expected,
Support::getCallerMethodList(), $compare,
'assert expected 12' 'assert expected 12'
); );
break; break;

View File

@@ -99,7 +99,7 @@ final class CoreLibsGetSystemTest extends TestCase
1 => 'phpunit', 1 => 'phpunit',
2 => 'phpunit', 2 => 'phpunit',
// NOTE: this can change, so it is a regex check // NOTE: this can change, so it is a regex check
3 => "/^(\/?.*\/?)?vendor\/bin\/phpunit$/", 3 => "/^(\/?.*\/?)?(vendor\/bin|tools)\/phpunit$/",
], ],
'some path with extension' => [ 'some path with extension' => [
0 => '/some/path/to/file.txt', 0 => '/some/path/to/file.txt',

View File

@@ -20,7 +20,7 @@ final class CoreLibsLoggingLoggingTest extends TestCase
private const LOG_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR; 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\.:]+\]\s{1}" // date
. "\[[\w\.]+(:\d+)?\]\s{1}" // host:port . "\[[\w\.]+(:\d+)?\]\s{1}" // host:port
. "\[[\w\-\.\/]+:\d+\]\s{1}" // folder/file . "\[(phar:\/\/)?[\w\-\.\/]+:\d+\]\s{1}" // folder/file [note phar:// is for phpunit]
. "\[\w+\]\s{1}" // run id . "\[\w+\]\s{1}" // run id
. "{[\w\\\\]+((::|->)\w+)?}\s{1}"; // class . "{[\w\\\\]+((::|->)\w+)?}\s{1}"; // class

View File

@@ -16,17 +16,89 @@ final class CoreLibsOutputImageTest extends TestCase
/** /**
* Undocumented function * Undocumented function
* *
* @testdox Output\Image Class tests * @covers ::createThumbnail
* @testdox createThumbnail checks
* *
* @return void * @return void
*/ */
public function testOutputImage() public function testCreateThumbnail(): void
{ {
// $this->assertTrue(true, 'Output Image Tests not implemented'); // CONVERT does not exist
$this->markTestIncomplete( $this->expectException(\RuntimeException::class);
'Output\Image Tests have not yet been implemented' \CoreLibs\Output\Image::createThumbnail('do_not_exist.png', 200, 200);
// set convert
$paths = [
'/bin',
'/usr/bin',
'/usr/local/bin',
];
// find convert
foreach ($paths as $path) {
if (
file_exists($path . DIRECTORY_SEPARATOR . 'convert') &&
is_file($path . DIRECTORY_SEPARATOR . 'convert')
) {
// image magick convert location
define('CONVERT', $path . DIRECTORY_SEPARATOR . 'convert');
break;
}
}
unset($paths);
// cannot set dummy file
$this->expectException(\Exception::class);
\CoreLibs\Output\Image::createThumbnail('do_not_exist.png', 200, 200);
}
/**
* Undocumented function
*
* @covers ::createThumbnailSimple
* @testdox createThumbnailSimple checks
*
* @return void
*/
public function testCreateThumbnailSimple(): void
{
// file does not exist
$this->expectException(\UnexpectedValueException::class);
\CoreLibs\Output\Image::createThumbnailSimple(
'do_not_exist.png',
200,
200,
cache_folder: '/tmp/',
web_folder: '/tmp/'
); );
// $this->markTestSkipped('No implementation for Output\Image at the moment'); // cache folder is not dir
$this->expectException(\UnexpectedValueException::class);
\CoreLibs\Output\Image::createThumbnailSimple(
'do_not_exist.png',
200,
200,
cache_folder: '/foo/bar/',
web_folder: '/tmp/'
);
// target cache folder is not writeable
// RuntimeException: imagecreatetruecolor failed
// RuntimeException: imagecolorallocatealpha failed
}
/**
* Undocumented function
*
* @covers ::correctImageOrientation
* @testdox correctImageOrientation checks
*
* @return void
*/
public function testCorrectImageOrientation(): void
{
// test file does not exist
$this->expectException(\UnexpectedValueException::class);
\CoreLibs\Output\Image::correctImageOrientation('do_not_exist.png');
// test folder not writeable
// test exit_read_data not present (how)?
// test image rotate
} }
} }

View File

@@ -0,0 +1,15 @@
<?php
$set = 0;
foreach (['/../../www', '/../www', '/../..', '/..', '/../../src', '/../src'] as $src) {
if (is_file(dirname(__DIR__) . $src . '/vendor/autoload.php')) {
require dirname(__DIR__) . $src . '/vendor/autoload.php';
$set = 1;
break;
}
}
if (!$set) {
die("Cannot find /vendor/autoload.php in reference to: " . dirname(__DIR__));
}
// __END__

1
tools/phan Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/phan-5.4.2.phar

1
tools/phpcbf Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/phpcbf-3.7.2.phar

1
tools/phpcs Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/phpcs-3.7.2.phar

1
tools/phpstan Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/phpstan-1.10.37.phar

1
tools/phpunit Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/phpunit-9.6.13.phar

1
tools/psalm Symbolic link
View File

@@ -0,0 +1 @@
/home/clemens/.phive/phars/psalm-5.15.0.phar