Compare commits

...

21 Commits

Author SHA1 Message Date
Clemens Schwaighofer
5c461a6fea core composer settings update 2024-10-18 09:29:44 +09:00
Clemens Schwaighofer
2e59e50df8 Set phpstan to max level for update testing 2024-10-18 09:22:02 +09:00
Clemens Schwaighofer
4b45f8d556 Update and fix composer json file, phars file 2024-10-18 09:20:53 +09:00
Clemens Schwaighofer
4b4e655374 Merge branch 'NewFeatures' into phpstan-strict 2024-10-18 09:16:16 +09:00
Clemens Schwaighofer
9d131cf6dd Bug: Remove echo in call 2024-10-17 13:58:52 +09:00
Clemens Schwaighofer
dfcae20f64 Update DB\IO and do not print call steck on DB_INFO calls 2024-10-17 13:52:44 +09:00
Clemens Schwaighofer
61e489ee4c Remove entries from an array wrapper
just wrapper around array_diff
2024-10-17 09:44:24 +09:00
Clemens Schwaighofer
29982f90bc Admin\Backend change non filled dat part comment
the not filled data or data_binary part is a JSON with "type" set to the
type that is used with a general message

To decode try to read both sides if data = JSON + "type" and "message" set
then data is in data_binary else data_binary holds the type on the left side
2024-10-16 16:45:13 +09:00
Clemens Schwaighofer
7cced63c4b Update the Admin\Backend edit log call with query params and different data compressors
All queries uses now Params

On load checks for valid write types for edit log write, eg if bzip and lzip compression
are avaiable

adbEditLog:
Also add JSON type encoding for data outside STRING/SERIAL and BINARY/BZIP (bzip compressed)
Add ZLIB as altnerative to BZIP
Add alert if invalid type was set
Auto fallback to JSON if other write types are not available

adbLiveQueue:
Also convert the live queue query to a params style call
2024-10-16 16:21:51 +09:00
Clemens Schwaighofer
06c2ea5e0d Admin\Backend: make sure we do not access unset ->action vars 2024-10-16 12:34:48 +09:00
Clemens Schwaighofer
2e9239ec23 Ingore node_modules/ folder 2024-10-16 12:18:51 +09:00
Clemens Schwaighofer
0c89840dba Admin\Backend move _POST action read to sub function and trigger not auto loading it
On default it still auto loads the _POST vars for backwards compatible, but add a load class
flag to ignore it "init_action_vars"

also add a get vor tha "acl" array adbGetAcl()
2024-10-16 12:15:19 +09:00
Clemens Schwaighofer
db144493f3 Message system: allow warning level to be logged
Like error messages, they are written to the log if debug is on or the
flag is explicit set
2024-09-24 15:10:53 +09:00
Clemens Schwaighofer
5cec54d508 Add "Success" to message logging levels, fixes for PHP 8.4, other preg_match fixes
The Logger/MessageLevel gets "success" as level 110 to something a bit
heigher than "ok" which is the general "OK" for anything ending without
an error. The "success" is currently only used in file uploads with the
java script ajax file uploader

Fix any "type $var = null" with correctly "?type $var = null" for PHP 8.4 (phphan)

Fix preg match no return catches for DB IO compare version and for language
look up.
2024-09-20 13:33:19 +09:00
Clemens Schwaighofer
8e60c992f1 Fixes phan/phpstan 2024-09-03 12:06:01 +09:00
Clemens Schwaighofer
1b5437b675 Add testing for new added bom utf8 replace 2024-09-03 11:58:36 +09:00
Clemens Schwaighofer
ef80cba561 Add new functions: get IPs, strip UTF8 BOM from text, text updates
Add the following new static methods

Convert\Strings::stripUTF8BomBytes: removes the UTF8 BOM bytes from the beginning of a line
Used for CSV files created in Excel for the first header entry (line 0/row 0)

Get\Systen::getIpAddresses: gets all IP addresses for the the current access user
and returns an array

Moved the frontend folder detection from the first load config to the config.path.php

Cleaned up the translations JS scripts
2024-09-03 09:49:01 +09:00
Clemens Schwaighofer
2d71e760e8 Composer update 2024-08-21 11:45:17 +09:00
Clemens Schwaighofer
a8d07634ff Add soba.egplusww.jp as local development host, jshint esversion update to 11 2024-08-07 13:41:09 +09:00
Clemens Schwaighofer
da0d939068 First phpstan strict check 2023-02-28 06:54:20 +09:00
Clemens Schwaighofer
537bc0a477 add phpstan strict 2023-02-28 06:39:36 +09:00
63 changed files with 714 additions and 1373 deletions

4
.gitignore vendored
View File

@@ -1 +1,5 @@
.libs
node_modules/
composer.lock
vendor/
tools/

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^9.6" installed="9.6.19" location="./tools/phpunit" copy="false"/>
<phar name="phpcbf" version="^3.7.2" installed="3.10.0" location="./tools/phpcbf" copy="false"/>
<phar name="phpcs" version="^3.7.2" installed="3.10.0" location="./tools/phpcs" copy="false"/>
<phar name="phpstan" version="^1.10.37" installed="1.11.1" location="./tools/phpstan" copy="false"/>
<phar name="phpunit" version="^9.6" installed="9.6.21" location="./tools/phpunit" copy="false"/>
<phar name="phpcbf" version="^3.7.2" installed="3.10.3" location="./tools/phpcbf" copy="false"/>
<phar name="phpcs" version="^3.7.2" installed="3.10.3" location="./tools/phpcs" copy="false"/>
<phar name="phpstan" version="^1.10.37" installed="1.12.6" location="./tools/phpstan" copy="false"/>
<phar name="phan" version="^5.4.2" installed="5.4.3" location="./tools/phan" copy="false"/>
<phar name="psalm" version="^5.15.0" installed="5.24.0" location="./tools/psalm" copy="false"/>
<phar name="phpdox" version="^0.12.0" installed="0.12.0" location="./tools/phpdox" copy="false"/>

View File

@@ -1,19 +1,20 @@
#!/usr/bin/env bash
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# Assume script is in 4dev/bin
base_folder="${BASE_FOLDER}../../www/";
# locale gettext po to mo translator master
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do
file=$(basename $file .po);
for file in "${base_folder}"../4dev/locale/*.po; do
[[ -e "$file" ]] || break
file=$(basename "$file" .po);
locale=$(echo "${file}" | cut -d "-" -f 1);
domain=$(echo "${file}" | cut -d "-" -f 2);
echo "- Translate language file '${file}' for locale '${locale}' and domain '${domain}':";
if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then
mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/";
fi;
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}../4dev/locale/${locale}-${domain}.po;
msgfmt -o "${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo" "${base_folder}../4dev/locale/${locale}-${domain}.po";
done;
# __END__

View File

@@ -2,16 +2,18 @@
# read source mo files and writes target js files in object form
# check for ARG 1 is "mv"
# then move the files directly and don't do manual check (don't create temp files)
FILE_MOVE=0;
if [ "${1}" = "mv" ]; then
# check for ARG 1 is "no-move"
# then do not move the files directly for manual check
FILE_MOVE=1;
if [ "${1}" = "no-move" ]; then
echo "+++ CREATE TEMPORARY FILES +++";
FILE_MOVE=0;
else
echo "*** Direct write ***";
FILE_MOVE=1;
fi;
target='';
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# Assume script is in 4dev/bin
base_folder="${BASE_FOLDER}../../www/";
po_folder='../4dev/locale/'
@@ -26,7 +28,7 @@ if [ "${target}" == '' ]; then
echo "*** Non smarty ***";
TEXTDOMAINDIR=${base_folder}${mo_folder}.
# default is admin
TEXTDOMAIN=admin;
TEXTDOMAIN="admin";
fi;
js_folder="${TEXTDOMAIN}/layout/javascript/";
@@ -44,15 +46,16 @@ if [ ${error} -eq 1 ]; then
fi;
# locale gettext po to mo translator master
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do
file=$(basename $file .po);
echo "Translate language ${file}";
for file in "${base_folder}"../4dev/locale/*.po; do
[[ -e "$file" ]] || break
file=$(basename "$file" .po);
locale=$(echo "${file}" | cut -d "-" -f 1);
domain=$(echo "${file}" | cut -d "-" -f 2);
echo "- Translate language file '${file}' for locale '${locale}' and domain '${domain}':";
if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then
mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/";
fi;
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}${po_folder}${locale}-${domain}.po;
msgfmt -o "${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo" "${base_folder}${po_folder}${locale}-${domain}.po";
done;
rx_msgid_empty="^msgid \"\"";
@@ -62,7 +65,7 @@ rx_msgstr="^msgstr \""
# quick copy string at the end
quick_copy='';
for language in ${language_list[*]}; do
for language in "${language_list[@]}"; do
# I don't know which one must be set, but I think at least LANGUAGE
case ${language} in
ja)
@@ -79,7 +82,8 @@ for language in ${language_list[*]}; do
esac;
# write only one for language and then symlink files
template_file=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##//" | sed -e "s/##LANGUAGE##/${LANG}/");
original_file=$(echo ${template_file} | sed -e 's/\.TMP//g');
# original_file=$(echo ${template_file} | sed -e 's/\.TMP//g');
original_file=${template_file//.TMP/};
if [ "${FILE_MOVE}" -eq 0 ]; then
file=${target_folder}${template_file};
else
@@ -88,16 +92,18 @@ for language in ${language_list[*]}; do
echo "===> Write translation file ${file}";
echo ". = normal, : = escape, x = skip";
# init line [aka don't touch this file]
echo "// AUTO FILL, changes will be overwritten" > $file;
echo "// source: ${suffix}, language: ${language}" >> $file;
echo "// Translation strings in the format" >> $file;
echo "// \"Original\":\"Translated\""$'\n' >> $file;
echo "var i18n = {" >> $file;
echo "// AUTO FILL, changes will be overwritten" > "$file";
{
echo "// source: ${suffix}, language: ${language}";
echo "// Translation strings in the format";
echo "// \"Original\":\"Translated\""$'\n'
echo "var i18n = {"
} >> "$file"
# translations stuff
# read the po file
pos=0; # do we add a , for the next line
cat "${base_folder}${po_folder}${language}-${TEXTDOMAIN}.po" |
while read str; do
while read -r str; do
# echo "S: ${str}";
# skip empty
if [[ "${str}" =~ ${rx_msgid_empty} ]]; then
@@ -112,12 +118,13 @@ for language in ${language_list[*]}; do
str_source=$(echo "${str}" | sed -e "s/^msgid \"//" | sed -e "s/\"$//");
# close right side, if not last add ,
if [ "${pos}" -eq 1 ]; then
echo -n "," >> $file;
echo -n "," >> "$file";
fi;
# all " inside string need to be escaped
str_source=$(echo "${str_source}" | sed -e 's/"/\\"/g');
# str_source=$(echo "${str_source}" | sed -e 's/"/\\"/g');
str_source=${str_source//\"/\\\"}
# fix with proper layout
echo -n "\"$str_source\":\"$(TEXTDOMAINDIR=${TEXTDOMAINDIR} LANGUAGE=${language} LANG=${LANG} gettext ${TEXTDOMAIN} "${str_source}")\"" >> $file;
echo -n "\"$str_source\":\"$(TEXTDOMAINDIR=${TEXTDOMAINDIR} LANGUAGE=${language} LANG=${LANG} gettext "${TEXTDOMAIN}" "${str_source}")\"" >> "$file";
pos=1;
elif [[ "${str}" =~ ${rx_msgstr} ]]; then
# open right side (ignore)
@@ -128,8 +135,8 @@ for language in ${language_list[*]}; do
fi;
done;
echo "" >> $file;
echo "};" >> $file;
echo "" >> "$file";
echo "};" >> "$file";
echo " [DONE]";
# on no move
@@ -140,19 +147,19 @@ for language in ${language_list[*]}; do
fi;
# symlink to master file
for suffix in ${source_list[*]}; do
for suffix in "${source_list[@]}"; do
# symlink with full lang name
symlink_file[0]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANG}/" | sed -e 's/\.TMP//g');
# create second one with lang (no country) + encoding
symlink_file[1]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANGUAGE}\.${ENCODING}/" | sed -e 's/\.TMP//g');
for template_file in ${symlink_file[@]}; do
for template_file in "${symlink_file[@]}"; do
# if this is not symlink, create them
if [ ! -h "${template_file}" ]; then
echo "Create symlink: ${template_file}";
# symlik to original
cd "${target_folder}";
cd "${target_folder}" || exit;
ln -sf "${original_file}" "${template_file}";
cd - >/dev/null;
cd - >/dev/null || exit;
fi;
done;
done;

View File

@@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsConvertStringsTest extends TestCase
{
private const DATA_FOLDER = __DIR__ . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR;
/**
* Undocumented function
*
@@ -330,6 +332,52 @@ final class CoreLibsConvertStringsTest extends TestCase
\CoreLibs\Convert\Strings::stripMultiplePathSlashes($input)
);
}
/**
* Undocumented function
*
* @return array
*/
public function providerStripUTF8BomBytes(): array
{
return [
"utf8-bom" => [
"file" => "UTF8BOM.csv",
"expect" => "Asset Type,Epic,File Name\n",
],
"utf8" => [
"file" => "UTF8.csv",
"expect" => "Asset Type,Epic,File Name\n",
],
];
}
/**
* test utf8 bom remove
*
* @covers ::stripUTF8BomBytes
* @dataProvider providerStripUTF8BomBytes
* @testdox stripUTF8BomBytes $file will be $expected [$_dataName]
*
* @param string $file
* @param string $expected
* @return void
*/
public function testStripUTF8BomBytes(string $file, string $expected): void
{
// load sample file
if (!is_file(self::DATA_FOLDER . $file)) {
$this->markTestSkipped('File: ' . $file . ' could not be opened');
}
$file = file_get_contents(self::DATA_FOLDER . $file);
if ($file === false) {
$this->markTestSkipped('File: ' . $file . ' could not be read');
}
$this->assertEquals(
$expected,
\CoreLibs\Convert\Strings::stripUTF8BomBytes($file)
);
}
}
// __END__

View File

@@ -0,0 +1 @@
Asset Type,Epic,File Name
1 Asset Type Epic File Name

View File

@@ -0,0 +1 @@
Asset Type,Epic,File Name
1 Asset Type Epic File Name

View File

@@ -216,6 +216,29 @@ final class CoreLibsGetSystemTest extends TestCase
);
}
}
/**
* Undocumented function
*
* @covers ::getIpAddresses
* @testdox getIpAddresses check
*
* @return void
*/
public function testGetIpAddresses()
{
// response must have "REMOTE_ADDR" entry, others are optional
// NOTE: we have no IP addresses on command line
$this->assertTrue(
true,
"We do not have REMOTE_ADDR on command line"
);
// $this->assertContains(
// 'REMOTE_ADDR',
// array_keys(\CoreLibs\Get\System::getIpAddresses()),
// 'failed REMOTE_ADDR assert'
// );
}
}
// __END__

View File

@@ -39,6 +39,11 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'OK',
'expected' => 'ok',
],
'success' => [
'level' => 'success',
'str' => 'SUCCESS',
'expected' => 'success',
],
'info' => [
'level' => 'info',
'str' => 'INFO',
@@ -225,6 +230,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<ERROR> ERROR MESSAGE',
],
'error, logged' => [
@@ -233,6 +239,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => null,
'log_error' => true,
'log_warning' => null,
'expected' => '<ERROR> ERROR MESSAGE',
],
'error, logged, message' => [
@@ -241,14 +248,43 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ERROR MESSAGE',
'message' => 'OTHER ERROR MESSAGE',
'log_error' => true,
'log_warning' => null,
'expected' => '<ERROR> OTHER ERROR MESSAGE',
],
'warn, not logged' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<WARNING> WARNING MESSAGE',
],
'warn, logged' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => true,
'expected' => '<WARNING> WARNING MESSAGE',
],
'warn, logged, message' => [
'id' => '300',
'level' => 'warn',
'str' => 'WARNING MESSAGE',
'message' => 'OTHER WARNING MESSAGE',
'log_error' => null,
'log_warning' => true,
'expected' => '<WARNING> OTHER WARNING MESSAGE',
],
'notice' => [
'id' => '100',
'level' => 'notice',
'str' => 'NOTICE MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<NOTICE> NOTICE MESSAGE',
],
'notice, message' => [
@@ -257,6 +293,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'NOTICE MESSAGE',
'message' => 'OTHER NOTICE MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<NOTICE> OTHER NOTICE MESSAGE',
],
'crash' => [
@@ -265,6 +302,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'CRASH MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<ALERT> CRASH MESSAGE',
],
'crash, message' => [
@@ -273,6 +311,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'CRASH MESSAGE',
'message' => 'OTHER CRASH MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<ALERT> OTHER CRASH MESSAGE',
],
'abort' => [
@@ -281,6 +320,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ABORT MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<CRITICAL> ABORT MESSAGE',
],
'abort, message' => [
@@ -289,6 +329,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'ABORT MESSAGE',
'message' => 'OTHER ABORT MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<CRITICAL> OTHER ABORT MESSAGE',
],
'unknown' => [
@@ -297,6 +338,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'WRONG LEVEL MESSAGE',
'message' => null,
'log_error' => null,
'log_warning' => null,
'expected' => '<EMERGENCY> WRONG LEVEL MESSAGE',
],
'unknown, message' => [
@@ -305,6 +347,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
'str' => 'WRONG LEVEL MESSAGE',
'message' => 'OTHER WRONG LEVEL MESSAGE',
'log_error' => null,
'log_warning' => null,
'expected' => '<EMERGENCY> OTHER WRONG LEVEL MESSAGE',
],
];
@@ -321,6 +364,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
* @param string $str
* @param string|null $message
* @param bool|null $log_error
* @param bool|null $log_warning
* @param string $expected
* @return void
*/
@@ -330,6 +374,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
string $str,
?string $message,
?bool $log_error,
?bool $log_warning,
string $expected
): void {
$log = new \CoreLibs\Logging\Logging([
@@ -344,7 +389,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$level,
$str,
message: $message,
log_error: $log_error
log_error: $log_error,
log_warning: $log_warning
);
$file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) {
@@ -358,6 +404,11 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$expected,
$file_content
);
} elseif ($level == 'warn' && ($log_warning === null || $log_warning === false)) {
$this->assertStringNotContainsString(
$expected,
$file_content
);
} else {
$this->assertStringContainsString(
$expected,
@@ -377,6 +428,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
* @param string $str
* @param string|null $message
* @param bool|null $log_error
* @param bool|null $log_warning
* @param string $expected
* @return void
*/
@@ -386,6 +438,7 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
string $str,
?string $message,
?bool $log_error,
?bool $log_warning,
string $expected
): void {
$log = new \CoreLibs\Logging\Logging([
@@ -400,7 +453,8 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$level,
$str,
message: $message,
log_error: $log_error
log_error: $log_error,
log_warning: $log_warning
);
$file_content = '';
if (is_file($log->getLogFolder() . $log->getLogFile())) {
@@ -414,6 +468,11 @@ final class CoreLibsLoggingErrorMessagesTest extends TestCase
$expected,
$file_content
);
} elseif ($level == 'warn' && $log_warning === false) {
$this->assertStringNotContainsString(
$expected,
$file_content
);
} else {
$this->assertStringContainsString(
$expected,

View File

@@ -3,9 +3,19 @@
"version": "dev-master",
"description": "CoreLibs: Development package",
"type": "library",
"config": {
},
"require": {
"php": ">=8.1"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phan/phan": "^5.4",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan-strict-rules": "^1.6",
"phpunit/phpunit": "^9"
},
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
}
}
}

20
composer.lock generated
View File

@@ -1,20 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3c37bd2878b371840fc0d7d4a249ea4c",
"packages": [],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=8.1"
},
"platform-dev": [],
"plugin-api-version": "2.3.0"
}

View File

@@ -3,9 +3,23 @@ includes:
- phpstan-conditional.php
parameters:
tmpDir: %currentWorkingDirectory%/tmp/phpstan-corelibs
level: 8 # max is now 9
level: 9 # max is now 9
checkMissingCallableSignature: true
treatPhpDocTypesAsCertain: false
strictRules:
allRules: false
disallowedLooseComparison: false
booleansInConditions: false
uselessCast: true
requireParentConstructorCall: false
disallowedConstructs: false
overwriteVariablesWithLoop: false
closureUsesThis: false
matchingInheritedMethodNames: false
numericOperandsInArithmeticOperators: false
strictCalls: false
switchConditionsMatchingType: false
noVariableVariables: false
paths:
- %currentWorkingDirectory%/www
bootstrapFiles:
@@ -35,13 +49,15 @@ parameters:
- www/log
- www/media
- www/tmp
# File uploader
- www/lib/FileUpload
# ignore composer
- www/vendor
# ignore errores with
ignoreErrors:
- # in the class_test tree we allow deprecated calls
message: "#^Call to deprecated method #"
path: %currentWorkingDirectory%/www/admin/class_test.*.php
# - # in the class_test tree we allow deprecated calls
# message: "#^Call to deprecated method #"
# path: %currentWorkingDirectory%/www/admin/class_test.*.php
# - '#Expression in empty\(\) is always falsy.#'
# -
# message: '#Reflection error: [a-zA-Z0-9\\_]+ not found.#'

View File

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

View File

@@ -1 +0,0 @@
/home/clemens/.phive/phars/php-cs-fixer-3.57.2.phar

View File

@@ -1 +0,0 @@
/home/clemens/.phive/phars/phpdocumentor-3.4.3.phar

View File

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

View File

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

View File

@@ -1 +0,0 @@
/home/clemens/.phive/phars/phpdox-0.12.0.phar

View File

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

View File

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

View File

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

25
vendor/autoload.php vendored
View File

@@ -1,25 +0,0 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitdd705c6e8ab22e0d642372dec7767718::getLoader();

View File

@@ -1,581 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
(self::$includeFile)($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
private static function initializeIncludeClosure(): void
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = static function($file) {
include $file;
};
}
}

View File

@@ -1,352 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @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<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = require __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
$installed[] = self::$installed;
return $installed;
}
}

View File

@@ -1,21 +0,0 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,10 +0,0 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
);

View File

@@ -1,9 +0,0 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -1,9 +0,0 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -1,38 +0,0 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitdd705c6e8ab22e0d642372dec7767718
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInitdd705c6e8ab22e0d642372dec7767718', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitdd705c6e8ab22e0d642372dec7767718', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitdd705c6e8ab22e0d642372dec7767718::getInitializer($loader));
$loader->register(true);
return $loader;
}
}

View File

@@ -1,20 +0,0 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitdd705c6e8ab22e0d642372dec7767718
{
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->classMap = ComposerStaticInitdd705c6e8ab22e0d642372dec7767718::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -1,5 +0,0 @@
{
"packages": [],
"dev": true,
"dev-package-names": []
}

View File

@@ -1,23 +0,0 @@
<?php return array(
'root' => array(
'name' => 'egrajp/development-corelibs-dev',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => NULL,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => true,
),
'versions' => array(
'egrajp/development-corelibs-dev' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => NULL,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@@ -1,26 +0,0 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 80100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
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
);
}

View File

@@ -55,7 +55,25 @@ print '<div><h1>' . $PAGE_NAME . '</h1></div>';
print "SETACL[]: <br>";
$backend->setACL(['EMPTY' => 'EMPTY']);
print "ADBEDITLOG: <br>";
$backend->adbEditLog('CLASSTEST-ADMIN', 'Some info string');
$backend->adbEditLog('CLASSTEST-ADMIN-BINARY', 'Some info string', 'BINARY');
$backend->adbEditLog('CLASSTEST-ADMIN-ZLIB', 'Some info string', 'ZLIB');
$backend->adbEditLog('CLASSTEST-ADMIN-SERIAL', 'Some info string', 'SERIAL');
$backend->adbEditLog('CLASSTEST-ADMIN-INVALID', 'Some info string', 'INVALID');
// test with various
$backend->action = 'TEST ACTION';
$backend->action_id = 'TEST ACTION ID';
$backend->action_yes = 'TEST ACTION YES';
$backend->action_flag = 'TEST ACTION FLAG';
$backend->action_menu = 'TEST ACTION MENU';
$backend->action_loaded = 'TEST ACTION LOADED';
$backend->action_value = 'TEST ACTION VALUE';
$backend->action_type = 'TEST ACTION TYPE';
$backend->action_error = 'TEST ACTION ERROR';
$backend->adbEditLog('CLASSTEST-ADMIN-JSON', [
"_GET" => $_GET,
"_POST" => $_POST,
], 'JSON');
print "ADBTOPMENU(0): " . Support::printAr($backend->adbTopMenu(CONTENT_PATH)) . "<br>";
print "ADBMSG: <br>";
$backend->adbMsg('info', 'Message: %1$d', [1]);

View File

@@ -45,6 +45,8 @@ $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');
$em->setErrorMsg('123', 'error', 'msg this is bad, logged always', log_error:true);
$em->setErrorMsg('123', 'error', 'msg this is bad, never logged', log_error:false);
$em->setErrorMsg('500', 'warning', 'This is perhaps not super good, logged_always', log_warning:true);
$em->setErrorMsg('500', 'warning', 'This is perhaps not super good, logged_never', log_warning:false);
$em->setErrorMsg('1000', 'info', 'This is good');
$em->setErrorMsg('9999', 'abort', 'BAD: This is critical (abort)');
$em->setErrorMsg('10-1000', 'wrong', 'Wrong level: This is emergency');
@@ -59,6 +61,8 @@ print "ErrorsIds: <pre>" . $log->prAr($em->getErrorIds()) . "</pre>";
print "Errors: <pre>" . $log->prAr($em->getErrorMsg()) . "</pre>";
print "JumpTargets: <pre>" . $log->prAr($em->getJumpTarget()) . "</pre>";
print "IS info > ok: " . ml::fromName('info')->isHigherThan(ml::ok) . "<br>";
print "</body></html>";
$log->debug('[END]', '==========================================>');

View File

@@ -42,6 +42,7 @@ print '<div><h1>' . $PAGE_NAME . '</h1></div>';
$string = "Something < = > Other <br> Next line and Quotes '\"";
echo "String: <pre>$string</pre><br>";
$log->debug('HTMLENT', Html::htmlent($string));
print "HTMLENT: " . Html::htmlent($string) . ": " . $_html->htmlent($string) . " (" . htmlentities($string) . ")<br>";
print "REMOVELB: " . Html::htmlent($string) . ": " . $_html->removeLB($string) . "<br>";
$date_str = [2021, 5, 1, 11, 10];

View File

@@ -178,7 +178,7 @@ $log->debug('SOME MARK', 'Some error output');
print "EDIT ACCESS ID: " . $backend->edit_access_id . "<br>";
if (is_object($login)) {
// print "ACL: <br>".$backend->print_ar($login->loginGetAcl())."<br>";
$log->debug('ACL', "ACL: " . \CoreLibs\Debug\Support::dumpVar($login->loginGetAcl()));
// $log->debug('ACL', "ACL: " . \CoreLibs\Debug\Support::dumpVar($login->loginGetAcl()));
// print "DEFAULT ACL: <br>".$backend->print_ar($login->default_acl_list)."<br>";
// print "DEFAULT ACL: <br>".$backend->print_ar($login->default_acl_list)."<br>";
// $result = array_flip(

View File

@@ -41,7 +41,7 @@ print "GETPAGENAME(0): " . System::getPageName() . "<br>";
print "GETPAGENAME(1): " . System::getPageName(System::NO_EXTENSION) . "<br>";
print "GETPAGENAME(2): " . System::getPageName(System::FULL_PATH) . "<br>";
print "System::getPageNameArray():<br>";
print "GETPAGENAMEARRAY: " . \CoreLibs\Debug\Support::printAr(System::getPageNameArray()) . "<br>";
print "GETPAGENAMEARRAY: " . DgS::printAr(System::getPageNameArray()) . "<br>";
// seting errro codes file upload
print "System::fileUploadErrorMessage():<br>";
print "FILEUPLOADERRORMESSAGE(): " . System::fileUploadErrorMessage(-1) . "<br>";
@@ -51,4 +51,6 @@ print "FILEUPLOADERRORMESSAGE(UPLOAD_ERR_CANT_WRITE): "
print "System::checkCLI():<br>";
print "Are we in an CLI: " . (System::checkCLI() ? 'Yes' : 'No') . "<br>";
print "Get Addresses: " . DgS::printAr(System::getIpAddresses()) . "<br>";
print "</body></html>";

View File

@@ -1,7 +1,7 @@
/* general edit javascript */
/* jquery version */
/* jshint esversion: 6 */
/* jshint esversion: 11 */
/* global i18n */
@@ -931,7 +931,7 @@ function rel(base) // eslint-disable-line no-unused-vars
/**
* searches and removes style from css array
* @param {Object} _element element to work one
* @param {String css style sheet to remove (name)
* @param {String} css style sheet to remove (name)
* @return {Object} returns full element
*/
function rcssel(_element, css)

12
www/composer.lock generated
View File

@@ -38,16 +38,16 @@
},
{
"name": "gullevek/dotenv",
"version": "v2.0.8",
"version": "v2.1.0",
"source": {
"type": "git",
"url": "https://github.com/gullevek/dotEnv.git",
"reference": "e29f9fcd8853a09bb89b0eb8ee555b754ecee36e"
"reference": "b9feacaded4e48effff9da7d1173752aef3dc27f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/gullevek/dotEnv/zipball/e29f9fcd8853a09bb89b0eb8ee555b754ecee36e",
"reference": "e29f9fcd8853a09bb89b0eb8ee555b754ecee36e",
"url": "https://api.github.com/repos/gullevek/dotEnv/zipball/b9feacaded4e48effff9da7d1173752aef3dc27f",
"reference": "b9feacaded4e48effff9da7d1173752aef3dc27f",
"shasum": ""
},
"require": {
@@ -86,9 +86,9 @@
],
"support": {
"issues": "https://github.com/gullevek/dotEnv/issues",
"source": "https://github.com/gullevek/dotEnv/tree/v2.0.8"
"source": "https://github.com/gullevek/dotEnv/tree/v2.1.0"
},
"time": "2023-03-03T00:32:02+00:00"
"time": "2024-08-21T02:41:15+00:00"
},
{
"name": "psr/log",

View File

@@ -24,35 +24,29 @@ declare(strict_types=1);
// ];
$__LOCAL_CONFIG = [
// db config selection
'db_host' => 'test',
// other db connections
// 'db_host_target' => '',
// 'db_host_other' => '',
// location flagging (test/dev/live) for debug output
'location' => 'test',
// show DEBUG override
'debug_level' => 'debug',
// site locale
'site_locale' => 'en_US.UTF-8',
// site encoding
'site_encoding' => 'UTF-8',
// enable/disable login override
'login_enabled' => true
];
// each host has a different db_host
$SITE_CONFIG = [
// development host
'soba.tokyo.tequila.jp' => [
// db config selection
'db_host' => 'test',
// other db connections
// 'db_host_target' => '',
// 'db_host_other' => '',
// location flagging (test/dev/live) for debug output
'location' => 'test',
// show DEBUG override
'debug_level' => 'debug',
// site locale
'site_locale' => 'en_US.UTF-8',
// site encoding
'site_encoding' => 'UTF-8',
// enable/disable login override
'login_enabled' => true
],
'soba.tokyo.tequila.jp' => $__LOCAL_CONFIG,
// 'other.host.com' => $__LOCAL_CONFIG
'soba.egplusww.jp' => $__LOCAL_CONFIG,
'soba-dev.tequila.jp' => $__LOCAL_CONFIG,
'soba.tequila.jp' => $__LOCAL_CONFIG,
'soba.teq.jp' => $__LOCAL_CONFIG,

View File

@@ -205,11 +205,13 @@ if (
}
// set SSL on
$is_secure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
$is_secure = true;
} elseif (
!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ||
!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on'
!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ||
!empty($_SERVER['HTTP_X_FORWARDED_SSL']) &&
$_SERVER['HTTP_X_FORWARDED_SSL'] === 'on'
) {
$is_secure = true;
}

View File

@@ -1,4 +1,4 @@
<?php
<?php // phpcs:ignore PSR1.Files.SideEffects
/********************************************************************
* AUTHOR: Clemens Schwaighofer
@@ -11,6 +11,20 @@
declare(strict_types=1);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// File and Folder paths
// ID is TARGET (first array element)
/*$PATHS = [

View File

@@ -1,4 +1,4 @@
<?php // phpcs:ignore warning
<?php // phpcs:ignore PSR1.Files.SideEffects
/********************************************************************
* AUTHOR: Clemens Schwaighofer
@@ -53,19 +53,6 @@ for (
\gullevek\dotEnv\DotEnv::readEnvFile(
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// load master config file that loads all other config files
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
break;

View File

@@ -31,6 +31,8 @@ declare(strict_types=1);
namespace CoreLibs\Admin;
use CoreLibs\Convert\Json;
class Backend
{
// page name
@@ -42,7 +44,7 @@ class Backend
/** @var array<string> */
public array $action_list = [
'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag',
'action_menu', 'action_value', 'action_error', 'action_loaded'
'action_menu', 'action_value', 'action_type', 'action_error', 'action_loaded'
];
/** @var string */
public string $action;
@@ -61,20 +63,31 @@ class Backend
/** @var string */
public string $action_value;
/** @var string */
public string $action_type;
/** @var string */
public string $action_error;
// ACL array variable if we want to set acl data from outisde
/** @var array<mixed> */
public array $acl = [];
/** @var int */
public int $default_acl;
// queue key
/** @var string */
public string $queue_key;
/** @var array<string> list of allowed types for edit log write */
private const WRITE_TYPES = ['BINARY', 'BZIP2', 'LZIP', 'STRING', 'SERIAL', 'JSON'];
/** @var array<string> list of available write types for log */
private array $write_types_available = [];
// the current active edit access id
/** @var int|null */
public int|null $edit_access_id;
/** @var string */
public string $page_name;
// error/warning/info messages
/** @var array<mixed> */
public array $messages = [];
@@ -84,6 +97,7 @@ class Backend
public bool $warning = false;
/** @var bool */
public bool $info = false;
// internal lang & encoding vars
/** @var string */
public string $lang_dir = '';
@@ -95,6 +109,7 @@ class Backend
public string $domain;
/** @var string */
public string $encoding;
/** @var \CoreLibs\Logging\Logging logger */
public \CoreLibs\Logging\Logging $log;
/** @var \CoreLibs\DB\IO database */
@@ -103,6 +118,7 @@ class Backend
public \CoreLibs\Language\L10n $l;
/** @var \CoreLibs\Create\Session session class */
public \CoreLibs\Create\Session $session;
// smarty publics [end processing in smarty class]
/** @var array<mixed> */
public array $DATA = [];
@@ -117,18 +133,20 @@ class Backend
/**
* main class constructor
*
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param int|null $set_default_acl_level Default ACL level
* @param \CoreLibs\DB\IO $db Database connection class
* @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class
* @param \CoreLibs\Language\L10n $l10n l10n language class
* @param int|null $set_default_acl_level [default=null] Default ACL level
* @param bool $init_action_vars [default=true] If the action vars should be set
*/
public function __construct(
\CoreLibs\DB\IO $db,
\CoreLibs\Logging\Logging $log,
\CoreLibs\Create\Session $session,
\CoreLibs\Language\L10n $l10n,
?int $set_default_acl_level = null
?int $set_default_acl_level = null,
bool $init_action_vars = true
) {
// attach db class
$this->db = $db;
@@ -151,9 +169,9 @@ class Backend
// set the page name
$this->page_name = \CoreLibs\Get\System::getPageName();
// set the action ids
foreach ($this->action_list as $_action) {
$this->$_action = $_POST[$_action] ?? '';
// NOTE: if any of the "action" vars are used somewhere, it is recommended to NOT set them here
if ($init_action_vars) {
$this->adbSetActionVars();
}
if ($set_default_acl_level === null) {
@@ -170,9 +188,12 @@ class Backend
}
// queue key
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action)) {
if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action ?? '')) {
$this->queue_key = \CoreLibs\Create\RandomKey::randomKeyGen(3);
}
// check what edit log data write types are allowed
$this->adbSetEditLogWriteTypeAvailable();
}
/**
@@ -183,7 +204,26 @@ class Backend
// NO OP
}
// PUBLIC METHODS |=================================================>
// MARK: PRIVATE METHODS
/**
* set the write types that are allowed
*
* @return void
*/
private function adbSetEditLogWriteTypeAvailable()
{
// check what edit log data write types are allowed
$this->write_types_available = self::WRITE_TYPES;
if (!function_exists('bzcompress')) {
$this->write_types_available = array_diff($this->write_types_available, ['BINARY', 'BZIP']);
}
if (!function_exists('gzcompress')) {
$this->write_types_available = array_diff($this->write_types_available, ['LZIP']);
}
}
// MARK: PUBLIC METHODS |=================================================>
/**
* set internal ACL from login ACL
@@ -195,30 +235,95 @@ class Backend
$this->acl = $acl;
}
/**
* Return current set ACL
*
* @return array<mixed>
*/
public function adbGetAcl(): array
{
return $this->acl;
}
/**
* Set _POST action vars if needed
*
* @return void
*/
public function adbSetActionVars()
{
// set the action ids
foreach ($this->action_list as $_action) {
$this->$_action = $_POST[$_action] ?? '';
}
}
/**
* writes all action vars plus other info into edit_log table
*
* @param string $event any kind of event description,
* @param string|array<mixed> $data any kind of data related to that event
* @param string $write_type write type can bei STRING or BINARY
* @param string|null $db_schema override target schema
* @param string $event [default=''] any kind of event description,
* @param string|array<mixed> $data [default=''] any kind of data related to that event
* @param string $write_type [default=JSON] write type can be
* JSON, STRING/SERIEAL, BINARY/BZIP or ZLIB
* @param string|null $db_schema [default=null] override target schema
* @return void
*/
public function adbEditLog(
string $event = '',
string|array $data = '',
string $write_type = 'STRING',
string $write_type = 'JSON',
?string $db_schema = null
): void {
$data_binary = '';
$data_write = '';
if ($write_type == 'BINARY') {
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
$data_write = 'see bzip compressed data_binary field';
// check if write type is valid, if not fallback to JSON
if (!in_array($write_type, $this->write_types_available)) {
$this->log->warning('Write type not in allowed array, fallback to JSON', context:[
"write_type" => $write_type,
"write_list" => $this->write_types_available,
]);
$write_type = 'JSON';
}
if ($write_type == 'STRING') {
$data_binary = '';
$data_write = $this->db->dbEscapeString(serialize($data));
switch ($write_type) {
case 'BINARY':
case 'BZIP':
$data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data)));
$data_write = Json::jsonConvertArrayTo([
'type' => 'BZIP',
'message' => 'see bzip compressed data_binary field'
]);
break;
case 'ZLIB':
$data_binary = $this->db->dbEscapeBytea((string)gzcompress(serialize($data)));
$data_write = Json::jsonConvertArrayTo([
'type' => 'ZLIB',
'message' => 'see zlib compressed data_binary field'
]);
break;
case 'STRING':
case 'SERIAL':
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
'type' => 'SERIAL',
'message' => 'see serial string data field'
]));
$data_write = serialize($data);
break;
case 'JSON':
$data_binary = $this->db->dbEscapeBytea(Json::jsonConvertArrayTo([
'type' => 'JSON',
'message' => 'see json string data field'
]));
// must be converted to array
if (!is_array($data)) {
$data = ["data" => $data];
}
$data_write = Json::jsonConvertArrayTo($data);
break;
default:
$this->log->alert('Invalid type for data compression was set', context:[
"write_type" => $write_type
]);
break;
}
/** @var string $DB_SCHEMA check schema */
@@ -228,44 +333,62 @@ class Backend
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
$q = "INSERT INTO " . $DB_SCHEMA . ".edit_log "
. "(euid, event_date, event, data, data_binary, page, "
. "ip, user_agent, referer, script_name, query_string, server_name, http_host, "
. "http_accept, http_accept_charset, http_accept_encoding, session_id, "
. "action, action_id, action_yes, action_flag, action_menu, action_loaded, action_value, action_error) "
. "VALUES "
. "(" . $this->db->dbEscapeString(isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] :
'NULL')
. ", "
. "NOW(), "
. "'" . $this->db->dbEscapeString((string)$event) . "', "
. "'" . $data_write . "', "
. "'" . $data_binary . "', "
. "'" . $this->db->dbEscapeString((string)$this->page_name) . "', "
. "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['SERVER_NAME'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_HOST'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '') . "', "
. "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '') . "', "
. ($this->session->getSessionId() === false ?
"NULL" :
"'" . $this->session->getSessionId() . "'")
. ", "
. "'" . $this->db->dbEscapeString($this->action) . "', "
. "'" . $this->db->dbEscapeString($this->action_id) . "', "
. "'" . $this->db->dbEscapeString($this->action_yes) . "', "
. "'" . $this->db->dbEscapeString($this->action_flag) . "', "
. "'" . $this->db->dbEscapeString($this->action_menu) . "', "
. "'" . $this->db->dbEscapeString($this->action_loaded) . "', "
. "'" . $this->db->dbEscapeString($this->action_value) . "', "
. "'" . $this->db->dbEscapeString($this->action_error) . "')";
$this->db->dbExec($q, 'NULL');
$q = <<<SQL
INSERT INTO {DB_SCHEMA}.edit_log (
euid, event_date, event, data, data_binary, page,
ip, user_agent, referer, script_name, query_string, server_name, http_host,
http_accept, http_accept_charset, http_accept_encoding, session_id,
action, action_id, action_yes, action_flag, action_menu, action_loaded,
action_value, action_type, action_error
) VALUES (
$1, NOW(), $2, $3, $4, $5,
$6, $7, $8, $9, $10, $11, $12,
$13, $14, $15, $16,
$17, $18, $19, $20, $21, $22,
$23, $24, $25
)
SQL;
$this->db->dbExecParams(
str_replace(
['{DB_SCHEMA}'],
[$DB_SCHEMA],
$q
),
[
// row 1
isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] : null,
(string)$event,
$data_write,
$data_binary,
(string)$this->page_name,
// row 2
$_SERVER["REMOTE_ADDR"] ?? '',
$_SERVER['HTTP_USER_AGENT'] ?? '',
$_SERVER['HTTP_REFERER'] ?? '',
$_SERVER['SCRIPT_FILENAME'] ?? '',
$_SERVER['QUERY_STRING'] ?? '',
$_SERVER['SERVER_NAME'] ?? '',
$_SERVER['HTTP_HOST'] ?? '',
// row 3
$_SERVER['HTTP_ACCEPT'] ?? '',
$_SERVER['HTTP_ACCEPT_CHARSET'] ?? '',
$_SERVER['HTTP_ACCEPT_ENCODING'] ?? '',
$this->session->getSessionId() !== false ?
$this->session->getSessionId() : null,
// row 4
$this->action ?? '',
$this->action_id ?? '',
$this->action_yes ?? '',
$this->action_flag ?? '',
$this->action_menu ?? '',
$this->action_loaded ?? '',
$this->action_value ?? '',
$this->action_type ?? '',
$this->action_error ?? '',
],
'NULL'
);
}
/**
@@ -504,9 +627,9 @@ class Backend
string $data,
string $key_name,
string $key_value,
string $associate = null,
string $file = null,
string $db_schema = null,
?string $associate = null,
?string $file = null,
?string $db_schema = null,
): void {
/** @var string $DB_SCHEMA check schema */
$DB_SCHEMA = 'public';
@@ -515,16 +638,30 @@ class Backend
} elseif (!empty($this->db->dbGetSchema())) {
$DB_SCHEMA = $this->db->dbGetSchema();
}
$q = "INSERT INTO " . $DB_SCHEMA . ".live_queue ("
. "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file"
. ") VALUES ("
. "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', "
. "'" . $this->db->dbEscapeString($key_name) . "', '" . $this->db->dbEscapeString($type) . "', "
. "'" . $this->db->dbEscapeString($target) . "', '" . $this->db->dbEscapeString($data) . "', "
. "'" . $this->queue_key . "', '" . $this->action . "', "
. "'" . $this->db->dbEscapeString((string)$associate) . "', "
. "'" . $this->db->dbEscapeString((string)$file) . "')";
$this->db->dbExec($q);
$q = <<<SQL
INSERT INTO {DB_SCHEMA}.live_queue (
queue_key, key_value, key_name, type,
target, data, group_key, action, associate, file
) VALUES (
$1, $2, $3, $4,
$5, $6, $7, $8, $9, $10
)
SQL;
// $this->db->dbExec($q);
$this->db->dbExecParams(
str_replace(
['{DB_SCHEMA}'],
[$DB_SCHEMA],
$q
),
[
$queue_key, $key_value,
$key_name, $type,
$target, $data,
$this->queue_key, $this->action,
(string)$associate, (string)$file
]
);
}
/**

View File

@@ -90,7 +90,7 @@ class Basic
* @deprecated DO NOT USE Class\Basic anymore. Use dedicated logger and sub classes
*/
public function __construct(
\CoreLibs\Logging\Logging $log = null,
?\CoreLibs\Logging\Logging $log = null,
?string $session_name = null
) {
trigger_error('Class \CoreLibs\Basic is deprected', E_USER_DEPRECATED);

View File

@@ -509,6 +509,22 @@ class ArrayHandler
}
return $array;
}
/**
* Remove entries from a simple array, will not keep key order
*
* any array content is allowed
*
* https://stackoverflow.com/a/369608
*
* @param array<mixed> $array Array where elements are located
* @param array<mixed> $remove Elements to remove
* @return array<mixed> Array with $remove elements removed
*/
public static function arrayRemoveEntry(array $array, array $remove): array
{
return array_diff($array, $remove);
}
}
// __END__

View File

@@ -52,7 +52,7 @@ class SetVarTypeMain
*/
protected static function makeStrMain(
mixed $val,
string $default = null,
?string $default = null,
bool $to_null = false
): ?string {
// int/float/string/bool/null, everything else is ignored
@@ -113,7 +113,7 @@ class SetVarTypeMain
*/
protected static function makeIntMain(
mixed $val,
int $default = null,
?int $default = null,
bool $to_null = false
): ?int {
// if we can filter it to a valid int, we can convert it
@@ -167,7 +167,7 @@ class SetVarTypeMain
*/
protected static function makeFloatMain(
mixed $val,
float $default = null,
?float $default = null,
bool $to_null = false
): ?float {
if (

View File

@@ -35,7 +35,7 @@ class SetVarTypeNull extends Extends\SetVarTypeMain
* @param string|null $default Default override value
* @return string|null Input value as string or default as string/null
*/
public static function makeStr(mixed $val, string $default = null): ?string
public static function makeStr(mixed $val, ?string $default = null): ?string
{
return SetVarTypeMain::makeStrMain($val, $default, true);
}
@@ -60,7 +60,7 @@ class SetVarTypeNull extends Extends\SetVarTypeMain
* @param int|null $default Default override value
* @return int|null Input value as int or default as int/null
*/
public static function makeInt(mixed $val, int $default = null): ?int
public static function makeInt(mixed $val, ?int $default = null): ?int
{
return SetVarTypeMain::makeIntMain($val, $default, true);
}
@@ -84,7 +84,7 @@ class SetVarTypeNull extends Extends\SetVarTypeMain
* @param float|null $default Default override value
* @return float|null Input value as float or default as float/null
*/
public static function makeFloat(mixed $val, float $default = null): ?float
public static function makeFloat(mixed $val, ?float $default = null): ?float
{
return SetVarTypeMain::makeFloatMain($val, $default, true);
}

View File

@@ -134,6 +134,18 @@ class Strings
$path
) ?? $path;
}
/**
* Remove UTF8 BOM Byte string from line
* Note: this is often found in CSV files exported from Excel at the first row, first element
*
* @param string $text
* @return string
*/
public static function stripUTF8BomBytes(string $text): string
{
return trim($text, pack('H*', 'EFBBBF'));
}
}
// __END__

View File

@@ -823,6 +823,10 @@ class IO
);
break;
default:
// no context on DB_INFO
if ($id == 'DB_INFO') {
$context = [];
}
// used named arguments so we can easy change the order of debug
$this->log->debug(
group_id: $debug_id,
@@ -1814,14 +1818,13 @@ class IO
$html_tags = ['{b}', '{/b}', '{br}'];
$replace_html = ['<b>', '</b>', '<br>'];
$replace_text = ['', '', ' **** '];
$string = '';
$string .= '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} ';
$string .= 'with schema {b}\'' . $this->db_schema . '\'{/b} ';
$string .= 'as user {b}\'' . $this->db_user . '\'{/b} ';
$string .= 'at host {b}\'' . $this->db_host . '\'{/b} ';
$string .= 'on port {b}\'' . $this->db_port . '\'{/b} ';
$string .= 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}';
$string .= '{b}-DB-info->{/b} DB IO Class debug output: {b}'
$string = '{b}-DB-info->{/b} Connected to db {b}\'' . $this->db_name . '\'{/b} '
. 'with schema {b}\'' . $this->db_schema . '\'{/b} '
. 'as user {b}\'' . $this->db_user . '\'{/b} '
. 'at host {b}\'' . $this->db_host . '\'{/b} '
. 'on port {b}\'' . $this->db_port . '\'{/b} '
. 'with ssl mode {b}\'' . $this->db_ssl . '\'{/b}{br}'
. '{b}-DB-info->{/b} DB IO Class debug output: {b}'
. ($this->dbGetDebug() ? 'Yes' : 'No') . '{/b}';
if ($log === true) {
// if debug, remove / change b
@@ -1829,7 +1832,7 @@ class IO
$html_tags,
$replace_text,
$string
), 'dbInfo');
), 'DB_INFO');
} else {
$string = $string . '{br}';
}
@@ -1896,7 +1899,12 @@ class IO
$matches = [];
// compare has =, >, < prefix, and gets stripped
// if the rest is not X.Y format then error
preg_match("/^([<>=]{1,})(\d{1,})\.(\d{1,})/", $compare, $matches);
if (!preg_match("/^([<>=]{1,})(\d{1,})\.(\d{1,})/", $compare, $matches)) {
$this->log->error('Could not regex match compare version string', [
"compare" => $compare
]);
return false;
}
$compare = $matches[1];
$to_master = $matches[2];
$to_minor = $matches[3];
@@ -1908,11 +1916,18 @@ class IO
}
// db_version can return X.Y.Z
// we only compare the first two
preg_match(
"/^(\d{1,})\.(\d{1,})\.?(\d{1,})?/",
$this->dbVersion(),
$matches
);
if (
!preg_match(
"/^(\d{1,})\.(\d{1,})\.?(\d{1,})?/",
$this->dbVersion(),
$matches
)
) {
$this->log->error('Could not regex match dbVersion string', [
"dbVersion" => $this->dbVersion()
]);
return false;
}
$master = $matches[1];
$minor = $matches[2];
$version = $master . ($minor < 10 ? '0' : '') . $minor;
@@ -1973,7 +1988,7 @@ class IO
if (is_array($array)) {
$this->nbsp = '';
$string .= $this->__printArray($array);
$this->__dbDebugMessage('db', $string, 'dbDumpData');
$this->__dbDebugMessage('db', $string, 'DB_INFO');
}
return $string;
}
@@ -2402,7 +2417,7 @@ class IO
// flag if we have cache data stored at the moment
'cached' => false,
// when fetch array or cache read returns false
// in loop read that means dbReturn retuns false without erro
// in loop read that means dbReturn retuns false without error
'finished' => false,
// read from cache/db (pos == rows)
'read_finished' => false,

View File

@@ -116,6 +116,29 @@ class System
3
) === 'cli' ? true : false;
}
/**
* Collect all IP addresses
* REMOTE_ADDR, HTTP_X_FORWARD_FOR, CLIENT_IP
* and retuns them in an array with index of io source
* if address source has addresses with "," will add "-array" with these as array block
*
* @return array<string,string|array<string>>
*/
public static function getIpAddresses(): array
{
$ip_addr = [];
foreach (['REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP'] as $_ip_source) {
if (!empty($_SERVER[$_ip_source])) {
$ip_addr[$_ip_source] = $_SERVER[$_ip_source];
// same level as ARRAY IF there is a , inside
if (strstr($_SERVER[$_ip_source], ',') !== false) {
$ip_addr[$_ip_source . '-array'] = explode(',', $_SERVER[$_ip_source]);
}
}
}
return $ip_addr;
}
}
// __END__

View File

@@ -128,7 +128,7 @@ class GetLocale
$matches
)
) {
$lang = ($matches['lang'] ?? 'en')
$lang = $matches['lang']
// add country only if set
. (!empty($matches['country']) ? '_' . $matches['country'] : '');
} else {
@@ -235,7 +235,7 @@ class GetLocale
$matches
)
) {
$lang = ($matches['lang'] ?? 'en')
$lang = $matches['lang']
// add country only if set
. (!empty($matches['country']) ? '_' . $matches['country'] : '');
} else {

View File

@@ -24,16 +24,20 @@ class ErrorMessage
/** @var bool $log_error global flag to log error level message */
private bool $log_error = false;
/** @var bool $log_warning global flat to log warning level messages */
private bool $log_warning = false;
/**
* init ErrorMessage
*
* @param \CoreLibs\Logging\Logging $log
* @param null|bool $log_error [=null], defaults to false if log is not level debug
* @param null|bool $log_warning [=null], defaults to false if log is not level debug
*/
public function __construct(
\CoreLibs\Logging\Logging $log,
?bool $log_error = null
?bool $log_error = null,
?bool $log_warning = null
) {
$this->log = $log;
// if log default logging is debug then log_error is default set to true
@@ -43,6 +47,13 @@ class ErrorMessage
$log_error = $log_error ?? false;
}
$this->log_error = $log_error;
// if log default logging is debug then log_warning is default set to true
if ($this->log->loggingLevelIsDebug() && $log_warning === null) {
$log_warning = true;
} else {
$log_warning = $log_warning ?? false;
}
$this->log_warning = $log_warning;
}
/**
@@ -81,6 +92,8 @@ class ErrorMessage
* @param array<mixed> $context Additionl info for abort/crash messages
* @param bool|null $log_error [=null] log level 'error' to error, if null use global,
* else set for this call only
* @param bool|null $log_warning [=null] log level 'warning' to warning, if null use global,
* else set for this call only
*/
public function setErrorMsg(
string $error_id,
@@ -93,10 +106,14 @@ class ErrorMessage
?string $message = null,
array $context = [],
?bool $log_error = null,
?bool $log_warning = null,
): void {
if ($log_error === null) {
$log_error = $this->log_error;
}
if ($log_warning === null) {
$log_warning = $this->log_warning;
}
$original_level = $level;
$level = MessageLevel::fromName($level)->name;
// if not string set, write message string if set, else level/error id
@@ -121,6 +138,14 @@ class ErrorMessage
'level' => $original_level,
], $context));
break;
case 'warn':
if ($log_warning) {
$this->log->warning($message ?? $str, array_merge([
'id' => $error_id,
'level' => $original_level,
], $context));
}
break;
case 'error':
if ($log_error) {
$this->log->error($message ?? $str, array_merge([
@@ -169,6 +194,8 @@ class ErrorMessage
* @param array<mixed> $context Additionl info for abort/crash messages
* @param bool|null $log_error [=null] log level 'error' to error, if null use global,
* else set for this call only
* @param bool|null $log_warning [=null] log level 'warning' to warning, if null use global,
* else set for this call only
*/
public function setMessage(
string $level,
@@ -181,6 +208,7 @@ class ErrorMessage
?string $message = null,
array $context = [],
?bool $log_error = null,
?bool $log_warning = null,
): void {
$this->setErrorMsg(
$error_id ?? '',
@@ -192,7 +220,8 @@ class ErrorMessage
$jump_target,
$message,
$context,
$log_error
$log_error,
$log_warning
);
}
@@ -314,6 +343,27 @@ class ErrorMessage
{
return $this->log_error;
}
/**
* Set the log warning flag
*
* @param bool $flag True to log level warning too, False for do not (Default)
* @return void
*/
public function setFlagLogWarning(bool $flag): void
{
$this->log_warning = $flag;
}
/**
* Get the current log error flag
*
* @return bool
*/
public function getFlagLogWarning(): bool
{
return $this->log_warning;
}
}
// __END__

View File

@@ -14,6 +14,7 @@ namespace CoreLibs\Logging\Logger;
enum MessageLevel: int
{
case ok = 100;
case success = 150; // special for file uploads
case info = 200;
case notice = 250;
case warn = 300;
@@ -30,6 +31,7 @@ enum MessageLevel: int
{
return match (strtolower($name)) {
'ok' => self::ok,
'success' => self::success,
'info' => self::info,
'notice' => self::notice,
'warn', 'warning' => self::warn,

View File

@@ -194,13 +194,13 @@ class Elements
"/(mailto:)?(\>)?\b([\w\.-]+)@([\w\.\-]+)\.([a-zA-Z]{2,4})\b(\|([^\||^#]+)(#([^\|]+))?\|)?/",
function ($matches) {
return self::createEmail(
$matches[1] ?? '',
$matches[2] ?? '',
$matches[3] ?? '',
$matches[4] ?? '',
$matches[5] ?? '',
$matches[1],
$matches[2],
$matches[3],
$matches[4],
$matches[5],
$matches[7] ?? '',
$matches[9] ?? ''
$matches[9] ?? '',
);
},
$output

View File

@@ -19,7 +19,7 @@ use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
class Block
{
/**
* Undocumented function
* Create Element
*
* @param string $tag
* @param string $id
@@ -86,7 +86,7 @@ class Block
}
/**
* Undocumented function
* Add multiple elements to the base element
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $base
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} ...$attach
@@ -101,7 +101,7 @@ class Block
}
/**
* Undocumented function
* Add multiple sub elements to the base element
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $sub
@@ -117,7 +117,7 @@ class Block
}
/**
* Undocumented function
* Remove all sub element entries
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
@@ -131,7 +131,7 @@ class Block
// CSS Elements
/**
* Undocumented function
* Add css entry to the css entries
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param string ...$css
@@ -144,7 +144,7 @@ class Block
}
/**
* Undocumented function
* Remove a css entry entry from the css array
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param string ...$css
@@ -157,7 +157,7 @@ class Block
}
/**
* Undocumented function
* Switch CSS entries
* scssel (switch) is not supported
* use rcssel -> acssel
*
@@ -175,7 +175,7 @@ class Block
}
/**
* Undocumented function
* Build HTML from the content tree
* alias phfo
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree
@@ -231,7 +231,19 @@ class Block
}
/**
* Undocumented function
* Alias for phfo
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree
* @param bool $add_nl [default=false]
* @return string
*/
public static function phfo(array $tree, bool $add_nl = false): string
{
return self::buildHtml($tree, $add_nl);
}
/**
* Build HTML elements from an array of elements
* alias phfa
*
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list
@@ -248,8 +260,7 @@ class Block
}
/**
* Undocumented function
* wrapper for buildHtmlFromList
* alias for buildHtmlFromList
*
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list array of Elements to build string from
* @param bool $add_nl [default=false] Optional output string line break

View File

@@ -401,7 +401,7 @@ class Element
* @param bool $add_nl [default=false] Optional output string line breaks
* @return string HTML as string
*/
public function buildHtml(Element $tree = null, bool $add_nl = false): string
public function buildHtml(?Element $tree = null, bool $add_nl = false): string
{
// print "D01: " . microtime(true) . "<br>";
if ($tree === null) {
@@ -533,7 +533,7 @@ class Element
* @return string build html as string
* @deprecated Do not use, use Element->buildHtml() instead
*/
public static function printHtmlFromObject(Element $tree = null, bool $add_nl = false): string
public static function printHtmlFromObject(?Element $tree = null, bool $add_nl = false): string
{
// nothing ->bad
if ($tree === null) {

View File

@@ -203,7 +203,8 @@ class SmartyExtend extends \Smarty
_bind_textdomain_codeset($this->domain, $this->encoding);
// register smarty variable
$this->registerPlugin('modifier', 'getvar', [&$this, 'getTemplateVars']);
// $this->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'getvar', [&$this, 'getTemplateVars']);
$this->registerPlugin(self::PLUGIN_MODIFIER, 'getvar', [&$this, 'getTemplateVars']);
$this->page_name = \CoreLibs\Get\System::getPageName();

View File

@@ -35,17 +35,17 @@
},
{
"name": "gullevek/dotenv",
"version": "v2.0.8",
"version_normalized": "2.0.8.0",
"version": "v2.1.0",
"version_normalized": "2.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/gullevek/dotEnv.git",
"reference": "e29f9fcd8853a09bb89b0eb8ee555b754ecee36e"
"reference": "b9feacaded4e48effff9da7d1173752aef3dc27f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/gullevek/dotEnv/zipball/e29f9fcd8853a09bb89b0eb8ee555b754ecee36e",
"reference": "e29f9fcd8853a09bb89b0eb8ee555b754ecee36e",
"url": "https://api.github.com/repos/gullevek/dotEnv/zipball/b9feacaded4e48effff9da7d1173752aef3dc27f",
"reference": "b9feacaded4e48effff9da7d1173752aef3dc27f",
"shasum": ""
},
"require": {
@@ -56,7 +56,7 @@
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9"
},
"time": "2023-03-03T00:32:02+00:00",
"time": "2024-08-21T02:41:15+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -86,7 +86,7 @@
],
"support": {
"issues": "https://github.com/gullevek/dotEnv/issues",
"source": "https://github.com/gullevek/dotEnv/tree/v2.0.8"
"source": "https://github.com/gullevek/dotEnv/tree/v2.1.0"
},
"install-path": "../gullevek/dotenv"
},

View File

@@ -29,9 +29,9 @@
'dev_requirement' => false,
),
'gullevek/dotenv' => array(
'pretty_version' => 'v2.0.8',
'version' => '2.0.8.0',
'reference' => 'e29f9fcd8853a09bb89b0eb8ee555b754ecee36e',
'pretty_version' => 'v2.1.0',
'version' => '2.1.0.0',
'reference' => 'b9feacaded4e48effff9da7d1173752aef3dc27f',
'type' => 'library',
'install_path' => __DIR__ . '/../gullevek/dotenv',
'aliases' => array(),

View File

@@ -61,6 +61,29 @@ DOUBLE="I will be used"
DOUBLE="This will be ignored"
```
A prefix name can be set with `[PrefixName]`. Tne name rules are like for variables, but spaces
are allowed, but will be converted to "_".
The prefix is valid from the time set until the next prefix block appears or the file ends.
Example
```ini
FOO="bar"
FOOBAR="bar bar"
[SecitonA]
FOO="other bar"
FOOBAR="other bar bar"
```
Will have environmen variables as
```php
$_ENV["FOO"];
$_ENV["FOOBAR"];
$_ENV["SecitonA.FOO"];
$_ENV["SecitonA.FOOBAR"];
```
## Development
### Phan

View File

@@ -22,6 +22,9 @@ class DotEnv
* if there are two variables with the same name only the first is used
* variables are case sensitive
*
* [] Grouping Block Name as prefix until next or end if set,
* space replaced by _, all other var rules apply
*
* @param string $path Folder to file, default is __DIR__
* @param string $env_file What file to load, default is .env
* @return int -1 other error
@@ -56,10 +59,14 @@ class DotEnv
$status = 1;
$block = false;
$var = '';
$prefix_name = '';
while ($line = fgets($fp)) {
// main match for variable = value part
if (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
$var = $matches[1];
// [] block must be a single line, or it will be ignored
if (preg_match("/^\s*\[([\w_.\s]+)\]/", $line, $matches)) {
$prefix_name = preg_replace("/\s+/", "_", $matches[1]) . ".";
} elseif (preg_match("/^\s*([\w_.]+)\s*=\s*((\"?).*)/", $line, $matches)) {
// main match for variable = value part
$var = $prefix_name . $matches[1];
$value = $matches[2];
$quotes = $matches[3];
// write only if env is not set yet, and write only the first time