Compare commits

...

69 Commits

Author SHA1 Message Date
Clemens Schwaighofer
6e59b63791 DB\IO phpdoc and phpstan fixes 2022-12-14 14:18:33 +09:00
Clemens Schwaighofer
9c7b3cea83 SQL Interface docstring fix 2022-12-14 13:53:54 +09:00
Clemens Schwaighofer
26af6a07f4 PHP unit tests updates for class changes 2022-12-09 16:53:10 +09:00
Clemens Schwaighofer
b7c6d4b478 DB\IO add unescape bytea data 2022-12-09 16:33:58 +09:00
Clemens Schwaighofer
9936fc04da Convert\Byte class fix string in abs call 2022-12-09 16:33:47 +09:00
Clemens Schwaighofer
1e0dfa2106 Update documentation for Convert\Byte Class
add more info in parameters flag
2022-12-09 13:43:15 +09:00
Clemens Schwaighofer
3af6f6a8f0 edit interface, hard set edit.css style sheet 2022-12-07 06:56:47 +09:00
Clemens Schwaighofer
1e793c0d16 Switch all SQL from tab to spaces 2022-12-06 09:27:08 +09:00
Clemens Schwaighofer
5be34453ce Fix in Smarty Template class and PAGE WIDTH set 2022-11-10 10:26:59 +09:00
Clemens Schwaighofer
7773b78e17 Fix in CoreLib Bytes for null to trim 2022-11-09 18:11:14 +09:00
Clemens Schwaighofer
2a3798c8c2 Create mo file update, basic edit css/javascript updates 2022-10-25 16:48:34 +09:00
Clemens Schwaighofer
bc8303fe5f Composer update 2022-10-25 16:48:12 +09:00
Clemens Schwaighofer
ba89b188d9 Mo create script update, phpstan fixes, document updates
create_mo:
set auto base folder bases on current location so we do not need do
adjust paths in script

phpstan fixes:
edit_base.php
CoreLibs/Basci.php
CoreLibs/DB/SQL/PgSQL.php

Update documentation in method headers
CoreLibs/Combined/DateTime.php
2022-10-12 09:48:22 +09:00
Clemens Schwaighofer
d15618cde4 Add JS_TRANSLATE file to smart template flow 2022-10-04 17:35:46 +09:00
Clemens Schwaighofer
0fd89727e9 Update Output\Form to allow ACL controlled edit/view entries
Fixed phpunit test runs with encoding test run and not resetting the
subsitute character back to default

Note: There are mime encoding failures for php 7.4 and 8.0 and one ACL
login failure test for php 7.4
2022-09-06 11:17:03 +09:00
Clemens Schwaighofer
a8e75d158b Update composer installed packages 2022-09-06 11:16:33 +09:00
Clemens Schwaighofer
4b3fbaa309 Updates based on latest phpstan run 2022-09-02 17:00:22 +09:00
Clemens Schwaighofer
1a6c65df0e Minor test updates, comment typo updates, DB_CONFIG_SET for default
$DB_CONFIG_SET is now default current selcted db config instead of
$DB_CONFIG so to not overwrite the array itself
2022-08-05 12:43:57 +09:00
Clemens Schwaighofer
24f553a17e Update comments for split element counter 2022-07-29 13:20:54 +09:00
Clemens Schwaighofer
9a3ea2f7db update strings class with split counter method 2022-07-29 13:19:45 +09:00
Clemens Schwaighofer
bcdb877d90 Phan/phpstan fixes 2022-07-29 11:06:53 +09:00
Clemens Schwaighofer
6d0e528c38 Combined\Datetime date/number to weekday conversion
Convert functions for date or weekday number to weekday name or date to
weekday number
2022-07-29 11:02:25 +09:00
Clemens Schwaighofer
7e6474195b String split format fix for non ascii characters
Currently just abort and return string as is
2022-07-29 10:38:32 +09:00
Clemens Schwaighofer
1795d3ba6c String convert class added
Currently with one method: splitFormatString

Converts a string to a string with separater characters based on a
format string
2022-07-29 07:00:02 +09:00
Clemens Schwaighofer
e1340acf55 Class header info string fix 2022-07-29 06:59:33 +09:00
Clemens Schwaighofer
b5ead3e266 Minor code block comment clean ups 2022-07-15 17:42:38 +09:00
Clemens Schwaighofer
f5daaca598 Fixes for Create\Email docstrings 2022-07-08 17:25:45 +09:00
Clemens Schwaighofer
6b4f310cd2 Email\Sending add dedicated kv folding flag
kv folding is now done via flag and only if an encoded is detected that
is japanese or UTF-8
2022-07-04 15:45:51 +09:00
Clemens Schwaighofer
7b5bddb529 Create\Email fixes
Remove not needed reaplce content count for first global replace
Move logger out of test only and log if a logger class is attached
2022-07-01 08:57:14 +09:00
Clemens Schwaighofer
0a6fdf1248 Use logged encoding from JSON debug block for non UTF-8 tests 2022-06-30 18:18:17 +09:00
Clemens Schwaighofer
3220180d58 Bug fix in Email for encoding subject/body with empty replace
Also store encoding in json log if test and debug print is given
2022-06-30 18:16:28 +09:00
Clemens Schwaighofer
8c8f14ec74 Fix logging per run to be setable not only on start
Move per run set into method.
Add set/get method and add set method override (set new) flag

Update phpUnit testing and move providers to test methods
2022-06-30 18:15:36 +09:00
Clemens Schwaighofer
643991c3fd Update Debug\Support, add Create\Email
update debug support to add html escape for html strings on request.
Default is keep as is. debugString gets new third parameter for this as
bool flag.

Add Create\Email to send basic text emails to several too addresses.
Content replace in subject and body is possible with {} entries.
Default encoding is UTF-8 but others can be set and content will be
converted to this.
The dynamic replace works on all data or can be set per receiver.
2022-06-28 17:29:31 +09:00
Clemens Schwaighofer
c81c46d426 Move read_env_file.php to deprecated folder 2022-06-23 14:46:19 +09:00
Clemens Schwaighofer
d97b173ee7 ACL\Login move public var to private: login
the former public var $login is now private and if it is set can be
checked with loginActionSet (true if login_login was in _POST as login
action.

Some info update for phpUnit ACL\Login test file
2022-06-23 09:12:46 +09:00
Clemens Schwaighofer
b61152f10e Skipped/Incomplete tests update 2022-06-23 07:09:19 +09:00
Clemens Schwaighofer
0c68ebe652 Login\ACL revalidate flow fixes
- DB function had wrong column name
- Queries in ACL\Login had wrong column name
- Renamed from login_user_id_last_login to login_user_id_last_revalidate
  to make it more clear what this column is
- add edit_user admin page output for this column
- add phpUnit test case for revalidate is needed and login with next
  loginUserId is ok again
2022-06-23 06:50:07 +09:00
Clemens Schwaighofer
31d0cdb8ad Fix revalidate after flow in ACL\Login
After revalidate time was reached, it was never reset because it used
the original loginUserId set date.
A new column has been added that gets reset every time the user logs in
with username and password if a loginUserId is set in the database
2022-06-22 19:38:03 +09:00
Clemens Schwaighofer
0f823bd283 Just minor line length fixes in ArrayIO class 2022-06-22 18:10:23 +09:00
Clemens Schwaighofer
6385a48824 add back unique constraint because null login_user_id are allowed 2022-06-22 16:56:51 +09:00
Clemens Schwaighofer
a754d897cf Bug fixes for emptynull type in ArrayIO, Form\Generate interval
Form\Generate for intervals also allows day(s), month(s), year(s), call
case insensitive

ArrayIO fix for missing escale literal for
date/datetime/interval/emptynull text type
2022-06-22 16:17:16 +09:00
Clemens Schwaighofer
4600f8f7bf Update edit_user form page and also minor updates to Form and ArraIO
login_user_id is unique if not null (as index, constraint only with
PostgreSQL 15)
login_user_id_revalidate_after is not longer not null and default set,
no need for this

DB\Extended\ArrayIO:
add sql_read for datetime fields to change amount of data (eg only up
to minute) with to_char() method. sample: YYYY-MM-DD HH24:MI
Add date/datetime/emptynull for setting empty fields to null and not
empty string

Output\From\Generate:
Remove all fill for spacer and change them to placeholder html types.
Add datetime check next to date, time only checks

edit_user Admin Form:
add all new columns there
2022-06-22 15:50:07 +09:00
Clemens Schwaighofer
04e4fe46f2 Update ACL\Login class with _GET/_POST login parameter
loginUserId parameter in _GET or _POST for direct login without username
and password.

This can be secured by:
- must login after x days from set loginUserId on
- can only login with loginUserId in given time range
- flag lock loginUserId
2022-06-22 13:52:47 +09:00
Clemens Schwaighofer
c35d3c9324 Remove constant from deprecated ReadEnvFile class (now dotEnv) 2022-06-14 16:27:00 +09:00
Clemens Schwaighofer
e92a682a8c ACL\Login phpUnit tets update for ajax page tests 2022-06-14 16:24:17 +09:00
Clemens Schwaighofer
ea07e4b95b Update ACL\Login with internal ajax_page flag override
Also ajax flag return method
2022-06-14 16:23:24 +09:00
Clemens Schwaighofer
88178cb08d Rename class ReadEnvFile to DotEnv and add test cases
previous named Get\ReadEnvFile is no Get\DotEnv, static method is the
same.
Update for not parsing comments at the end of a line if the line was not
in quotes. Strips everything after comment mark and also right trims any
trailing spaces

Old:
FOO=Test # Comment -> $_ENV['FOO'] = "Test # Comment"

New:
FOO=Test # Comment -> $_ENV['FOO'] = "Test"

Add phpUnit tests for DotEnv class.
Update config.php with new class name

The old class name exists and is markted as deprecated until next major
release
2022-06-09 09:05:48 +09:00
Clemens Schwaighofer
5d98be06be Code clean up for phan and phpstan 2022-06-07 18:16:23 +09:00
Clemens Schwaighofer
183cadb0fd Class ACL\Login update with phpunit testing
Move logic from constructor to separate function
Add more public access methods for internal variable access (password
min length settings, error login code, error login string error)
All error messages are declared in constructor with wrapper function to
create html error string for template creation
Add wrapper function for exit/abort and page name read for easier mocking
in testing
Fixes for multi login main function caller and cached query problem: do
not cache query for login
Add reverse default access list SESSION variable and public readers
Update logout with unset of full SESSION array to empty, use external
session class for all session calls. Also unset euid on logout
2022-06-07 18:05:50 +09:00
Clemens Schwaighofer
2067a6fe1d Config master SSL site detection update 2022-06-07 18:05:34 +09:00
Clemens Schwaighofer
f5b6c639fb Fix primary key base number after more inserts are done 2022-06-03 11:13:35 +09:00
Clemens Schwaighofer
cde29c0362 Update DB\IO dbReturn and update connected tests
Switch the code point for these below for logic reasons
CLEAR_CACHE 1 => 2 (clear cache AFTER END read)
READ_NEW 2 => 1 (clear cache BEFORE first read)

in dbReturn cursor ext array:
remove firstcall entry because it is not needed
add new:
- cache_flag: $cache method call number
- assoc_flag: the assoc read flag from the method call
- cached: if there is data cached in the cursor ext array this is true
- finished: true if the last read was false
- db_read_finished: if true the db read has fiinished (read_rows =
  num_rows)
- read_finished: if true the current read (cache or db) via pos =
  num_rows is done
- log_pos: sequential number for each call with the same query hash
- log: array with current actions done in the last read

Update DB IO class test with all cursor, cursor ext, read single step,
read in loop, read again, etc tests
2022-06-03 11:03:06 +09:00
Clemens Schwaighofer
10234000b7 ACL\Login test class add
- db create shell script for ACL\Login to reset full database to known
  good stated
- basic tests written to check core login class
2022-06-02 18:14:58 +09:00
Clemens Schwaighofer
a63a50a412 add tests for dbReturn only
dbReturn special call test file, update main db test file

Main class_test file with links update
2022-06-02 16:38:10 +09:00
Clemens Schwaighofer
59da10b649 Session class update with session destroy / start wrapper
session start wrapper as protected method

session destroy wrapper with _SESSION array unset
2022-06-02 16:35:40 +09:00
Clemens Schwaighofer
b714de498f Add print boolean stand allone support function
in the Debug\Support add printBool to print out bool as string.
Same as printAsString with bool alone but you can control prefix name,
and true/false string names

Add printArray alias to prAr
2022-06-02 16:31:35 +09:00
Clemens Schwaighofer
aa11937ab2 Update Running time for better high resolution timer
Instead of ending with the second hr timer call, we print out difference
to the last one.
Add new method to print out from start time difference and add a reset
method
2022-06-02 16:30:22 +09:00
Clemens Schwaighofer
d64d5f081c Add Class for Memory Usage tracking 2022-06-02 16:26:55 +09:00
Clemens Schwaighofer
3085b52714 Update PHPdoc parts
Add empty line between description and first @param entry.
Some other minor comment layout and text fixes
2022-06-02 16:07:38 +09:00
Clemens Schwaighofer
9949a5ef7f Update core edit_* tables with various fixes
- import script with write to file option
- fix file names for functions
- add generic (non edit tables) for only set date, set uid or combine
- fix edit table edit_language insert data
- all trigger create remove the drop on exists, as in the flow the trigger will never exists
2022-05-31 20:17:32 +09:00
Clemens Schwaighofer
74ba935e96 Comment info update in L10n class 2022-05-27 15:01:30 +09:00
Clemens Schwaighofer
39a62ed59d Update phpunit tests for Debug\Logging 2022-05-26 15:20:19 +09:00
Clemens Schwaighofer
1379cf1519 Add print bool in logging class 2022-05-26 14:31:48 +09:00
Clemens Schwaighofer
2d15b78d21 Composer update 2022-05-26 09:52:37 +09:00
Clemens Schwaighofer
92ebdb4b9e Update session class and write session clas tester, update DB\IO Tester
DB\IO Tester now has correct testing for pgVersion string compare. Uses
mocked pgVersion return for this

Session class update with full magic set/get or method set/get for
_SESSION var. Also added full testing for this
2022-05-26 09:27:57 +09:00
Clemens Schwaighofer
a523a4e831 ACL\Login class update for phpstan check 2022-05-24 16:50:37 +09:00
Clemens Schwaighofer
db8e17ae7c Convert static Session class to normal session class
All static Session:: calls (except for checking valid session name) are
converted to object type. This Object is passed on to Login, Admin
Backend and any other class that needs basic session checking
2022-05-24 15:00:04 +09:00
Clemens Schwaighofer
5b581c2ed6 Fix checkCLI call on false return from php_sapi_name() 2022-05-24 13:12:17 +09:00
Clemens Schwaighofer
1e734581d7 Session class update, cli check add, tests updates, edit table update
Update edit_access_data table and set unique check for edit_access_id +
name so we do not have two identical keys for one edit access set

Update config host and add more test domains for various access tests

Update Session and move cli check to Get\System class. Some other minor
session info updates

New method \Get\System::checkCLI() returns true if the sapi name has
cli inside, else false
2022-05-24 11:36:03 +09:00
569 changed files with 14984 additions and 27965 deletions

View File

@@ -1,13 +1,18 @@
#!/usr/bin/env bash
base_folder='/var/www/html/developers/clemens/core_data/php_libraries/trunk/www/';
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);
echo "Translate language ${file}";
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;
done;

View File

@@ -1,10 +1,11 @@
# this list only holds edit_* related table data
# functions
function/set_uid.sql
function/set_generic.sql
function/random_string.sql
function/set_edit_generic.sql
function/edit_set_access_uid.sql
function/edit_access_set_uid.sql
function/edit_group_set_uid.sql
function/edit_log_partition_insert.sql
function/edit_user_set_login_user_id_set_date.sql
# generic tables
table/edit_temp_files.sql
table/edit_generic.sql

View File

@@ -6,20 +6,25 @@
#exit;
# if flagged 'y' then it will ask after each import to continue
development='y';
development='n';
# do not import anything, just order flow output
test='n';
input='';
# write to file do not write to DB directly
write='y';
# database connection info
db='<db name>';
host='<db host>';
user='<db user>';
schema="public";
schemas='public';
export PGPASSWORD='';
# log files
error_file="log/error";
output_file="log/output";
error_file='log/error';
output_file='log/output';
data_file='database_create_data.sql';
if [ "$write" = 'y' ]; then
rm -f "${data_file}";
fi;
if [ ! -f ORDER ]; then
echo "Could not find ORDER file";
exit;
@@ -40,26 +45,37 @@ while read file <&3; do
if [ -f "$file" ]; then
for path in "$schemas"; do
echo "[+] WORK ON '${file}' @ '${path}'";
# skip all on test
if [ "$test" = 'n' ]; then
echo "=== START [$file] ===>" >> ${error_file};
psql -U ${user} -h ${host} -f "${file}" ${db} 1>> ${output_file} 2>> ${error_file}
echo "=== END [$file] ===>" >> ${error_file};
fi;
if [ "$development" = "y" ]; then
echo "Press 'y' to move to next. Press 'r' to reload last file. ^c to abort";
fi;
while [ "$development" = "y" ] && [ "$input" != "y" ]; do
read -ep "Continue (y|r|^c): " input;
if [ "$input" = "r" ]; then
echo "Reload File '${file}' ...";
if [ "$test" = 'n' ]; then
echo "=== START RELOAD [$file] ===>" >> ${error_file};
psql -U ${user} -h ${host} -f "${file}" ${db} 1>> ${output_file} 2>> ${error_file}
echo "=== END RELOAD [$file] ===>" >> ${error_file};
# write to file
if [ "$write" = 'y' ]; then
echo "-- START: ${file}" >> ${data_file};
cat "${file}" >> ${data_file};
echo "-- END: ${file}" >> ${data_file};
else
# write to DB
echo "=== START [$file] ===>" >> ${error_file};
psql -U ${user} -h ${host} -f "${file}" ${db} 1>> ${output_file} 2>> ${error_file}
echo "=== END [$file] ===>" >> ${error_file};
# next wait for dev
if [ "$development" = "y" ]; then
echo "Press 'y' to move to next. Press 'r' to reload last file. ^c to abort";
fi;
# loop run for reload on failed
while [ "$development" = "y" ] && [ "$input" != "y" ]; do
read -ep "Continue (y|r|^c): " input;
if [ "$input" = "r" ]; then
echo "Reload File '${file}' ...";
if [ "$test" = 'n' ]; then
echo "=== START RELOAD [$file] ===>" >> ${error_file};
psql -U ${user} -h ${host} -f "${file}" ${db} 1>> ${output_file} 2>> ${error_file}
echo "=== END RELOAD [$file] ===>" >> ${error_file};
fi;
fi;
done;
input='';
fi;
done;
input='';
fi;
done;
elif [[ ${file::1} != "#" ]]; then
echo "[!] COULD NOT FIND FILE: '${file}'";

View File

@@ -68,10 +68,11 @@ INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('Visitor', 'B0C4B3
INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('User', '1E789E', 1);
-- edit language
-- short_name = locale without encoding
-- iso_name = encoding
DELETE FROM edit_language;
INSERT INTO edit_language (long_name, short_name, iso_name, order_number, enabled, lang_default) VALUES ('English', 'en_US', 'UTF-8', 1, 1, 1);
INSERT INTO edit_language (long_name, short_name, long_name, iso_name, order_number, enabled, lang_default) VALUES ('Japanese', 'ja_JP', 'UTF-8', 2, 1, 0);
INSERT INTO edit_language (long_name, short_name, iso_name, order_number, enabled, lang_default) VALUES ('Japanese', 'ja_JP', 'UTF-8', 2, 1, 0);
-- edit group
DELETE FROM edit_group;
@@ -130,7 +131,7 @@ INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_
-- inserts admin user so basic users can be created
DELETE FROM edit_user;
INSERT INTO edit_user (username, password, enabled, debug, db_debug, email, protected, admin, edit_language_id, edit_group_id, edit_scheme_id, edit_access_right_id) VALUES ('admin', 'admin', 1, 1, 1, '', 1, 1,
(SELECT edit_language_id FROM edit_language WHERE short_name = 'en'),
(SELECT edit_language_id FROM edit_language WHERE short_name = 'en_US'),
(SELECT edit_group_id FROM edit_group WHERE name = 'Admin'),
(SELECT edit_scheme_id FROM edit_scheme WHERE name = 'Admin'),
(SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin')

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
-- add uid add for edit_access table
CREATE OR REPLACE FUNCTION set_edit_access_uid() RETURNS TRIGGER AS
$$
DECLARE
myrec RECORD;
v_uid VARCHAR;
BEGIN
-- skip if NEW.name is not set
IF NEW.name IS NOT NULL AND NEW.name <> '' THEN
-- use NEW.name as base, remove all spaces
-- name data is already unique, so we do not need to worry about this here
v_uid := REPLACE(NEW.name, ' ', '');
IF TG_OP = 'INSERT' THEN
-- always set
NEW.uid := v_uid;
ELSIF TG_OP = 'UPDATE' THEN
-- check if not set, then set
SELECT INTO myrec t.* FROM edit_access t WHERE edit_access_id = NEW.edit_access_id;
IF FOUND THEN
NEW.uid := v_uid;
END IF;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -0,0 +1,28 @@
-- add uid add for edit_group table
CREATE OR REPLACE FUNCTION set_edit_group_uid() RETURNS TRIGGER AS
$$
DECLARE
myrec RECORD;
v_uid VARCHAR;
BEGIN
-- skip if NEW.name is not set
IF NEW.name IS NOT NULL AND NEW.name <> '' THEN
-- use NEW.name as base, remove all spaces
-- name data is already unique, so we do not need to worry about this here
v_uid := REPLACE(NEW.name, ' ', '');
IF TG_OP = 'INSERT' THEN
-- always set
NEW.uid := v_uid;
ELSIF TG_OP = 'UPDATE' THEN
-- check if not set, then set
SELECT INTO myrec t.* FROM edit_group t WHERE edit_group_id = NEW.edit_group_id;
IF FOUND THEN
NEW.uid := v_uid;
END IF;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -9,142 +9,142 @@ CREATE OR REPLACE FUNCTION edit_log_insert_trigger ()
RETURNS TRIGGER AS
$$
DECLARE
start_date DATE := '2010-01-01';
end_date DATE;
timeformat TEXT := 'YYYY';
selector TEXT := 'year';
base_table TEXT := 'edit_log';
_interval INTERVAL := '1 ' || selector;
_interval_next INTERVAL := '2 ' || selector;
table_name TEXT;
-- compare date column
compare_date DATE := NEW.event_date;
compare_date_name TEXT := 'event_date';
-- the create commands
command_create_table TEXT := 'CREATE TABLE IF NOT EXISTS {TABLE_NAME} (CHECK({COMPARE_DATE_NAME} >= {START_DATE} AND {COMPARE_DATE_NAME} < {END_DATE})) INHERITS ({BASE_NAME})';
command_create_primary_key TEXT := 'ALTER TABLE {TABLE_NAME} ADD PRIMARY KEY ({BASE_TABLE}_id)';
command_create_foreign_key_1 TEXT := 'ALTER TABLE {TABLE_NAME} ADD CONSTRAINT {TABLE_NAME}_euid_fkey FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL';
command_create_trigger_1 TEXT = 'CREATE TRIGGER trg_{TABLE_NAME} BEFORE INSERT OR UPDATE ON {TABLE_NAME} FOR EACH ROW EXECUTE PROCEDURE set_edit_generic()';
start_date DATE := '2010-01-01';
end_date DATE;
timeformat TEXT := 'YYYY';
selector TEXT := 'year';
base_table TEXT := 'edit_log';
_interval INTERVAL := '1 ' || selector;
_interval_next INTERVAL := '2 ' || selector;
table_name TEXT;
-- compare date column
compare_date DATE := NEW.event_date;
compare_date_name TEXT := 'event_date';
-- the create commands
command_create_table TEXT := 'CREATE TABLE IF NOT EXISTS {TABLE_NAME} (CHECK({COMPARE_DATE_NAME} >= {START_DATE} AND {COMPARE_DATE_NAME} < {END_DATE})) INHERITS ({BASE_NAME})';
command_create_primary_key TEXT := 'ALTER TABLE {TABLE_NAME} ADD PRIMARY KEY ({BASE_TABLE}_id)';
command_create_foreign_key_1 TEXT := 'ALTER TABLE {TABLE_NAME} ADD CONSTRAINT {TABLE_NAME}_euid_fkey FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL';
command_create_trigger_1 TEXT = 'CREATE TRIGGER trg_{TABLE_NAME} BEFORE INSERT OR UPDATE ON {TABLE_NAME} FOR EACH ROW EXECUTE PROCEDURE set_edit_generic()';
BEGIN
-- we are in valid start time area
IF (NEW.event_date >= start_date) THEN
-- current table name
table_name := base_table || '_' || to_char(NEW.event_date, timeformat);
BEGIN
EXECUTE 'INSERT INTO ' || quote_ident(table_name) || ' SELECT ($1).*' USING NEW;
-- if insert failed because of missing table, create new below
EXCEPTION
WHEN undefined_table THEN
-- another block, so in case the creation fails here too
BEGIN
-- create new table here + all indexes
start_date := date_trunc(selector, NEW.event_date);
end_date := date_trunc(selector, NEW.event_date + _interval);
-- creat table
EXECUTE format(REPLACE( -- end date
REPLACE( -- start date
REPLACE( -- compare date name
REPLACE( -- base name (inherit)
REPLACE( -- table name
command_create_table,
'{TABLE_NAME}',
table_name
),
'{BASE_NAME}',
base_table
),
'{COMPARE_DATE_NAME}',
compare_date_name
),
'{START_DATE}',
quote_literal(start_date)
),
'{END_DATE}',
quote_literal(end_date)
));
-- create all indexes and triggers
EXECUTE format(REPLACE(
REPLACE(
command_create_primary_key,
'{TABLE_NAME}',
table_name
),
'{BASE_TABLE}',
base_table
));
-- FK constraints
EXECUTE format(REPLACE(command_create_foreign_key_1, '{TABLE_NAME}', table_name));
-- generic trigger
EXECUTE format(REPLACE(command_create_trigger_1, '{TABLE_NAME}', table_name));
-- we are in valid start time area
IF (NEW.event_date >= start_date) THEN
-- current table name
table_name := base_table || '_' || to_char(NEW.event_date, timeformat);
BEGIN
EXECUTE 'INSERT INTO ' || quote_ident(table_name) || ' SELECT ($1).*' USING NEW;
-- if insert failed because of missing table, create new below
EXCEPTION
WHEN undefined_table THEN
-- another block, so in case the creation fails here too
BEGIN
-- create new table here + all indexes
start_date := date_trunc(selector, NEW.event_date);
end_date := date_trunc(selector, NEW.event_date + _interval);
-- creat table
EXECUTE format(REPLACE( -- end date
REPLACE( -- start date
REPLACE( -- compare date name
REPLACE( -- base name (inherit)
REPLACE( -- table name
command_create_table,
'{TABLE_NAME}',
table_name
),
'{BASE_NAME}',
base_table
),
'{COMPARE_DATE_NAME}',
compare_date_name
),
'{START_DATE}',
quote_literal(start_date)
),
'{END_DATE}',
quote_literal(end_date)
));
-- create all indexes and triggers
EXECUTE format(REPLACE(
REPLACE(
command_create_primary_key,
'{TABLE_NAME}',
table_name
),
'{BASE_TABLE}',
base_table
));
-- FK constraints
EXECUTE format(REPLACE(command_create_foreign_key_1, '{TABLE_NAME}', table_name));
-- generic trigger
EXECUTE format(REPLACE(command_create_trigger_1, '{TABLE_NAME}', table_name));
-- insert try again
EXECUTE 'INSERT INTO ' || quote_ident(table_name) || ' SELECT ($1).*' USING NEW;
EXCEPTION
WHEN OTHERS THEN
-- if this faled, throw it into the overflow table (so we don't loose anything)
INSERT INTO edit_log_overflow VALUES (NEW.*);
END;
-- other errors, insert into overlow
WHEN OTHERS THEN
-- if this faled, throw it into the overflow table (so we don't loose anything)
INSERT INTO edit_log_overflow VALUES (NEW.*);
END;
-- main insert run done, check if we have to create next months table
BEGIN
-- check if next month table exists
table_name := base_table || '_' || to_char((SELECT NEW.event_date + _interval)::DATE, timeformat);
-- RAISE NOTICE 'SEARCH NEXT: %', table_name;
IF (SELECT to_regclass(table_name)) IS NULL THEN
-- move inner interval same
start_date := date_trunc(selector, NEW.event_date + _interval);
end_date := date_trunc(selector, NEW.event_date + _interval_next);
-- RAISE NOTICE 'CREATE NEXT: %', table_name;
-- create table
EXECUTE format(REPLACE( -- end date
REPLACE( -- start date
REPLACE( -- compare date name
REPLACE( -- base name (inherit)
REPLACE( -- table name
command_create_table,
'{TABLE_NAME}',
table_name
),
'{BASE_NAME}',
base_table
),
'{COMPARE_DATE_NAME}',
compare_date_name
),
'{START_DATE}',
quote_literal(start_date)
),
'{END_DATE}',
quote_literal(end_date)
));
-- create all indexes and triggers
EXECUTE format(REPLACE(
REPLACE(
command_create_primary_key,
'{TABLE_NAME}',
table_name
),
'{BASE_TABLE}',
base_table
));
-- FK constraints
EXECUTE format(REPLACE(command_create_foreign_key_1, '{TABLE_NAME}', table_name));
-- generic trigger
EXECUTE format(REPLACE(command_create_trigger_1, '{TABLE_NAME}', table_name));
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Failed to create next table: %', table_name;
END;
ELSE
-- if outside valid date, insert into overflow
INSERT INTO edit_log_overflow VALUES (NEW.*);
END IF;
RETURN NULL;
-- insert try again
EXECUTE 'INSERT INTO ' || quote_ident(table_name) || ' SELECT ($1).*' USING NEW;
EXCEPTION
WHEN OTHERS THEN
-- if this faled, throw it into the overflow table (so we don't loose anything)
INSERT INTO edit_log_overflow VALUES (NEW.*);
END;
-- other errors, insert into overlow
WHEN OTHERS THEN
-- if this faled, throw it into the overflow table (so we don't loose anything)
INSERT INTO edit_log_overflow VALUES (NEW.*);
END;
-- main insert run done, check if we have to create next months table
BEGIN
-- check if next month table exists
table_name := base_table || '_' || to_char((SELECT NEW.event_date + _interval)::DATE, timeformat);
-- RAISE NOTICE 'SEARCH NEXT: %', table_name;
IF (SELECT to_regclass(table_name)) IS NULL THEN
-- move inner interval same
start_date := date_trunc(selector, NEW.event_date + _interval);
end_date := date_trunc(selector, NEW.event_date + _interval_next);
-- RAISE NOTICE 'CREATE NEXT: %', table_name;
-- create table
EXECUTE format(REPLACE( -- end date
REPLACE( -- start date
REPLACE( -- compare date name
REPLACE( -- base name (inherit)
REPLACE( -- table name
command_create_table,
'{TABLE_NAME}',
table_name
),
'{BASE_NAME}',
base_table
),
'{COMPARE_DATE_NAME}',
compare_date_name
),
'{START_DATE}',
quote_literal(start_date)
),
'{END_DATE}',
quote_literal(end_date)
));
-- create all indexes and triggers
EXECUTE format(REPLACE(
REPLACE(
command_create_primary_key,
'{TABLE_NAME}',
table_name
),
'{BASE_TABLE}',
base_table
));
-- FK constraints
EXECUTE format(REPLACE(command_create_foreign_key_1, '{TABLE_NAME}', table_name));
-- generic trigger
EXECUTE format(REPLACE(command_create_trigger_1, '{TABLE_NAME}', table_name));
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Failed to create next table: %', table_name;
END;
ELSE
-- if outside valid date, insert into overflow
INSERT INTO edit_log_overflow VALUES (NEW.*);
END IF;
RETURN NULL;
END
$$
LANGUAGE 'plpgsql';

View File

@@ -1,28 +0,0 @@
-- add uid add for edit_access table
CREATE OR REPLACE FUNCTION set_edit_access_uid() RETURNS TRIGGER AS
$$
DECLARE
myrec RECORD;
v_uid VARCHAR;
BEGIN
-- skip if NEW.name is not set
IF NEW.name IS NOT NULL AND NEW.name <> '' THEN
-- use NEW.name as base, remove all spaces
-- name data is already unique, so we do not need to worry about this here
v_uid := REPLACE(NEW.name, ' ', '');
IF TG_OP = 'INSERT' THEN
-- always set
NEW.uid := v_uid;
ELSIF TG_OP = 'UPDATE' THEN
-- check if not set, then set
SELECT INTO myrec t.* FROM edit_access t WHERE edit_access_id = NEW.edit_access_id;
IF FOUND THEN
NEW.uid := v_uid;
END IF;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -1,28 +0,0 @@
-- add uid add for edit_group table
CREATE OR REPLACE FUNCTION set_edit_group_uid() RETURNS TRIGGER AS
$$
DECLARE
myrec RECORD;
v_uid VARCHAR;
BEGIN
-- skip if NEW.name is not set
IF NEW.name IS NOT NULL AND NEW.name <> '' THEN
-- use NEW.name as base, remove all spaces
-- name data is already unique, so we do not need to worry about this here
v_uid := REPLACE(NEW.name, ' ', '');
IF TG_OP = 'INSERT' THEN
-- always set
NEW.uid := v_uid;
ELSIF TG_OP = 'UPDATE' THEN
-- check if not set, then set
SELECT INTO myrec t.* FROM edit_group t WHERE edit_group_id = NEW.edit_group_id;
IF FOUND THEN
NEW.uid := v_uid;
END IF;
END IF;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -0,0 +1,26 @@
-- set edit user login_user_id_set_date if login_user_id is set
-- NOW() if not empty
CREATE OR REPLACE FUNCTION set_login_user_id_set_date()
RETURNS TRIGGER AS
$$
BEGIN
-- if new is not null/empty
-- and old one is null or old one different new one
-- set NOW()
-- if new one is NULL
-- set NULL
IF
NEW.login_user_id IS NOT NULL AND NEW.login_user_id <> '' AND
(OLD.login_user_id IS NULL OR NEW.login_user_id <> OLD.login_user_id)
THEN
NEW.login_user_id_set_date = NOW();
NEW.login_user_id_last_revalidate = NOW();
ELSIF NEW.login_user_id IS NULL OR NEW.login_user_id = '' THEN
NEW.login_user_id_set_date = NULL;
NEW.login_user_id_last_revalidate = NULL;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -1,18 +1,20 @@
-- create random string with length X
CREATE FUNCTION random_string(randomLength int)
RETURNS text AS $$
RETURNS text AS
$$
SELECT array_to_string(
ARRAY(
SELECT substring(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
trunc(random() * 62)::int + 1,
1
)
FROM generate_series(1, randomLength) AS gs(x)
),
''
ARRAY(
SELECT substring(
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
trunc(random() * 62)::int + 1,
1
)
FROM generate_series(1, randomLength) AS gs(x)
),
''
)
$$ LANGUAGE SQL
$$
LANGUAGE SQL
RETURNS NULL ON NULL INPUT
VOLATILE; -- LEAKPROOF;
VOLATILE; -- LEAKPROOF;

View File

@@ -0,0 +1,15 @@
-- adds the created or updated date tags
CREATE OR REPLACE FUNCTION set_date()
RETURNS TRIGGER AS
$$
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.date_created := 'now';
ELSIF TG_OP = 'UPDATE' THEN
NEW.date_updated := 'now';
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -1,15 +1,18 @@
-- adds the created or updated date tags
CREATE OR REPLACE FUNCTION set_edit_generic() RETURNS TRIGGER AS '
DECLARE
random_length INT = 12; -- that should be long enough
BEGIN
IF TG_OP = ''INSERT'' THEN
NEW.date_created := ''now'';
NEW.cuid := random_string(random_length);
ELSIF TG_OP = ''UPDATE'' THEN
NEW.date_updated := ''now'';
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION set_edit_generic()
RETURNS TRIGGER AS
$$
DECLARE
random_length INT = 25; -- that should be long enough
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.date_created := 'now';
NEW.cuid := random_string(random_length);
ELSIF TG_OP = 'UPDATE' THEN
NEW.date_updated := 'now';
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -1,12 +0,0 @@
-- adds the created or updated date tags
CREATE OR REPLACE FUNCTION set_generic() RETURNS TRIGGER AS '
BEGIN
IF TG_OP = ''INSERT'' THEN
NEW.date_created := ''now'';
ELSIF TG_OP = ''UPDATE'' THEN
NEW.date_updated := ''now'';
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';

View File

@@ -0,0 +1,21 @@
-- set generic with date and uid combined
-- don't use with set_generic/set_uid together
CREATE OR REPLACE FUNCTION set_generic()
RETURNS TRIGGER AS
$$
DECLARE
random_length INT = 32; -- long for massive data
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.date_created := 'now';
IF NEW.uid IS NULL THEN
NEW.uid := random_string(random_length);
END IF;
ELSIF TG_OP = 'UPDATE' THEN
NEW.date_updated := 'now';
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -1,12 +1,15 @@
-- adds the created or updated date tags
CREATE OR REPLACE FUNCTION set_uid() RETURNS TRIGGER AS '
DECLARE
random_length INT = 32; -- that should be long enough
BEGIN
IF TG_OP = ''INSERT'' THEN
NEW.uid := random_string(random_length);
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION set_uid()
RETURNS TRIGGER AS
$$
DECLARE
random_length INT = 32; -- that should be long enough
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.uid := random_string(random_length);
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

View File

@@ -2,15 +2,18 @@
-- OLD, DEPRECATED, use set_generic.sql
-- CREATE OR REPLACE FUNCTION set_generic() RETURNS TRIGGER AS '
-- BEGIN
-- IF TG_OP = ''INSERT'' THEN
-- NEW.date_created := clock_timestamp();
-- NEW.user_created := current_user;
-- ELSIF TG_OP = ''UPDATE'' THEN
-- NEW.date_updated := clock_timestamp();
-- NEW.user_updated := current_user;
-- END IF;
-- RETURN NEW;
-- END;
-- ' LANGUAGE 'plpgsql';
-- CREATE OR REPLACE FUNCTION set_generic()
-- RETURNS TRIGGER AS
-- $$
-- BEGIN
-- IF TG_OP = 'INSERT' THEN
-- NEW.date_created := clock_timestamp();
-- NEW.user_created := current_user;
-- ELSIF TG_OP = 'UPDATE' THEN
-- NEW.date_updated := clock_timestamp();
-- NEW.user_updated := current_user;
-- END IF;
-- RETURN NEW;
-- END;
-- $$
-- LANGUAGE 'plpgsql';

View File

@@ -7,13 +7,13 @@
-- DROP TABLE edit_access;
CREATE TABLE edit_access (
edit_access_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
protected SMALLINT DEFAULT 0,
deleted SMALLINT DEFAULT 0,
uid VARCHAR,
name VARCHAR UNIQUE,
description VARCHAR,
color VARCHAR,
additional_acl JSONB
edit_access_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
protected SMALLINT DEFAULT 0,
deleted SMALLINT DEFAULT 0,
uid VARCHAR,
name VARCHAR UNIQUE,
description VARCHAR,
color VARCHAR,
additional_acl JSONB
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,10 +7,14 @@
-- DROP TABLE edit_access_data;
CREATE TABLE edit_access_data (
edit_access_data_id SERIAL PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
value VARCHAR
edit_access_data_id SERIAL PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
value VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;
-- create a unique index for each attached data block for each edit access can
-- only have ONE value;
CREATE UNIQUE INDEX edit_access_data_edit_access_id_name_ukey ON edit_access_data (edit_access_id, name);

View File

@@ -8,9 +8,9 @@
-- DROP TABLE edit_access_right;
CREATE TABLE edit_access_right (
edit_access_right_id SERIAL PRIMARY KEY,
name VARCHAR,
level SMALLINT,
type VARCHAR,
UNIQUE (level,type)
edit_access_right_id SERIAL PRIMARY KEY,
name VARCHAR,
level SMALLINT,
type VARCHAR,
UNIQUE (level,type)
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,13 +7,13 @@
-- DROP TABLE edit_access_user;
CREATE TABLE edit_access_user (
edit_access_user_id SERIAL PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_user_id INT NOT NULL,
FOREIGN KEY (edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_default SMALLINT DEFAULT 0,
enabled SMALLINT NOT NULL DEFAULT 0
edit_access_user_id SERIAL PRIMARY KEY,
edit_access_id INT NOT NULL,
FOREIGN KEY (edit_access_id) REFERENCES edit_access (edit_access_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_user_id INT NOT NULL,
FOREIGN KEY (edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_default SMALLINT DEFAULT 0,
enabled SMALLINT NOT NULL DEFAULT 0
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,7 +7,7 @@
-- DROP TABLE edit_generic;
CREATE TABLE edit_generic (
cuid VARCHAR,
date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT clock_timestamp(),
date_updated TIMESTAMP WITHOUT TIME ZONE
cuid VARCHAR,
date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT clock_timestamp(),
date_updated TIMESTAMP WITHOUT TIME ZONE
);

View File

@@ -7,14 +7,14 @@
-- DROP TABLE edit_group;
CREATE TABLE edit_group (
edit_group_id SERIAL PRIMARY KEY,
edit_scheme_id INT,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT DEFAULT 0,
uid VARCHAR,
name VARCHAR,
additional_acl JSONB
edit_group_id SERIAL PRIMARY KEY,
edit_scheme_id INT,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT DEFAULT 0,
uid VARCHAR,
name VARCHAR,
additional_acl JSONB
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -8,11 +8,11 @@
-- DROP TABLE edit_language;
CREATE TABLE edit_language (
edit_language_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
lang_default SMALLINT NOT NULL DEFAULT 0,
long_name VARCHAR,
short_name VARCHAR, -- en_US, en or en_US@latin without encoding
iso_name VARCHAR, -- should actually be encoding
order_number INT
edit_language_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
lang_default SMALLINT NOT NULL DEFAULT 0,
long_name VARCHAR,
short_name VARCHAR, -- en_US, en or en_US@latin without encoding
iso_name VARCHAR, -- should actually be encoding
order_number INT
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,35 +7,35 @@
-- DROP TABLE edit_log;
CREATE TABLE edit_log (
edit_log_id SERIAL PRIMARY KEY,
euid INT, -- this is a foreign key, but I don't nedd to reference to it
FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL,
username VARCHAR,
password VARCHAR,
event_date TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ip VARCHAR,
error TEXT,
event TEXT,
data_binary BYTEA,
data TEXT,
page VARCHAR,
action VARCHAR,
action_id VARCHAR,
action_yes VARCHAR,
action_flag VARCHAR,
action_menu VARCHAR,
action_loaded VARCHAR,
action_value VARCHAR,
action_type VARCHAR,
action_error VARCHAR,
user_agent VARCHAR,
referer VARCHAR,
script_name VARCHAR,
query_string VARCHAR,
server_name VARCHAR,
http_host VARCHAR,
http_accept VARCHAR,
http_accept_charset VARCHAR,
http_accept_encoding VARCHAR,
session_id VARCHAR
edit_log_id SERIAL PRIMARY KEY,
euid INT, -- this is a foreign key, but I don't nedd to reference to it
FOREIGN KEY (euid) REFERENCES edit_user (edit_user_id) MATCH FULL ON UPDATE CASCADE ON DELETE SET NULL,
username VARCHAR,
password VARCHAR,
event_date TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
ip VARCHAR,
error TEXT,
event TEXT,
data_binary BYTEA,
data TEXT,
page VARCHAR,
action VARCHAR,
action_id VARCHAR,
action_yes VARCHAR,
action_flag VARCHAR,
action_menu VARCHAR,
action_loaded VARCHAR,
action_value VARCHAR,
action_type VARCHAR,
action_error VARCHAR,
user_agent VARCHAR,
referer VARCHAR,
script_name VARCHAR,
query_string VARCHAR,
server_name VARCHAR,
http_host VARCHAR,
http_accept VARCHAR,
http_accept_charset VARCHAR,
http_accept_encoding VARCHAR,
session_id VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,10 +7,10 @@
-- DROP TABLE edit_menu_group;
CREATE TABLE edit_menu_group (
edit_menu_group_id SERIAL PRIMARY KEY,
name VARCHAR,
flag VARCHAR,
order_number INT NOT NULL
edit_menu_group_id SERIAL PRIMARY KEY,
name VARCHAR,
flag VARCHAR,
order_number INT NOT NULL
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,16 +7,16 @@
-- DROP TABLE edit_page;
CREATE TABLE edit_page (
edit_page_id SERIAL PRIMARY KEY,
content_alias_edit_page_id INT, -- alias for page content, if the page content is defined on a different page, ege for ajax backend pages
FOREIGN KEY (content_alias_edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
filename VARCHAR,
name VARCHAR UNIQUE,
order_number INT NOT NULL,
online SMALLINT NOT NULL DEFAULT 0,
menu SMALLINT NOT NULL DEFAULT 0,
popup SMALLINT NOT NULL DEFAULT 0,
popup_x SMALLINT,
popup_y SMALLINT,
hostname VARCHAR
edit_page_id SERIAL PRIMARY KEY,
content_alias_edit_page_id INT, -- alias for page content, if the page content is defined on a different page, ege for ajax backend pages
FOREIGN KEY (content_alias_edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
filename VARCHAR,
name VARCHAR UNIQUE,
order_number INT NOT NULL,
online SMALLINT NOT NULL DEFAULT 0,
menu SMALLINT NOT NULL DEFAULT 0,
popup SMALLINT NOT NULL DEFAULT 0,
popup_x SMALLINT,
popup_y SMALLINT,
hostname VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,14 +7,14 @@
-- DROP TABLE edit_page_access;
CREATE TABLE edit_page_access (
edit_page_access_id SERIAL PRIMARY KEY,
edit_group_id INT NOT NULL,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0
edit_page_access_id SERIAL PRIMARY KEY,
edit_group_id INT NOT NULL,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -8,13 +8,13 @@
-- DROP TABLE edit_page_content;
CREATE TABLE edit_page_content (
edit_page_content_id SERIAL PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
uid VARCHAR UNIQUE,
name VARCHAR,
order_number INT NOT NULL,
online SMALLINT NOT NULL DEFAULT 0
edit_page_content_id SERIAL PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
uid VARCHAR UNIQUE,
name VARCHAR,
order_number INT NOT NULL,
online SMALLINT NOT NULL DEFAULT 0
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,8 +7,8 @@
-- DROP TABLE edit_page_menu_group;
CREATE TABLE edit_page_menu_group (
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_menu_group_id INT NOT NULL,
FOREIGN KEY (edit_menu_group_id) REFERENCES edit_menu_group (edit_menu_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_menu_group_id INT NOT NULL,
FOREIGN KEY (edit_menu_group_id) REFERENCES edit_menu_group (edit_menu_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE
);

View File

@@ -7,8 +7,8 @@
-- DROP TABLE edit_page_visible_group;
CREATE TABLE edit_page_visible_group (
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_visible_group_id INT NOT NULL,
FOREIGN KEY (edit_visible_group_id) REFERENCES edit_visible_group (edit_visible_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_visible_group_id INT NOT NULL,
FOREIGN KEY (edit_visible_group_id) REFERENCES edit_visible_group (edit_visible_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE
);

View File

@@ -7,11 +7,11 @@
-- DROP TABLE edit_query_string;
CREATE TABLE edit_query_string (
edit_query_string_id SERIAL PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
value VARCHAR,
dynamic SMALLINT NOT NULL DEFAULT 0
edit_query_string_id SERIAL PRIMARY KEY,
edit_page_id INT NOT NULL,
FOREIGN KEY (edit_page_id) REFERENCES edit_page (edit_page_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
value VARCHAR,
dynamic SMALLINT NOT NULL DEFAULT 0
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,10 +7,10 @@
-- DROP TABLE edit_scheme;
CREATE TABLE edit_scheme (
edit_scheme_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
header_color VARCHAR,
css_file VARCHAR,
template VARCHAR
edit_scheme_id SERIAL PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
header_color VARCHAR,
css_file VARCHAR,
template VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -7,6 +7,6 @@
-- DROP TABLE temp_files;
CREATE TABLE temp_files (
filename VARCHAR,
folder VARCHAR
filename VARCHAR,
folder VARCHAR
);

View File

@@ -7,42 +7,93 @@
-- DROP TABLE edit_user;
CREATE TABLE edit_user (
edit_user_id SERIAL PRIMARY KEY,
connect_edit_user_id INT, -- possible reference to other user
FOREIGN KEY (connect_edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_language_id INT NOT NULL,
FOREIGN KEY (edit_language_id) REFERENCES edit_language (edit_language_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_group_id INT NOT NULL,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_scheme_id INT,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT NOT NULL DEFAULT 0,
username VARCHAR UNIQUE,
password VARCHAR,
first_name VARCHAR,
last_name VARCHAR,
first_name_furigana VARCHAR,
last_name_furigana VARCHAR,
debug SMALLINT NOT NULL DEFAULT 0,
db_debug SMALLINT NOT NULL DEFAULT 0,
email VARCHAR,
protected SMALLINT NOT NULL DEFAULT 0,
admin SMALLINT NOT NULL DEFAULT 0,
last_login TIMESTAMP WITHOUT TIME ZONE,
login_error_count INT DEFAULT 0,
login_error_date_last TIMESTAMP WITHOUT TIME ZONE,
login_error_date_first TIMESTAMP WITHOUT TIME ZONE,
strict SMALLINT DEFAULT 0,
locked SMALLINT DEFAULT 0,
password_change_date TIMESTAMP WITHOUT TIME ZONE, -- only when password is first set or changed
password_change_interval INTERVAL, -- null if no change is needed, or d/m/y time interval
password_reset_time TIMESTAMP WITHOUT TIME ZONE, -- when the password reset was requested
password_reset_uid VARCHAR, -- the uid to access the password reset page
additional_acl JSONB -- additional ACL as JSON string (can be set by other pages)
edit_user_id SERIAL PRIMARY KEY,
connect_edit_user_id INT, -- possible reference to other user
FOREIGN KEY (connect_edit_user_id) REFERENCES edit_user (edit_user_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_language_id INT NOT NULL,
FOREIGN KEY (edit_language_id) REFERENCES edit_language (edit_language_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_group_id INT NOT NULL,
FOREIGN KEY (edit_group_id) REFERENCES edit_group (edit_group_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_scheme_id INT,
FOREIGN KEY (edit_scheme_id) REFERENCES edit_scheme (edit_scheme_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
edit_access_right_id INT NOT NULL,
FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE,
-- username/password
username VARCHAR UNIQUE,
password VARCHAR,
-- name block
first_name VARCHAR,
last_name VARCHAR,
first_name_furigana VARCHAR,
last_name_furigana VARCHAR,
-- email
email VARCHAR,
-- eanbled/deleted flag
enabled SMALLINT NOT NULL DEFAULT 0,
deleted SMALLINT NOT NULL DEFAULT 0,
-- general flags
strict SMALLINT DEFAULT 0,
locked SMALLINT DEFAULT 0,
protected SMALLINT NOT NULL DEFAULT 0,
-- legacy, debug flags
debug SMALLINT NOT NULL DEFAULT 0,
db_debug SMALLINT NOT NULL DEFAULT 0,
-- is admin user
admin SMALLINT NOT NULL DEFAULT 0,
-- last login log
last_login TIMESTAMP WITHOUT TIME ZONE,
-- login error
login_error_count INT DEFAULT 0,
login_error_date_last TIMESTAMP WITHOUT TIME ZONE,
login_error_date_first TIMESTAMP WITHOUT TIME ZONE,
-- time locked
lock_until TIMESTAMP WITHOUT TIME ZONE,
lock_after TIMESTAMP WITHOUT TIME ZONE,
-- password change
password_change_date TIMESTAMP WITHOUT TIME ZONE, -- only when password is first set or changed
password_change_interval INTERVAL, -- null if no change is needed, or d/m/y time interval
password_reset_time TIMESTAMP WITHOUT TIME ZONE, -- when the password reset was requested
password_reset_uid VARCHAR, -- the uid to access the password reset page
-- _GET login id for direct login
login_user_id VARCHAR UNIQUE, -- the loginUserId, at least 32 chars
login_user_id_set_date TIMESTAMP WITHOUT TIME ZONE, -- when above uid was set
login_user_id_last_revalidate TIMESTAMP WITHOUT TIME ZONE, -- when the last login was done with user name and password
login_user_id_valid_from TIMESTAMP WITHOUT TIME ZONE, -- if set, from when the above uid is valid
login_user_id_valid_until TIMESTAMP WITHOUT TIME ZONE, -- if set, until when the above uid is valid
login_user_id_revalidate_after INTERVAL, -- user must login to revalidated loginUserId after set days, 0 for forever
login_user_id_locked SMALLINT DEFAULT 0, -- lock for loginUserId, but still allow normal login
-- additional ACL json block
additional_acl JSONB -- additional ACL as JSON string (can be set by other pages)
) INHERITS (edit_generic) WITHOUT OIDS;
-- create unique index
-- CREATE UNIQUE INDEX edit_user_login_user_id_key ON edit_user (login_user_id) WHERE login_user_id IS NOT NULL;
COMMENT ON COLUMN edit_user.username IS 'Login username, must set';
COMMENT ON COLUMN edit_user.password IS 'Login password, must set';
COMMENT ON COLUMN edit_user.enabled IS 'Login is enabled (master switch)';
COMMENT ON COLUMN edit_user.deleted IS 'Login is deleted (master switch), overrides all other';
COMMENT ON COLUMN edit_user.strict IS 'If too many failed logins user will be locked, default off';
COMMENT ON COLUMN edit_user.locked IS 'Locked from too many wrong password logins';
COMMENT ON COLUMN edit_user.protected IS 'User can only be chnaged by admin user';
COMMENT ON COLUMN edit_user.debug IS 'Turn debug flag on (legacy)';
COMMENT ON COLUMN edit_user.db_debug IS 'Turn DB debug flag on (legacy)';
COMMENT ON COLUMN edit_user.admin IS 'If set, this user is SUPER admin';
COMMENT ON COLUMN edit_user.last_login IS 'Last succesfull login tiemstamp';
COMMENT ON COLUMN edit_user.login_error_count IS 'Number of failed logins, reset on successful login';
COMMENT ON COLUMN edit_user.login_error_date_last IS 'Last login error date';
COMMENT ON COLUMN edit_user.login_error_date_first IS 'First login error date, reset on successfull login';
COMMENT ON COLUMN edit_user.lock_until IS 'Account is locked until this date, <';
COMMENT ON COLUMN edit_user.lock_after IS 'Account is locked after this date, >';
COMMENT ON COLUMN edit_user.password_change_date IS 'Password was changed on';
COMMENT ON COLUMN edit_user.password_change_interval IS 'After how many days the password has to be changed';
COMMENT ON COLUMN edit_user.password_reset_time IS 'When the password reset was requested. For reset page uid valid check';
COMMENT ON COLUMN edit_user.password_reset_uid IS 'Password reset page uid';
COMMENT ON COLUMN edit_user.password_reset_uid IS 'Password reset page uid, one time, invalid after reset successful or time out';
COMMENT ON COLUMN edit_user.login_user_id IS 'Min 32 character UID to be used to login without password. Via GET/POST parameter';
COMMENT ON COLUMN edit_user.login_user_id_set_date IS 'loginUserId was set at what date';
COMMENT ON COLUMN edit_user.login_user_id_last_revalidate IS 'set when username/password login is done and loginUserId is set';
COMMENT ON COLUMN edit_user.login_user_id_valid_from IS 'loginUserId is valid from this date, >=';
COMMENT ON COLUMN edit_user.login_user_id_valid_until IS 'loginUserId is valid until this date, <=';
COMMENT ON COLUMN edit_user.login_user_id_revalidate_after IS 'If set to a number greater 0 then user must login after given amount of days to revalidate the loginUserId, set to 0 for valid forver';
COMMENT ON COLUMN edit_user.login_user_id_locked IS 'A separte lock flag for loginUserId, user can still login normal';
COMMENT ON COLUMN edit_user.additional_acl IS 'Additional Access Control List stored in JSON format';

View File

@@ -7,7 +7,7 @@
-- DROP TABLE edit_visible_group;
CREATE TABLE edit_visible_group (
edit_visible_group_id SERIAL PRIMARY KEY,
name VARCHAR,
flag VARCHAR
edit_visible_group_id SERIAL PRIMARY KEY,
name VARCHAR,
flag VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;

View File

@@ -1,12 +1,13 @@
-- AUTHOR: Clemens Schwaighofer
-- DATE: 2005/07/05
-- DESCRIPTION:
-- cms tables; generic basic table
-- generic basic table with date and uid column
-- TABLE: generic
-- HISTORY:
-- DROP TABLE edit_generic;
-- DROP TABLE generic;
CREATE TABLE generic (
date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT clock_timestamp(),
date_updated TIMESTAMP WITHOUT TIME ZONE
date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT clock_timestamp(),
date_updated TIMESTAMP WITHOUT TIME ZONE,
uid VARCHAR
);

View File

@@ -0,0 +1,81 @@
--
SELECT
eu.cuid, eu.username,
eu.lock_until, eu.lock_after,
CASE WHEN (
(eu.lock_until IS NULL
OR (eu.lock_until IS NOT NULL AND NOW() >= eu.lock_until))
AND (eu.lock_after IS NULL
OR (eu.lock_after IS NOT NULL AND NOW() <= eu.lock_after))
) THEN 0::INT ELSE 1::INT END locked_period
FROM edit_user eu
WHERE eu.username = 'empty';
UPDATE edit_user SET
lock_until = NOW() + '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET
lock_after = NOW() - '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET
lock_until = NOW() - '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET
lock_after = NOW() + '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET lock_until = NULL, lock_after = NULL WHERE username = 'empty';
--
SELECT
eu.cuid, eu.username,
eu.login_user_id, login_user_id_set_date, eu.login_user_id_last_revalidate,
(eu.login_user_id_last_revalidate + eu.login_user_id_revalidate_after)::DATE AS reval_date, NOW()::DATE,
eu.login_user_id_valid_from, eu.login_user_id_valid_until,
eu.login_user_id_revalidate_after,
CASE WHEN (
(eu.login_user_id_valid_from IS NULL
OR (eu.login_user_id_valid_from IS NOT NULL AND NOW() >= eu.login_user_id_valid_from))
AND (eu.login_user_id_valid_until IS NULL
OR (eu.login_user_id_valid_until IS NOT NULL AND NOW() <= eu.login_user_id_valid_until))
) THEN 1::INT ELSE 0::INT END AS login_user_id_valid_date,
CASE WHEN eu.login_user_id_revalidate_after IS NOT NULL
AND eu.login_user_id_revalidate_after > '0 days'::INTERVAL
AND (eu.login_user_id_last_revalidate + eu.login_user_id_revalidate_after)::DATE <= NOW()::DATE
THEN 1::INT ELSE 0::INT END AS login_user_id_revalidate
FROM edit_user eu
WHERE eu.username = 'empty';
-- init
UPDATE edit_user SET login_user_id = random_string(5) WHERE username = 'empty';
-- outside valid
UPDATE edit_user SET
login_user_id_valid_from = NOW() - '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET
login_user_id_valid_until = NOW() + '1 day'::interval
WHERE username = 'empty';
-- inside valid
UPDATE edit_user SET
login_user_id_valid_from = NOW() + '1 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET
login_user_id_valid_until = NOW() - '1 day'::interval
WHERE username = 'empty';
-- revalidate must
UPDATE edit_user SET
login_user_id_last_revalidate = NOW() - '1 day'::interval,
login_user_id_revalidate_after = '1 day'::interval
WHERE username = 'empty';
-- revalidate not yet
UPDATE edit_user SET
login_user_id_last_revalidate = NOW(),
login_user_id_revalidate_after = '6 day'::interval
WHERE username = 'empty';
UPDATE edit_user SET login_user_id_set_date = NULL, login_user_id_last_revalidate = NULL, login_user_id_valid_from = NULL, login_user_id_valid_until = NULL, login_user_id_revalidate_after = NULL WHERE username = 'empty';

View File

@@ -1,9 +1,9 @@
DROP TRIGGER IF EXISTS trg_edit_access ON edit_access;
-- DROP TRIGGER IF EXISTS trg_edit_access ON edit_access;
CREATE TRIGGER trg_edit_access
BEFORE INSERT OR UPDATE ON edit_access
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();
DROP TRIGGER IF EXISTS trg_set_edit_access_uid ON edit_access;
-- DROP TRIGGER IF EXISTS trg_set_edit_access_uid ON edit_access;
CREATE TRIGGER trg_set_edit_access_uid
BEFORE INSERT OR UPDATE ON edit_access
FOR EACH ROW EXECUTE PROCEDURE set_edit_access_uid();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_access_data ON edit_access_data;
-- DROP TRIGGER IF EXISTS trg_edit_access_data ON edit_access_data;
CREATE TRIGGER trg_edit_access_data
BEFORE INSERT OR UPDATE ON edit_access_data
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_access_right ON edit_access_right;
-- DROP TRIGGER IF EXISTS trg_edit_access_right ON edit_access_right;
CREATE TRIGGER trg_edit_access_right
BEFORE INSERT OR UPDATE ON edit_access_right
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_access_user ON edit_access_user;
-- DROP TRIGGER IF EXISTS trg_edit_access_user ON edit_access_user;
CREATE TRIGGER trg_edit_access_user
BEFORE INSERT OR UPDATE ON edit_access_user
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,9 +1,9 @@
DROP TRIGGER IF EXISTS trg_edit_group ON edit_group;
-- DROP TRIGGER IF EXISTS trg_edit_group ON edit_group;
CREATE TRIGGER trg_edit_group
BEFORE INSERT OR UPDATE ON edit_group
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();
DROP TRIGGER IF EXISTS trg_set_edit_group_uid ON edit_group;
-- DROP TRIGGER IF EXISTS trg_set_edit_group_uid ON edit_group;
CREATE TRIGGER trg_set_edit_group_uid
BEFORE INSERT OR UPDATE ON edit_group
FOR EACH ROW EXECUTE PROCEDURE set_edit_group_uid();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_language ON edit_language;
-- DROP TRIGGER IF EXISTS trg_edit_language ON edit_language;
CREATE TRIGGER trg_edit_language
BEFORE INSERT OR UPDATE ON edit_language
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,9 +1,9 @@
DROP TRIGGER IF EXISTS trg_edit_log ON edit_log;
-- DROP TRIGGER IF EXISTS trg_edit_log ON edit_log;
CREATE TRIGGER trg_edit_log
BEFORE INSERT OR UPDATE ON edit_log
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();
DROP TRIGGER IF EXISTS trg_edit_log_insert_partition ON edit_log;
-- DROP TRIGGER IF EXISTS trg_edit_log_insert_partition ON edit_log;
CREATE TRIGGER trg_edit_log_insert_partition
BEFORE INSERT OR UPDATE ON edit_log
FOR EACH ROW EXECUTE PROCEDURE edit_log_insert_trigger();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_log_overflow ON edit_log_overflow;
-- DROP TRIGGER IF EXISTS trg_edit_log_overflow ON edit_log_overflow;
CREATE TRIGGER trg_edit_log_overflow
BEFORE INSERT OR UPDATE ON edit_log_overflow
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_menu_group ON edit_menu_group;
-- DROP TRIGGER IF EXISTS trg_edit_menu_group ON edit_menu_group;
CREATE TRIGGER trg_edit_menu_group
BEFORE INSERT OR UPDATE ON edit_menu_group
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_page ON edit_page;
-- DROP TRIGGER IF EXISTS trg_edit_page ON edit_page;
CREATE TRIGGER trg_edit_page
BEFORE INSERT OR UPDATE ON edit_page
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_page_access ON edit_page_access;
-- DROP TRIGGER IF EXISTS trg_edit_page_access ON edit_page_access;
CREATE TRIGGER trg_edit_page_access
BEFORE INSERT OR UPDATE ON edit_page_access
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_page_content ON edit_page_content;
-- DROP TRIGGER IF EXISTS trg_edit_page_content ON edit_page_content;
CREATE TRIGGER trg_edit_page_content
BEFORE INSERT OR UPDATE ON edit_page_content
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_query_string ON edit_query_string;
-- DROP TRIGGER IF EXISTS trg_edit_query_string ON edit_query_string;
CREATE TRIGGER trg_edit_query_string
BEFORE INSERT OR UPDATE ON edit_query_string
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_scheme ON edit_scheme;
-- DROP TRIGGER IF EXISTS trg_edit_scheme ON edit_scheme;
CREATE TRIGGER trg_edit_scheme
BEFORE INSERT OR UPDATE ON edit_scheme
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -1,4 +1,9 @@
DROP TRIGGER IF EXISTS trg_edit_user ON edit_user;
-- DROP TRIGGER IF EXISTS trg_edit_user ON edit_user;
CREATE TRIGGER trg_edit_user
BEFORE INSERT OR UPDATE ON edit_user
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();
-- DROP TRIGGER IF EXISTS trg_edit_user_set_login_user_id_set_date ON edit_user;
CREATE TRIGGER trg_edit_user_set_login_user_id_set_date
BEFORE INSERT OR UPDATE ON edit_user
FOR EACH ROW EXECUTE PROCEDURE set_login_user_id_set_date();

View File

@@ -1,4 +1,4 @@
DROP TRIGGER IF EXISTS trg_edit_visible_group ON edit_visible_group;
-- DROP TRIGGER IF EXISTS trg_edit_visible_group ON edit_visible_group;
CREATE TRIGGER trg_edit_visible_group
BEFORE INSERT OR UPDATE ON edit_visible_group
FOR EACH ROW EXECUTE PROCEDURE set_edit_generic();

View File

@@ -25,7 +25,7 @@ declare(strict_types=1);
* 1 for file loadable, but no data inside
* 2 for file not readable
* 3 for file not found
* @deprecated V6 Use \CoreLibs\Get\ReadEnvFile::readEnvFile()
* @deprecated V6 Use \CoreLibs\Get\DotEnv::readEnvFile()
*/
function readEnvFile(string $path = __DIR__, string $env_file = '.env'): int
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# note: there is currently no port selection, standard 5432 port is assumed
# note: we use the default in path postgresql commands and connect to whatever default DB is set
# PARAMETER 1: database data file to load
# PARAMETER 2: db user WHO MUST BE ABLE TO CREATE A DATABASE
# PARAMETER 3: db name
# PARAMETER 4: db host
# PARAMETER 5: print out for testing
load_sql="${1}";
# abort with 1 if we cannot find the file
if [ ! -f "${load_sql}" ]; then
echo 1;
exit 1;
fi;
db_user="${2}";
db_name="${3}";
db_host="${4}";
# empty db name or db user -> exit with 2
if [ -z "${db_user}" ] || [ -z "${db_name}" ] || [ -z "${db_host}" ]; then
echo 2;
exit 2;
fi;
# drop database, on error exit with 3
dropdb -U ${db_user} -h ${db_host} ${db_name} 2>&1;
if [ $? -ne 0 ]; then
echo 3;
exit 3;
fi;
# create database, on error exit with 4
createdb -U ${db_user} -O ${db_user} -h ${db_host} -E utf8 ${db_name} 2>&1;
if [ $? -ne 0 ]; then
echo 4;
exit 4;
fi;
# if error 5 thrown, test with enabled below
if [ ! -z "${5}" ]; then
psql -U ${db_user} -h ${db_host} -f ${load_sql} ${db_name};
else
# load data (redirect ALL error to null), on error exit with 5
psql -U ${db_user} -h ${db_host} -f ${load_sql} ${db_name} 2>&1 1>/dev/null 2>/dev/null;
fi;
if [ $? -ne 0 ]; then
echo 5;
exit 5;
fi;
echo 0;
exit 0;
# __END__

View File

@@ -92,6 +92,7 @@ final class CoreLibsCheckEncodingTest extends TestCase
$error_char,
$expected
): void {
$current_subsitute_character = mb_substitute_character();
if ($error_char !== null) {
\CoreLibs\Check\Encoding::setErrorChar($error_char);
if (!in_array($error_char, ['none', 'long', 'entity'])) {
@@ -111,6 +112,8 @@ final class CoreLibsCheckEncodingTest extends TestCase
$expected,
$return
);
// reset after test
mb_substitute_character($current_subsitute_character);
}
}

View File

@@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsCombinedDateTimeTest extends TestCase
{
/**
* timestamps
*
@@ -618,13 +617,169 @@ final class CoreLibsCombinedDateTimeTest extends TestCase
* @param array $expected
* @return void
*/
public function testCalcDaysInterval(string $input_a, string $input_b, bool $flag, $expected): void
{
public function testCalcDaysInterval(
string $input_a,
string $input_b,
bool $flag,
$expected
): void {
$this->assertEquals(
$expected,
\CoreLibs\Combined\DateTime::calcDaysInterval($input_a, $input_b, $flag)
);
}
/**
* Undocumented function
*
* @return array
*/
public function weekdayNumberProvider(): array
{
return [
'0 invalid' => [0, null, 'Inv',],
'0 invalid long' => [0, true, 'Invalid',],
'1 short' => [1, null, 'Mon',],
'1 long' => [1, true, 'Monday',],
'2 short' => [2, null, 'Tue',],
'2 long' => [2, true, 'Tuesday',],
'3 short' => [3, null, 'Wed',],
'3 long' => [3, true, 'Wednesday',],
'4 short' => [4, null, 'Thu',],
'4 long' => [4, true, 'Thursday',],
'5 short' => [5, null, 'Fri',],
'5 long' => [5, true, 'Friday',],
'6 short' => [6, null, 'Sat',],
'6 long' => [6, true, 'Saturday',],
'7 short' => [7, null, 'Sun',],
'7 long' => [7, true, 'Sunday',],
'8 invalid' => [8, null, 'Inv',],
'8 invalid long' => [8, true, 'Invalid',],
];
}
/**
* int weekday number to string weekday
*
* @covers ::setWeekdayNameFromIsoDow
* @dataProvider weekdayNumberProvider
* @testdox weekdayListProvider $input (short $flag) will be $expected [$_dataName]
*
* @param int $input
* @param bool|null $flag
* @param string $expected
* @return void
*/
public function testSetWeekdayNameFromIsoDow(
int $input,
?bool $flag,
string $expected
): void {
if ($flag === null) {
$output = \CoreLibs\Combined\DateTime::setWeekdayNameFromIsoDow($input);
} else {
$output = \CoreLibs\Combined\DateTime::setWeekdayNameFromIsoDow($input, $flag);
}
$this->assertEquals(
$expected,
$output
);
}
/**
* Undocumented function
*
* @return array
*/
public function weekdayDateProvider(): array
{
return [
'invalid date' => ['2022-02-31', -1],
'1: monday' => ['2022-07-25', 1],
'2: tuesday' => ['2022-07-26', 2],
'3: wednesday' => ['2022-07-27', 3],
'4: thursday' => ['2022-07-28', 4],
'5: friday' => ['2022-07-29', 5],
'6: saturday' => ['2022-07-30', 6],
'7: sunday' => ['2022-07-31', 7],
];
}
/**
* date to weekday number
*
* @covers ::setWeekdayNumberFromDate
* @dataProvider weekdayDateProvider
* @testdox setWeekdayNumberFromDate $input will be $expected [$_dataName]
*
* @param string $input
* @param int $expected
* @return void
*/
public function testSetWeekdayNumberFromDate(
string $input,
int $expected
): void {
$this->assertEquals(
$expected,
\CoreLibs\Combined\DateTime::setWeekdayNumberFromDate($input)
);
}
/**
* Undocumented function
*
* @return array
*/
public function weekdayDateNameProvider(): array
{
return [
'invalid date short' => ['2022-02-31', null, 'Inv'],
'invalid date long' => ['2022-02-31', true, 'Invalid'],
'Mon short' => ['2022-07-25', null, 'Mon'],
'Monday long' => ['2022-07-25', true, 'Monday'],
'Tue short' => ['2022-07-26', null, 'Tue'],
'Tuesday long' => ['2022-07-26', true, 'Tuesday'],
'Wed short' => ['2022-07-27', null, 'Wed'],
'Wednesday long' => ['2022-07-27', true, 'Wednesday'],
'Thu short' => ['2022-07-28', null, 'Thu'],
'Thursday long' => ['2022-07-28', true, 'Thursday'],
'Fri short' => ['2022-07-29', null, 'Fri'],
'Friday long' => ['2022-07-29', true, 'Friday'],
'Sat short' => ['2022-07-30', null, 'Sat'],
'Saturday long' => ['2022-07-30', true, 'Saturday'],
'Sun short' => ['2022-07-31', null, 'Sun'],
'Sunday long' => ['2022-07-31', true, 'Sunday'],
];
}
/**
* date to weekday name
*
* @covers ::setWeekdayNameFromDate
* @dataProvider weekdayDateNameProvider
* @testdox setWeekdayNameFromDate $input (short $flag) will be $expected [$_dataName]
*
* @param string $input
* @param bool|null $flag
* @param string $expected
* @return void
*/
public function testSetWeekdayNameFromDate(
string $input,
?bool $flag,
string $expected
): void {
if ($flag === null) {
$output = \CoreLibs\Combined\DateTime::setWeekdayNameFromDate($input);
} else {
$output = \CoreLibs\Combined\DateTime::setWeekdayNameFromDate($input, $flag);
}
$this->assertEquals(
$expected,
$output
);
}
}
// __END__

View File

@@ -16,7 +16,6 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsConvertByteTest extends TestCase
{
/**
* Undocumented function
*
@@ -24,7 +23,31 @@ final class CoreLibsConvertByteTest extends TestCase
*/
public function byteProvider(): array
{
/*
* 0: input string
* 1: default flags
* 2: BYTE_FORMAT_SI
* 3: BYTE_FORMAT_NOSPACE
* 4: BYTE_FORMAT_ADJUST
* 5: BYTE_FORMAT_SI | BYTE_FORMAT_NOSPACE
*/
return [
'string number' => [
0 => '1024',
1 => '1 KB',
2 => '1.02 KiB',
3 => '1KB',
4 => '1.00 KB',
5 => '1.02KiB',
],
'invalud string number' => [
0 => '1024 MB',
1 => '1024 MB',
2 => '1024 MB',
3 => '1024 MB',
4 => '1024 MB',
5 => '1024 MB',
],
'negative number' => [
0 => -123123123,
1 => '-117.42 MB',

View File

@@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsConvertJsonTest extends TestCase
{
/**
* test list for json convert tests
*

View File

@@ -0,0 +1,261 @@
<?php // phpcs:disable Generic.Files.LineLength
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
/**
* Test class for Convert\Strings
* @coversDefaultClass \CoreLibs\Convert\Strings
* @testdox \CoreLibs\Convert\Strings method tests
*/
final class CoreLibsConvertStringsTest extends TestCase
{
/**
* Undocumented function
*
* @return array
*/
public function splitFormatStringProvider(): array
{
// 0: input
// 1: format
// 2: split characters as string, null for default
// 3: expected
return [
'all empty string' => [
'',
'',
null,
''
],
'empty input string' => [
'',
'2-2',
null,
''
],
'empty format string string' => [
'1234',
'',
null,
'1234'
],
'string format match' => [
'1234',
'2-2',
null,
'12-34'
],
'string format trailing match' => [
'1234',
'2-2-',
null,
'12-34'
],
'string format leading match' => [
'1234',
'-2-2',
null,
'12-34'
],
'string format double inside match' => [
'1234',
'2--2',
null,
'12--34',
],
'string format short first' => [
'1',
'2-2',
null,
'1'
],
'string format match first' => [
'12',
'2-2',
null,
'12'
],
'string format short second' => [
'123',
'2-2',
null,
'12-3'
],
'string format too long' => [
'1234567',
'2-2',
null,
'12-34-567'
],
'string format invalid format string' => [
'1234',
'2_2',
null,
'1234'
],
'different split character' => [
'1234',
'2_2',
'_',
'12_34'
],
'mixed split characters' => [
'123456',
'2-2_2',
'-_',
'12-34_56'
],
'length mixed' => [
'ABCD12345568ABC13',
'2-4_5-2#4',
'-_#',
'AB-CD12_34556-8A#BC13'
],
'split with split chars in string' => [
'12-34',
'2-2',
null,
'12--3-4'
],
'mutltibyte string' => [
'あいうえ',
'2-2',
null,
'あいうえ'
],
'mutltibyte split string' => [
'1234',
'-',
null,
'1234'
],
];
}
/**
* split format string
*
* @covers ::splitFormatString
* @dataProvider splitFormatStringProvider
* @testdox splitFormatString $input with format $format and splitters $split_characters will be $expected [$_dataName]
*
* @param string $input
* @param string $format
* @param string|null $split_characters
* @param string $expected
* @return void
*/
public function testSplitFormatString(
string $input,
string $format,
?string $split_characters,
string $expected
): void {
if ($split_characters === null) {
$output = \CoreLibs\Convert\Strings::splitFormatString(
$input,
$format
);
} else {
$output = \CoreLibs\Convert\Strings::splitFormatString(
$input,
$format,
$split_characters
);
}
$this->assertEquals(
$expected,
$output
);
}
/**
* Undocumented function
*
* @return array
*/
public function countSplitPartsProvider(): array
{
return [
'0 elements' => [
'',
null,
0
],
'1 element' => [
'1',
null,
1,
],
'2 elements, trailing' => [
'1-2-',
null,
2
],
'2 elements, leading' => [
'-1-2',
null,
2
],
'2 elements, midde double' => [
'1--2',
null,
2
],
'4 elements' => [
'1-2-3-4',
null,
4
],
'3 elemenst, other splitter' => [
'2-3_3',
'-_',
3
],
'illegal splitter' => [
'あsdf',
null,
0
]
];
}
/**
* count split parts
*
* @covers ::countSplitParts
* @dataProvider countSplitPartsProvider
* @testdox countSplitParts $input with splitters $split_characters will be $expected [$_dataName]
*
* @param string $input
* @param string|null $split_characters
* @param int $expected
* @return void
*/
public function testCountSplitParts(
string $input,
?string $split_characters,
int $expected
): void {
if ($split_characters === null) {
$output = \CoreLibs\Convert\Strings::countSplitParts(
$input
);
} else {
$output = \CoreLibs\Convert\Strings::countSplitParts(
$input,
$split_characters
);
}
$this->assertEquals(
$expected,
$output
);
}
}
// __END__

View File

@@ -0,0 +1,700 @@
<?php
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
/**
* Test class for Create\Email
* @coversDefaultClass \CoreLibs\Create\Email
* @testdox \CoreLibs\Create\Email method tests
*/
final class CoreLibsCreateEmailTest extends TestCase
{
private static $log;
/**
* start DB conneciton, setup DB, etc
*
* @return void
*/
public static function setUpBeforeClass(): void
{
self::$log = new \CoreLibs\Debug\Logging([
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'file_id' => 'CoreLibs-Create-Email-Test',
'debug_all' => true,
'echo_all' => false,
'print_all' => true,
]);
}
/**
* Undocumented function
*
* @return array
*/
public function encodeEmailNameProvider(): array
{
// 0: email
// 1: name
// 2: encoding
// 3: kv_folding
// 4: expected
return [
'all empty' => [
'',
null,
null,
null,
''
],
'email only' => [
'test@test.com',
null,
null,
null,
'test@test.com'
],
'email and name' => [
'test@test.com',
'Test Name',
null,
null,
'"Test Name" <test@test.com>'
],
'name in mime encoded, default UTF-8' => [
'test@test.com',
'日本語',
null,
null,
'"=?UTF-8?B?5pel5pys6Kqe?=" <test@test.com>'
],
'name in mime encoded with half width Katakana, default UTF-8' => [
'test@test.com',
'日本語カタカナパ',
null,
null,
'"=?UTF-8?B?5pel5pys6Kqe7722776A7722776F776K776f?=" <test@test.com>'
],
'name in mime encoded with half width Katakana, folding on, default UTF-8' => [
'test@test.com',
'日本語カタカナパ',
'UTF-8',
true,
'"=?UTF-8?B?5pel5pys6Kqe44Kr44K/44Kr44OK44OR?=" <test@test.com>'
],
'name in mime encoded, UTF-8 parameter' => [
'test@test.com',
'日本語',
'UTF-8',
null,
'"=?UTF-8?B?5pel5pys6Kqe?=" <test@test.com>'
],
// does internal UTF-8 to ISO-2022-JP convert
'encoding in ISO-2022-JP' => [
'test@test.com',
'日本語',
'ISO-2022-JP',
null,
'"=?ISO-2022-JP?B?GyRCRnxLXDhsGyhC?=" <test@test.com>'
],
'encoding with half width Katakana in ISO-2022-JP' => [
'test@test.com',
'日本語カタカナパ',
'ISO-2022-JP',
null,
'"=?ISO-2022-JP?B?GyRCRnxLXDhsGyhCPz8/Pz8/?=" <test@test.com>'
],
'encoding with half width Katakana, folding on in ISO-2022-JP' => [
'test@test.com',
'日本語カタカナパ',
'ISO-2022-JP',
true,
// was ok php 8.1
// '"=?ISO-2022-JP?B?GyRCRnxLXDhsGyhCPz8/Pz8=?=" <test@test.com>'
// below ok php 8.1.12, 2022/12/9
'"=?ISO-2022-JP?B?GyRCRnxLXDhsGyhCPz8/Pz8/?=" <test@test.com>'
]
];
}
/**
* Undocumented function
*
* @dataProvider encodeEmailNameProvider
* @testdox encode email $email, name $name, encoding $encoding, folding $kv_folding will be $expected [$_dataName]
*
* @param string $email
* @param string|null $name
* @param string|null $encoding
* @param bool|null $kv_folding
* @param string $expected
* @return void
*/
public function testEncodeEmailName(
string $email,
?string $name,
?string $encoding,
?bool $kv_folding,
string $expected
): void {
if ($name === null && $encoding === null && $kv_folding === null) {
$encoded_email = \CoreLibs\Create\Email::encodeEmailName($email);
} elseif ($encoding === null && $kv_folding === null) {
$encoded_email = \CoreLibs\Create\Email::encodeEmailName($email, $name);
} elseif ($kv_folding === null) {
$encoded_email = \CoreLibs\Create\Email::encodeEmailName($email, $name, $encoding);
} else {
$encoded_email = \CoreLibs\Create\Email::encodeEmailName($email, $name, $encoding, $kv_folding);
}
$this->assertEquals(
$expected,
$encoded_email
);
}
public function sendEmailProvider(): array
{
// 0: subject
// 1: body
// 2: from email
// 3: from name ('')
// 4: array for to email
// 5: replace content ([]/null)
// 6: encoding (UTF-8/null)
// 7: kv_folding
// 8: return status
// 9: expected content
return [
'all empty, fail -1' => [
'subject' => '',
'body' => '',
'from_email' => '',
'from_name' => '',
'to_email' => [],
'replace' => null,
'encoding' => null,
'kv_folding' => null,
'expected_status' => -1,
'expected_content' => [],
],
'missing to entry, fail -2' => [
'subject' => 'SUBJECT',
'body' => 'BODY',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [],
'replace' => null,
'encoding' => null,
'kv_folding' => null,
'expected_status' => -2,
'expected_content' => [],
],
'bad encoding, fail -3' => [
'subject' => 'SUBJECT',
'body' => 'BODY',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => ['to@test.com'],
'replace' => null,
'encoding' => 'IDONTEXISTENCODING',
'kv_folding' => null,
'expected_status' => -3,
'expected_content' => [],
],
'sending email 1' => [
'subject' => 'SUBJECT',
'body' => 'BODY',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => null,
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT',
'body' => 'BODY',
]
],
],
'sending email 1, encoded' => [
'subject' => 'SUBJECT 日本語',
'body' => 'BODY 日本語',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => null,
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6Kqe?=',
'body' => 'BODY 日本語',
]
],
],
'sending email 1, encoded, with half width katakanata' => [
'subject' => 'SUBJECT 日本語カタカナパ',
'body' => 'BODY 日本語',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => null,
'encoding' => 'UTF-8',
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6Kqe7722776A7722776F776K776f?=',
'body' => 'BODY 日本語',
]
],
],
'sending email 1, encoded, with half width katakanata, folding on' => [
'subject' => 'SUBJECT 日本語カタカナパ',
'body' => 'BODY 日本語',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => null,
'encoding' => 'UTF-8',
'kv_folding' => true,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6Kqe44Kr44K/44Kr44OK44OR?=',
'body' => 'BODY 日本語',
]
],
],
'sending email 1, encoded subject ISO-2022-JP' => [
'subject' => 'SUBJECT 日本語',
'body' => 'BODY 日本語',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => null,
'encoding' => 'ISO-2022-JP',
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?ISO-2022-JP?B?GyRCRnxLXDhsGyhC?=',
// body is stored as UTF-8 in log and here, so both must be translated
'body' => 'BODY 日本語',
]
],
],
'sending email 2' => [
'subject' => 'SUBJECT',
'body' => 'BODY',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'e1@test.com',
'e2@test.com'
],
'replace' => null,
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'e1@test.com',
'subject' => 'SUBJECT',
'body' => 'BODY',
],
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'e2@test.com',
'subject' => 'SUBJECT',
'body' => 'BODY',
]
],
],
'sending email 1: dynamic' => [
'subject' => 'SUBJECT {FOO}',
'body' => 'BODY {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT foo',
'body' => 'BODY foo bar',
]
],
],
'sending email 1: dynamic encoded' => [
'subject' => 'SUBJECT 日本語 {FOO}',
'body' => 'BODY 日本語 {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
'test@test.com'
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6KqeIGZvbw==?=',
'body' => 'BODY 日本語 foo bar',
]
],
],
'sending email 1: dynamic, to override' => [
'subject' => 'SUBJECT {FOO}',
'body' => 'BODY {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
[
'email' => 'test@test.com',
'replace' => [
'FOO' => 'foo to'
]
]
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT foo to',
'body' => 'BODY foo to bar',
]
],
],
'sending email 1: dynamic, to override encoded' => [
'subject' => 'SUBJECT 日本語 {FOO}',
'body' => 'BODY 日本語 {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
[
'email' => 'test@test.com',
'replace' => [
'FOO' => 'foo to'
]
]
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 'test@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6KqeIGZvbyB0bw==?=',
'body' => 'BODY 日本語 foo to bar',
]
],
],
'sending email 3: dynamic, to mixed override' => [
'subject' => 'SUBJECT {FOO}',
'body' => 'BODY {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
[
'email' => 't1@test.com',
'replace' => [
'FOO' => 'foo to 1'
]
],
[
'email' => 't2@test.com',
'replace' => [
'FOO' => 'foo to 2'
]
],
[
'email' => 't3@test.com',
],
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't1@test.com',
'subject' => 'SUBJECT foo to 1',
'body' => 'BODY foo to 1 bar',
],
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't2@test.com',
'subject' => 'SUBJECT foo to 2',
'body' => 'BODY foo to 2 bar',
],
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't3@test.com',
'subject' => 'SUBJECT foo',
'body' => 'BODY foo bar',
],
],
],
'sending email 3: dynamic, to mixed override encoded' => [
'subject' => 'SUBJECT 日本語 {FOO}',
'body' => 'BODY 日本語 {FOO} {VAR}',
'from_email' => 'test@test.com',
'from_name' => '',
'to_email' => [
[
'email' => 't1@test.com',
'replace' => [
'FOO' => 'foo to 1'
]
],
[
'email' => 't2@test.com',
'replace' => [
'FOO' => 'foo to 2'
]
],
[
'email' => 't3@test.com',
],
],
'replace' => [
'FOO' => 'foo',
'VAR' => 'bar',
],
'encoding' => null,
'kv_folding' => null,
'expected_status' => 2,
'expected_content' => [
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't1@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6KqeIGZvbyB0byAx?=',
'body' => 'BODY 日本語 foo to 1 bar',
],
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't2@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6KqeIGZvbyB0byAy?=',
'body' => 'BODY 日本語 foo to 2 bar',
],
[
'header' => [
'From' => 'test@test.com'
],
'to' => 't3@test.com',
'subject' => 'SUBJECT =?UTF-8?B?5pel5pys6KqeIGZvbw==?=',
'body' => 'BODY 日本語 foo bar',
],
],
],
];
}
/**
* Undocumented function
*
* @dataProvider sendEmailProvider
* @testdox email sending with expected status $expected_status [$_dataName]
*
* @param string $subject
* @param string $body
* @param string $from_email
* @param string $from_name
* @param array $to_email
* @param array|null $replace
* @param string|null $encoding
* @param bool|null $kv_folding
* @param int $expected_status
* @param array $expected_content
* @return void
*/
public function testSendEmail(
string $subject,
string $body,
string $from_email,
string $from_name,
array $to_email,
?array $replace,
?string $encoding,
?bool $kv_folding,
int $expected_status,
array $expected_content
): void {
if ($replace === null) {
$replace = [];
}
if ($encoding === null) {
$encoding = 'UTF-8';
}
if ($kv_folding === null) {
$kv_folding = false;
}
// force new set for each run
self::$log->setLogUniqueId(true);
// set on of unique log id
self::$log->setLogPer('run', true);
// init logger
$status = \CoreLibs\Create\Email::sendEmail(
$subject,
$body,
$from_email,
$from_name,
$to_email,
$replace,
$encoding,
$kv_folding,
true,
self::$log
);
$this->assertEquals(
$expected_status,
$status,
'Assert sending status'
);
// assert content: must load JSON from log file
if ($status == 2) {
// open file, get last entry with 'SEND EMAIL JSON' key
$file = file_get_contents(self::$log->getLogFileName());
if ($file !== false) {
// extract SEND EMAIL JSON line
$found = preg_match_all("/^.* <SEND EMAIL JSON> - (.*)$/m", $file, $matches);
// print "Found: $found | EMAIL: " . print_r($matches, true) . "\n";
if (!empty($matches[1])) {
foreach ($matches[1] as $pos => $email_json) {
$email = \CoreLibs\Convert\Json::jsonConvertToArray($email_json);
// print "EMAIL: " . print_r($email, true) . "\n";
$this->assertEquals(
$expected_content[$pos]['header']['From'] ?? 'MISSING FROM',
$email['header']['From'] ?? '',
'Email check: assert header from'
);
$this->assertEquals(
'text/plain; charset=' . $encoding ?? 'UTF-8',
$email['header']['Content-type'] ?? '',
'Email check: assert header content type'
);
$this->assertEquals(
'1.0',
$email['header']['MIME-Version'] ?? '',
'Email check: assert header mime version'
);
$this->assertEquals(
$expected_content[$pos]['to'] ?? 'MISSING TO',
$email['to'] ?? '',
'Email check: assert to'
);
$this->assertEquals(
$expected_content[$pos]['subject'] ?? 'MISSING SUBJECT',
$email['subject'] ?? '',
'Email check: assert subject'
);
// body must be translated back to encoding if encoding is not UTF-8
$this->assertEquals(
$encoding != 'UTF-8' ?
mb_convert_encoding($expected_content[$pos]['body'] ?? '', $encoding, 'UTF-8') :
$expected_content[$pos]['body'] ?? 'MISSING BODY',
$email['encoding'] != 'UTF-8' ?
mb_convert_encoding($email['body'] ?? '', $email['encoding'], 'UTF-8') :
$email['body'] ?? '',
'Email check: assert body'
);
}
}
}
}
}
}
// __END__

View File

@@ -13,7 +13,11 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsCreateHashTest extends TestCase
{
/**
* Undocumented function
*
* @return array
*/
public function hashData(): array
{
return [

View File

@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
/**
* Test class for Create\Session
@@ -20,86 +21,451 @@ final class CoreLibsCreateSessionTest extends TestCase
*/
public function sessionProvider(): array
{
// 0: session name as parameter or for GLOBAL value
// 1: type p: parameter, g: global, d: php.ini default
// 2: mock data as array
// checkCliStatus: true/false,
// getSessionStatus: PHP_SESSION_DISABLED for abort,
// PHP_SESSION_NONE/ACTIVE for ok
// setSessionName: true/false,
// checkActiveSession: true/false, [1st call, 2nd call]
// getSessionId: string or false
// 3: exepcted name (session)
// 4: expected error string
return [
'session parameter' => [
'sessionNameParameter',
'p',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'sessionNameParameter',
'/^\w+$/'
''
],
'session globals' => [
'sessionNameGlobals',
'g',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'sessionNameGlobals',
'/^\w+$/'
''
],
'session constant' => [
'sessionNameConstant',
'c',
'sessionNameConstant',
'/^\w+$/'
'session name default' => [
'',
'd',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'',
''
],
// error checks
// 1: we are in cli
'on cli error' => [
'',
'd',
[
'checkCliStatus' => true,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'',
'[SESSION] No sessions in php cli'
],
// 2: session disabled
'session disabled error' => [
'',
'd',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_DISABLED,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'',
'[SESSION] Sessions are disabled'
],
// 3: invalid session name: string
'invalid name chars error' => [
'1invalid$session#;',
'p',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => false,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'',
'[SESSION] Invalid session name: 1invalid$session#;'
],
// 3: invalid session name: only numbers
'invalid name numbers only error' => [
'123',
'p',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => false,
'checkActiveSession' => [false, true],
'getSessionId' => '1234abcd4567'
],
'',
'[SESSION] Invalid session name: 123'
],
// 3: invalid session name: invalid name short
// 3: invalid session name: too long (128)
// 4: failed to start session (2nd false on check active session)
'invalid name numbers only error' => [
'',
'd',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, false],
'getSessionId' => '1234abcd4567'
],
'',
'[SESSION] Failed to activate session'
],
// 5: get session id return false
'invalid name numbers only error' => [
'',
'd',
[
'checkCliStatus' => false,
'getSessionStatus' => PHP_SESSION_NONE,
'setSessionName' => true,
'checkActiveSession' => [false, true],
'getSessionId' => false
],
'',
'[SESSION] getSessionId did not return a session id'
],
];
}
/**
* Undocumented function
* Test session start
*
* @covers ::startSession
* @dataProvider sessionProvider
* @testdox startSession $input name for $type will be $expected (error: $expected_error) [$_dataName]
*
* @param string $input
* @param string $type
* @param array<mixed> $mock_data
* @param string $expected
* @param string $expected_error
* @return void
*/
protected function setUp(): void
{
if (session_id()) {
session_destroy();
public function testStartSession(
string $input,
string $type,
array $mock_data,
string $expected,
string $expected_error
): void {
// override expected
if ($type == 'd') {
$expected = ini_get('session.name');
}
/** @var \CoreLibs\Create\Session&MockObject $session_mock */
$session_mock = $this->createPartialMock(
\CoreLibs\Create\Session::class,
[
'checkCliStatus', 'getSessionStatus', 'checkActiveSession',
'setSessionName', 'startSessionCall', 'getSessionId',
'getSessionName'
]
);
// set return values based requested input values
// OK: true
// error: false
$session_mock->method('checkCliStatus')->willReturn($mock_data['checkCliStatus']);
// OK: PHP_SESSION_ACTIVE, PHP_SESSION_NONE
// error: PHP_SESSION_DISABLED
$session_mock->method('getSessionStatus')->willReturn($mock_data['getSessionStatus']);
// false: try start
// true: skip start
// note that on second call if false -> error
$session_mock->method('checkActiveSession')
->willReturnOnConsecutiveCalls(
$mock_data['checkActiveSession'][0],
$mock_data['checkActiveSession'][1],
);
// dummy set for session name
$session_mock->method('setSessionName')->with($input)->willReturn($mock_data['setSessionName']);
// set session name & return bsed on request data
$session_mock->method('getSessionName')->willReturn($expected);
// will not return anything
$session_mock->method('startSessionCall');
// in test case only return string
// false: will return false
$session_mock->method('getSessionId')->willReturn($mock_data['getSessionId']);
// regex for session id
$ression_id_regex = "/^\w+$/";
unset($GLOBALS['SET_SESSION_NAME']);
$session_id = '';
switch ($type) {
case 'p':
$session_id = $session_mock->startSession($input);
break;
case 'g':
$GLOBALS['SET_SESSION_NAME'] = $input;
$session_id = $session_mock->startSession();
break;
case 'd':
$session_id = $session_mock->startSession();
break;
}
// asert checks
if (!empty($session_id)) {
$this->assertMatchesRegularExpression(
$ression_id_regex,
(string)$session_id,
'session id regex from retrun'
);
$this->assertMatchesRegularExpression(
$ression_id_regex,
(string)$session_mock->getSessionId()
);
$this->assertEquals(
$expected,
$session_mock->getSessionName()
);
} else {
// false checks
$this->assertEquals(
$expected_error,
$session_mock->getErrorStr(),
'error assert'
);
}
}
/**
* Undocumented function
* provider for session name check
*
* @dataProvider sessionProvider
* @testdox startSession $input name for $type will be $expected_n with $expected_i [$_dataName]
* @return array
*/
public function sessionNameProvider(): array
{
// 0: string for session
// 1: expected return as bool
return [
'valid name' => [
'abc',
true
],
'valid name longer' => [
'something-abc-123',
true
],
'invalid name' => [
'abc#abc',
false
],
'only numbers' => [
'123',
false
],
'longer than 128 chars' => [
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
. 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'
. 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz',
false
],
'too short' => [
'',
false
],
];
}
/**
* test valid session name
*
* @param string $input
* @param string $type
* @param string|bool $expected_n
* @param string|bool $expected_i
* @covers ::checkValidSessionName
* @dataProvider sessionNameProvider
* @testdox checkValidSessionName $input seessionn name is $expected [$_dataName]
*
* @param string $input
* @param bool $expected
* @return void
*/
public function testStartSession(string $input, string $type, $expected_n, $expected_i): void
public function testCheckValidSessionName(string $input, bool $expected): void
{
// NEEDS MOCKING
/* $session_id = '';
switch ($type) {
case 'p':
$session_id = \CoreLibs\Create\Session::startSession($input);
break;
case 'g':
$GLOBALS['SET_SESSION_NAME'] = $input;
$session_id = \CoreLibs\Create\Session::startSession();
break;
case 'c':
define('SET_SESSION_NAME', $input);
$session_id = \CoreLibs\Create\Session::startSession();
break;
}
$this->assertMatchesRegularExpression(
$expected_i,
(string)$session_id
);
$this->assertMatchesRegularExpression(
$expected_i,
(string)\CoreLibs\Create\Session::getSessionId()
);
$this->assertEquals(
$expected_n,
\CoreLibs\Create\Session::getSessionName()
$expected,
\CoreLibs\Create\Session::checkValidSessionName($input)
);
if ($type == 'g') {
unset($GLOBALS['SET_SESSION_NAME']);
} */
$this->markTestSkipped('[CoreLibsCreateSessionTest] No implementation '
. 'for Create\Session. Cannot run session_start in CLI');
}
/**
* provider for set/get tests
*
* @return array
*/
public function sessionDataProvider(): array
{
return [
'test' => [
'foo',
'bar',
'bar',
],
'int key test' => [
123,
'bar',
'bar',
],
// more complex value tests
'array values' => [
'array',
[1, 2, 3],
[1, 2, 3],
]
];
}
/**
* method call test
*
* @covers ::setS
* @covers ::getS
* @covers ::issetS
* @covers ::unsetS
* @dataProvider sessionDataProvider
* @testdox setS/getS/issetS/unsetS $name with $input is $expected [$_dataName]
*
* @param string|int $name
* @param mixed $input
* @param mixed $expected
* @return void
*/
public function testMethodSetGet($name, $input, $expected): void
{
$session = new \CoreLibs\Create\Session();
$session->setS($name, $input);
$this->assertEquals(
$expected,
$session->getS($name),
'method set assert'
);
// isset true
$this->assertTrue(
$session->issetS($name),
'method isset assert ok'
);
$session->unsetS($name);
$this->assertEquals(
'',
$session->getS($name),
'method unset assert'
);
// iset false
$this->assertFalse(
$session->issetS($name),
'method isset assert false'
);
}
/**
* magic call test
*
* @covers ::__set
* @covers ::__get
* @covers ::__isset
* @covers ::__unset
* @dataProvider sessionDataProvider
* @testdox __set/__get/__iseet/__unset $name with $input is $expected [$_dataName]
*
* @param string|int $name
* @param mixed $input
* @param mixed $expected
* @return void
*/
public function testMagicSetGet($name, $input, $expected): void
{
$session = new \CoreLibs\Create\Session();
$session->$name = $input;
$this->assertEquals(
$expected,
$session->$name,
'magic set assert'
);
// isset true
$this->assertTrue(
isset($session->$name),
'magic isset assert ok'
);
unset($session->$name);
$this->assertEquals(
'',
$session->$name,
'magic unset assert'
);
// isset true
$this->assertFalse(
isset($session->$name),
'magic isset assert false'
);
}
/**
* unset all test
*
* @covers ::unsetAllS
* @testdox unsetAllS test
*
* @return void
*/
public function testUnsetAll(): void
{
$test_values = [
'foo' => 'abc',
'bar' => '123'
];
$session = new \CoreLibs\Create\Session();
foreach ($test_values as $name => $value) {
$session->setS($name, $value);
// confirm set
$this->assertEquals(
$value,
$session->getS($name),
'set assert: ' . $name
);
}
// unset all
$session->unsetAllS();
// check unset
foreach (array_keys($test_values) as $name) {
$this->assertEquals(
'',
$session->getS($name),
'unsert assert: ' . $name
);
}
}
}

View File

@@ -36,9 +36,9 @@ final class CoreLibsDBExtendedArrayIOTest extends TestCase
*
* @return void
*/
public function testDBIO()
public function testArrayDBIO()
{
$this->assertTrue(true, 'DB Extended ArrayIO Tests not implemented');
// $this->assertTrue(true, 'DB Extended ArrayIO Tests not implemented');
$this->markTestIncomplete(
'DB\Extended\ArrayIO Tests have not yet been implemented'
);

File diff suppressed because it is too large Load Diff

View File

@@ -15,8 +15,6 @@ use PHPUnit\Framework\TestCase;
*/
final class CoreLibsDebugLoggingTest extends TestCase
{
public $log;
/**
* test set for options BASIC
*
@@ -85,6 +83,47 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* init logging class
*
* @dataProvider optionsProvider
* @testdox init test [$_dataName]
*
* @param array|null $options
* @param array $expected
* @param array $override
* @return void
*/
public function testClassInit(?array $options, array $expected, array $override): void
{
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
define($var, $value);
}
}
if ($options === null) {
$log = new \CoreLibs\Debug\Logging();
} else {
$log = new \CoreLibs\Debug\Logging($options);
}
// check that settings match
$this->assertEquals(
$expected['log_folder'],
$log->getSetting('log_folder')
);
$this->assertEquals(
$expected['debug_all'],
$log->getSetting('debug_output_all')
);
$this->assertEquals(
$expected['print_all'],
$log->getSetting('print_output_all')
);
// print "LOG: " . $log->getSetting('log_folder') . "\n";
// print "DEBUG: " . $log->getSetting('debug_output_all') . "\n";
// print "PRINT: " . $log->getSetting('print_output_all') . "\n";
}
/**
* adds log ID settings based on basic options
*
@@ -173,6 +212,52 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* test the setting and getting of LogId
*
* @covers ::setLogId
* @dataProvider logIdOptionsProvider
* @testdox log id set/get tests [$_dataName]
*
* @param array|null $options
* @param array $expected
* @param array $override
* @return void
*/
public function testLogId(?array $options, array $expected, array $override): void
{
// we need to set with file_id option, globals LOG_FILE_ID, constant LOG_FILE_ID
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
define($var, $value);
}
}
if (!empty($override['globals'])) {
foreach ($override['globals'] as $var => $value) {
$GLOBALS[$var] = $value;
}
}
if ($options === null) {
$log = new \CoreLibs\Debug\Logging();
} else {
$log = new \CoreLibs\Debug\Logging($options);
}
// check current
$this->assertEquals(
$log->getLogId(),
$expected['log_file_id']
);
// we need to override now too
if (!empty($override['values'])) {
// check if we have values, set them post and assert
$log->setLogId($override['values']['log_file_id']);
$this->assertEquals(
$log->getLogId(),
$expected['set_log_file_id']
);
}
}
/**
* Undocumented function
*
@@ -180,6 +265,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/
public function logLevelAllProvider(): array
{
// 0: type
// 1: flag
// 2: expected set
// 3: expected get
return [
'debug all true' => [
'debug',
@@ -208,6 +297,38 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* check set/get for log level all flag
*
* @dataProvider logLevelAllProvider
* @testdox set/get all log level $type with flag $flag [$_dataName]
*
* @param string $type
* @param bool $flag
* @param bool $expected_set
* @param bool $expected_get
* @return void
*/
public function testSetGetLogLevelAll(
string $type,
bool $flag,
bool $expected_set,
bool $expected_get
): void {
// neutral start with default
$log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$log->setLogLevelAll($type, $flag),
$expected_set
);
// get and check
$this->assertEquals(
$log->getLogLevelAll($type),
$expected_get
);
}
/**
* Undocumented function
*
@@ -215,6 +336,12 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/
public function logLevelProvider(): array
{
// 0: type
// 1: flag
// 2: debug on (array)
// 3: expected set
// 4: level
// 5: expected get
return [
'set debug on for level A,B,C and check full set' => [
'debug',
@@ -287,6 +414,43 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* checks setting for per log info level
*
* @covers ::setLogLevel
* @dataProvider logLevelProvider
* @testdox set/get log level $type to $flag check with $level [$_dataName]
*
* @param string $type
* @param string $flag
* @param array $debug_on
* @param bool $expected_set
* @param string|null $level
* @param bool|array<mixed> $expected_get
* @return void
*/
public function testSetGetLogLevel(
string $type,
string $flag,
array $debug_on,
bool $expected_set,
?string $level,
$expected_get
): void {
// neutral start with default
$log = new \CoreLibs\Debug\Logging();
// set
$this->assertEquals(
$log->setLogLevel($type, $flag, $debug_on),
$expected_set
);
// get, if level is null compare to?
$this->assertEquals(
$log->getLogLevel($type, $flag, $level),
$expected_get
);
}
/**
* Undocumented function
*
@@ -294,6 +458,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
*/
public function logPerProvider(): array
{
// 0: type
// 1: set
// 2: expected set
// 3: expected get
return [
'level set true' => [
'level',
@@ -328,6 +496,68 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* set and get per log
* for level/class/page/run flags
*
* @covers ::setLogPer
* @dataProvider logPerProvider
* @testdox set/get log per $type with $set [$_dataName]
*
* @param string $type
* @param boolean $set
* @param boolean $expected_set
* @param boolean $expected_get
* @return void
*/
public function testSetGetLogPer(
string $type,
bool $set,
bool $expected_set,
bool $expected_get
): void {
// neutral start with default
$log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$log->setLogPer($type, $set),
$expected_set
);
// get and check
$this->assertEquals(
$log->getLogPer($type),
$expected_get
);
}
/**
* set the print log file date part
*
* @covers ::setGetLogPrintFileDate
* @testWith [true, true, true]
* [false, false, false]
* @testdox set/get log file date to $input [$_dataName]
*
* @param boolean $input
* @param boolean $expected_set
* @param boolean $expected_get
* @return void
*/
public function testSetGetLogPrintFileDate(bool $input, bool $expected_set, bool $expected_get): void
{
// neutral start with default
$log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$log->setGetLogPrintFileDate($input),
$expected_set
);
$this->assertEquals(
$log->setGetLogPrintFileDate(),
$expected_get
);
}
/**
* Undocumented function
*
@@ -369,6 +599,95 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* convert array to string with ## pre replace space holders
*
* @covers ::prAr
* @dataProvider prArProvider
* @testdox check prAr array to string conversion [$_dataName]
*
* @param array $input
* @param string $expected
* @return void
*/
public function testPrAr(array $input, string $expected): void
{
$log = new \CoreLibs\Debug\Logging();
$this->assertEquals(
$log->prAr($input),
$expected
);
}
/**
* Undocumented function
*
* @return array
*/
public function prBlProvider(): array
{
// 0: input flag (bool)
// 1: is true
// 2: is flase
// 3: epxected
return [
'true bool default' => [
true,
null,
null,
'true'
],
'false bool default' => [
false,
null,
null,
'false'
],
'true bool override' => [
true,
'ok',
'not ok',
'ok'
],
'false bool override' => [
false,
'ok',
'not ok',
'not ok'
],
];
}
/**
* check bool to string converter
*
* @covers ::prBl
* @dataProvider prBlProvider
* @testdox check prBl $input ($true/$false) is expected $false [$_dataName]
*
* @param bool $input
* @param string|null $true
* @param string|null $false
* @param string $expected
* @return void
*/
public function testPrBl(bool $input, ?string $true, ?string $false, string $expected): void
{
$log = new \CoreLibs\Debug\Logging();
$return = '';
if ($true === null && $false === null) {
$return = $log->prBl($input);
} elseif ($true !== null || $false !== null) {
$return = $log->prBl($input, $true ?? '', $false ?? '');
}
$this->assertEquals(
$expected,
$return
);
}
// from here are complex debug tests
/**
* Undocumented function
*
@@ -471,246 +790,6 @@ final class CoreLibsDebugLoggingTest extends TestCase
];
}
/**
* init logging class
*
* @dataProvider optionsProvider
* @testdox init test [$_dataName]
*
* @param array|null $options
* @param array $expected
* @param array $override
* @return void
*/
public function testClassInit(?array $options, array $expected, array $override): void
{
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
define($var, $value);
}
}
if ($options === null) {
$this->log = new \CoreLibs\Debug\Logging();
} else {
$this->log = new \CoreLibs\Debug\Logging($options);
}
// check that settings match
$this->assertEquals(
$expected['log_folder'],
$this->log->getSetting('log_folder')
);
$this->assertEquals(
$expected['debug_all'],
$this->log->getSetting('debug_output_all')
);
$this->assertEquals(
$expected['print_all'],
$this->log->getSetting('print_output_all')
);
// print "LOG: " . $this->log->getSetting('log_folder') . "\n";
// print "DEBUG: " . $this->log->getSetting('debug_output_all') . "\n";
// print "PRINT: " . $this->log->getSetting('print_output_all') . "\n";
}
/**
* test the setting and getting of LogId
*
* @covers ::setLogId
* @dataProvider logIdOptionsProvider
* @testdox log id set/get tests [$_dataName]
*
* @param array|null $options
* @param array $expected
* @param array $override
* @return void
*/
public function testLogId(?array $options, array $expected, array $override): void
{
// we need to set with file_id option, globals LOG_FILE_ID, constant LOG_FILE_ID
if (!empty($override['constant'])) {
foreach ($override['constant'] as $var => $value) {
define($var, $value);
}
}
if (!empty($override['globals'])) {
foreach ($override['globals'] as $var => $value) {
$GLOBALS[$var] = $value;
}
}
if ($options === null) {
$this->log = new \CoreLibs\Debug\Logging();
} else {
$this->log = new \CoreLibs\Debug\Logging($options);
}
// check current
$this->assertEquals(
$this->log->getLogId(),
$expected['log_file_id']
);
// we need to override now too
if (!empty($override['values'])) {
// check if we have values, set them post and assert
$this->log->basicSetLogId($override['values']['log_file_id']);
$this->assertEquals(
$this->log->getLogId(),
$expected['set_log_file_id']
);
}
}
/**
* check set/get for log level all flag
*
* @dataProvider logLevelAllProvider
* @testdox set/get all log level $type with flag $flag [$_dataName]
*
* @param string $type
* @param bool $flag
* @param bool $expected_set
* @param bool $expected_get
* @return void
*/
public function testSetGetLogLevelAll(
string $type,
bool $flag,
bool $expected_set,
bool $expected_get
): void {
// neutral start with default
$this->log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$this->log->setLogLevelAll($type, $flag),
$expected_set
);
// get and check
$this->assertEquals(
$this->log->getLogLevelAll($type),
$expected_get
);
}
/**
* checks setting for per log info level
*
* @covers ::setLogLevel
* @dataProvider logLevelProvider
* @testdox set/get log level $type to $flag check with $level [$_dataName]
*
* @param string $type
* @param string $flag
* @param array $debug_on
* @param bool $expected_set
* @param string|null $level
* @param bool|array<mixed> $expected_get
* @return void
*/
public function testSetGetLogLevel(
string $type,
string $flag,
array $debug_on,
bool $expected_set,
?string $level,
$expected_get
): void {
// neutral start with default
$this->log = new \CoreLibs\Debug\Logging();
// set
$this->assertEquals(
$this->log->setLogLevel($type, $flag, $debug_on),
$expected_set
);
// get, if level is null compare to?
$this->assertEquals(
$this->log->getLogLevel($type, $flag, $level),
$expected_get
);
}
/**
* set and get per log
* for level/class/page/run flags
*
* @covers ::setLogPer
* @dataProvider logPerProvider
* @testdox set/get log per $type with $set [$_dataName]
*
* @param string $type
* @param boolean $set
* @param boolean $expected_set
* @param boolean $expected_get
* @return void
*/
public function testSetGetLogPer(
string $type,
bool $set,
bool $expected_set,
bool $expected_get
): void {
// neutral start with default
$this->log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$this->log->setLogPer($type, $set),
$expected_set
);
// get and check
$this->assertEquals(
$this->log->getLogPer($type),
$expected_get
);
}
/**
* set the print log file date part
*
* @covers ::setGetLogPrintFileDate
* @testWith [true, true, true]
* [false, false, false]
* @testdox set/get log file date to $input [$_dataName]
*
* @param boolean $input
* @param boolean $expected_set
* @param boolean $expected_get
* @return void
*/
public function testSetGetLogPrintFileDate(bool $input, bool $expected_set, bool $expected_get): void
{
// neutral start with default
$this->log = new \CoreLibs\Debug\Logging();
// set and check
$this->assertEquals(
$this->log->setGetLogPrintFileDate($input),
$expected_set
);
$this->assertEquals(
$this->log->setGetLogPrintFileDate(),
$expected_get
);
}
/**
* convert array to string with ## pre replace space holders
*
* @covers ::prAr
* @dataProvider prArProvider
* @testdox check prAr array to string conversion [$_dataName]
*
* @param array $input
* @param string $expected
* @return void
*/
public function testPrAr(array $input, string $expected): void
{
$this->log = new \CoreLibs\Debug\Logging();
$this->assertEquals(
$this->log->prAr($input),
$expected
);
}
// from here are complex debug tests
/**
* Test debug flow
*
@@ -766,11 +845,11 @@ final class CoreLibsDebugLoggingTest extends TestCase
// remove any files named /tmp/error_log_TestDebug*.log
array_map('unlink', glob($options['log_folder'] . 'error_msg_' . $options['file_id'] . '*.log'));
// init logger
$this->log = new \CoreLibs\Debug\Logging($options);
$log = new \CoreLibs\Debug\Logging($options);
// * debug (A/B)
// NULL check for strip/prefix
$this->assertEquals(
$this->log->debug(
$log->debug(
$debug_msg['level'],
$debug_msg['string'],
$debug_msg['strip'],
@@ -779,7 +858,7 @@ final class CoreLibsDebugLoggingTest extends TestCase
$expected_debug
);
// * if print check data in log file
$log_file = $this->log->getLogFileName();
$log_file = $log->getLogFileName();
if (!empty($options['debug_all']) && !empty($options['print_all'])) {
// file name matching
$this->assertStringStartsWith(
@@ -808,10 +887,10 @@ final class CoreLibsDebugLoggingTest extends TestCase
);
}
// ** ECHO ON
$log_string = $this->log->printErrorMsg();
$log_string = $log->printErrorMsg();
// * print
if (!empty($options['debug_all']) && !empty($options['echo_all'])) {
// print $this->log->printErrorMsg() . "\n";
// print $log->printErrorMsg() . "\n";
// echo string must start with
$this->assertStringStartsWith(
$expected_string_start,
@@ -835,6 +914,77 @@ final class CoreLibsDebugLoggingTest extends TestCase
);
}
}
// TODO: setLogUniqueId/getLogUniqueId
/**
* Undocumented function
*
* @return array
*/
public function logUniqueIdProvider(): array
{
return [
'option set' => [
'option' => true,
'override' => false,
],
'direct set' => [
'option' => false,
'override' => false,
],
'override set' => [
'option' => false,
'override' => true,
],
'option and override set' => [
'option' => false,
'override' => true,
],
];
}
/**
* Undocumented function
*
* @covers ::setLogUniqueId
* @covers ::getLogUniqueId
* @dataProvider logUniqueIdProvider
* @testdox per run log id set test: option: $option, override: $override [$_dataName]
*
* @param bool $option
* @param bool $override
* @return void
*/
public function testLogUniqueId(bool $option, bool $override): void
{
if ($option === true) {
$log = new \CoreLibs\Debug\Logging(['per_run' => $option]);
} else {
$log = new \CoreLibs\Debug\Logging();
$log->setLogUniqueId();
}
$per_run_id = $log->getLogUniqueId();
$this->assertMatchesRegularExpression(
"/^\d{4}-\d{2}-\d{2}_\d{6}_U_[a-z0-9]{8}$/",
$per_run_id,
'assert per log run id 1st'
);
if ($override === true) {
$log->setLogUniqueId(true);
$per_run_id_2nd = $log->getLogUniqueId();
$this->assertMatchesRegularExpression(
"/^\d{4}-\d{2}-\d{2}_\d{6}_U_[a-z0-9]{8}$/",
$per_run_id_2nd,
'assert per log run id 2nd'
);
$this->assertNotEquals(
$per_run_id,
$per_run_id_2nd,
'1st and 2nd don\'t match'
);
}
}
}
// __END__

View File

@@ -0,0 +1,119 @@
<?php
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
use CoreLibs\Debug\MemoryUsage;
/**
* Test class for Debug\MemoryUsage
* @coversDefaultClass \CoreLibs\Debug\MemoryUsage
* @testdox \CoreLibs\Debug\MemoryUsage method tests
*/
final class CoreLibsDebugMemoryUsageTest extends TestCase
{
/**
* Undocumented function
*
* @return array
*/
public function memoryUsageProvider(): array
{
$regex_raw_off = '/^\[[\w\s_-]+\] Peak\/Curr\/Change: \d+(\.\d+)? ?\w{1,2}\/'
. '\d+(\.\d+)? ?\w{1,2}\/'
. 'Since Start: \d+(\.\d+)? ?\w{1,2} \| '
. 'Since Last: \d+(\.\d+)? ?\w{1,2} \| '
. 'Since Set: \d+(\.\d+)? ?\w{1,2}$/';
$regex_raw_on = '/^\[[\w\s_-]+\] Peak\/Curr\/'
// . 'Change: \d+(\.\d+)? ?\w{1,2}\/\d+(\.\d+)? ?\w{1,2} \[\d+\]\/'
. 'Change: \d+(\.\d+)? ?\w{1,2}\/\d+(\.\d+)? ?\w{1,2}/'
. 'Since Start: \d+(\.\d+)? ?\w{1,2} \[\d+\] \| '
. 'Since Last: \d+(\.\d+)? ?\w{1,2} \[\d+\] \| '
. 'Since Set: \d+(\.\d+)? ?\w{1,2} \[\d+\]$/';
$regex_array = [
'prefix' => '/^[\w\s_-]+$/',
'peak' => '/^\d+$/',
'usage' => '/^\d+$/',
'start' => '/^\d+$/',
'last' => '/^\d+$/',
'set' => '/^\d+$/',
];
// 0: prefix
// 1: raw flag
// 2: set flags array
// 3: array output expected (as regex)
// 4: string output expected (as regex)
return [
'test normal' => [
'test',
null,
[],
$regex_array,
$regex_raw_off,
]
];
}
/**
* Undocumented function
*
* @cover ::resetMemory
* @cover ::debugMemoryFlag
* @cover ::setStartMemory
* @cover ::setMemory
* @cover ::memoryUsage
* @cover ::printMemoryUsage
* @dataProvider memoryUsageProvider
* @testdox memoryUsage with $prefix, raw memory $raw [$_dataName]
*
* @param string $prefix
* @param bool|null $raw
* @param array $set_flags
* @param array $expected_array
* @param string $expected_string
* @return void
*/
public function testMemoryUsage(
string $prefix,
?bool $raw,
array $settings,
array $expected_array,
string $expected_string
): void {
// always reeset to null
MemoryUsage::resetMemory();
MemoryUsage::debugMemoryFlag(true);
MemoryUsage::setStartMemory();
MemoryUsage::setMemory();
// run collector
$memory = MemoryUsage::memoryUsage($prefix);
if ($raw === null) {
$string = MemoryUsage::printMemoryUsage($memory);
} else {
$string = MemoryUsage::printMemoryUsage($memory, $raw);
}
// expected_array for each
foreach ($expected_array as $name => $regex) {
$this->assertMatchesRegularExpression(
$regex,
(string)$memory[$name],
'assert memory usage array ' . $name
);
}
// regex match string
$this->assertMatchesRegularExpression(
$expected_string,
$string,
'assert memory usage string as regex'
);
// TODO additional tests with use more memory and check diff matching
// TODO reset memory usage test
}
}
// __END__

View File

@@ -15,6 +15,8 @@ final class CoreLibsDebugRunningTimeTest extends TestCase
{
public function hrRunningTimeProvider(): array
{
// 0: return time difference
// 1: return time on first run in regex
return [
'default time' => [
0 => null,
@@ -69,21 +71,73 @@ final class CoreLibsDebugRunningTimeTest extends TestCase
*/
public function testHrRunningTime(?string $out_time, string $expected): void
{
// reset for each run
\CoreLibs\Debug\RunningTime::hrRunningTimeReset();
$start = \CoreLibs\Debug\RunningTime::hrRunningTime();
$this->assertEquals(
0,
$start
$start,
'assert first run 0'
);
time_nanosleep(1, 500);
if ($out_time === null) {
$end = \CoreLibs\Debug\RunningTime::hrRunningTime();
$second = \CoreLibs\Debug\RunningTime::hrRunningTime();
} else {
$end = \CoreLibs\Debug\RunningTime::hrRunningTime($out_time);
$second = \CoreLibs\Debug\RunningTime::hrRunningTime($out_time);
}
// print "E: " . $end . "\n";
$this->assertMatchesRegularExpression(
$expected,
(string)$end
(string)$second,
'assert second run regex'
);
if ($out_time === null) {
$end_second = \CoreLibs\Debug\RunningTime::hrRunningTimeFromStart();
} else {
$end_second = \CoreLibs\Debug\RunningTime::hrRunningTimeFromStart($out_time);
}
$this->assertEquals(
$end_second,
$second,
'assert end is equal second'
);
// sleep again, second messurement
time_nanosleep(1, 500);
if ($out_time === null) {
$third = \CoreLibs\Debug\RunningTime::hrRunningTime();
} else {
$third = \CoreLibs\Debug\RunningTime::hrRunningTime($out_time);
}
// third call is not null
$this->assertNotEquals(
0,
$third,
'assert third call not null'
);
// third call is bigger than end
$this->assertNotEquals(
$second,
$third,
'assert third different second'
);
// last messurement, must match start - end + last
if ($out_time === null) {
$end = \CoreLibs\Debug\RunningTime::hrRunningTimeFromStart();
} else {
$end = \CoreLibs\Debug\RunningTime::hrRunningTimeFromStart($out_time);
}
$this->assertGreaterThan(
$third,
$end,
'assert end greater third'
);
// new start
\CoreLibs\Debug\RunningTime::hrRunningTimeReset();
$new_start = \CoreLibs\Debug\RunningTime::hrRunningTime();
$this->assertEquals(
0,
$new_start,
'assert new run 0'
);
}

View File

@@ -45,7 +45,7 @@ final class CoreLibsDebugSupportTest extends TestCase
*
* @return array
*/
public function printArProvider(): array
public function printArrayProvider(): array
{
return [
'empty array' => [
@@ -62,6 +62,51 @@ final class CoreLibsDebugSupportTest extends TestCase
];
}
/**
* Undocumented function
*
* @return array
*/
public function printBoolProvider(): array
{
return [
'true input default' => [
0 => true,
1 => [],
2 => 'true'
],
'false input default' => [
0 => false,
1 => [],
2 => 'false'
],
'false input param name' => [
0 => false,
1 => [
'name' => 'param test'
],
2 => '<b>param test</b>: false'
],
'true input param name, true override' => [
0 => true,
1 => [
'name' => 'param test',
'true' => 'ok'
],
2 => '<b>param test</b>: ok'
],
'false input param name, true override, false override' => [
0 => false,
1 => [
'name' => 'param test',
'true' => 'ok',
'false' => 'not',
],
2 => '<b>param test</b>: not'
],
];
}
/**
* Undocumented function
*
@@ -75,6 +120,16 @@ final class CoreLibsDebugSupportTest extends TestCase
null,
'a string',
],
'string with html chars, encode' => [
'a string with <> &',
true,
'a string with &lt;&gt; &amp;',
],
'string with html chars' => [
'a string with <> &',
null,
'a string with <> &',
],
'a number' => [
1234,
null,
@@ -135,22 +190,41 @@ final class CoreLibsDebugSupportTest extends TestCase
*/
public function debugStringProvider(): array
{
// 0: input string
// 1: replace
// 2: html flag
// 3: expected
return [
'null string, default' => [
0 => null,
1 => null,
2 => '-'
null,
null,
null,
'-'
],
'empty string, ... replace' => [
0 => '',
1 => '...',
2 => '...'
'',
'...',
null,
'...'
],
'filled string' => [
0 => 'some string',
1 => null,
2 => 'some string'
]
'some string',
null,
null,
'some string'
],
'string with html chars, encode' => [
'a string with <> &',
'-',
true,
'a string with &lt;&gt; &amp;',
],
'string with html chars' => [
'a string with <> &',
'-',
null,
'a string with <> &',
],
];
}
@@ -184,8 +258,9 @@ final class CoreLibsDebugSupportTest extends TestCase
* Undocumented function
*
* @cover ::printAr
* @dataProvider printArProvider
* @testdox printAr $input will be $expected [$_dataName]
* @cover ::printArray
* @dataProvider printArrayProvider
* @testdox printAr/printArray $input will be $expected [$_dataName]
*
* @param array $input
* @param string $expected
@@ -195,7 +270,59 @@ final class CoreLibsDebugSupportTest extends TestCase
{
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::printAr($input)
\CoreLibs\Debug\Support::printAr($input),
'assert printAr'
);
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::printArray($input),
'assert printArray'
);
}
/**
* Undocumented function
*
* @cover ::printBool
* @dataProvider printBoolProvider
* @testdox printBool $input will be $expected [$_dataName]
*
* @param bool $input
* @param array $params
* @param string $expected
* @return void
*/
public function testPrintBool(bool $input, array $params, string $expected): void
{
if (
isset($params['name']) &&
isset($params['true']) &&
isset($params['false'])
) {
$string = \CoreLibs\Debug\Support::printBool(
$input,
$params['name'],
$params['true'],
$params['false']
);
} elseif (isset($params['name']) && isset($params['true'])) {
$string = \CoreLibs\Debug\Support::printBool(
$input,
$params['name'],
$params['true']
);
} elseif (isset($params['name'])) {
$string = \CoreLibs\Debug\Support::printBool(
$input,
$params['name']
);
} else {
$string = \CoreLibs\Debug\Support::printBool($input);
}
$this->assertEquals(
$expected,
$string,
'assert printBool'
);
}
@@ -268,12 +395,14 @@ final class CoreLibsDebugSupportTest extends TestCase
if (count($compare) == 10) {
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::getCallerMethodList()
\CoreLibs\Debug\Support::getCallerMethodList(),
'assert expected 10'
);
} else {
$this->assertEquals(
$expected_group,
\CoreLibs\Debug\Support::getCallerMethodList()
\CoreLibs\Debug\Support::getCallerMethodList(),
'assert expected group'
);
}
}
@@ -300,24 +429,33 @@ final class CoreLibsDebugSupportTest extends TestCase
*
* @cover ::debugString
* @dataProvider debugStringProvider
* @testdox debugString $input with replace $replace will be $expected [$_dataName]
* @testdox debugString $input with replace $replace and html $flag will be $expected [$_dataName]
*
* @param string|null $input
* @param string|null $replace
* @param string $expected
* @param bool|null $flag
* @param string $expected
* @return void
*/
public function testDebugString(?string $input, ?string $replace, string $expected)
public function testDebugString(?string $input, ?string $replace, ?bool $flag, string $expected): void
{
if ($replace === null) {
if ($replace === null && $flag === null) {
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::debugString($input)
\CoreLibs\Debug\Support::debugString($input),
'assert all default'
);
} elseif ($flag === null) {
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::debugString($input, $replace),
'assert flag default'
);
} else {
$this->assertEquals(
$expected,
\CoreLibs\Debug\Support::debugString($input, $replace)
\CoreLibs\Debug\Support::debugString($input, $replace, $flag),
'assert all set'
);
}
}

View File

@@ -0,0 +1,162 @@
<?php
declare(strict_types=1);
namespace tests;
use PHPUnit\Framework\TestCase;
use CoreLibs\Get\DotEnv;
/**
* Test class for ACL\Login
* @coversDefaultClass \CoreLibs\Get\DotEnv
* @testdox \CoreLibs\Get\DotEnv method tests
*/
final class CoreLibsGetDotEnvTest extends TestCase
{
/**
* Undocumented function
*
* @return array
*/
public function envFileProvider(): array
{
$dot_env_content = [
'SOMETHING' => 'A',
'OTHER' => 'B IS B',
'Complex' => 'A B \"D is F',
'HAS_SPACE' => 'ABC',
'HAS_COMMENT_QUOTES_SPACE' => 'Comment at end with quotes and space',
'HAS_COMMENT_QUOTES_NO_SPACE' => 'Comment at end with quotes no space',
'HAS_COMMENT_NO_QUOTES_SPACE' => 'Comment at end no quotes and space',
'HAS_COMMENT_NO_QUOTES_NO_SPACE' => 'Comment at end no quotes no space',
'COMMENT_IN_TEXT_QUOTES' => 'Foo bar # comment in here',
'FAILURE' => 'ABC',
'SIMPLEBOX' => 'A B C',
'TITLE' => '1',
'FOO' => '1.2',
'SOME.TEST' => 'Test Var',
'SOME.LIVE' => 'Live Var',
'A_TEST1' => 'foo',
'A_TEST2' => '${TEST1:-bar}',
'A_TEST3' => '${TEST4:-bar}',
'A_TEST5' => 'null',
'A_TEST6' => '${TEST5-bar}',
'A_TEST7' => '${TEST6:-bar}',
'B_TEST1' => 'foo',
'B_TEST2' => '${TEST1:=bar}',
'B_TEST3' => '${TEST4:=bar}',
'B_TEST5' => 'null',
'B_TEST6' => '${TEST5=bar}',
'B_TEST7' => '${TEST6=bar}',
'Test' => 'A',
'TEST' => 'B',
'LINE' => "ABC\nDEF",
'OTHERLINE' => "ABC\nAF\"ASFASDF\nMORESHIT",
'SUPERLINE' => '',
'__FOO_BAR_1' => 'b',
'__FOOFOO' => 'f ',
123123 => 'number',
'EMPTY' => '',
];
// 0: folder relative to test folder, if unset __DIR__
// 1: file, if unset .env
// 2: status to be returned
// 3: _ENV file content to be set
// 4: override chmod as octect in string
return [
'default' => [
'folder' => null,
'file' => null,
'status' => 3,
'content' => [],
'chmod' => null,
],
'cannot open file' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'cannot_read.env',
'status' => 2,
'content' => [],
'chmod' => '000',
],
'empty file' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'empty.env',
'status' => 1,
'content' => [],
'chmod' => null,
],
'override all' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => 'test.env',
'status' => 0,
'content' => $dot_env_content,
'chmod' => null,
],
'override directory' => [
'folder' => __DIR__ . DIRECTORY_SEPARATOR . 'dotenv',
'file' => null,
'status' => 0,
'content' => $dot_env_content,
'chmod' => null,
],
];
}
/**
* test read .env file
*
* @covers ::readEnvFile
* @dataProvider envFileProvider
* @testdox Read _ENV file from $folder / $file with expected status: $expected_status and chmod $chmod [$_dataName]
*
* @param string|null $folder
* @param string|null $file
* @param int $expected_status
* @param array $expected_env
* @param string|null $chmod
* @return void
*/
public function testReadEnvFile(
?string $folder,
?string $file,
int $expected_status,
array $expected_env,
?string $chmod
): void {
// if we have file + chmod set
$old_chmod = null;
if (
is_file($folder . DIRECTORY_SEPARATOR . $file) &&
!empty($chmod)
) {
// get the old permissions
$old_chmod = fileperms($folder . DIRECTORY_SEPARATOR . $file);
chmod($folder . DIRECTORY_SEPARATOR . $file, octdec($chmod));
}
if ($folder !== null && $file !== null) {
$status = DotEnv::readEnvFile($folder, $file);
} elseif ($folder !== null) {
$status = DotEnv::readEnvFile($folder);
} else {
$status = DotEnv::readEnvFile();
}
$this->assertEquals(
$status,
$expected_status,
'Assert returned status equal'
);
// now assert read data
$this->assertEquals(
$_ENV,
$expected_env,
'Assert _ENV correct'
);
// if we have file and chmod unset
if ($old_chmod !== null) {
chmod($folder . DIRECTORY_SEPARATOR . $file, $old_chmod);
}
}
}
// __END__

View File

@@ -22,7 +22,7 @@ final class CoreLibsOutputFormElementsTest extends TestCase
*/
public function testOutputFormElements()
{
$this->assertTrue(true, 'Output Form Elements Tests not implemented');
// $this->assertTrue(true, 'Output Form Elements Tests not implemented');
$this->markTestIncomplete(
'Output\Form\Elements Tests have not yet been implemented'
);

View File

@@ -22,7 +22,7 @@ final class CoreLibsOutputFormTokenTest extends TestCase
*/
public function testOutputFormToken()
{
$this->assertTrue(true, 'Output Form Token Tests not implemented');
// $this->assertTrue(true, 'Output Form Token Tests not implemented');
$this->markTestIncomplete(
'Output\Form\Token Tests have not yet been implemented'
);

View File

@@ -22,7 +22,7 @@ final class CoreLibsOutputImageTest extends TestCase
*/
public function testOutputImage()
{
$this->assertTrue(true, 'Output Image Tests not implemented');
// $this->assertTrue(true, 'Output Image Tests not implemented');
$this->markTestIncomplete(
'Output\Image Tests have not yet been implemented'
);

View File

@@ -22,10 +22,10 @@ final class CoreLibsOutputProgressbarTest extends TestCase
*/
public function testOutputProgressbar()
{
/* $this->assertTrue(true, 'Output Progressbar Tests not implemented');
$this->markTestIncomplete(
'Output\Progressbar Tests have not yet been implemented'
); */
// $this->assertTrue(true, 'Output Progressbar Tests not implemented');
// $this->markTestIncomplete(
// 'Output\Progressbar Tests have not yet been implemented'
// );
$this->markTestSkipped('No implementation for Output\Progressbar at the moment');
}
}

File diff suppressed because it is too large Load Diff

1
4dev/tests/dotenv/.env Symbolic link
View File

@@ -0,0 +1 @@
test.env

View File

View File

View File

@@ -0,0 +1,49 @@
# enviroment file
SOMETHING=A
OTHER="B IS B"
Complex="A B \"D is F"
# COMMENT
HAS_SPACE= "ABC";
# COMMENT AT END
HAS_COMMENT_QUOTES_SPACE="Comment at end with quotes and space" # Comment QE
HAS_COMMENT_QUOTES_NO_SPACE="Comment at end with quotes no space"# Comment QES
HAS_COMMENT_NO_QUOTES_SPACE=Comment at end no quotes and space # Comment NQE
HAS_COMMENT_NO_QUOTES_NO_SPACE=Comment at end no quotes no space# Comment NQES
COMMENT_IN_TEXT_QUOTES="Foo bar # comment in here"
FAILURE = ABC
SIMPLEBOX= A B C
TITLE=1
FOO=1.2
SOME.TEST=Test Var
SOME.LIVE=Live Var
# VAR TESTS -
A_TEST1 = foo
A_TEST2 = ${TEST1:-bar} # TEST1 is set so the value of TEST2 = foo
A_TEST3 = ${TEST4:-bar} # TEST4 is not set so the value of TEST3 = bar
A_TEST5 = null
A_TEST6 = ${TEST5-bar} # TEST5 is set but empty so the value of TEST6 = null
A_TEST7 = ${TEST6:-bar} # TEST5 is set and empty so the value of TEST7 = bar
# VAR TESTS =
B_TEST1 = foo
B_TEST2 = ${TEST1:=bar} # TEST1 is set so the value of TEST2 = foo
B_TEST3 = ${TEST4:=bar} # TEST4 is not set so the value of TEST3 = bar and TEST4 = bar
B_TEST5 = null
B_TEST6 = ${TEST5=bar} # TEST5 is set but emtpy so the value of TEST6 = null
B_TEST7 = ${TEST6=bar} # TEST5 is set and empty so the value of TEST7 = bar and TEST5 = bar
# VAR TEST END
Test="A"
TEST="B"
TEST="D"
LINE="ABC
DEF"
OTHERLINE="ABC
AF\"ASFASDF
MORESHIT"
SUPERLINE=
"asfasfasf"
__FOO_BAR_1 = b
__FOOFOO = f
123123=number
EMPTY=
= flase
asfasdf

View File

@@ -1,4 +1,4 @@
-- update missing edit_* table data
-- 2019/12/11 update missing edit_* table data
ALTER TABLE edit_generic ADD cuid VARCHAR;

View File

@@ -0,0 +1,53 @@
-- 2022/6/17 update edit_user with login uid
-- !!! COPY TABLE ARRAY FOLDER !!!
-- the login uid, at least 32 chars
ALTER TABLE edit_user ADD login_user_id VARCHAR UNIQUE;
-- CREATE UNIQUE INDEX edit_user_login_user_id_key ON edit_user (login_user_id) WHERE login_user_id IS NOT NULL;
-- ALTER TABLE edit_user ADD CONSTRAINT edit_user_login_user_id_key UNIQUE (login_user_id);
-- when above uid was set
ALTER TABLE edit_user ADD login_user_id_set_date TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE edit_user ADD login_user_id_last_revalidate TIMESTAMP WITHOUT TIME ZONE;
-- if set, from/until when the above uid is valid
ALTER TABLE edit_user ADD login_user_id_valid_from TIMESTAMP WITHOUT TIME ZONE;
ALTER TABLE edit_user ADD login_user_id_valid_until TIMESTAMP WITHOUT TIME ZONE;
-- user must login to revalidated login id after set days, 0 for forever
ALTER TABLE edit_user ADD login_user_id_revalidate_after INTERVAL;
-- lock for login user id, but still allow normal login
ALTER TABLE edit_user ADD login_user_id_locked SMALLINT NOT NULL DEFAULT 0;
-- disable login before date
ALTER TABLE edit_user ADD lock_until TIMESTAMP WITHOUT TIME ZONE;
-- disable login after date
ALTER TABLE edit_user ADD lock_after TIMESTAMP WITHOUT TIME ZONE;
CREATE OR REPLACE FUNCTION set_login_user_id_set_date()
RETURNS TRIGGER AS
$$
BEGIN
-- if new is not null/empty
-- and old one is null or old one different new one
-- set NOW()
-- if new one is NULL
-- set NULL
IF
NEW.login_user_id IS NOT NULL AND NEW.login_user_id <> '' AND
(OLD.login_user_id IS NULL OR NEW.login_user_id <> OLD.login_user_id)
THEN
NEW.login_user_id_set_date = NOW();
NEW.login_user_id_last_revalidate = NOW();
ELSIF NEW.login_user_id IS NULL OR NEW.login_user_id = '' THEN
NEW.login_user_id_set_date = NULL;
NEW.login_user_id_last_revalidate = NULL;
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';
CREATE TRIGGER trg_edit_user_set_login_user_id_set_date
BEFORE INSERT OR UPDATE ON edit_user
FOR EACH ROW EXECUTE PROCEDURE set_login_user_id_set_date();
-- __END__

View File

@@ -0,0 +1,22 @@
# Files to be changed
Change: Update Generate\Form to use ACL for form creation (basic)
Date: 2022/9/6
## File List
```sh
includes/table_arrays/array_edit_pages.php
includes/table_arrays/array_edit_users.php
includes/templates/admin/edit_body.tpl
includes/templates/admin/edit_elements.tpl
includes/templates/admin/edit_load.tpl
includes/templates/admin/edit_new.tpl
includes/templates/admin/edit_save_delete.tpl
includes/edit_base.php
lib/CoreLibs/ACL/Login.php
lib/CoreLibs/DB/Extended/ArrayIO.php
lib/CoreLibs/Convert/MimeEncode.php
lib/CoreLibs/Create/Email.php
lib/CoreLibs/Output/Form/Generate.php
```

View File

@@ -1,72 +1,47 @@
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$connection of function pg_connection_busy expects PgSql\\\\Connection, object\\|resource given\\.$#"
count: 3
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_connection_status expects PgSql\\\\Connection, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_escape_bytea expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_get_result expects PgSql\\\\Connection, object\\|resource given\\.$#"
count: 2
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_meta_data expects PgSql\\\\Connection, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_escape_identifier expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_send_query expects PgSql\\\\Connection, object\\|resource given\\.$#"
count: 2
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_socket expects PgSql\\\\Connection, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_escape_literal expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$connection of function pg_version expects PgSql\\\\Connection\\|null, object\\|resource given\\.$#"
count: 2
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_affected_rows expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_escape_string expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_fetch_all expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_execute expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_fetch_array expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_parameter_status expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_field_name expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_prepare expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_num_fields expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_query expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_num_rows expects PgSql\\\\Result, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php
-
message: "#^Parameter \\#1 \\$result of function pg_result_error expects PgSql\\\\Result, object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$connection of function pg_query_params expects PgSql\\\\Connection\\|string, object\\|resource given\\.$#"
count: 1
path: www/lib/CoreLibs/DB/SQL/PgSQL.php

View File

@@ -49,11 +49,11 @@ parameters:
- www/vendor
# ignore errores with
ignoreErrors:
- # this error is ignore because of the PHP 8.0 to 8.1 change for pg_*, only for 8.0 or lower
message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects resource(\\|null)?, object\\|resource(\\|bool)? given\\.$#"
path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php
#- # this error is ignore because of the PHP 8.0 to 8.1 change for pg_*, only for 8.0 or lower
# message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects resource(\\|null)?, object\\|resource(\\|bool)? given\\.$#"
# path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php
- # this is for 8.1 or newer
message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects PgSql\\\\(Result|Connection(\\|null)?), object\\|resource given\\.$#"
message: "#^Parameter \\#1 \\$(result|connection) of function pg_\\w+ expects PgSql\\\\(Result|Connection(\\|string)?(\\|null)?), object\\|resource given\\.$#"
path: %currentWorkingDirectory%/www/lib/CoreLibs/DB/SQL/PgSQL.php
# this is ignored for now
# - '#Expression in empty\(\) is always falsy.#'

View File

@@ -23,14 +23,12 @@ define('USE_DATABASE', true);
require 'config.php';
// override ECHO ALL FALSE
$ECHO_ALL = true;
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-admin';
$SET_SESSION_NAME = EDIT_SESSION_NAME;
ob_end_flush();
$session = new CoreLibs\Create\Session($SET_SESSION_NAME);
$log = new CoreLibs\Debug\Logging([
'log_folder' => BASE . LOG,
'file_id' => $LOG_FILE_ID,
@@ -49,7 +47,7 @@ $l10n = new \CoreLibs\Language\L10n(
$locale['domain'],
$locale['path'],
);
$backend = new CoreLibs\Admin\Backend($db, $log, $l10n, $locale);
$backend = new CoreLibs\Admin\Backend($db, $log, $session, $l10n, $locale);
$PAGE_NAME = 'TEST CLASS: ADMIN BACKEND';
print "<!DOCTYPE html>";

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-array';
ob_end_flush();

View File

@@ -20,10 +20,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-autoloader';
ob_end_flush();

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-byte';
ob_end_flush();
@@ -54,21 +50,22 @@ print '<div><h1>' . $PAGE_NAME . '</h1></div>';
$byte = 254779258;
$string = '242.98 MB';
// static
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_SI) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE FROM: $string: " . $byte_class::stringByteFormat($string) . "<br>";
print "S::BYTE TO (calls as var): $byte: " . $byte_class::humanReadableByteFormat($byte) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_SI) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE FROM: $string: " . Byte::stringByteFormat($string) . "<br>";
//
$byte = 314572800;
$string = '300 MB';
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_SI) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_SI) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST) . "<br>";
print "S::BYTE TO: $byte: "
. $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST | Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE TO: $byte: " . $byte_class::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE FROM: $string: " . $byte_class::stringByteFormat($string) . "<br>";
. Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_ADJUST | Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE TO: $byte: " . Byte::humanReadableByteFormat($byte, Byte::BYTE_FORMAT_NOSPACE) . "<br>";
print "S::BYTE FROM: $string: " . Byte::stringByteFormat($string) . "<br>";
// *** BYTES TEST ***
$bytes = [

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-colors';
ob_end_flush();

View File

@@ -0,0 +1,144 @@
<?php // phpcs:ignore warning
/**
* @phan-file-suppress PhanTypeSuspiciousStringExpression
*/
declare(strict_types=1);
// will be overwritten in config.master.php depending on location
$DEBUG_ALL_OVERRIDE = true; // set to 1 to debug on live/remote server locations
$DEBUG_ALL = true;
$PRINT_ALL = true;
$ECHO_ALL = true;
$DB_DEBUG = true;
if ($DEBUG_ALL) {
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
}
ob_start();
// basic class test file
define('USE_DATABASE', false);
// sample config
require 'config.php';
// define log file id
$LOG_FILE_ID = 'classTest-create_email';
ob_end_flush();
// override echo all from config.master.php
$ECHO_ALL = true;
use CoreLibs\Create\Email;
use CoreLibs\Convert\Html;
$log = new CoreLibs\Debug\Logging([
'log_folder' => BASE . LOG,
'file_id' => $LOG_FILE_ID,
// add file date
'print_file_date' => true,
// set debug and print flags
'debug_all' => $DEBUG_ALL,
'echo_all' => $ECHO_ALL,
'print_all' => $PRINT_ALL,
]);
// define a list of from to color sets for conversion test
$PAGE_NAME = 'TEST CLASS: CREATE EMAIL';
print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
print "<body>";
print '<div><a href="class_test.php">Class Test Master</a></div>';
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
$from_name = '日本語';
$from_email = 'test@test.com';
print "SET: $from_name / $from_email: "
. Html::htmlent(Email::encodeEmailName($from_email, $from_name)) . "<br>";
$status = Email::sendEmail(
'TEST',
'BODY',
'test@test.com',
'Test Name',
[
[
'name' => 'To 1',
'email' => 'to1@test.com'
],
],
[],
'UTF-8',
false,
true,
$log
);
print "SENDING A: " . $status . "<br>";
$status = Email::sendEmail(
'TEST {REPLACE}',
'BODY {OTHER}',
'test@test.com',
'Test Name',
[
[
'name' => 'To 1-A',
'email' => 'to1-a@test.com'
],
[
'name' => 'To 2-A',
'email' => 'to2-a@test.com',
'replace' => [
'OTHER' => '--FOR 2 A other--'
]
],
],
[
'REPLACE' => '**replaced**',
'OTHER' => '**other**'
],
'UTF-8',
false,
true,
$log
);
print "SENDING B: " . $status . "<br>";
$status = Email::sendEmail(
'TEST',
'BODY',
'test@test.com',
'Test Name',
['a@a.com', 'b@b.com'],
[],
'UTF-8',
false,
true,
$log
);
print "SENDING C: " . $status . "<br>";
// SUBJECT 日本語カタカナパ
$status = Email::sendEmail(
'TEST 日本語カタカナパカタカナバ',
'BODY 日本語カタカナパカタカナバ',
'test@test.com',
'Test Name 日本語カタカナパ',
[
['email' => 'a@a.com', 'name' => 'a 日本語カタカナパカタカナバ'],
['email' => 'b@b.com', 'name' => 'b 日本語プブガバケブプガバケ'],
],
[],
'UTF-8',
false,
true,
$log
);
print "SENDING D: " . $status . "<br>";
// error message
print $log->printErrorMsg();
print "</body></html>";
// __END__

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-datetime';
ob_end_flush();
@@ -143,6 +139,22 @@ foreach ($compare_dates as $compare_date) {
. DgS::printAr(DateTime::calcDaysInterval($compare_date[0], $compare_date[1], true)) . "<br>";
}
// test date conversion
$dow = 2;
print "DOW[$dow]: " . DateTime::setWeekdayNameFromIsoDow($dow) . "<br>";
print "DOW[$dow],long: " . DateTime::setWeekdayNameFromIsoDow($dow, true) . "<br>";
$date = '2022-7-22';
print "DATE-dow[$date]: " . DateTime::setWeekdayNameFromDate($date) . "<br>";
print "DATE-dow[$date],long: " . DateTime::setWeekdayNameFromDate($date, true) . "<br>";
print "DOW-date[$date]: " . DateTime::setWeekdayNumberFromDate($date) . "<br>";
$dow = 11;
print "DOW[$dow];invalid: " . DateTime::setWeekdayNameFromIsoDow($dow) . "<br>";
print "DOW[$dow],long;invalid: " . DateTime::setWeekdayNameFromIsoDow($dow, true) . "<br>";
$date = '2022-70-242';
print "DATE-dow[$date];invalid: " . DateTime::setWeekdayNameFromDate($date) . "<br>";
print "DATE-dow[$date],long;invalid: " . DateTime::setWeekdayNameFromDate($date, true) . "<br>";
print "DOW-date[$date];invalid: " . DateTime::setWeekdayNumberFromDate($date) . "<br>";
// error message
print $log->printErrorMsg();

View File

@@ -0,0 +1,140 @@
<?php // phpcs:ignore warning
/**
* @phan-file-suppress PhanTypeSuspiciousStringExpression
*/
declare(strict_types=1);
// turn on all error reporting
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR);
ob_start();
// basic class test file
define('USE_DATABASE', true);
// sample config
require 'config.php';
// override ECHO ALL FALSE
$ECHO_ALL = true;
// define log file id
$LOG_FILE_ID = 'classTest-db';
ob_end_flush();
use CoreLibs\Debug\Support;
use CoreLibs\Debug\RunningTime;
$log = new CoreLibs\Debug\Logging([
'log_folder' => BASE . LOG,
'file_id' => $LOG_FILE_ID,
// add file date
'print_file_date' => true,
// set debug and print flags
'debug_all' => $DEBUG_ALL ?? false,
'echo_all' => $ECHO_ALL ?? false,
'print_all' => $PRINT_ALL ?? false,
]);
// db connection and attach logger
$db = new CoreLibs\DB\IO(DB_CONFIG, $log);
$db->log->debug('START', '=============================>');
$PAGE_NAME = 'TEST CLASS: DB dbReturn';
print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
print "<body>";
print '<div><a href="class_test.php">Class Test Master</a></div>';
print '<div><a href="class_test.db.php">Class Test DB</a></div>';
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
print "LOGFILE NAME: " . $db->log->getSetting('log_file_name') . "<br>";
print "LOGFILE ID: " . $db->log->getSetting('log_file_id') . "<br>";
print "DBINFO: " . $db->dbInfo() . "<br>";
// DB client encoding
print "DB client encoding: " . $db->dbGetEncoding() . "<br>";
print "DB search path: " . $db->dbGetSchema() . "<br>";
// SELECT read tests with dbReturn and cache values
print "<br>";
print "<b>dbReturn CACHE tests</b><br>";
// DATA has two rows for reading
// delete and repare base data
$db->dbExec("DELETE FROM test_db_return");
$db->dbExec("INSERT INTO test_db_return (uid, data) VALUES ('A1', 'Test A'), ('B1', 'Test B')");
// read query to use
$q_db_ret = "SELECT * FROM test_db_return ORDER BY uid";
RunningTime::hrRunningTime();
$cache_flag = 'USE_CACHE (0)';
print "dbReturn '" . $cache_flag . "'/Default: " . $q_db_ret . "<br>";
// SINGLE read on multi row return
// Do twice
for ($i = 1; $i <= 6; $i++) {
$res = $db->dbReturn($q_db_ret);
print $i . ") " . $cache_flag . ": "
. "res: " . (is_bool($res) ?
"<b>Bool:</b> " . $db->log->prBl($res) :
(is_array($res) ?
"Array: " . $db->log->prBl(is_array($res)) : '{-}')
) . ", "
. "cursor_ext: <pre>" . Support::printAr($db->dbGetCursorExt($q_db_ret)) . "</pre>";
print "Run time: " . RunningTime::hrRunningTime() . "<br>";
}
// reset all read data
$db->dbCacheReset($q_db_ret);
echo "<hr>";
$cache_flag = 'READ_NEW (1)';
print "dbReturn '" . $cache_flag . "': " . $q_db_ret . "<br>";
// NO CACHE
for ($i = 1; $i <= 6; $i++) {
$res = $db->dbReturn($q_db_ret, $db::READ_NEW);
print $i . ") " . $cache_flag . ": "
. "res: " . (is_bool($res) ?
"<b>Bool:</b> " . $db->log->prBl($res) :
(is_array($res) ?
"Array: " . $db->log->prBl(is_array($res)) : '{-}')
) . ", "
. "cursor_ext: <pre>" . Support::printAr($db->dbGetCursorExt($q_db_ret)) . "</pre>";
print "Run time: " . RunningTime::hrRunningTime() . "<br>";
}
// reset all read data
$db->dbCacheReset($q_db_ret);
echo "<hr>";
$cache_flag = 'CLEAR_CACHE (2)';
print "dbReturn '" . $cache_flag . "': " . $q_db_ret . "<br>";
// NO CACHE
for ($i = 1; $i <= 6; $i++) {
$res = $db->dbReturn($q_db_ret, $db::CLEAR_CACHE);
print $i . ") " . $cache_flag . ": "
. "res: " . (is_bool($res) ?
"<b>Bool:</b> " . $db->log->prBl($res) :
(is_array($res) ?
"Array: " . $db->log->prBl(is_array($res)) : '{-}')
) . ", "
. "cursor_ext: <pre>" . Support::printAr($db->dbGetCursorExt($q_db_ret)) . "</pre>";
print "Run time: " . RunningTime::hrRunningTime() . "<br>";
}
// reset all read data
$db->dbCacheReset($q_db_ret);
echo "<hr>";
$cache_flag = 'NO_CACHE (3)';
print "dbReturn '" . $cache_flag . "': " . $q_db_ret . "<br>";
// NO CACHE
for ($i = 1; $i <= 6; $i++) {
$res = $db->dbReturn($q_db_ret, $db::NO_CACHE);
print $i . ") " . $cache_flag . ": "
. "res: " . (is_bool($res) ?
"<b>Bool:</b> " . $db->log->prBl($res) :
(is_array($res) ?
"Array: " . $db->log->prBl(is_array($res)) : '{-}')
) . ", "
. "cursor_ext: <pre>" . Support::printAr($db->dbGetCursorExt($q_db_ret)) . "</pre>";
print "Run time: " . RunningTime::hrRunningTime() . "<br>";
}
// reset all data
$db->dbCacheReset($q_db_ret);
print "<br>";
print "Overall Run time: " . RunningTime::hrRunningTimeFromStart() . "<br>";
// __END__

View File

@@ -44,6 +44,7 @@ print "<!DOCTYPE html>";
print "<html><head><title>" . $PAGE_NAME . "</title><head>";
print "<body>";
print '<div><a href="class_test.php">Class Test Master</a></div>';
print '<div><a href="class_test.db.dbReturn.php">Class Test DB dbReturn</a></div>';
print '<div><h1>' . $PAGE_NAME . '</h1></div>';
print "LOGFILE NAME: " . $db->log->getSetting('log_file_name') . "<br>";
@@ -72,6 +73,8 @@ $db->dbSetEncoding('SJIS');
print "ENCODING TEST: " . $db->dbVersionInfo('client_encoding') . "/" . $db->dbGetEncoding() . "<br>";
$db->dbResetEncoding();
// TEST CACHE READS
$res = $db->dbReturn("SELECT * FROM max_test");
print "DB RETURN ROWS: " . $db->dbGetNumRows() . "<br>";
@@ -97,6 +100,12 @@ print "NO CACHED DATA: <pre>" . print_r($db->dbGetCursorExt(), true) . "</pre><b
// print "UUD/TIME: " . $res['uid'] . "/" . $res['time'] . "<br>";
// }
// dbReturn tests on separate page
print "<br>";
print "<b>dbReturn CACHE tests</b><br>";
print '<a href="class_test.db.dbReturn.php">Class Test DB dbReturn</a><br>';
print "<br>";
print "<pre>";
print "SOCKET: " . pg_socket($db->dbGetDbh()) . "<br>";
@@ -182,7 +191,6 @@ print "UPDATE WITH PK " . $last_insert_pk
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// INSERT WITH NO RETURNING
$status = $db->dbExec("INSERT INTO test_foobar (type, integer) VALUES ('WITHOUT DATA', 456)");
print "INSERT WITH NO PRIMARY KEY NO RETURNING STATUS: " . Support::printToString($status) . " |<br>"
@@ -201,13 +209,12 @@ print "INSERT WITH NO PRIMARY KEY WITH RETURNING STATUS: " . Support::printToStr
print "</pre>";
// READ PREPARE
if (
$db->dbPrepare(
'sel_test_foo',
"SELECT test_foo_id, test, some_bool, string_a, number_a, number_a_numeric, some_time "
. "FROM test_foo ORDER BY test_foo_id DESC LIMIT 5"
) === false
) {
$q_prep = "SELECT test_foo_id, test, some_bool, string_a, number_a, "
. "number_a_numeric, some_time "
. "FROM test_foo "
. "WHERE test = $1 "
. "ORDER BY test_foo_id DESC LIMIT 5";
if ($db->dbPrepare('sel_test_foo', $q_prep) === false) {
print "Error in sel_test_foo prepare<br>";
} else {
$max_rows = 6;
@@ -221,7 +228,29 @@ if (
$i++;
}
}
// prepre a second time on normal connection
if ($db->dbPrepare('sel_test_foo', $q_prep) === false) {
print "Error prepareing<br>";
print "ERROR (dbPrepare on same query): "
. $db->dbGetLastError() . "/" . $db->dbGetLastWarning() . "/"
. "<pre>" . print_r($db->dbGetCombinedErrorHistory(), true) . "</pre><br>";
}
// NOTE: try to replacate connection still exists if script is run a second time
// open pg bouncer connection
$db_pgb = new CoreLibs\DB\IO($DB_CONFIG['test_pgbouncer'], $log);
print "[PGB] DBINFO: " . $db_pgb->dbInfo() . "<br>";
if ($db->dbPrepare('pgb_sel_test_foo', $q_prep) === false) {
print "[PGB] [1] Error in pgb_sel_test_foo prepare<br>";
} else {
print "[PGB] [1] pgb_sel_test_foo prepare OK<br>";
}
// second prepare
if ($db->dbPrepare('pgb_sel_test_foo', $q_prep) === false) {
print "[PGB] [2] Error in pgb_sel_test_foo prepare<br>";
} else {
print "[PGB] [2] pgb_sel_test_foo prepare OK<br>";
}
$db_pgb->dbClose();
# db write class test
$table = 'test_foo';

View File

@@ -66,7 +66,12 @@ print "S::GETCALLERMETHOD: " . test() . "<br>";
print "S::GETCALLERMETHODLIST: <pre>" . print_r(test2(), true) . "</pre><br>";
print "S::PRINTAR: " . DebugSupport::printAr(['Foo', 'Bar']) . "<br>";
print "V-S::PRINTAR: " . $debug_support_class::printAr(['Foo', 'Bar']) . "<br>";
print "S::PRINTBOOL(default): " . DebugSupport::printBool(true) . "<br>";
print "S::PRINTBOOL(name): " . DebugSupport::printBool(true, 'Name') . "<br>";
print "S::PRINTBOOL(name, ok): " . DebugSupport::printBool(true, 'Name', 'ok') . "<br>";
print "S::PRINTBOOL(name, ok, not): " . DebugSupport::printBool(false, 'Name', 'ok', 'not') . "<br>";
print "S::DEBUSTRING(s): " . DebugSupport::debugString('SET') . "<br>";
print "S::DEBUSTRING(s&gt;): " . DebugSupport::debugString('<SET>') . "<br>";
print "S::DEBUSTRING(''): " . DebugSupport::debugString('') . "<br>";
print "S::DEBUSTRING(,s): " . DebugSupport::debugString(null, '{-}') . "<br>";
@@ -181,6 +186,10 @@ $debug->debug('TEST PER LEVEL', 'Per level test');
$debug->debug('()', 'Per level test: invalid chars');
$debug->setLogPer('level', false);
$ar = ['A', 1, ['B' => 'D']];
$debug->debug('ARRAY', 'Array: ' . $debug->prAr($ar));
$debug->debug('BOOL', 'True: ' . $debug->prBl(true) . ', False: ' . $debug->prBl(false));
// error message
// future DEPRECATED
// $debug->debug('BASIC CLASS', 'Debug test');

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-email';
ob_end_flush();

View File

@@ -21,10 +21,6 @@ ob_start();
define('USE_DATABASE', false);
// sample config
require 'config.php';
// set session name
if (!defined('SET_SESSION_NAME')) {
define('SET_SESSION_NAME', EDIT_SESSION_NAME);
}
// define log file id
$LOG_FILE_ID = 'classTest-encoding';
ob_end_flush();

Some files were not shown because too many files have changed in this diff Show More