From 2e1b767a85ecd8bc13779f7401c6c298914ed539 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Thu, 5 Dec 2024 12:09:58 +0900 Subject: [PATCH] Fix Session class with Many update and get Update Login and Backend class to use interface when writing to avoid problems with not written _SESSION vars with session is in write close status --- .../Create/CoreLibsCreateSessionTest.php | 105 +++++++++-- www/admin/class_test.session.php | 36 +++- www/lib/CoreLibs/ACL/Login.php | 137 ++++++++------ www/lib/CoreLibs/Admin/Backend.php | 14 +- www/lib/CoreLibs/Create/Session.php | 171 +++++++++--------- 5 files changed, 294 insertions(+), 169 deletions(-) diff --git a/4dev/tests/Create/CoreLibsCreateSessionTest.php b/4dev/tests/Create/CoreLibsCreateSessionTest.php index d3a4f735..49b9720d 100644 --- a/4dev/tests/Create/CoreLibsCreateSessionTest.php +++ b/4dev/tests/Create/CoreLibsCreateSessionTest.php @@ -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 $set + * @param array $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' @@ -372,7 +453,7 @@ final class CoreLibsCreateSessionTest extends TestCase 'unsert assert: ' . $name ); } - } */ + } } // __END__ diff --git a/www/admin/class_test.session.php b/www/admin/class_test.session.php index 49f5b3ee..ed9439ef 100644 --- a/www/admin/class_test.session.php +++ b/www/admin/class_test.session.php @@ -45,6 +45,7 @@ $log = new CoreLibs\Logging\Logging([ 'log_file_id' => $LOG_FILE_ID, 'log_per_date' => true, ]); +use CoreLibs\Debug\Support; use CoreLibs\Create\Session; $PAGE_NAME = 'TEST CLASS: SESSION'; @@ -56,7 +57,7 @@ print '

' . $PAGE_NAME . '

'; $session_name = 'class-test-session'; print "Valid session name static check for '" . $session_name . "': " - . \CoreLibs\Debug\Support::prBl(Session::checkValidSessionName($session_name)) . "
"; + . Support::prBl(Session::checkValidSessionName($session_name)) . "
"; $var = 'foo'; $value = 'bar'; $session = new Session($session_name); @@ -96,13 +97,27 @@ print "[READ WRAP] Isset: " . ($session->isset('setwrap') ? 'Yes' : 'No') . "
unset('setwrap'); print "[READ WRAP] unset setwrap: " . $session->get('setwrap') . "
"; print "[READ WRAP] unset Isset: " . ($session->isset('setwrap') ? 'Yes' : 'No') . "
"; -// test __get/__set -$session->setwrap = 'YES, magic set _SESSION var'; /** @phpstan-ignore-line GET/SETTER */ -print "[READ MAGIC] A setwrap: " . ($session->setwrap ?? '') . "
"; -print "[READ MAGIC] Isset: " . (isset($session->setwrap) ? 'Yes' : 'No') . "
"; -unset($session->setwrap); -print "[READ MAGIC] unset setwrap: " . ($session->setwrap ?? '') . "
"; -print "[READ MAGIC] unset Isset: " . (isset($session->setwrap) ? 'Yes' : 'No') . "
"; +$session->set('foo 3', 'brause'); +// set many +$session->setMany([ + 'foo 1' => 'bar', + 'foo 2' => 'kamel', +]); +print "[READ MANY]: " . Support::printAr($session->getMany(['foo 1', 'foo 2'])) . "
"; +try { + $session->setMany([ /** @phpstan-ignore-line deliberate error */ + 'ok' => 'ok', + 'a123' => 'bar', + 1 => 'bar', + ]); +} catch (\Exception $e) { + print "FAILED] Session manySet failed:
" . $e->getMessage() . "
" . $e . "

"; +} +try { + $session->set('123', 'illigal'); +} catch (\Exception $e) { + print "FAILED] Session set failed:
" . $e->getMessage() . "
" . $e . "

"; +} print "
"; // differnt session name @@ -115,7 +130,8 @@ try { print "[3 FAILED] Session start failed:
" . $e->getMessage() . "
" . $e . "

"; } -print "[ALL SESSION]: " . \CoreLibs\Debug\Support::printAr($_SESSION) . "
"; + +print "[ALL SESSION]: " . Support::printAr($_SESSION) . "
"; // close session $session->writeClose(); @@ -142,7 +158,7 @@ try { } $_SESSION['will_be_written_again'] = 'Full'; -print "[ALL SESSION]: " . \CoreLibs\Debug\Support::printAr($_SESSION) . "
"; +print "[ALL SESSION]: " . Support::printAr($_SESSION) . "
"; // close session $session->writeClose(); diff --git a/www/lib/CoreLibs/ACL/Login.php b/www/lib/CoreLibs/ACL/Login.php index fa8cd99f..ccf028ef 100644 --- a/www/lib/CoreLibs/ACL/Login.php +++ b/www/lib/CoreLibs/ACL/Login.php @@ -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; } @@ -2652,7 +2671,7 @@ HTML; */ public function loginGetHeaderColor(): ?string { - return $_SESSION['HEADER_COLOR'] ?? null; + return $this->session->get('HEADER_COLOR'); } /** @@ -2663,7 +2682,7 @@ HTML; public function loginGetPages(): array { - return $_SESSION['PAGES'] ?? []; + return $this->session->get('PAGES'); } /** diff --git a/www/lib/CoreLibs/Admin/Backend.php b/www/lib/CoreLibs/Admin/Backend.php index 82d36807..6f02cd25 100644 --- a/www/lib/CoreLibs/Admin/Backend.php +++ b/www/lib/CoreLibs/Admin/Backend.php @@ -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 = []; } diff --git a/www/lib/CoreLibs/Create/Session.php b/www/lib/CoreLibs/Create/Session.php index 1bf910f5..f993735c 100644 --- a/www/lib/CoreLibs/Create/Session.php +++ b/www/lib/CoreLibs/Create/Session.php @@ -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,14 @@ 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 */ public function sessionDestroy(): bool { - $_SESSION = []; + $this->unsetAll(); if ( ini_get('session.use_cookies') && !ini_get('session.use_strict_mode') @@ -282,24 +318,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 /** @@ -310,8 +334,8 @@ class Session public function unsetAll(): void { $this->restartSession(); - foreach (array_keys($_SESSION ?? []) as $name) { - unset($_SESSION[$name]); + if (!empty($_SESSION)) { + $_SESSION = []; } $this->closeSessionCall(); } @@ -319,35 +343,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 $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 $set + * @return array + */ + 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 +408,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 +421,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 $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(); } }