phpunit script update, SmartyExtended allow load of plugins
- phpunit has better options set for testdox/php version - SmartyExtended has logger class as option (argument 2) and options - SmartyExtneded can via option set html escape and load of plugins - plugin array is set of - file: path to plugin file - type: what type this is - tag: tag name - callable: the callable for the tag name - will throw exceptions on plugin load - for all other things will set warning only and skip read - fix the Smarty call with the logger option - fix password test for PHP 8.4 password hash change *IMPORTANT* SmartyExtended($l10n, $logger, $cache_id, $compile_id) The second argument is now the Logger class, this MUST be updated for all calls
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
||||||
# must be run in ${base}
|
# must be run in ${base}
|
||||||
cd $base;
|
cd $base || exit;
|
||||||
${base}tools/phan --progress-bar -C --analyze-twice;
|
${base}tools/phan --progress-bar -C --analyze-twice;
|
||||||
cd ~;
|
cd ~ || exit;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
||||||
# must be run in ${base}
|
# must be run in ${base}
|
||||||
cd $base;
|
cd $base || exit;
|
||||||
${base}tools/phpstan;
|
${base}tools/phpstan;
|
||||||
cd ~;
|
cd ~ || exit;
|
||||||
|
|||||||
@@ -3,47 +3,44 @@
|
|||||||
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
base="/storage/var/www/html/developers/clemens/core_data/php_libraries/trunk/";
|
||||||
# -c phpunit.xml
|
# -c phpunit.xml
|
||||||
# --testdox
|
# --testdox
|
||||||
# call with "t" to give verbose testdox output
|
# call with "-tt" to give verbose testdox output
|
||||||
# SUPPORTED: https://www.php.net/supported-versions.php
|
# SUPPORTED: https://www.php.net/supported-versions.php
|
||||||
# call with php version number to force a certain php version
|
# call with -p <php version number> to force a certain php version
|
||||||
|
|
||||||
opt_testdox="";
|
opt_testdox="";
|
||||||
if [ "${1}" = "t" ] || [ "${2}" = "t" ]; then
|
|
||||||
opt_testdox="--testdox";
|
|
||||||
fi;
|
|
||||||
php_bin="";
|
php_bin="";
|
||||||
if [ -n "${1}" ]; then
|
while [ -n "${1-}" ]; do
|
||||||
case "${1}" in
|
case "${1}" in
|
||||||
# "7.3") php_bin="/usr/bin/php7.3 "; ;;
|
-t | --testdox)
|
||||||
# "7.4") php_bin="/usr/bin/php7.4 "; ;;
|
opt_testdox="--testdox";
|
||||||
# "8.0") php_bin="/usr/bin/php8.0 "; ;;
|
;;
|
||||||
# "8.1") php_bin="/usr/bin/php8.1 "; ;;
|
-p | --php)
|
||||||
"8.2") php_bin="/usr/bin/php8.2 "; ;;
|
php_bin="/usr/bin/php${2-}";
|
||||||
"8.3") php_bin="/usr/bin/php8.4 "; ;;
|
shift
|
||||||
*) echo "Not support PHP: ${1}"; exit; ;;
|
;;
|
||||||
esac;
|
# invalid option
|
||||||
fi;
|
-?*)
|
||||||
if [ -n "${2}" ] && [ -z "${php_bin}" ]; then
|
error "[!] Unknown option: '$1'."
|
||||||
case "${2}" in
|
;;
|
||||||
# "7.3") php_bin="/usr/bin/php7.3 "; ;;
|
esac
|
||||||
# "7.4") php_bin="/usr/bin/php7.4 "; ;;
|
shift;
|
||||||
# "8.0") php_bin="/usr/bin/php8.0 "; ;;
|
done;
|
||||||
# "8.1") php_bin="/usr/bin/php8.1 "; ;;
|
|
||||||
"8.2") php_bin="/usr/bin/php8.2 "; ;;
|
if [ ! -f "${php_bin}" ]; then
|
||||||
"8.3") php_bin="/usr/bin/php8.3 "; ;;
|
echo "Set php ${php_bin} does not exist";
|
||||||
*) echo "Not support PHP: ${1}"; exit; ;;
|
exit;
|
||||||
esac;
|
|
||||||
fi;
|
fi;
|
||||||
|
php_bin="${php_bin} ";
|
||||||
|
|
||||||
# Note 4dev/tests/bootstrap.php has to be set as bootstrap file in phpunit.xml
|
# Note 4dev/tests/bootstrap.php has to be set as bootstrap file in phpunit.xml
|
||||||
phpunit_call="${php_bin}${base}vendor/bin/phpunit ${opt_testdox} -c ${base}phpunit.xml ${base}4dev/tests/";
|
phpunit_call="${php_bin}${base}vendor/bin/phpunit ${opt_testdox} -c ${base}phpunit.xml ${base}4dev/tests/";
|
||||||
|
|
||||||
${phpunit_call};
|
${phpunit_call};
|
||||||
|
|
||||||
if [ ! -z "${php_bin}" ]; then
|
if [ -n "${php_bin}" ]; then
|
||||||
echo "CALLED WITH PHP: ${php_bin}"$(${php_bin} --version);
|
echo "CALLED WITH PHP: ${php_bin}$(${php_bin} --version)";
|
||||||
else
|
else
|
||||||
echo "Default PHP used: "$(php --version);
|
echo "Default PHP used: $(php --version)";
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
# __END__
|
# __END__
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ use PHPUnit\Framework\TestCase;
|
|||||||
*/
|
*/
|
||||||
final class CoreLibsSecurityPasswordTest extends TestCase
|
final class CoreLibsSecurityPasswordTest extends TestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Undocumented function
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function passwordProvider(): array
|
public function passwordProvider(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@@ -21,6 +26,11 @@ final class CoreLibsSecurityPasswordTest extends TestCase
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: we need different hash types for PHP versions
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function passwordRehashProvider(): array
|
public function passwordRehashProvider(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@@ -63,6 +73,10 @@ final class CoreLibsSecurityPasswordTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testPasswordRehashCheck(string $input, bool $expected): void
|
public function testPasswordRehashCheck(string $input, bool $expected): void
|
||||||
{
|
{
|
||||||
|
// in PHP 8.4 the length is $12
|
||||||
|
if (PHP_VERSION_ID > 80400) {
|
||||||
|
$input = str_replace('$2y$10$', '$2y$12$', $input);
|
||||||
|
}
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
$expected,
|
$expected,
|
||||||
\CoreLibs\Security\Password::passwordRehashCheck($input)
|
\CoreLibs\Security\Password::passwordRehashCheck($input)
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ print "PASSWORD REHASH: " . (string)$password_class::passwordRehashCheck($enc_pa
|
|||||||
// direct static
|
// direct static
|
||||||
print "S::PASSWORD VERFIY: " . (string)PwdChk::passwordVerify($password, $enc_password) . "<br>";
|
print "S::PASSWORD VERFIY: " . (string)PwdChk::passwordVerify($password, $enc_password) . "<br>";
|
||||||
|
|
||||||
|
$rehash_test = '$2y$10$EgWJ2WE73DWi.hIyFRCdpejLXTvHbmTK3LEOclO1tAvXAXUNuUS4W';
|
||||||
|
if (PwdChk::passwordRehashCheck($rehash_test)) {
|
||||||
|
print "Bad password<br>";
|
||||||
|
}
|
||||||
|
|
||||||
print "</body></html>";
|
print "</body></html>";
|
||||||
|
|
||||||
// __END__
|
// __END__
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ $l10n = new \CoreLibs\Language\L10n(
|
|||||||
);
|
);
|
||||||
$smarty = new CoreLibs\Template\SmartyExtend(
|
$smarty = new CoreLibs\Template\SmartyExtend(
|
||||||
$l10n,
|
$l10n,
|
||||||
|
$log,
|
||||||
CACHE_ID,
|
CACHE_ID,
|
||||||
COMPILE_ID,
|
COMPILE_ID,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ $l10n = new \CoreLibs\Language\L10n(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// create smarty object
|
// create smarty object
|
||||||
$smarty = new \CoreLibs\Template\SmartyExtend($l10n, CACHE_ID, COMPILE_ID);
|
$smarty = new \CoreLibs\Template\SmartyExtend($l10n, $log, CACHE_ID, COMPILE_ID);
|
||||||
// create new Backend class with db and loger attached
|
// create new Backend class with db and loger attached
|
||||||
$cms = new \CoreLibs\Admin\Backend($db, $log, $session, $l10n, DEFAULT_ACL_LEVEL);
|
$cms = new \CoreLibs\Admin\Backend($db, $log, $session, $l10n, DEFAULT_ACL_LEVEL);
|
||||||
// the menu show flag (what menu to show)
|
// the menu show flag (what menu to show)
|
||||||
|
|||||||
@@ -538,8 +538,7 @@ class EditBase
|
|||||||
* builds the smarty content and runs smarty display output
|
* builds the smarty content and runs smarty display output
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
* @throws Exception
|
* @throws \Smarty\Exception
|
||||||
* @throws SmartyException
|
|
||||||
*/
|
*/
|
||||||
public function editBaseRun(
|
public function editBaseRun(
|
||||||
?string $template_dir = null,
|
?string $template_dir = null,
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace CoreLibs\Template;
|
namespace CoreLibs\Template;
|
||||||
|
|
||||||
// leading slash if this is in lib\Smarty
|
|
||||||
class SmartyExtend extends \Smarty\Smarty
|
class SmartyExtend extends \Smarty\Smarty
|
||||||
{
|
{
|
||||||
// internal translation engine
|
// internal translation engine
|
||||||
/** @var \CoreLibs\Language\L10n */
|
/** @var \CoreLibs\Language\L10n language class */
|
||||||
public \CoreLibs\Language\L10n $l10n;
|
public \CoreLibs\Language\L10n $l10n;
|
||||||
|
/** @var \CoreLibs\Logging\Logging $log logging class */
|
||||||
|
public \CoreLibs\Logging\Logging $log;
|
||||||
|
|
||||||
// lang & encoding
|
// lang & encoding
|
||||||
/** @var string */
|
/** @var string */
|
||||||
@@ -157,14 +158,18 @@ class SmartyExtend extends \Smarty\Smarty
|
|||||||
* calls L10 for pass on internaly in smarty
|
* calls L10 for pass on internaly in smarty
|
||||||
* also registers the getvar caller plugin
|
* also registers the getvar caller plugin
|
||||||
*
|
*
|
||||||
* @param \CoreLibs\Language\L10n $l10n l10n language class
|
* @param \CoreLibs\Language\L10n $l10n l10n language class
|
||||||
* @param string|null $cache_id
|
* @param \CoreLibs\Logging\Logging $log Logger class
|
||||||
* @param string|null $compile_id
|
* @param string|null $cache_id [default=null]
|
||||||
|
* @param string|null $compile_id [default=null]
|
||||||
|
* @param array<string,mixed> $options [default=[]]
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
\CoreLibs\Language\L10n $l10n,
|
\CoreLibs\Language\L10n $l10n,
|
||||||
|
\CoreLibs\Logging\Logging $log,
|
||||||
?string $cache_id = null,
|
?string $cache_id = null,
|
||||||
?string $compile_id = null
|
?string $compile_id = null,
|
||||||
|
array $options = []
|
||||||
) {
|
) {
|
||||||
// trigger deprecation
|
// trigger deprecation
|
||||||
if (
|
if (
|
||||||
@@ -177,14 +182,33 @@ class SmartyExtend extends \Smarty\Smarty
|
|||||||
E_USER_DEPRECATED
|
E_USER_DEPRECATED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// set variables (to be deprecated)
|
// set variables from global constants (deprecated)
|
||||||
$cache_id = $cache_id ??
|
if ($cache_id === null && defined('CACHE_ID')) {
|
||||||
(defined('CACHE_ID') ? CACHE_ID : '');
|
trigger_error(
|
||||||
$compile_id = $compile_id ??
|
'SmartyExtended: No cache_id set and CACHE_ID constant set, this is deprecated',
|
||||||
(defined('COMPILE_ID') ? COMPILE_ID : '');
|
E_USER_DEPRECATED
|
||||||
|
);
|
||||||
|
$cache_id = CACHE_ID;
|
||||||
|
}
|
||||||
|
if ($compile_id === null && defined('COMPILE_ID')) {
|
||||||
|
trigger_error(
|
||||||
|
'SmartyExtended: No compile_id set and COMPILE_ID constant set, this is deprecated',
|
||||||
|
E_USER_DEPRECATED
|
||||||
|
);
|
||||||
|
$compile_id = COMPILE_ID;
|
||||||
|
}
|
||||||
|
if (empty($cache_id)) {
|
||||||
|
throw new \BadMethodCallException('cache_id parameter is not set');
|
||||||
|
}
|
||||||
|
if (empty($compile_id)) {
|
||||||
|
throw new \BadMethodCallException('compile_id parameter is not set');
|
||||||
|
}
|
||||||
|
|
||||||
// call basic smarty
|
// call basic smarty
|
||||||
// or Smarty::__construct();
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->log = $log;
|
||||||
|
|
||||||
// init lang
|
// init lang
|
||||||
$this->l10n = $l10n;
|
$this->l10n = $l10n;
|
||||||
// parse and read, legacy stuff
|
// parse and read, legacy stuff
|
||||||
@@ -194,7 +218,6 @@ class SmartyExtend extends \Smarty\Smarty
|
|||||||
$this->lang_short = $locale['lang_short'];
|
$this->lang_short = $locale['lang_short'];
|
||||||
$this->domain = $locale['domain'];
|
$this->domain = $locale['domain'];
|
||||||
$this->lang_dir = $locale['path'];
|
$this->lang_dir = $locale['path'];
|
||||||
|
|
||||||
// opt load functions so we can use legacy init for smarty run perhaps
|
// opt load functions so we can use legacy init for smarty run perhaps
|
||||||
\CoreLibs\Language\L10n::loadFunctions();
|
\CoreLibs\Language\L10n::loadFunctions();
|
||||||
_setlocale(LC_MESSAGES, $locale['locale']);
|
_setlocale(LC_MESSAGES, $locale['locale']);
|
||||||
@@ -203,7 +226,6 @@ class SmartyExtend extends \Smarty\Smarty
|
|||||||
_bind_textdomain_codeset($this->domain, $this->encoding);
|
_bind_textdomain_codeset($this->domain, $this->encoding);
|
||||||
|
|
||||||
// register smarty variable
|
// register smarty variable
|
||||||
// $this->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'getvar', [&$this, 'getTemplateVars']);
|
|
||||||
$this->registerPlugin(self::PLUGIN_MODIFIER, 'getvar', [&$this, 'getTemplateVars']);
|
$this->registerPlugin(self::PLUGIN_MODIFIER, 'getvar', [&$this, 'getTemplateVars']);
|
||||||
|
|
||||||
$this->page_name = \CoreLibs\Get\System::getPageName();
|
$this->page_name = \CoreLibs\Get\System::getPageName();
|
||||||
@@ -211,6 +233,76 @@ class SmartyExtend extends \Smarty\Smarty
|
|||||||
// set internal settings
|
// set internal settings
|
||||||
$this->CACHE_ID = $cache_id;
|
$this->CACHE_ID = $cache_id;
|
||||||
$this->COMPILE_ID = $compile_id;
|
$this->COMPILE_ID = $compile_id;
|
||||||
|
// set options
|
||||||
|
$this->setOptions($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set options
|
||||||
|
*
|
||||||
|
* @param array<string,mixed> $options
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function setOptions(array $options): void
|
||||||
|
{
|
||||||
|
// set escape html if option is set
|
||||||
|
if (!empty($options['escape_html'])) {
|
||||||
|
$this->setEscapeHtml(true);
|
||||||
|
}
|
||||||
|
// load plugins
|
||||||
|
// plugin array:
|
||||||
|
// 'file': string, path to plugin content to load
|
||||||
|
// 'type': a valid smarty type see Smarty PLUGIN_ constants for correct names
|
||||||
|
// 'tag': the smarty tag
|
||||||
|
// 'callback': the function to call in 'file'
|
||||||
|
if (!empty($options['plugins'])) {
|
||||||
|
foreach ($options['plugins'] as $plugin) {
|
||||||
|
// file is readable
|
||||||
|
if (
|
||||||
|
empty($plugin['file']) ||
|
||||||
|
!is_file($plugin['file']) ||
|
||||||
|
!is_readable($plugin['file'])
|
||||||
|
) {
|
||||||
|
$this->log->warning('SmartyExtended plugin load failed, file not accessable', [
|
||||||
|
'plugin' => $plugin,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// tag is alphanumeric
|
||||||
|
if (!preg_match("/^\w+$/", $plugin['tag'] ?? '')) {
|
||||||
|
$this->log->warning('SmartyExtended plugin load failed, invalid tag', [
|
||||||
|
'plugin' => $plugin,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// callback is alphanumeric
|
||||||
|
if (!preg_match("/^\w+$/", $plugin['callback'] ?? '')) {
|
||||||
|
$this->log->warning('SmartyExtended plugin load failed, invalid callback', [
|
||||||
|
'plugin' => $plugin,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
new \ReflectionClassConstant($this, $plugin['type']);
|
||||||
|
} catch (\ReflectionException $e) {
|
||||||
|
$this->log->error('SmartyExtended plugin load failed, type is not valid', [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'plugin' => $plugin,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
require $plugin['file'];
|
||||||
|
$this->registerPlugin($plugin['type'], $plugin['tag'], $plugin['callback']);
|
||||||
|
} catch (\Smarty\Exception $e) {
|
||||||
|
$this->log->error('SmartyExtended plugin load failed with exception', [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'plugin' => $plugin,
|
||||||
|
]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user