Compare commits

...

6 Commits

Author SHA1 Message Date
Clemens Schwaighofer
5b1ca4241c phan min php update to 8.3, add missing phpunit test folder for language check 2024-12-10 15:29:54 +09:00
Clemens Schwaighofer
c8d6263c0f Fix DB IO placeholder count 2024-12-10 14:59:58 +09:00
Clemens Schwaighofer
bd1972d894 Composer keywords 2024-12-10 14:52:50 +09:00
Clemens Schwaighofer
fa29477c80 Release: v9.23.1 2024-12-05 14:08:56 +09:00
Clemens Schwaighofer
20ee958db9 Session class update with many methods and general clean up 2024-12-05 14:07:39 +09:00
Clemens Schwaighofer
157616582f Release: v9.23.0 2024-12-04 16:40:51 +09:00
13 changed files with 353 additions and 190 deletions

View File

@@ -54,7 +54,8 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
// Automatically inferred from composer.json requirement for "php" of ">=8.2"
'target_php_version' => '8.1',
'target_php_version' => '8.2',
"minimum_target_php_version" => "8.2",
// If enabled, missing properties will be created when
// they are first seen. If false, we'll report an

View File

@@ -3,6 +3,7 @@
"description": "CoreLibs in a composer package",
"type": "library",
"license": "MIT",
"keywords": ["corelib", "logging", "database", "templating", "tools"],
"autoload": {
"psr-4": {
"CoreLibs\\": "src/"

View File

@@ -1 +1 @@
9.22.0
9.23.1

View File

@@ -372,9 +372,6 @@ class Login
],
];
// init default ACL list array
$_SESSION['DEFAULT_ACL_LIST'] = [];
$_SESSION['DEFAULT_ACL_LIST_TYPE'] = [];
// read the current edit_access_right list into an array
$q = "SELECT level, type, name FROM edit_access_right "
. "WHERE level >= 0 ORDER BY level";
@@ -387,8 +384,10 @@ class Login
$this->default_acl_list_type[(string)$res['type']] = (int)$res['level'];
}
// write that into the session
$_SESSION['DEFAULT_ACL_LIST'] = $this->default_acl_list;
$_SESSION['DEFAULT_ACL_LIST_TYPE'] = $this->default_acl_list_type;
$this->session->setMany([
'DEFAULT_ACL_LIST' => $this->default_acl_list,
'DEFAULT_ACL_LIST_TYPE' => $this->default_acl_list_type,
]);
$this->loginSetEditLogWriteTypeAvailable();
@@ -580,7 +579,7 @@ class Login
// set path
$options['locale_path'] = BASE . INCLUDES . LOCALE;
}
$_SESSION['LOCALE_PATH'] = $options['locale_path'];
$this->session->set('LOCALE_PATH', $options['locale_path']);
// LANG: LOCALE
if (empty($options['site_locale'])) {
trigger_error(
@@ -615,7 +614,7 @@ class Login
$options['set_domain'] = str_replace(DIRECTORY_SEPARATOR, '', CONTENT_PATH);
}
}
$_SESSION['DEFAULT_DOMAIN'] = $options['site_domain'];
$this->session->set('DEFAULT_DOMAIN', $options['site_domain']);
// LANG: ENCODING
if (empty($options['site_encoding'])) {
trigger_error(
@@ -901,9 +900,14 @@ class Login
}
// normal user processing
// set class var and session var
$_SESSION['EUID'] = $this->euid = (int)$res['edit_user_id'];
$_SESSION['ECUID'] = $this->ecuid = (string)$res['cuid'];
$_SESSION['ECUUID'] = $this->ecuuid = (string)$res['cuuid'];
$this->euid = (int)$res['edit_user_id'];
$this->ecuid = (string)$res['cuid'];
$this->ecuuid = (string)$res['cuuid'];
$this->session->setMany([
'EUID' => $this->euid,
'ECUID' => $this->ecuid,
'ECUUID' => $this->ecuuid,
]);
// check if user is okay
$this->loginCheckPermissions();
if ($this->login_error == 0) {
@@ -916,27 +920,39 @@ class Login
. "WHERE edit_user_id = " . $this->euid;
$this->db->dbExec($q);
}
// now set all session vars and read page permissions
$_SESSION['DEBUG_ALL'] = $this->db->dbBoolean($res['debug']);
$_SESSION['DB_DEBUG'] = $this->db->dbBoolean($res['db_debug']);
// general info for user logged in
$_SESSION['USER_NAME'] = $res['username'];
$_SESSION['ADMIN'] = $res['admin'];
$_SESSION['GROUP_NAME'] = $res['edit_group_name'];
$_SESSION['USER_ACL_LEVEL'] = $res['user_level'];
$_SESSION['USER_ACL_TYPE'] = $res['user_type'];
$_SESSION['USER_ADDITIONAL_ACL'] = Json::jsonConvertToArray($res['user_additional_acl']);
$_SESSION['GROUP_ACL_LEVEL'] = $res['group_level'];
$_SESSION['GROUP_ACL_TYPE'] = $res['group_type'];
$_SESSION['GROUP_ADDITIONAL_ACL'] = Json::jsonConvertToArray($res['group_additional_acl']);
// deprecated TEMPLATE setting
$_SESSION['TEMPLATE'] = $res['template'] ? $res['template'] : '';
$_SESSION['HEADER_COLOR'] = !empty($res['second_header_color']) ?
$res['second_header_color'] :
$res['first_header_color'];
$locale = $res['locale'] ?? 'en';
$encoding = $res['encoding'] ?? 'UTF-8';
$this->session->setMany([
// now set all session vars and read page permissions
'DEBUG_ALL' => $this->db->dbBoolean($res['debug']),
'DB_DEBUG' => $this->db->dbBoolean($res['db_debug']),
// general info for user logged in
'USER_NAME' => $res['username'],
'ADMIN' => $res['admin'],
'GROUP_NAME' => $res['edit_group_name'],
'USER_ACL_LEVEL' => $res['user_level'],
'USER_ACL_TYPE' => $res['user_type'],
'USER_ADDITIONAL_ACL' => Json::jsonConvertToArray($res['user_additional_acl']),
'GROUP_ACL_LEVEL' => $res['group_level'],
'GROUP_ACL_TYPE' => $res['group_type'],
'GROUP_ADDITIONAL_ACL' => Json::jsonConvertToArray($res['group_additional_acl']),
// deprecated TEMPLATE setting
'TEMPLATE' => $res['template'] ? $res['template'] : '',
'HEADER_COLOR' => !empty($res['second_header_color']) ?
$res['second_header_color'] :
$res['first_header_color'],
// LANGUAGE/LOCALE/ENCODING:
'LANG' => $locale,
'DEFAULT_CHARSET' => $encoding,
'DEFAULT_LOCALE' => $locale . '.' . strtoupper($encoding),
'DEFAULT_LANG' => $locale . '_' . strtolower(str_replace('-', '', $encoding))
]);
// missing # before, this is for legacy data, will be deprecated
if (preg_match("/^[\dA-Fa-f]{6,8}$/", $_SESSION['HEADER_COLOR'])) {
$_SESSION['HEADER_COLOR'] = '#' . $_SESSION['HEADER_COLOR'];
if (
!empty($this->session->get('HEADER_COLOR')) &&
preg_match("/^[\dA-Fa-f]{6,8}$/", $this->session->get('HEADER_COLOR'))
) {
$this->session->set('HEADER_COLOR', '#' . $this->session->get('HEADER_COLOR'));
}
// TODO: make sure that header color is valid:
// # + 6 hex
@@ -945,13 +961,6 @@ class Login
// rgb: nnn.n for each
// hsl: nnn.n for first, nnn.n% for 2nd, 3rd
// Check\Colors::validateColor()
// LANGUAGE/LOCALE/ENCODING:
$_SESSION['LANG'] = $res['locale'] ?? 'en';
$_SESSION['DEFAULT_CHARSET'] = $res['encoding'] ?? 'UTF-8';
$_SESSION['DEFAULT_LOCALE'] = $_SESSION['LANG']
. '.' . strtoupper($_SESSION['DEFAULT_CHARSET']);
$_SESSION['DEFAULT_LANG'] = $_SESSION['LANG'] . '_'
. strtolower(str_replace('-', '', $_SESSION['DEFAULT_CHARSET']));
// reset any login error count for this user
if ($res['login_error_count'] > 0) {
$q = "UPDATE edit_user "
@@ -1041,8 +1050,10 @@ class Login
];
}
// write back the pages data to the output array
$_SESSION['PAGES'] = $pages;
$_SESSION['PAGES_ACL_LEVEL'] = $pages_acl;
$this->session->setMany([
'PAGES' => $pages,
'PAGES_ACL_LEVEL' => $pages_acl,
]);
// load the edit_access user rights
$q = "SELECT ea.edit_access_id, level, type, ea.name, "
. "ea.color, ea.uid, edit_default, ea.additional_acl "
@@ -1054,6 +1065,7 @@ class Login
$unit_access = [];
$eauid = [];
$unit_acl = [];
$unit_uid = [];
while (is_array($res = $this->db->dbReturn($q))) {
// read edit access data fields and drop them into the unit access array
$q_sub = "SELECT name, value "
@@ -1077,16 +1089,19 @@ class Login
];
// set the default unit
if ($res['edit_default']) {
$_SESSION['UNIT_DEFAULT'] = (int)$res['edit_access_id'];
$this->session->set('UNIT_DEFAULT', (int)$res['edit_access_id']);
}
$_SESSION['UNIT_UID'][$res['uid']] = (int)$res['edit_access_id'];
$unit_uid[$res['uid']] = (int)$res['edit_access_id'];
// sub arrays for simple access
array_push($eauid, $res['edit_access_id']);
$unit_acl[$res['edit_access_id']] = $res['level'];
}
$_SESSION['UNIT'] = $unit_access;
$_SESSION['UNIT_ACL_LEVEL'] = $unit_acl;
$_SESSION['EAID'] = $eauid;
$this->session->setMany([
'UNIT_UID' => $unit_uid,
'UNIT' => $unit_access,
'UNIT_ACL_LEVEL' => $unit_acl,
'EAID' => $eauid,
]);
} // user has permission to THIS page
} // user was not enabled or other login error
if ($this->login_error && is_array($res)) {
@@ -1182,7 +1197,7 @@ class Login
$this->acl['base'] = (int)$_SESSION['USER_ACL_LEVEL'];
}
}
$_SESSION['BASE_ACL_LEVEL'] = $this->acl['base'];
$this->session->set('BASE_ACL_LEVEL', $this->acl['base']);
// set the current page acl
// start with base acl
@@ -1889,13 +1904,13 @@ HTML;
),
[
// row 1
empty($username) ? $_SESSION['USER_NAME'] ?? '' : $username,
!empty($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] : null,
!empty($_SESSION['ECUID']) && is_string($_SESSION['ECUID']) ?
$_SESSION['ECUID'] : null,
!empty($_SESSION['ECUUID']) && Uids::validateUuuidv4($_SESSION['ECUUID']) ?
$_SESSION['ECUUID'] : null,
empty($username) ? $this->session->get('USER_NAME') ?? '' : $username,
is_numeric($this->session->get('EUID')) ?
$this->session->get('EUID') : null,
is_string($this->session->get('ECUID')) ?
$this->session->get('ECUID') : null,
!empty($this->session->get('ECUUID')) && Uids::validateUuuidv4($this->session->get('ECUUID')) ?
$this->session->get('ECUUID') : null,
(string)$event,
(string)$error,
$data_write,
@@ -2022,10 +2037,10 @@ HTML;
}
}
// if there is none, there is none, saves me POST/GET check
$this->euid = array_key_exists('EUID', $_SESSION) ? (int)$_SESSION['EUID'] : 0;
$this->euid = (int)($this->session->get('EUID') ?? 0);
// TODO: allow load from cuid
// $this->ecuid = array_key_exists('ECUID', $_SESSION) ? (string)$_SESSION['ECUID'] : '';
// $this->ecuuid = array_key_exists('ECUUID', $_SESSION) ? (string)$_SESSION['ECUUID'] : '';
// $this->ecuid = (string)($this->session->get('ECUID') ?? '');
// $this->ecuuid = (string)($this->session->get('ECUUID') ?? '');
// get login vars, are so, can't be changed
// prepare
// pass on vars to Object vars
@@ -2368,8 +2383,12 @@ HTML;
$this->login_error = 103;
}
// set ECUID
$_SESSION['ECUID'] = $this->ecuid = (string)$res['cuid'];
$_SESSION['ECUUID'] = $this->ecuuid = (string)$res['cuuid'];
$this->ecuid = (string)$res['cuid'];
$this->ecuuid = (string)$res['cuuid'];
$this->session->setMany([
'ECUID' => $this->ecuid,
'ECUUID' => $this->ecuuid,
]);
// if called from public, so we can check if the permissions are ok
return $this->permission_okay;
}
@@ -2515,13 +2534,12 @@ HTML;
{
if (
$edit_access_id !== null &&
isset($_SESSION['UNIT']) &&
is_array($_SESSION['UNIT']) &&
!array_key_exists($edit_access_id, $_SESSION['UNIT'])
is_array($this->session->get('UNIT')) &&
!array_key_exists($edit_access_id, $this->session->get('UNIT'))
) {
$edit_access_id = null;
if (is_numeric($_SESSION['UNIT_DEFAULT'])) {
$edit_access_id = (int)$_SESSION['UNIT_DEFAULT'];
if (is_numeric($this->session->get('UNIT_DEFAULT'))) {
$edit_access_id = (int)$this->session->get('UNIT_DEFAULT');
}
}
return $edit_access_id;
@@ -2652,7 +2670,7 @@ HTML;
*/
public function loginGetHeaderColor(): ?string
{
return $_SESSION['HEADER_COLOR'] ?? null;
return $this->session->get('HEADER_COLOR');
}
/**
@@ -2663,7 +2681,7 @@ HTML;
public function loginGetPages(): array
{
return $_SESSION['PAGES'] ?? [];
return $this->session->get('PAGES');
}
/**

View File

@@ -380,12 +380,12 @@ class Backend
[
// row 1
'',
!empty($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ?
$_SESSION['EUID'] : null,
!empty($_SESSION['ECUID']) && is_string($_SESSION['ECUID']) ?
$_SESSION['ECUID'] : null,
!empty($_SESSION['ECUUID']) && Uids::validateUuuidv4($_SESSION['ECUID']) ?
$_SESSION['ECUID'] : null,
is_numeric($this->session->get('EUID')) ?
$this->session->get('EUID') : null,
is_string($this->session->get('ECUID')) ?
$this->session->get('ECUID') : null,
!empty($this->session->get('ECUUID')) && Uids::validateUuuidv4($this->session->get('ECUID')) ?
$this->session->get('ECUID') : null,
(string)$event,
'',
$data_write,
@@ -468,7 +468,7 @@ class Backend
}
// get the session pages array
$PAGES = $_SESSION['PAGES'] ?? null;
$PAGES = $this->session->get('PAGES');
if (!isset($PAGES) || !is_array($PAGES)) {
$PAGES = [];
}

View File

@@ -97,6 +97,23 @@ class Session
return true;
}
/**
* validate _SESSION key, must be valid variable
*
* @param int|float|string $key
* @return true
*/
private function checkValidSessionEntryKey(int|float|string $key): true
{
if (!is_string($key) || is_numeric($key)) {
throw new \UnexpectedValueException(
'[SESSION] Given key for _SESSION is not a valid value for a varaible: ' . $key,
1
);
}
return true;
}
// MARK: init session (on class start)
/**
@@ -162,6 +179,9 @@ class Session
public function restartSession(): bool
{
if (!$this->checkActiveSession()) {
if (empty($this->session_name)) {
throw new \RuntimeException('[SESSION] Cannot restart session without a session name', 1);
}
$this->startSessionCall();
return true;
}
@@ -235,6 +255,21 @@ class Session
return \CoreLibs\Get\System::checkCLI();
}
/**
* get session status
* PHP_SESSION_DISABLED if sessions are disabled.
* PHP_SESSION_NONE if sessions are enabled, but none exists.
* PHP_SESSION_ACTIVE if sessions are enabled, and one exists.
*
* https://www.php.net/manual/en/function.session-status.php
*
* @return int See possible return int values above
*/
public function getSessionStatus(): int
{
return session_status();
}
// MARK: write close session
/**
@@ -256,13 +291,18 @@ class Session
* Proper destroy a session
* - unset the _SESSION array
* - unset cookie if cookie on and we have not strict mode
* - unset session_name and session_id internal vars
* - destroy session
*
* @return bool
* @return bool True on successful session destroy
*/
public function sessionDestroy(): bool
{
$_SESSION = [];
// abort to false if not unsetable
if (!session_unset()) {
return false;
}
$this->clear();
if (
ini_get('session.use_cookies') &&
!ini_get('session.use_strict_mode')
@@ -282,24 +322,12 @@ class Session
$params['httponly']
);
}
// unset internal vars
$this->session_name = '';
$this->session_id = '';
return session_destroy();
}
/**
* get session status
* PHP_SESSION_DISABLED if sessions are disabled.
* PHP_SESSION_NONE if sessions are enabled, but none exists.
* PHP_SESSION_ACTIVE if sessions are enabled, and one exists.
*
* https://www.php.net/manual/en/function.session-status.php
*
* @return int See possible return int values above
*/
public function getSessionStatus(): int
{
return session_status();
}
// MARK: _SESSION set/unset methods
/**
@@ -307,11 +335,14 @@ class Session
*
* @return void
*/
public function unsetAll(): void
public function clear(): void
{
$this->restartSession();
foreach (array_keys($_SESSION ?? []) as $name) {
unset($_SESSION[$name]);
if (!session_unset()) {
throw new \RuntimeException('[SESSION] Cannot unset session vars', 1);
}
if (!empty($_SESSION)) {
$_SESSION = [];
}
$this->closeSessionCall();
}
@@ -319,35 +350,64 @@ class Session
/**
* set _SESSION entry 'name' with any value
*
* @param string|int $name array name in _SESSION
* @param mixed $value value to set (can be anything)
* @param string $name array name in _SESSION
* @param mixed $value value to set (can be anything)
* @return void
*/
public function set(string|int $name, mixed $value): void
public function set(string $name, mixed $value): void
{
$this->checkValidSessionEntryKey($name);
$this->restartSession();
$_SESSION[$name] = $value;
$this->closeSessionCall();
}
/**
* set many session entries in one set
*
* @param array<string,mixed> $set key is the key in the _SESSION, value is any data to set
* @return void
*/
public function setMany(array $set): void
{
$this->restartSession();
// skip any that are not valid
foreach ($set as $key => $value) {
$this->checkValidSessionEntryKey($key);
$_SESSION[$key] = $value;
}
$this->closeSessionCall();
}
/**
* get _SESSION 'name' entry or empty string if not set
*
* @param string|int $name value key to get from _SESSION
* @return mixed value stored in _SESSION
* @param string $name value key to get from _SESSION
* @return mixed value stored in _SESSION, if not found set to null
*/
public function get(string|int $name): mixed
public function get(string $name): mixed
{
return $_SESSION[$name] ?? null;
}
/**
* get multiple session entries
*
* @param array<string> $set
* @return array<string,mixed>
*/
public function getMany(array $set): array
{
return array_intersect_key($_SESSION, array_flip($set));
}
/**
* Check if a name is set in the _SESSION array
*
* @param string|int $name Name to check for
* @return bool True for set, False fornot set
* @param string $name Name to check for
* @return bool True for set, False fornot set
*/
public function isset(string|int $name): bool
public function isset(string $name): bool
{
return isset($_SESSION[$name]);
}
@@ -355,10 +415,10 @@ class Session
/**
* unset one _SESSION entry 'name' if exists
*
* @param string|int $name _SESSION key name to remove
* @param string $name _SESSION key name to remove
* @return void
*/
public function unset(string|int $name): void
public function unset(string $name): void
{
if (!isset($_SESSION[$name])) {
return;
@@ -368,65 +428,21 @@ class Session
$this->closeSessionCall();
}
// MARK: [DEPRECATED] __set/__get magic methods
// ->var = value;
/**
* Undocumented function
* reset many session entry
*
* @param string|int $name
* @param mixed $value
* @param array<string> $set list of session keys to reset
* @return void
* @deprecated use ->set()
*/
public function __set(string|int $name, mixed $value): void
public function unsetMany(array $set): void
{
$this->restartSession();
$_SESSION[$name] = $value;
$this->closeSessionCall();
}
/**
* Undocumented function
*
* @param string|int $name
* @return mixed If name is not found, it will return null
* @deprecated use ->get()
*/
public function __get(string|int $name): mixed
{
if (isset($_SESSION[$name])) {
return $_SESSION[$name];
foreach ($set as $key) {
if (!isset($_SESSION[$key])) {
continue;
}
unset($_SESSION[$key]);
}
return null;
}
/**
* Undocumented function
*
* @param string|int $name
* @return bool
* @deprecated use ->isset()
*/
public function __isset(string|int $name): bool
{
return isset($_SESSION[$name]);
}
/**
* Undocumented function
*
* @param string|int $name
* @return void
* @deprecated use ->unset()
*/
public function __unset(string|int $name): void
{
if (!isset($_SESSION[$name])) {
return;
}
$this->restartSession();
unset($_SESSION[$name]);
$this->closeSessionCall();
}
}

View File

@@ -1332,6 +1332,7 @@ class IO
*/
private function __dbCheckQueryParams(string $query, array $params): bool
{
// $this->log->debug('DB QUERY PARAMS REGEX', ConvertPlaceholder::REGEX_LOOKUP_PLACEHOLDERS);
$placeholder_count = $this->__dbCountQueryParams($query);
$params_count = count($params);
if ($params_count != $placeholder_count) {

View File

@@ -14,8 +14,19 @@ namespace CoreLibs\DB\Support;
class ConvertPlaceholder
{
/** @var string split regex */
private const PATTERN_QUERY_SPLIT = '[(<>=,?-]|->|->>|#>|#>>|@>|<@|\?\|\?\&|\|\||#-';
// NOTE for missing: range */+ are not iplemented in the regex below, but - is for now
// NOTE some combinations are allowed, but the query will fail before this
/** @var string split regex, entries before $ group */
private const PATTERN_QUERY_SPLIT =
',|' // for ',' mostly in INSERT
. '[(<>=]|' // general set for (, <, >, = in any query with any combination
. '(?:[\(,]\s*\-\-[\s\w]*)\r?\n|' // a comment that starts after a ( or ,
. '\^@|' // text search for start from text with ^@
. '\|\||' // concats two elements
. '&&|' // array overlap
. '\-\|\-|' // range overlap
. '[^-]-{1}|' // single -, used in JSON too
. '->|->>|#>|#>>|@>|<@|@@|@\?|\?{1}|\?\||\?&|#-'; //JSON searches, Array searchs, etc
/** @var string the main regex including the pattern query split */
private const PATTERN_ELEMENT = '(?:\'.*?\')?\s*(?:\?\?|' . self::PATTERN_QUERY_SPLIT . ')\s*';
/** @var string parts to ignore in the SQL */

View File

@@ -2,7 +2,7 @@
/*
* sets a form token in the _SESSION variable
* session must be started for this to work
* session must be started and running for this to work
*/
declare(strict_types=1);

View File

@@ -321,7 +321,7 @@ CREATE TABLE edit_generic (
-- DROP TABLE edit_visible_group;
CREATE TABLE edit_visible_group (
edit_visible_group_id SERIAL PRIMARY KEY,
edit_visible_group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
flag VARCHAR
) INHERITS (edit_generic) WITHOUT OIDS;
@@ -336,7 +336,7 @@ CREATE TABLE edit_visible_group (
-- DROP TABLE edit_menu_group;
CREATE TABLE edit_menu_group (
edit_menu_group_id SERIAL PRIMARY KEY,
edit_menu_group_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
flag VARCHAR,
order_number INT NOT NULL
@@ -354,7 +354,7 @@ CREATE TABLE edit_menu_group (
-- DROP TABLE edit_page;
CREATE TABLE edit_page (
edit_page_id SERIAL PRIMARY KEY,
edit_page_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -378,7 +378,7 @@ CREATE TABLE edit_page (
-- DROP TABLE edit_query_string;
CREATE TABLE edit_query_string (
edit_query_string_id SERIAL PRIMARY KEY,
edit_query_string_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -430,7 +430,7 @@ CREATE TABLE edit_page_menu_group (
-- DROP TABLE edit_access_right;
CREATE TABLE edit_access_right (
edit_access_right_id SERIAL PRIMARY KEY,
edit_access_right_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR,
level SMALLINT,
type VARCHAR,
@@ -447,7 +447,7 @@ CREATE TABLE edit_access_right (
-- DROP TABLE edit_scheme;
CREATE TABLE edit_scheme (
edit_scheme_id SERIAL PRIMARY KEY,
edit_scheme_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
name VARCHAR,
header_color VARCHAR,
@@ -466,7 +466,7 @@ CREATE TABLE edit_scheme (
-- DROP TABLE edit_language;
CREATE TABLE edit_language (
edit_language_id SERIAL PRIMARY KEY,
edit_language_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
lang_default SMALLINT NOT NULL DEFAULT 0,
long_name VARCHAR,
@@ -485,7 +485,7 @@ CREATE TABLE edit_language (
-- DROP TABLE edit_group;
CREATE TABLE edit_group (
edit_group_id SERIAL PRIMARY KEY,
edit_group_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -507,7 +507,7 @@ CREATE TABLE edit_group (
-- DROP TABLE edit_page_access;
CREATE TABLE edit_page_access (
edit_page_access_id SERIAL PRIMARY KEY,
edit_page_access_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -530,7 +530,7 @@ CREATE TABLE edit_page_access (
-- DROP TABLE edit_page_content;
CREATE TABLE edit_page_content (
edit_page_content_id SERIAL PRIMARY KEY,
edit_page_content_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -551,7 +551,7 @@ CREATE TABLE edit_page_content (
-- DROP TABLE edit_user;
CREATE TABLE edit_user (
edit_user_id SERIAL PRIMARY KEY,
edit_user_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -652,11 +652,11 @@ COMMENT ON COLUMN edit_user.additional_acl IS 'Additional Access Control List st
-- DROP TABLE edit_log;
CREATE TABLE edit_log (
edit_log_id SERIAL PRIMARY KEY,
edit_log_id INT GENERATED ALWAYS AS IDENTITY 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,
ecuid VARCHAR,
ecuuid UUID,
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,
@@ -712,7 +712,7 @@ ALTER TABLE edit_log_overflow ADD CONSTRAINT edit_log_overflow_euid_fkey FOREIGN
-- DROP TABLE edit_access;
CREATE TABLE edit_access (
edit_access_id SERIAL PRIMARY KEY,
edit_access_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
enabled SMALLINT NOT NULL DEFAULT 0,
protected SMALLINT DEFAULT 0,
deleted SMALLINT DEFAULT 0,
@@ -733,7 +733,7 @@ CREATE TABLE edit_access (
-- DROP TABLE edit_access_user;
CREATE TABLE edit_access_user (
edit_access_user_id SERIAL PRIMARY KEY,
edit_access_user_id INT GENERATED ALWAYS AS IDENTITY 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,
@@ -754,7 +754,7 @@ CREATE TABLE edit_access_user (
-- DROP TABLE edit_access_data;
CREATE TABLE edit_access_data (
edit_access_data_id SERIAL PRIMARY KEY,
edit_access_data_id INT GENERATED ALWAYS AS IDENTITY 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,

View File

@@ -272,24 +272,27 @@ final class CoreLibsCreateSessionTest extends TestCase
*
* @return array
*/
public function sessionDataProvider(): array
public function providerSessionData(): array
{
return [
'test' => [
'foo',
'bar',
'bar',
null,
],
'int key test' => [
123,
'bar',
'bar',
\UnexpectedValueException::class
],
// more complex value tests
'array values' => [
'array',
[1, 2, 3],
[1, 2, 3],
null,
]
];
}
@@ -299,21 +302,28 @@ final class CoreLibsCreateSessionTest extends TestCase
/**
* method call test
*
* @covers ::setS
* @covers ::getS
* @covers ::issetS
* @covers ::unsetS
* @dataProvider sessionDataProvider
* @testdox setS/getS/issetS/unsetS $name with $input is $expected [$_dataName]
* @covers ::set
* @covers ::get
* @covers ::isset
* @covers ::unset
* @dataProvider providerSessionData
* @testdox set/get/isset/unset $name with $input is $expected ($exception) [$_dataName]
*
* @param string|int $name
* @param mixed $input
* @param mixed $expected
* @param ?mixed $exception
* @return void
*/
/* public function testMethodSetGet($name, $input, $expected): void
public function testMethodSetGet($name, $input, $expected, $exception): void
{
if (\CoreLibs\Get\System::checkCLI()) {
$this->markTestSkipped('Cannot run testMethodSetGet in CLI');
}
$session = new \CoreLibs\Create\Session('TEST_METHOD');
if ($expected !== null) {
$this->expectException($exception);
}
$session->set($name, $input);
$this->assertEquals(
$expected,
@@ -331,12 +341,80 @@ final class CoreLibsCreateSessionTest extends TestCase
$session->get($name),
'method unset assert'
);
// iset false
// isset false
$this->assertFalse(
$session->isset($name),
'method isset assert false'
);
} */
}
/**
* Undocumented function
*
* @return array
*/
public function providerSessionDataMany(): array
{
return [
'valid set' => [
[
'foo 1' => 'bar 1',
'foo 2' => 'bar 1',
],
[
'foo 1' => 'bar 1',
'foo 2' => 'bar 1',
],
null,
],
'invalid entry' => [
[
'foo 1' => 'bar 1',
123 => 'bar 1',
],
[
'foo 1' => 'bar 1',
],
\UnexpectedValueException::class
]
];
}
/**
* Undocumented function
*
* @covers ::setMany
* @covers ::getMany
* @dataProvider providerSessionDataMany
* @testdox setMany/getMany/unsetMany $set is $expected ($exception) [$_dataName]
*
* @param array<string|int,mixed> $set
* @param array<string,mixed> $expected
* @param ?mixed $exception
* @return void
*/
public function testMany($set, $expected, $exception): void
{
if (\CoreLibs\Get\System::checkCLI()) {
$this->markTestSkipped('Cannot run testMethodSetGet in CLI');
}
$session = new \CoreLibs\Create\Session('TEST_METHOD');
if ($expected !== null) {
$this->expectException($exception);
}
$session->setMany($set);
$this->assertEquals(
$expected,
$session->getMany(array_keys($set)),
'set many failed'
);
$session->unsetMany(array_keys($set));
$this->assertEquals(
[],
$session->getMany(array_keys($set)),
'unset many failed'
);
}
/**
* unset all test
@@ -346,8 +424,11 @@ final class CoreLibsCreateSessionTest extends TestCase
*
* @return void
*/
/* public function testUnsetAll(): void
public function testUnsetAll(): void
{
if (\CoreLibs\Get\System::checkCLI()) {
$this->markTestSkipped('Cannot run testUnsetAll in CLI');
}
$test_values = [
'foo' => 'abc',
'bar' => '123'
@@ -363,7 +444,7 @@ final class CoreLibsCreateSessionTest extends TestCase
);
}
// unset all
$session->unsetAll();
$session->clear();
// check unset
foreach (array_keys($test_values) as $name) {
$this->assertEquals(
@@ -372,7 +453,7 @@ final class CoreLibsCreateSessionTest extends TestCase
'unsert assert: ' . $name
);
}
} */
}
}
// __END__

View File

@@ -17,7 +17,7 @@ Table with Primary Key: table_with_primary_key
Table without Primary Key: table_without_primary_key
Table with primary key has additional row:
row_primary_key SERIAL PRIMARY KEY,
row_primary_key INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
Each table has the following rows
row_int INT,
row_numeric NUMERIC,
@@ -160,7 +160,6 @@ final class CoreLibsDBIOTest extends TestCase
// create the tables
$db->dbExec(
// primary key name is table + '_id'
// table_with_primary_key_id SERIAL PRIMARY KEY,
<<<SQL
CREATE TABLE table_with_primary_key (
table_with_primary_key_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
@@ -5136,6 +5135,39 @@ final class CoreLibsDBIOTest extends TestCase
SQL,
'count' => 6,
'convert' => false,
],
'comments in insert' => [
'query' => <<<SQL
INSERT INTO table_with_primary_key (
row_int, row_numeric, row_varchar, row_varchar_literal
) VALUES (
-- comment 1
$1, $2,
-- comment 2
$3
-- comment 3
, $4
)
SQL,
'count' => 4,
'convert' => false
],
// Note some are not set
'a complete set of possible' => [
'query' => <<<SQL
UPDATE table_with_primary_key SET
-- ROW
row_varchar = $1
WHERE
row_varchar = ANY($2) AND row_varchar <> $3
AND row_varchar > $4 AND row_varchar < $5
AND row_varchar >= $6 AND row_varchar <=$7
AND row_jsonb->'a' = $8 AND row_jsonb->>$9 = 'a'
AND row_jsonb<@$10 AND row_jsonb@>$11
AND row_varchar ^@ $12
SQL,
'count' => 12,
'convert' => false,
]
];
}

View File

@@ -0,0 +1,2 @@
*
!.gitignore