From 201404f2e99923ece9687c2c2cc4e18e8d8bf4f8 Mon Sep 17 00:00:00 2001 From: rotimi Date: Mon, 12 Aug 2024 17:30:06 -0600 Subject: [PATCH 01/19] Session now implements \Josantonius\Session\SessionInterface, exception methods have been moved to ExceptionThrowingMethodsTrait & start method now calls session_name if a name option was passed in the options array --- src/Session.php | 71 +++++++------------------------------------------ 1 file changed, 9 insertions(+), 62 deletions(-) diff --git a/src/Session.php b/src/Session.php index 465a0f9..3672b40 100644 --- a/src/Session.php +++ b/src/Session.php @@ -21,8 +21,10 @@ /** * Session handler. */ -class Session +class Session implements SessionInterface { + use ExceptionThrowingMethodsTrait; + /** * Starts the session. * @@ -66,7 +68,12 @@ public function start(array $options = []): bool $this->throwExceptionIfHeadersWereSent(); $this->throwExceptionIfSessionWasStarted(); $this->throwExceptionIfHasWrongOptions($options); - + + if(isset($options['name'])) { + + session_name($options['name']); + } + return session_start($options); } @@ -237,64 +244,4 @@ public function isStarted(): bool { return session_status() === PHP_SESSION_ACTIVE; } - - /** - * Throw exception if the session have wrong options. - * - * @throws WrongSessionOptionException If setting options failed. - */ - private function throwExceptionIfHasWrongOptions(array $options): void - { - $validOptions = array_flip([ - 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_samesite', 'cookie_secure', - 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'lazy_write', - 'name', 'read_and_close', 'referer_check', 'save_handler', - 'save_path', 'serialize_handler', 'sid_bits_per_character', 'sid_length', - 'trans_sid_hosts', 'trans_sid_tags', 'use_cookies', 'use_only_cookies', - 'use_strict_mode', 'use_trans_sid', - ]); - - foreach (array_keys($options) as $key) { - if (!isset($validOptions[$key])) { - throw new WrongSessionOptionException($key); - } - } - } - - /** - * Throw exception if headers have already been sent. - * - * @throws HeadersSentException if headers already sent. - */ - private function throwExceptionIfHeadersWereSent(): void - { - $headersWereSent = (bool) ini_get('session.use_cookies') && headers_sent($file, $line); - - $headersWereSent && throw new HeadersSentException($file, $line); - } - - /** - * Throw exception if the session has already been started. - * - * @throws SessionStartedException if session already started. - */ - private function throwExceptionIfSessionWasStarted(): void - { - $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; - - $this->isStarted() && throw new SessionStartedException($methodName); - } - - /** - * Throw exception if the session was not started. - * - * @throws SessionNotStartedException if session was not started. - */ - private function throwExceptionIfSessionWasNotStarted(): void - { - $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; - - !$this->isStarted() && throw new SessionNotStartedException($methodName); - } } From e0fea6c5d9591499add97dc8705192cdd2b13261 Mon Sep 17 00:00:00 2001 From: rotimi Date: Mon, 12 Aug 2024 17:34:38 -0600 Subject: [PATCH 02/19] Added \Josantonius\Session\Exceptions\EmptySegmentNameException for \Josantonius\Session\FlashableSessionSegment --- src/Exceptions/EmptySegmentNameException.php | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/Exceptions/EmptySegmentNameException.php diff --git a/src/Exceptions/EmptySegmentNameException.php b/src/Exceptions/EmptySegmentNameException.php new file mode 100644 index 0000000..030a83d --- /dev/null +++ b/src/Exceptions/EmptySegmentNameException.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Josantonius\Session\Exceptions; + +/** + * @author https://github.com/rotexdegba + */ +class EmptySegmentNameException extends SessionException +{ + public function __construct(string $methodName) + { + parent::__construct( + $methodName . '(): Session segment name cannot be an empty string.' + ); + } +} From bba821162467478aa0beca7e14dd109c69cddc7d Mon Sep 17 00:00:00 2001 From: rotimi Date: Mon, 12 Aug 2024 17:35:02 -0600 Subject: [PATCH 03/19] updated gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 014d167..247ad6b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ phpcbf-fixed.difff php-session.code-workspace .repository.md .phpunit.result.cache -coverage.xml \ No newline at end of file +coverage.xml +/nbproject/ From 41e82faa0ea3664bcd72006af36f0184d5954e59 Mon Sep 17 00:00:00 2001 From: rotimi Date: Mon, 12 Aug 2024 17:36:20 -0600 Subject: [PATCH 04/19] Exception methods have been moved to ExceptionThrowingMethodsTrait --- src/ExceptionThrowingMethodsTrait.php | 85 +++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/ExceptionThrowingMethodsTrait.php diff --git a/src/ExceptionThrowingMethodsTrait.php b/src/ExceptionThrowingMethodsTrait.php new file mode 100644 index 0000000..6cec745 --- /dev/null +++ b/src/ExceptionThrowingMethodsTrait.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Josantonius\Session; + +use Josantonius\Session\Exceptions\HeadersSentException; +use Josantonius\Session\Exceptions\SessionStartedException; +use Josantonius\Session\Exceptions\SessionNotStartedException; +use Josantonius\Session\Exceptions\WrongSessionOptionException; + +/** + * @author https://github.com/rotexdegba + */ +trait ExceptionThrowingMethodsTrait +{ + /** + * Throw exception if the session have wrong options. + * + * @throws WrongSessionOptionException If setting options failed. + */ + private function throwExceptionIfHasWrongOptions(array $options): void + { + $validOptions = array_flip([ + 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', + 'cookie_lifetime', 'cookie_path', 'cookie_samesite', 'cookie_secure', + 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'lazy_write', + 'name', 'read_and_close', 'referer_check', 'save_handler', + 'save_path', 'serialize_handler', 'sid_bits_per_character', 'sid_length', + 'trans_sid_hosts', 'trans_sid_tags', 'use_cookies', 'use_only_cookies', + 'use_strict_mode', 'use_trans_sid', + ]); + + foreach (array_keys($options) as $key) { + if (!isset($validOptions[$key])) { + throw new WrongSessionOptionException($key); + } + } + } + + /** + * Throw exception if headers have already been sent. + * + * @throws HeadersSentException if headers already sent. + */ + private function throwExceptionIfHeadersWereSent(): void + { + $headersWereSent = (bool) ini_get('session.use_cookies') && headers_sent($file, $line); + + $headersWereSent && throw new HeadersSentException($file, $line); + } + + /** + * Throw exception if the session has already been started. + * + * @throws SessionStartedException if session already started. + */ + private function throwExceptionIfSessionWasStarted(): void + { + $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; + + $this->isStarted() && throw new SessionStartedException($methodName); + } + + /** + * Throw exception if the session was not started. + * + * @throws SessionNotStartedException if session was not started. + */ + private function throwExceptionIfSessionWasNotStarted(): void + { + $methodName = debug_backtrace()[1]['function'] ?? 'unknown'; + + !$this->isStarted() && throw new SessionNotStartedException($methodName); + } +} From d33f20ab58b8b7edb9db985c838769b5b6201dd5 Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 01:19:33 -0600 Subject: [PATCH 05/19] Added \Josantonius\Session\FlashableSessionSegment --- src/FlashableSessionSegment.php | 586 ++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100644 src/FlashableSessionSegment.php diff --git a/src/FlashableSessionSegment.php b/src/FlashableSessionSegment.php new file mode 100644 index 0000000..70f901c --- /dev/null +++ b/src/FlashableSessionSegment.php @@ -0,0 +1,586 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Josantonius\Session; + +use Josantonius\Session\Exceptions\SessionNotStartedException; +use Josantonius\Session\Exceptions\EmptySegmentNameException; + +/** + * @author https://github.com/rotexdegba + * + * Each valid instance of this class will always have a valid session started or resumed + */ +class FlashableSessionSegment implements SessionInterface +{ + use ExceptionThrowingMethodsTrait; + + /** + * Used for performing some session operations for each instance of this class + */ + protected SessionInterface $storage; + + /** + * Flash data for current request is stored here. + * + * It must be copied from + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * every time an instance of this class is created. + * + * If $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * isn't set, this $this->flashDataForCurrentRequest should maintain + * the default value of empty array. + */ + protected array $flashDataForCurrentRequest = []; + + /** + * When different libraries and projects try to modify data with the same keys + * in $_SESSION , the resulting conflicts can result in unexpected behavior. + * + * This value will be used as a key in $_SESSION to avoid session + * data for an instance of this class from colliding with or being + * overwritten by other libraries or projects within an application. + * + * Be sure to set it to a unique value for each instance of this class. + * For example, you could use a value such as the fully qualified + * class name concatenated with the method name of the method where + * an instance of this class is being created. + */ + protected string $segmentName; + + /** + * Key for storing flash data in $_SESSION[$this->segmentName] + */ + public const FLASH_DATA_FOR_NEXT_REQUEST = self::class . '__flash'; + + /** + * List of available $options with their default values: + * + * * cache_expire: "180" + * * cache_limiter: "nocache" + * * cookie_domain: "" + * * cookie_httponly: "0" + * * cookie_lifetime: "0" + * * cookie_path: "/" + * * cookie_samesite: "" + * * cookie_secure: "0" + * * gc_divisor: "100" + * * gc_maxlifetime: "1440" + * * gc_probability: "1" + * * lazy_write: "1" + * * name: "PHPSESSID" + * * read_and_close: "0" + * * referer_check: "" + * * save_handler: "files" + * * save_path: "" + * * serialize_handler: "php" + * * sid_bits_per_character: "4" + * * sid_length: "32" + * * trans_sid_hosts: $_SERVER['HTTP_HOST'] + * * trans_sid_tags: "a=href,area=href,frame=src,form=" + * * use_cookies: "1" + * * use_only_cookies: "1" + * * use_strict_mode: "0" + * * use_trans_sid: "0" + * + * @see https://php.net/session.configuration + * + * + * @param string $segmentName Name of key to be used in $_SESSION to store all + * session data for an instance of this class. This + * helps avoid writing session data directly to + * $_SESSION, which runs the risk of being overwritten + * by other libraries that write to $_SESSION with the + * same key(s). The value specified for this key should + * be something unique, like the domain name of the web + * application, or some other unique value that other + * libraries writing to $_SESSION wouldn't use. + * + * @param null|\Josantonius\Session\SessionInterface $storage used for performing some session operations for each instance of this class. + * If null, an instance of \Josantonius\Session\Session will be created + * + * @param array $options session start configuration options that will be used to + * automatically start a new session or resume existing session + * when an instance of this class is created + * + * @throws \Josantonius\Session\Exceptions\EmptySegmentNameException + * @throws \Josantonius\Session\Exceptions\HeadersSentException + * @throws \Josantonius\Session\Exceptions\SessionNotStartedException + * @throws \Josantonius\Session\Exceptions\WrongSessionOptionException + */ + public function __construct(string $segmentName, ?SessionInterface $storage=null, array $options = []) + { + if($segmentName === '') { + + throw new EmptySegmentNameException(__METHOD__); + } + + $this->storage = $storage ?? new Session(); + $this->segmentName = $segmentName; + + if( !$this->isStarted() ) { + + // start or resume session + $this->start($options); + } + + if( !$this->isStarted() ) { + + $msg = 'Error: Could not start session in ' . __METHOD__; + throw new SessionNotStartedException($msg); + } + + $this->initializeOrReinitialize(); + $this->moveNextFlashToCurrentFlash(); + } + + protected function initializeOrReinitialize(): void { + + if($this->isStarted()) { + + if(!isset($_SESSION[$this->segmentName])) { + + // We want session data to be in a segment to protect it from + // being overwritten by other packages + $_SESSION[$this->segmentName] = []; + + if(!isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST])) { + + // Initialize the flash storage in the session's segment + $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; + } + } + } + } + + protected function moveNextFlashToCurrentFlash() { + + if($this->isStarted()) { + + /////////////////////////////////////////////////////////////////////////// + // Flash update logic: We update the flash data by copying the existing + // flash data stored in + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // to $this->flashDataForCurrentRequest & then reset + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // to an empty array. + // + // Flash data inside $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // will only be accessible in the next request + // + // Flash data copied from $_SESSION into $this->flashDataForCurrentRequest from the previous + // request is flash data that will be accessible in the current request. + /////////////////////////////////////////////////////////////////////////// + $this->flashDataForCurrentRequest = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; + + // Reset the flash data in session to an empty array + // but we still have the existing flash data in $this->flashDataForCurrentRequest + $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; + } + } + + /** + * Starts the session. + * + * List of available $options with their default values: + * + * * cache_expire: "180" + * * cache_limiter: "nocache" + * * cookie_domain: "" + * * cookie_httponly: "0" + * * cookie_lifetime: "0" + * * cookie_path: "/" + * * cookie_samesite: "" + * * cookie_secure: "0" + * * gc_divisor: "100" + * * gc_maxlifetime: "1440" + * * gc_probability: "1" + * * lazy_write: "1" + * * name: "PHPSESSID" + * * read_and_close: "0" + * * referer_check: "" + * * save_handler: "files" + * * save_path: "" + * * serialize_handler: "php" + * * sid_bits_per_character: "4" + * * sid_length: "32" + * * trans_sid_hosts: $_SERVER['HTTP_HOST'] + * * trans_sid_tags: "a=href,area=href,frame=src,form=" + * * use_cookies: "1" + * * use_only_cookies: "1" + * * use_strict_mode: "0" + * * use_trans_sid: "0" + * + * @see https://php.net/session.configuration + */ + public function start(array $options = []): bool + { + $isStarted = true; + + if(!$this->isStarted()) { + + $isStarted = $this->storage->start($options); + + if($isStarted) { + + $this->initializeOrReinitialize(); + } // if($isStarted) + } // if(!$this->isStarted()) + + return $isStarted; + } + + /** + * Gets all attributes in $_SESSION[$this->segmentName]. + */ + public function all(): array + { + return $this->isStarted() ? ($_SESSION[$this->segmentName] ?? []) : []; + } + + /** + * Checks if an attribute exists in $_SESSION[$this->segmentName]. + */ + public function has(string $name): bool + { + return $this->isStarted() && isset($_SESSION[$this->segmentName][$name]); + } + + /** + * Gets an attribute by name from $_SESSION[$this->segmentName]. + */ + public function get(string $name, mixed $default = null): mixed + { + return $this->isStarted() ? ($_SESSION[$this->segmentName][$name] ?? $default) : $default; + } + + /** + * Sets an attribute by name in $_SESSION[$this->segmentName]. + */ + public function set(string $name, mixed $value): void + { + if ($this->isStarted()) { + // Set it in this session object's segmented session data + $_SESSION[$this->segmentName][$name] = $value; + } + } + + /** + * Sets several attributes at once inside $_SESSION[$this->segmentName]. + * + * If attributes exist they are replaced, if they do not exist they are created. + */ + public function replace(array $data): void + { + if ($this->isStarted()) { + + // Replace it in this session object's segmented session data + $_SESSION[$this->segmentName] = + array_merge($_SESSION[$this->segmentName], $data); + } + } + + /** + * Deletes an attribute by name from $_SESSION[$this->segmentName] and returns its value. + * + * Optionally defines a default value when the attribute does not exist. + */ + public function pull(string $name, mixed $default = null): mixed + { + $value = $default; + + if($this->isStarted()) { + + // Try to get it from this session object's segmented session data + // or return the default value + $value = $_SESSION[$this->segmentName][$name] ?? $default; + + if(isset($_SESSION[$this->segmentName][$name])) { + + // Remove it from this session object's segmented session data + unset($_SESSION[$this->segmentName][$name]); + } + } + + return $value; + } + + /** + * Deletes an attribute by name from $_SESSION[$this->segmentName]. + */ + public function remove(string $name): void + { + if ($this->isStarted() && isset($_SESSION[$this->segmentName][$name])) { + + // Remove it from this session object's segmented session data + unset($_SESSION[$this->segmentName][$name]); + } + } + + /** + * Clears the session segment ($_SESSION[$this->segmentName]) and restores + * this object to its default original state after creation. + */ + public function clear(): void + { + if ($this->isStarted() && isset($_SESSION[$this->segmentName])) { + + // Get rid of this session object's segmented session data, but we + // don't destroy $_SESSION since other data may be stored in it by + // other instances of this class or other code in the application + // this class is being used in. + unset($_SESSION[$this->segmentName]); + + // Reset segment to empty array + $_SESSION[$this->segmentName] = []; + + // Reset the flash data in session segment to an empty arrays + $this->flashDataForCurrentRequest = []; + $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; + } + } + + /** + * Gets the session ID. + */ + public function getId(): string + { + return $this->storage->getId(); + } + + /** + * Sets the session ID. + * + * This method will be of no effect if called outside the constructor + * of this class since the session will already be started after the + * constructor method finishes execution + */ + public function setId(string $sessionId): void + { + (!$this->storage->isStarted()) && $this->storage->setId($sessionId); + } + + /** + * Updates the current session id with a newly generated one. + */ + public function regenerateId(bool $deleteOldSession = false): bool + { + return $this->isStarted() && $this->storage->regenerateId($deleteOldSession); + } + + /** + * Gets the session name. + */ + public function getName(): string + { + return $this->storage->getName(); + } + + /** + * Sets the session name. + * + * This method will be of no effect if called outside the constructor + * of this class since the session will already be started after the + * constructor method finishes execution + */ + public function setName(string $name): void + { + (!$this->storage->isStarted()) && $this->storage->setName($name); + } + + /** + * Clears the session segment ($_SESSION[$this->segmentName]) and restores + * this object to its original state after creation. + * + * The session ($_SESSION) is not destroyed. + */ + public function destroy(): bool + { + $this->clear(); + + return true; + } + + /** + * Checks if the session is started. + */ + public function isStarted(): bool + { + return $this->storage->isStarted(); + } + + /** + * Sets an item with the specified $key in the flash storage for an instance + * of this class (i.e. $this->flashDataForCurrentRequest). + * + * The item will only be retrievable from the instance of this class it was set in. + */ + public function setInCurrentFlash(string $key, mixed $value): void + { + $this->flashDataForCurrentRequest[$key] = $value; + } + + /** + * Sets an item with the specified $key in the flash storage located in + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * + * The item will only be retrievable by calling the getFromCurrentFlash + * on the next instance of this class created with the same segment name. + */ + public function setInNextFlash(string $key, mixed $value): void + { + if( + $this->isStarted() + && isset($_SESSION[$this->segmentName]) + && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) + ) { + // Set it in this session object's segmented session data + $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key] = $value; + + } + } + + /** + * Check if item with specified $key exists in the flash storage for + * an instance of this class (i.e. in $this->flashDataForCurrentRequest). + */ + public function hasInCurrentFlash(string $key): bool + { + //////////////////////////////////////////////////////////////////////// + // Accessible flash data for current request is always inside + // $this->flashDataForCurrentRequest + // while + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // contains flash data for the next request + //////////////////////////////////////////////////////////////////////// + return \array_key_exists($key, $this->flashDataForCurrentRequest); + } + + /** + * Check if item with specified $key exists in + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]. + */ + public function hasInNextFlash(string $key): bool + { + //////////////////////////////////////////////////////////////////////// + // Accessible flash data for current request is always inside + // $this->flashDataForCurrentRequest + // while + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // contains flash data for the next request + //////////////////////////////////////////////////////////////////////// + return + ( // Check in this session object's segmented session data + $this->isStarted() + && isset($_SESSION[$this->segmentName]) + && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) + && is_array($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) + && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]) + ); + } + + /** + * Get an item with the specified $key from the flash storage for an instance + * of this class (i.e. $this->flashDataForCurrentRequest) if it exists or return $default. + */ + public function getFromCurrentFlash(string $key, mixed $default=null): mixed + { + //////////////////////////////////////////////////////////////////////// + // Accessible flash data for current request is always inside + // $this->flashDataForCurrentRequest + // while + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // contains flash data for the next request + //////////////////////////////////////////////////////////////////////// + return ($this->isStarted() && $this->hasInCurrentFlash($key)) ? $this->flashDataForCurrentRequest[$key] : $default; + } + + /** + * Get an item with the specified $key from + * + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * if it exists or return $default. + */ + public function getFromNextFlash(string $key, mixed $default=null): mixed + { + return ($this->isStarted() && $this->hasInNextFlash($key)) + ? $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key] + : $default; + } + + /** + * Remove an item with the specified $key (if it exists) from: + * - the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest), if $for_current_request === true + * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], if $for_next_request === true + */ + public function removeFromFlash( + string $key, + bool $for_current_request=true, + bool $for_next_request=false + ): void + { + //////////////////////////////////////////////////////////////////////// + // Accessible flash data for current request is always inside + // $this->flashDataForCurrentRequest + // while + // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // contains flash data for the next request + //////////////////////////////////////////////////////////////////////// + if($for_current_request && $this->hasInCurrentFlash($key)) { + + unset($this->flashDataForCurrentRequest[$key]); + } + + if($for_next_request && $this->isStarted() && $this->hasInNextFlash($key)) { + + // Remove it from this session object's segmented session data + unset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]); + } // if($for_next_request) + } + + /** + * Get all items in the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest) + */ + public function getAllFromCurrentFlash(): array + { + return $this->flashDataForCurrentRequest; + } + + /** + * Get all items in $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + */ + public function getAllFromNextFlash(): array + { + if( + $this->isStarted() + && isset($_SESSION[$this->segmentName]) + && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) + && is_array($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) + ) { + // Get it from this session object's segmented session data + return $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]; + } + + return []; + } + + public function getSegmentName(): string + { + return $this->segmentName; + } + + public function getStorage(): SessionInterface + { + return $this->storage; + } +} From 3f0c793354283c91979f2e97646b39908e045f5e Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 01:20:47 -0600 Subject: [PATCH 06/19] Tweaked getId & getName --- src/Session.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Session.php b/src/Session.php index 3672b40..946d2f3 100644 --- a/src/Session.php +++ b/src/Session.php @@ -176,7 +176,9 @@ public function clear(): void */ public function getId(): string { - return session_id(); + $id = session_id(); + + return ($id !== false) ? $id : ''; // session_id returns false on failure } /** @@ -210,7 +212,7 @@ public function getName(): string { $name = session_name(); - return $name ? $name : ''; + return ($name !== false) ? $name : ''; } /** From 06a5feb4cac0e744f1623c3ab4efeda4ff413966 Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 01:23:13 -0600 Subject: [PATCH 07/19] Added \Josantonius\Session\SessionInterface --- src/SessionInterface.php | 157 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/SessionInterface.php diff --git a/src/SessionInterface.php b/src/SessionInterface.php new file mode 100644 index 0000000..d320877 --- /dev/null +++ b/src/SessionInterface.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Josantonius\Session; + +/** + * Description of SessionInterface + * + * @author https://github.com/rotexdegba + */ +interface SessionInterface +{ + /** + * Starts the session. + * + * List of available $options with their default values: + * + * * cache_expire: "180" + * * cache_limiter: "nocache" + * * cookie_domain: "" + * * cookie_httponly: "0" + * * cookie_lifetime: "0" + * * cookie_path: "/" + * * cookie_samesite: "" + * * cookie_secure: "0" + * * gc_divisor: "100" + * * gc_maxlifetime: "1440" + * * gc_probability: "1" + * * lazy_write: "1" + * * name: "PHPSESSID" + * * read_and_close: "0" + * * referer_check: "" + * * save_handler: "files" + * * save_path: "" + * * serialize_handler: "php" + * * sid_bits_per_character: "4" + * * sid_length: "32" + * * trans_sid_hosts: $_SERVER['HTTP_HOST'] + * * trans_sid_tags: "a=href,area=href,frame=src,form=" + * * use_cookies: "1" + * * use_only_cookies: "1" + * * use_strict_mode: "0" + * * use_trans_sid: "0" + * + * @see https://php.net/session.configuration + */ + public function start(array $options = []): bool; + + /** + * Gets all attributes. + */ + public function all(): array; + + /** + * Checks if an attribute exists in the session. + */ + public function has(string $name): bool; + + /** + * Gets an attribute by name. + * + * Optionally defines a default value when the attribute does not exist. + */ + public function get(string $name, mixed $default = null): mixed; + + /** + * Sets an attribute by name. + * + * @throws SessionNotStartedException if session was not started. + */ + public function set(string $name, mixed $value): void; + + /** + * Sets several attributes at once. + * + * If attributes exist they are replaced, if they do not exist they are created. + * + * @throws SessionNotStartedException if session was not started. + */ + public function replace(array $data): void; + + /** + * Deletes an attribute by name and returns its value. + * + * Optionally defines a default value when the attribute does not exist. + * + * @throws SessionNotStartedException if session was not started. + */ + public function pull(string $name, mixed $default = null): mixed; + + /** + * Deletes an attribute by name. + * + * @throws SessionNotStartedException if session was not started. + */ + public function remove(string $name): void; + + /** + * Free all session variables or all session segment variables. + * + * @throws SessionNotStartedException if session was not started. + */ + public function clear(): void; + + /** + * Gets the session ID. + */ + public function getId(): string; + + /** + * Sets the session ID. + * + * @throws SessionStartedException if session already started. + */ + public function setId(string $sessionId): void; + + /** + * Updates the current session id with a newly generated one. + * + * @throws SessionNotStartedException if session was not started. + */ + public function regenerateId(bool $deleteOldSession = false): bool; + + /** + * Gets the session name. + */ + public function getName(): string; + + /** + * Sets the session name. + * + * @throws SessionStartedException if session already started. + */ + public function setName(string $name): void; + + /** + * Destroys the session or session segment. + * + * @throws SessionNotStartedException if session was not started. + */ + public function destroy(): bool; + + /** + * Checks if the session is started. + */ + public function isStarted(): bool; +} From a47e8d6972587870c6c3b2d3ece7f8ad03c89322 Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 01:24:00 -0600 Subject: [PATCH 08/19] Added new tests and updated some existing tests --- tests/AllMethodSegmentedSessionTest.php | 92 ++++++++++ tests/ClearMethodSegmentedSessionTest.php | 95 ++++++++++ .../ConstructorMethodSegmentedSessionTest.php | 171 ++++++++++++++++++ tests/DestroyMethodSegmentedSessionTest.php | 97 ++++++++++ tests/GetAllFromCurrentFlashMethodTest.php | 63 +++++++ tests/GetAllFromNextFlashMethodTest.php | 66 +++++++ tests/GetFromCurrentFlashMethodTest.php | 69 +++++++ tests/GetFromNextFlashMethodTest.php | 69 +++++++ tests/GetIdMethodSegmentedSessionTest.php | 49 +++++ tests/GetMethodSegmentedSessionTest.php | 119 ++++++++++++ tests/GetSegmentNameMethodTest.php | 35 ++++ tests/GetStorageMethodTest.php | 36 ++++ tests/HasInCurrentFlashMethodTest.php | 59 ++++++ tests/HasInNextFlashMethodTest.php | 59 ++++++ tests/HasMethodSegmentedSessionTest.php | 49 +++++ tests/IsStartedMethodSegmentedSessionTest.php | 54 ++++++ tests/PullMethodSegmentedSessionTest.php | 75 ++++++++ ...RegenerateIdMethodSegmentedSessionTest.php | 44 +++++ tests/RemoveFromFlashMethodTest.php | 73 ++++++++ tests/RemoveMethodSegmentedSessionTest.php | 69 +++++++ tests/ReplaceMethodSegmentedSessionTest.php | 71 ++++++++ tests/SetIdMethodSegmentedSessionTest.php | 39 ++++ tests/SetInCurrentFlashMethodTest.php | 43 +++++ tests/SetInNextFlashMethodTest.php | 43 +++++ tests/SetMethodSegmentedSessionTest.php | 51 ++++++ tests/SetNameMethodSegmentedSessionTest.php | 39 ++++ tests/StartMethodSegmentedSessionTest.php | 46 +++++ tests/StartMethodTest.php | 3 +- 28 files changed, 1777 insertions(+), 1 deletion(-) create mode 100644 tests/AllMethodSegmentedSessionTest.php create mode 100644 tests/ClearMethodSegmentedSessionTest.php create mode 100644 tests/ConstructorMethodSegmentedSessionTest.php create mode 100644 tests/DestroyMethodSegmentedSessionTest.php create mode 100644 tests/GetAllFromCurrentFlashMethodTest.php create mode 100644 tests/GetAllFromNextFlashMethodTest.php create mode 100644 tests/GetFromCurrentFlashMethodTest.php create mode 100644 tests/GetFromNextFlashMethodTest.php create mode 100644 tests/GetIdMethodSegmentedSessionTest.php create mode 100644 tests/GetMethodSegmentedSessionTest.php create mode 100644 tests/GetSegmentNameMethodTest.php create mode 100644 tests/GetStorageMethodTest.php create mode 100644 tests/HasInCurrentFlashMethodTest.php create mode 100644 tests/HasInNextFlashMethodTest.php create mode 100644 tests/HasMethodSegmentedSessionTest.php create mode 100644 tests/IsStartedMethodSegmentedSessionTest.php create mode 100644 tests/PullMethodSegmentedSessionTest.php create mode 100644 tests/RegenerateIdMethodSegmentedSessionTest.php create mode 100644 tests/RemoveFromFlashMethodTest.php create mode 100644 tests/RemoveMethodSegmentedSessionTest.php create mode 100644 tests/ReplaceMethodSegmentedSessionTest.php create mode 100644 tests/SetIdMethodSegmentedSessionTest.php create mode 100644 tests/SetInCurrentFlashMethodTest.php create mode 100644 tests/SetInNextFlashMethodTest.php create mode 100644 tests/SetMethodSegmentedSessionTest.php create mode 100644 tests/SetNameMethodSegmentedSessionTest.php create mode 100644 tests/StartMethodSegmentedSessionTest.php diff --git a/tests/AllMethodSegmentedSessionTest.php b/tests/AllMethodSegmentedSessionTest.php new file mode 100644 index 0000000..560d9d2 --- /dev/null +++ b/tests/AllMethodSegmentedSessionTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class AllMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_all_attributes_in_segment(): void + { + $session = new SegSession('da-segment'); + + $this->assertIsArray($_SESSION); + + $session->set('foo', 'bar'); + + $this->assertEquals(['foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $session->all()); + + // foo should only be inside $_SESSION[$session->getSegmentName()] + $this->assertArrayNotHasKey('foo', $_SESSION); + + // SegSession::FLASH_DATA_FOR_NEXT_REQUEST should only be inside $_SESSION[$session->getSegmentName()] + $this->assertArrayNotHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION); + + $this->assertEquals( + [ + $session->getSegmentName() => + [ + 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [] + ] + ], + $_SESSION + ); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_all_attributes_in_segment_when_session_started_outside_library(): void + { + session_start(); + + $this->assertIsArray($_SESSION); + + $session = new SegSession('da-segment'); + + $_SESSION['top-key'] = 'top-value'; + + $session->set('foo', 'bar'); + + $this->assertEquals(['foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $session->all()); + + // foo should only be inside $_SESSION[$session->getSegmentName()] + $this->assertArrayNotHasKey('foo', $_SESSION); + + // SegSession::FLASH_DATA_FOR_NEXT_REQUEST should only be inside $_SESSION[$session->getSegmentName()] + $this->assertArrayNotHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION); + + // Make sure both data set in $_SESSION from outside & within this + // library are where they should be + $this->assertEquals( + [ + 'top-key' => 'top-value', + $session->getSegmentName() => + [ + 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [] + ] + ], + $_SESSION + ); + } +} diff --git a/tests/ClearMethodSegmentedSessionTest.php b/tests/ClearMethodSegmentedSessionTest.php new file mode 100644 index 0000000..b428281 --- /dev/null +++ b/tests/ClearMethodSegmentedSessionTest.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class ClearMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_clear_only_session_segment(): void + { + $session = new SegSession('da-segment'); + + $_SESSION['bar'] = 'foo'; + + $session->set('foo', 'bar'); + + $segmentBeforeClearing = [ + 'foo' => 'bar', + SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], + ]; + + // Verify segment data before clearing + $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); + + $session->clear(); + + // Cleared segment should only contain an empty array for flash data + $this->assertEquals( + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + $_SESSION[$session->getSegmentName()] + ); + + // Items set directly in $_SESSION should still be present & not cleared + $this->assertArrayHasKey('bar', $_SESSION); + $this->assertEquals('foo', $_SESSION['bar']); + } + + /** + * @runInSeparateProcess + */ + public function test_should_clear_only_session_segment_when_session_started_outside_library(): void + { + session_start(); + + $_SESSION['bar'] = 'foo'; + + $session = new SegSession('da-segment'); + + $_SESSION['bar1'] = 'foo1'; + + $session->set('foo', 'bar'); + + $segmentBeforeClearing = [ + 'foo' => 'bar', + SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], + ]; + + // Verify segment data before clearing + $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); + + $session->clear(); + + // Cleared segment should only contain an empty array for flash data + $this->assertEquals( + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + $_SESSION[$session->getSegmentName()] + ); + + // Items set directly in $_SESSION should still be present & not cleared + $this->assertArrayHasKey('bar', $_SESSION); + $this->assertArrayHasKey('bar1', $_SESSION); + $this->assertEquals('foo', $_SESSION['bar']); + $this->assertEquals('foo1', $_SESSION['bar1']); + } +} diff --git a/tests/ConstructorMethodSegmentedSessionTest.php b/tests/ConstructorMethodSegmentedSessionTest.php new file mode 100644 index 0000000..1da1293 --- /dev/null +++ b/tests/ConstructorMethodSegmentedSessionTest.php @@ -0,0 +1,171 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\Session; +use Josantonius\Session\FlashableSessionSegment as SegSession; +use Josantonius\Session\Exceptions\EmptySegmentNameException; +use Josantonius\Session\Exceptions\HeadersSentException; +use Josantonius\Session\Exceptions\SessionStartedException; +use Josantonius\Session\Exceptions\SessionNotStartedException; +use Josantonius\Session\Exceptions\WrongSessionOptionException; + +class ConstructorMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_verify_segment_exists_in_session_and_session_options_were_properly_set(): void + { + $options = [ + 'name' => 'boooooooo', + 'cookie_lifetime' => 8000, + ]; + $segmentName = 'da-segment'; + $session = new SegSession($segmentName, null, $options); + + // Session was started outside the library. + $this->assertTrue($session->isStarted()); + + // Check that the segment name was properly set in the session object + $this->assertEquals($segmentName, $session->getSegmentName()); + + // Check that session options were not set in the constructor + // since in this scenario the session was started outside the library. + $this->assertEquals($options['name'], $session->getName()); + $this->assertEquals($options['cookie_lifetime'], ini_get('session.cookie_lifetime')); + + // check that flash was initialized + $this->assertArrayHasKey($segmentName , $_SESSION); + $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []] , $_SESSION[$segmentName]); + $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST , $_SESSION[$segmentName]); + $this->assertEquals([] , $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); + } + + /** + * @runInSeparateProcess + */ + public function test_should_verify_segment_exists_in_session_and_session_options_were_properly_set_when_session_started_outside_library(): void + { + session_start(); + $options = [ + 'name' => 'boooooooo', + 'cookie_lifetime' => 8000, + ]; + $segmentName = 'da-segment'; + $session = new SegSession($segmentName, null, $options); + + // Session was started outside the library. + $this->assertTrue($session->isStarted()); + + // Check that the segment name was properly set in the session object + $this->assertEquals($segmentName, $session->getSegmentName()); + + // Check that session options were not set in the constructor + // since in this scenario the session was started outside the library. + $this->assertEquals('PHPSESSID', $session->getName()); + $this->assertNotEquals($options['name'], $session->getName()); + $this->assertNotEquals($options['cookie_lifetime'], ini_get('session.cookie_lifetime')); + + // check that flash was initialized + $this->assertArrayHasKey($segmentName , $_SESSION); + $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []] , $_SESSION[$segmentName]); + $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST , $_SESSION[$segmentName]); + $this->assertEquals([] , $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); + } + + /** + * @runInSeparateProcess + */ + public function test_should_verify_injected_session_object_was_properly_set(): void + { + $segmentName = 'da-segment'; + $storage = new Session(); + $session = new SegSession($segmentName, $storage); + + // Injected $storage should be returned by $session->getStorage() + $this->assertSame($storage, $session->getStorage()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_verify_injected_session_object_was_properly_set_when_session_started_outside_library(): void + { + session_start(); + $segmentName = 'da-segment'; + $storage = new Session(); + $session = new SegSession($segmentName, $storage); + + // Injected $storage should be returned by $session->getStorage() + $this->assertSame($storage, $session->getStorage()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_fail_with_empty_segment_name(): void + { + $this->expectException(EmptySegmentNameException::class); + + $session = new SegSession(''); + } + + /** + * @runInSeparateProcess + */ + public function test_should_fail_with_wrong_options(): void + { + $this->expectException(WrongSessionOptionException::class); + + $session = new SegSession('a', null, ['foo' => 'bar']); + } + + public function test_should_fail_when_headers_sent(): void + { + // Because we are not running this in a separate process it will trigger the exception + $this->expectException(HeadersSentException::class); + + $session = new SegSession('a'); + } + + /** + * @runInSeparateProcess + */ + public function test_should_fail_when_session_not_startable(): void + { + $this->expectException(SessionNotStartedException::class); + + $sessionStorageThatNeverStarts = new class('vlah') extends SegSession { + + public function start(array $options = []): bool + { + return false; + } + + public function isStarted(): bool + { + return false; + } + }; + + $session = new SegSession('a', $sessionStorageThatNeverStarts); + } +} diff --git a/tests/DestroyMethodSegmentedSessionTest.php b/tests/DestroyMethodSegmentedSessionTest.php new file mode 100644 index 0000000..be8d26e --- /dev/null +++ b/tests/DestroyMethodSegmentedSessionTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class DestroyMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_clear_only_session_segment(): void + { + $session = new SegSession('da-segment'); + + $_SESSION['bar'] = 'foo'; + + $session->set('foo', 'bar'); + + $segmentBeforeClearing = [ + 'foo' => 'bar', + SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], + ]; + + // Verify segment data before clearing + $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); + + // Verify that it always returns true + $this->assertTrue($session->destroy()); + + // Cleared segment should only contain an empty array for flash data + $this->assertEquals( + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + $_SESSION[$session->getSegmentName()] + ); + + // Items set directly in $_SESSION should still be present & not cleared + $this->assertArrayHasKey('bar', $_SESSION); + $this->assertEquals('foo', $_SESSION['bar']); + } + + /** + * @runInSeparateProcess + */ + public function test_should_clear_only_session_segment_when_session_started_outside_library(): void + { + session_start(); + + $_SESSION['bar'] = 'foo'; + + $session = new SegSession('da-segment'); + + $_SESSION['bar1'] = 'foo1'; + + $session->set('foo', 'bar'); + + $segmentBeforeClearing = [ + 'foo' => 'bar', + SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], + ]; + + // Verify segment data before clearing + $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); + + // Verify that it always returns true + $this->assertTrue($session->destroy()); + + // Cleared segment should only contain an empty array for flash data + $this->assertEquals( + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + $_SESSION[$session->getSegmentName()] + ); + + // Items set directly in $_SESSION should still be present & not cleared + $this->assertArrayHasKey('bar', $_SESSION); + $this->assertArrayHasKey('bar1', $_SESSION); + $this->assertEquals('foo', $_SESSION['bar']); + $this->assertEquals('foo1', $_SESSION['bar1']); + } +} diff --git a/tests/GetAllFromCurrentFlashMethodTest.php b/tests/GetAllFromCurrentFlashMethodTest.php new file mode 100644 index 0000000..bbf0fc2 --- /dev/null +++ b/tests/GetAllFromCurrentFlashMethodTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetAllFromCurrentFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_empty_array_on_newly_created_segment(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals([], $session->getAllFromCurrentFlash()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_before_and_after_setting_items_in_current_flash(): void + { + $session = new SegSession('da-segment'); + + $session->setInCurrentFlash('foo', 'bar'); + $session->setInCurrentFlash('bar', 'foo'); + + $this->assertEquals( + ['foo'=>'bar', 'bar'=>'foo'], + $session->getAllFromCurrentFlash() + ); + + // these values should be available in the current flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should now be in the current flash for this instance + $this->assertEquals( + ['foo2'=>'bar2', 'foo3'=>'bar3'], + $session2->getAllFromCurrentFlash() + ); + } +} diff --git a/tests/GetAllFromNextFlashMethodTest.php b/tests/GetAllFromNextFlashMethodTest.php new file mode 100644 index 0000000..79cd079 --- /dev/null +++ b/tests/GetAllFromNextFlashMethodTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetAllFromNextFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_empty_array_on_newly_created_segment(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals([], $session->getAllFromNextFlash()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_before_and_after_setting_items_in_next_flash(): void + { + $session = new SegSession('da-segment'); + + $session->setInNextFlash('foo', 'bar'); + $session->setInNextFlash('bar', 'foo'); + + $this->assertEquals( + ['foo'=>'bar', 'bar'=>'foo'], + $session->getAllFromNextFlash() + ); + + // these values should not be available in the next flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should not be in the next flash for this instance + $this->assertEquals([], $session2->getAllFromNextFlash()); + + // test the return [] scenario in getAllFromNextFlash + $session2->getStorage()->clear(); // we clear the actual session, not just the segment + $session2->getStorage()->destroy(); // we destroy the actual session, not just the segment + + $this->assertEquals([], $session2->getAllFromNextFlash()); + } +} diff --git a/tests/GetFromCurrentFlashMethodTest.php b/tests/GetFromCurrentFlashMethodTest.php new file mode 100644 index 0000000..d3f5900 --- /dev/null +++ b/tests/GetFromCurrentFlashMethodTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetFromCurrentFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_null_default_for_non_existent_attribute(): void + { + $session = new SegSession('da-segment'); + + $this->assertNull($session->getFromCurrentFlash('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_custom_default_for_non_existent_attribute(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals('bar', $session->getFromCurrentFlash('foo', 'bar')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_after_setting_items_in_current_flash(): void + { + $session = new SegSession('da-segment'); + + $session->setInCurrentFlash('foo', 'bar'); + $session->setInCurrentFlash('bar', 'foo'); + + $this->assertEquals('bar', $session->getFromCurrentFlash('foo')); + $this->assertEquals('foo', $session->getFromCurrentFlash('bar')); + + // these values should be available in the current flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should now be in the current flash for this instance + $this->assertEquals('bar2', $session2->getFromCurrentFlash('foo2')); + $this->assertEquals('bar3', $session2->getFromCurrentFlash('foo3')); + } +} diff --git a/tests/GetFromNextFlashMethodTest.php b/tests/GetFromNextFlashMethodTest.php new file mode 100644 index 0000000..c4ca63a --- /dev/null +++ b/tests/GetFromNextFlashMethodTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetFromNextFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_null_default_for_non_existent_attribute(): void + { + $session = new SegSession('da-segment'); + + $this->assertNull($session->getFromNextFlash('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_custom_default_for_non_existent_attribute(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals('bar', $session->getFromNextFlash('foo', 'bar')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_after_setting_items_in_current_flash(): void + { + $session = new SegSession('da-segment'); + + $session->setInNextFlash('foo', 'bar'); + $session->setInNextFlash('bar', 'foo'); + + $this->assertEquals('bar', $session->getFromNextFlash('foo')); + $this->assertEquals('foo', $session->getFromNextFlash('bar')); + + // these values should NOT be available in the next flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should NOT be in the next flash for this instance + $this->assertNotEquals('bar2', $session2->getFromNextFlash('foo2')); + $this->assertNotEquals('bar3', $session2->getFromNextFlash('foo3')); + } +} diff --git a/tests/GetIdMethodSegmentedSessionTest.php b/tests/GetIdMethodSegmentedSessionTest.php new file mode 100644 index 0000000..926822c --- /dev/null +++ b/tests/GetIdMethodSegmentedSessionTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetIdMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_session_id(): void + { + $session = new SegSession('da-segment'); + + // Should have the same id as it's internal storage object + $this->assertEquals($session->getId(), $session->getStorage()->getId()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_session_id_when_session_started_outside_library(): void + { + session_start(); + + $session = new SegSession('da-segment'); + + // Should have the same id as it's internal storage object + $this->assertEquals($session->getId(), $session->getStorage()->getId()); + } +} diff --git a/tests/GetMethodSegmentedSessionTest.php b/tests/GetMethodSegmentedSessionTest.php new file mode 100644 index 0000000..e43cda5 --- /dev/null +++ b/tests/GetMethodSegmentedSessionTest.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_attribute_if_exists(): void + { + $session = new SegSession('da-segment'); + + $session->set('foo', 'bar'); + + $this->assertEquals('bar', $session->get('foo')); + + // Verify that set item was inside the segment in $_SESSION and not directly in $_SESSION + $this->assertArrayHasKey('foo', $_SESSION[$session->getSegmentName()]); + $this->assertEquals('bar', $_SESSION[$session->getSegmentName()]['foo']); + $this->assertArrayNotHasKey('foo', $_SESSION); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void + { + session_start(); + + $session = new SegSession('da-segment'); + + $session->set('foo', 'bar'); + + $this->assertEquals('bar', $session->get('foo')); + + // Verify that set item was inside the segment in $_SESSION and not directly in $_SESSION + $this->assertArrayHasKey('foo', $_SESSION[$session->getSegmentName()]); + $this->assertEquals('bar', $_SESSION[$session->getSegmentName()]['foo']); + $this->assertArrayNotHasKey('foo', $_SESSION); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_default_value_if_not_exists(): void + { + $session = new SegSession('da-segment'); + + $this->assertNull($session->get('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_default_value_if_not_exists_when_session_started_outside_library(): void + { + session_start(); + + $session = new SegSession('da-segment'); + + $this->assertNull($session->get('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_custom_default_value_if_not_exists(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals('bar', $session->get('foo', 'bar')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_custom_default_value_if_not_exists_when_session_started_outside_library(): void + { + session_start(); + + $session = new SegSession('da-segment'); + + $this->assertEquals('bar', $session->get('foo', 'bar')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_not_get_attribute_defined_outside_library(): void + { + session_start(); + + $_SESSION['foo'] = 'bar'; + + $session = new SegSession('da-segment'); + + $this->assertNull($session->get('foo')); + } +} diff --git a/tests/GetSegmentNameMethodTest.php b/tests/GetSegmentNameMethodTest.php new file mode 100644 index 0000000..13f062d --- /dev/null +++ b/tests/GetSegmentNameMethodTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetSegmentNameMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals('da-segment', $session->getSegmentName()); + } +} diff --git a/tests/GetStorageMethodTest.php b/tests/GetStorageMethodTest.php new file mode 100644 index 0000000..5edd832 --- /dev/null +++ b/tests/GetStorageMethodTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class GetStorageMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void + { + $storage = new \Josantonius\Session\Session(); + $session = new SegSession('da-segment', $storage); + + $this->assertSame($storage, $session->getStorage()); + } +} diff --git a/tests/HasInCurrentFlashMethodTest.php b/tests/HasInCurrentFlashMethodTest.php new file mode 100644 index 0000000..8a6e37e --- /dev/null +++ b/tests/HasInCurrentFlashMethodTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class HasInCurrentFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_false_on_newly_created_segment(): void + { + $session = new SegSession('da-segment'); + + $this->assertFalse($session->hasInCurrentFlash('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_before_and_after_setting_items_in_current_flash(): void + { + $session = new SegSession('da-segment'); + + $this->assertFalse($session->hasInCurrentFlash('foo')); + + $session->setInCurrentFlash('foo', 'bar'); + + $this->assertTrue($session->hasInCurrentFlash('foo')); + + // these values should be available in the current flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should now be in the current flash for this instance + $this->assertTrue($session2->hasInCurrentFlash('foo2')); + $this->assertTrue($session2->hasInCurrentFlash('foo3')); + } +} diff --git a/tests/HasInNextFlashMethodTest.php b/tests/HasInNextFlashMethodTest.php new file mode 100644 index 0000000..94a2730 --- /dev/null +++ b/tests/HasInNextFlashMethodTest.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class HasInNextFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_false_on_newly_created_segment(): void + { + $session = new SegSession('da-segment'); + + $this->assertFalse($session->hasInNextFlash('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_right_values_before_and_after_setting_items_in_next_flash(): void + { + $session = new SegSession('da-segment'); + + $this->assertFalse($session->hasInNextFlash('foo')); + + $session->setInNextFlash('foo', 'bar'); + + $this->assertTrue($session->hasInNextFlash('foo')); + + // these values should not be available in the next flash of the next instance below + $session->setInNextFlash('foo2', 'bar2'); + $session->setInNextFlash('foo3', 'bar3'); + + $session2 = new SegSession('da-segment'); + + // previous next flash items should not be in the next flash for this instance + $this->assertFalse($session2->hasInNextFlash('foo2')); + $this->assertFalse($session2->hasInNextFlash('foo3')); + } +} diff --git a/tests/HasMethodSegmentedSessionTest.php b/tests/HasMethodSegmentedSessionTest.php new file mode 100644 index 0000000..f0d6a40 --- /dev/null +++ b/tests/HasMethodSegmentedSessionTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class HasMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_check_if_attribute_exists(): void + { + $session = new SegSession('da-segment'); + $session->set('foo', 'bar'); + + $this->assertTrue($session->has('foo')); + $this->assertFalse($session->has('bar')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_check_attribute_defined_outside_library(): void + { + session_start(); + $_SESSION['foo'] = 'bar'; + + $session = new SegSession('da-segment'); + $this->assertFalse($session->has('foo')); + } +} diff --git a/tests/IsStartedMethodSegmentedSessionTest.php b/tests/IsStartedMethodSegmentedSessionTest.php new file mode 100644 index 0000000..1dfd125 --- /dev/null +++ b/tests/IsStartedMethodSegmentedSessionTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class IsStartedMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_check_if_session_is_active(): void + { + $session = new SegSession('da-segment'); + + $this->assertTrue($session->isStarted()); // always auto-started + + $session->start(); + + $this->assertTrue($session->isStarted()); // should still be started + } + + /** + * @runInSeparateProcess + */ + public function test_should_check_if_session_is_active_when_session_started_outside_library(): void + { + session_start(); + $session = new SegSession('da-segment'); + + $this->assertTrue($session->isStarted()); // always auto-started + + $session->start(); + + $this->assertTrue($session->isStarted()); // should still be started + } +} diff --git a/tests/PullMethodSegmentedSessionTest.php b/tests/PullMethodSegmentedSessionTest.php new file mode 100644 index 0000000..13a5f10 --- /dev/null +++ b/tests/PullMethodSegmentedSessionTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class PullMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_pull_attribute_and_return_the_value_if_exists(): void + { + $session = new SegSession('da-segment'); + + $_SESSION['foo'] = 'bar'; + + // foo has not yet been set in the segment + // default value of null should be returned + $this->assertNull($session->pull('foo')); + + // pull above should not affect $_SESSION['foo'] + $this->assertArrayHasKey('foo', $_SESSION); + + $session->set('foo', 'bar2'); // this will be stored in the segment + + // we are pulling the foo in the segment & not $_SESSION['foo'] + $this->assertEquals('bar2', $session->pull('foo')); + + // foo set directly in $_SESSION remains unchanged + $this->assertArrayHasKey('foo', $_SESSION); + $this->assertEquals('bar', $_SESSION['foo']); + + // foo in segment has been removed + $this->assertIsArray($_SESSION[$session->getSegmentName()]); + $this->assertArrayNotHasKey('foo', $_SESSION[$session->getSegmentName()]); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_default_value_if_attribute_not_exists(): void + { + $session = new SegSession('da-segment'); + + $this->assertNull($session->pull('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_return_custom_default_value_if_attribute_not_exists(): void + { + $session = new SegSession('da-segment'); + + $this->assertEquals('bar', $session->pull('foo', 'bar')); + } +} diff --git a/tests/RegenerateIdMethodSegmentedSessionTest.php b/tests/RegenerateIdMethodSegmentedSessionTest.php new file mode 100644 index 0000000..82d72ca --- /dev/null +++ b/tests/RegenerateIdMethodSegmentedSessionTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class RegenerateIdMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_regenerate_session_id_without_deleting_old_session(): void + { + $session = new SegSession('da-segment'); + $sessionId = session_id(); + + $this->assertTrue($session->regenerateId()); + + $this->assertNotEquals($sessionId, session_id()); + + $sessionId2 = session_id(); + + $this->assertTrue($session->regenerateId()); + + $this->assertNotEquals($sessionId2, session_id()); + } +} diff --git a/tests/RemoveFromFlashMethodTest.php b/tests/RemoveFromFlashMethodTest.php new file mode 100644 index 0000000..3a6e1b2 --- /dev/null +++ b/tests/RemoveFromFlashMethodTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class RemoveFromFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_remove_set_attributes(): void + { + $storage = new \Josantonius\Session\Session(); + $session = new SegSession('da-segment', $storage); + + $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); + $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); + + $session->setInNextFlash('foo-next-1', 'val-in-next-1'); + $session->setInNextFlash('foo-next-2', 'val-in-next-2'); + + $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); + $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); + $this->assertTrue($session->hasInNextFlash('foo-next-1')); + $this->assertTrue($session->hasInNextFlash('foo-next-2')); + + $session->removeFromFlash('foo-current-1', true); + + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); + $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); + $this->assertTrue($session->hasInNextFlash('foo-next-1')); + $this->assertTrue($session->hasInNextFlash('foo-next-2')); + + $session->removeFromFlash('foo-current-2', true); + + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); + $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); + $this->assertTrue($session->hasInNextFlash('foo-next-1')); + $this->assertTrue($session->hasInNextFlash('foo-next-2')); + + $session->removeFromFlash('foo-next-1', true, true); + + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); + $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); + $this->assertFalse($session->hasInNextFlash('foo-next-1')); + $this->assertTrue($session->hasInNextFlash('foo-next-2')); + + $session->removeFromFlash('foo-next-2', true, true); + + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); + $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); + $this->assertFalse($session->hasInNextFlash('foo-next-1')); + $this->assertFalse($session->hasInNextFlash('foo-next-2')); + } +} diff --git a/tests/RemoveMethodSegmentedSessionTest.php b/tests/RemoveMethodSegmentedSessionTest.php new file mode 100644 index 0000000..201cbf2 --- /dev/null +++ b/tests/RemoveMethodSegmentedSessionTest.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class RemoveMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_remove_attribute_even_if_not_exist(): void + { + $session = new SegSession('da-segment'); + + $originalSegmentContent = $session->all(); + + $session->remove('foo'); + + $this->assertEquals($originalSegmentContent, $session->all()); + } + + /** + * @runInSeparateProcess + */ + public function test_should_remove_attribute_if_exist(): void + { + $session = new SegSession('da-segment'); + + $_SESSION['foo'] = 'bar'; + + $session->remove('foo'); + + // Remove above should not affect $_SESSION['foo'] + $this->assertArrayHasKey('foo', $_SESSION); + $this->assertEquals('bar', $_SESSION['foo']); + + // Set foo in the segment + $session->set('foo', 'bar2'); + + // foo should be in segment + $this->assertTrue($session->has('foo')); + $this->assertEquals('bar2', $session->get('foo')); + + $session->remove('foo'); // foo in the segment will be removed + $this->assertFalse($session->has('foo')); + + // $_SESSION['foo'] should still remain unaffected + $this->assertArrayHasKey('foo', $_SESSION); + $this->assertEquals('bar', $_SESSION['foo']); + } +} diff --git a/tests/ReplaceMethodSegmentedSessionTest.php b/tests/ReplaceMethodSegmentedSessionTest.php new file mode 100644 index 0000000..4733df6 --- /dev/null +++ b/tests/ReplaceMethodSegmentedSessionTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class ReplaceMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_add_attributes_if_not_exist(): void + { + $session = new SegSession('da-segment'); + + $_SESSION['bar'] = 'foo'; + + // foo has not yet been set in the segment + $this->assertFalse($session->has('foo')); + + // bar should not be in the segment + $this->assertFalse($session->has('bar')); + + $session->replace(['foo' => 'bar']); + + // foo was just set via the call to replace above + $this->assertTrue($session->has('foo')); + + // $_SESSION['bar'] should be untouched + $this->assertEquals('foo', $_SESSION['bar']); + + // assert that replaced value is present + $this->assertEquals('bar', $session->get('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_replace_attributes_if_exist(): void + { + $session = new SegSession('da-segment'); + + $session->set('foo', 'bar'); + $session->set('bar', 'foo'); + + $session->replace(['foo' => 'val']); + + $this->assertEquals('val', $session->get('foo')); + $this->assertEquals('foo', $session->get('bar')); + + $this->assertArrayNotHasKey('foo', $_SESSION); + $this->assertArrayNotHasKey('bar', $_SESSION); + } +} diff --git a/tests/SetIdMethodSegmentedSessionTest.php b/tests/SetIdMethodSegmentedSessionTest.php new file mode 100644 index 0000000..c1aa18e --- /dev/null +++ b/tests/SetIdMethodSegmentedSessionTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class SetIdMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_not_set_session_id_since_session_is_auto_started(): void + { + $session = new SegSession('da-segment'); + $originalId = $session->getId(); + + $session->setId('foo'); + + $this->assertEquals($originalId, session_id()); + $this->assertNotEquals('foo', session_id()); + } +} diff --git a/tests/SetInCurrentFlashMethodTest.php b/tests/SetInCurrentFlashMethodTest.php new file mode 100644 index 0000000..e7852fa --- /dev/null +++ b/tests/SetInCurrentFlashMethodTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class SetInCurrentFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_correctly_set_attributes(): void + { + $storage = new \Josantonius\Session\Session(); + $session = new SegSession('da-segment', $storage); + + $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); + $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); + + $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); + $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); + + $this->assertEquals('val-in-current-1', $session->getFromCurrentFlash('foo-current-1')); + $this->assertEquals('val-in-current-2', $session->getFromCurrentFlash('foo-current-2')); + } +} diff --git a/tests/SetInNextFlashMethodTest.php b/tests/SetInNextFlashMethodTest.php new file mode 100644 index 0000000..f7d6946 --- /dev/null +++ b/tests/SetInNextFlashMethodTest.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class SetInNextFlashMethodTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_correctly_set_attributes(): void + { + $storage = new \Josantonius\Session\Session(); + $session = new SegSession('da-segment', $storage); + + $session->setInNextFlash('foo-next-1', 'val-in-next-1'); + $session->setInNextFlash('foo-next-2', 'val-in-next-2'); + + $this->assertTrue($session->hasInNextFlash('foo-next-1')); + $this->assertTrue($session->hasInNextFlash('foo-next-2')); + + $this->assertEquals('val-in-next-1', $session->getFromNextFlash('foo-next-1')); + $this->assertEquals('val-in-next-2', $session->getFromNextFlash('foo-next-2')); + } +} diff --git a/tests/SetMethodSegmentedSessionTest.php b/tests/SetMethodSegmentedSessionTest.php new file mode 100644 index 0000000..675f8ff --- /dev/null +++ b/tests/SetMethodSegmentedSessionTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class SetMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_set_attribute_if_session_was_started(): void + { + $session = new SegSession('da-segment'); + + $session->set('foo', 'bar'); + + $this->assertEquals('bar', $session->get('foo')); + } + + /** + * @runInSeparateProcess + */ + public function test_should_set_attribute_if_native_session_was_started(): void + { + session_start(); + + $session = new SegSession('da-segment'); + + $session->set('foo', 'bar'); + + $this->assertEquals('bar', $session->get('foo')); + } +} diff --git a/tests/SetNameMethodSegmentedSessionTest.php b/tests/SetNameMethodSegmentedSessionTest.php new file mode 100644 index 0000000..d1001a8 --- /dev/null +++ b/tests/SetNameMethodSegmentedSessionTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class SetNameMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_should_not_set_session_name_since_session_is_auto_started(): void + { + $session = new SegSession('da-segment'); // auto-starts session + $originalSessionName = $session->getName(); + + $session->setName('foo'); + + $this->assertEquals($originalSessionName, session_name()); + $this->assertNotEquals('foo', session_name()); + } +} diff --git a/tests/StartMethodSegmentedSessionTest.php b/tests/StartMethodSegmentedSessionTest.php new file mode 100644 index 0000000..39ba890 --- /dev/null +++ b/tests/StartMethodSegmentedSessionTest.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * @phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps + */ + +namespace Josantonius\Session\Tests; + +use PHPUnit\Framework\TestCase; +use Josantonius\Session\FlashableSessionSegment as SegSession; + +class StartMethodSegmentedSessionTest extends TestCase +{ + public function setUp(): void + { + parent::setUp(); + } + + /** + * @runInSeparateProcess + */ + public function test_session_should_always_be_started_since_it_gets_auto_started_in_constructor(): void + { + $session = new SegSession('da-segment'); + + $this->assertTrue($session->start()); + + $this->assertEquals(PHP_SESSION_ACTIVE, session_status()); + + $this->assertTrue(isset($_SESSION)); + + // Call again + $this->assertTrue($session->start()); + + $this->assertEquals(PHP_SESSION_ACTIVE, session_status()); + + $this->assertTrue(isset($_SESSION)); + } +} diff --git a/tests/StartMethodTest.php b/tests/StartMethodTest.php index e7e53d9..fe8cf74 100644 --- a/tests/StartMethodTest.php +++ b/tests/StartMethodTest.php @@ -48,9 +48,10 @@ public function test_should_start_session(): void */ public function test_should_accept_options(): void { - $this->session->start(['cookie_lifetime' => 8000]); + $this->session->start(['cookie_lifetime' => 8000, 'name'=>'boooo']); $this->assertEquals(8000, ini_get('session.cookie_lifetime')); + $this->assertEquals('boooo', $this->session->getName()); } /** From 6da61ef63b84ce4e65afe45257401231974bfbcb Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 02:23:25 -0600 Subject: [PATCH 09/19] phpcs fixes --- src/FlashableSessionSegment.php | 244 +++++++++++++++----------------- 1 file changed, 113 insertions(+), 131 deletions(-) diff --git a/src/FlashableSessionSegment.php b/src/FlashableSessionSegment.php index 70f901c..10843a9 100644 --- a/src/FlashableSessionSegment.php +++ b/src/FlashableSessionSegment.php @@ -18,51 +18,51 @@ /** * @author https://github.com/rotexdegba - * + * * Each valid instance of this class will always have a valid session started or resumed */ class FlashableSessionSegment implements SessionInterface { use ExceptionThrowingMethodsTrait; - + /** * Used for performing some session operations for each instance of this class */ protected SessionInterface $storage; - + /** * Flash data for current request is stored here. - * - * It must be copied from + * + * It must be copied from * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] * every time an instance of this class is created. - * - * If $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - * isn't set, this $this->flashDataForCurrentRequest should maintain + * + * If $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * isn't set, this $this->flashDataForCurrentRequest should maintain * the default value of empty array. */ protected array $flashDataForCurrentRequest = []; - + /** - * When different libraries and projects try to modify data with the same keys + * When different libraries and projects try to modify data with the same keys * in $_SESSION , the resulting conflicts can result in unexpected behavior. - * + * * This value will be used as a key in $_SESSION to avoid session - * data for an instance of this class from colliding with or being + * data for an instance of this class from colliding with or being * overwritten by other libraries or projects within an application. - * + * * Be sure to set it to a unique value for each instance of this class. * For example, you could use a value such as the fully qualified * class name concatenated with the method name of the method where * an instance of this class is being created. */ protected string $segmentName; - + /** * Key for storing flash data in $_SESSION[$this->segmentName] */ public const FLASH_DATA_FOR_NEXT_REQUEST = self::class . '__flash'; - + /** * List of available $options with their default values: * @@ -94,101 +94,94 @@ class FlashableSessionSegment implements SessionInterface * * use_trans_sid: "0" * * @see https://php.net/session.configuration - * - * - * @param string $segmentName Name of key to be used in $_SESSION to store all + * + * + * @param string $segmentName Name of key to be used in $_SESSION to store all * session data for an instance of this class. This - * helps avoid writing session data directly to + * helps avoid writing session data directly to * $_SESSION, which runs the risk of being overwritten * by other libraries that write to $_SESSION with the * same key(s). The value specified for this key should * be something unique, like the domain name of the web - * application, or some other unique value that other + * application, or some other unique value that other * libraries writing to $_SESSION wouldn't use. - * - * @param null|\Josantonius\Session\SessionInterface $storage used for performing some session operations for each instance of this class. + * + * @param null|\Josantonius\Session\SessionInterface $storage used for performing some session operations for each instance of this class. * If null, an instance of \Josantonius\Session\Session will be created - * - * @param array $options session start configuration options that will be used to + * + * @param array $options session start configuration options that will be used to * automatically start a new session or resume existing session * when an instance of this class is created - * + * * @throws \Josantonius\Session\Exceptions\EmptySegmentNameException * @throws \Josantonius\Session\Exceptions\HeadersSentException * @throws \Josantonius\Session\Exceptions\SessionNotStartedException * @throws \Josantonius\Session\Exceptions\WrongSessionOptionException */ - public function __construct(string $segmentName, ?SessionInterface $storage=null, array $options = []) + public function __construct(string $segmentName, ?SessionInterface $storage = null, array $options = []) { - if($segmentName === '') { - + if ($segmentName === '') { throw new EmptySegmentNameException(__METHOD__); } - + $this->storage = $storage ?? new Session(); $this->segmentName = $segmentName; - - if( !$this->isStarted() ) { - + + if (!$this->isStarted()) { // start or resume session $this->start($options); } - - if( !$this->isStarted() ) { - + + if (!$this->isStarted()) { $msg = 'Error: Could not start session in ' . __METHOD__; throw new SessionNotStartedException($msg); } - + $this->initializeOrReinitialize(); $this->moveNextFlashToCurrentFlash(); } - - protected function initializeOrReinitialize(): void { - - if($this->isStarted()) { - if(!isset($_SESSION[$this->segmentName])) { - + protected function initializeOrReinitialize(): void + { + if ($this->isStarted()) { + if (!isset($_SESSION[$this->segmentName])) { // We want session data to be in a segment to protect it from // being overwritten by other packages $_SESSION[$this->segmentName] = []; - - if(!isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST])) { - + + if (!isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST])) { // Initialize the flash storage in the session's segment $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } } } - - protected function moveNextFlashToCurrentFlash() { - - if($this->isStarted()) { - + + protected function moveNextFlashToCurrentFlash(): void + { + if ($this->isStarted()) { /////////////////////////////////////////////////////////////////////////// // Flash update logic: We update the flash data by copying the existing - // flash data stored in + // flash data stored in // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // to $this->flashDataForCurrentRequest & then reset // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // to an empty array. - // - // Flash data inside $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + // + // Flash data inside $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // will only be accessible in the next request - // - // Flash data copied from $_SESSION into $this->flashDataForCurrentRequest from the previous + // + // Flash data copied from $_SESSION into $this->flashDataForCurrentRequest from the previous // request is flash data that will be accessible in the current request. /////////////////////////////////////////////////////////////////////////// $this->flashDataForCurrentRequest = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; - // Reset the flash data in session to an empty array + // Reset the flash data in session to an empty array // but we still have the existing flash data in $this->flashDataForCurrentRequest $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } - + /** * Starts the session. * @@ -226,17 +219,15 @@ protected function moveNextFlashToCurrentFlash() { public function start(array $options = []): bool { $isStarted = true; - - if(!$this->isStarted()) { - + + if (!$this->isStarted()) { $isStarted = $this->storage->start($options); - - if($isStarted) { - + + if ($isStarted) { $this->initializeOrReinitialize(); } // if($isStarted) } // if(!$this->isStarted()) - + return $isStarted; } @@ -283,9 +274,8 @@ public function set(string $name, mixed $value): void public function replace(array $data): void { if ($this->isStarted()) { - // Replace it in this session object's segmented session data - $_SESSION[$this->segmentName] = + $_SESSION[$this->segmentName] = array_merge($_SESSION[$this->segmentName], $data); } } @@ -298,20 +288,18 @@ public function replace(array $data): void public function pull(string $name, mixed $default = null): mixed { $value = $default; - - if($this->isStarted()) { - - // Try to get it from this session object's segmented session data + + if ($this->isStarted()) { + // Try to get it from this session object's segmented session data // or return the default value $value = $_SESSION[$this->segmentName][$name] ?? $default; - if(isset($_SESSION[$this->segmentName][$name])) { - + if (isset($_SESSION[$this->segmentName][$name])) { // Remove it from this session object's segmented session data unset($_SESSION[$this->segmentName][$name]); } } - + return $value; } @@ -321,29 +309,27 @@ public function pull(string $name, mixed $default = null): mixed public function remove(string $name): void { if ($this->isStarted() && isset($_SESSION[$this->segmentName][$name])) { - // Remove it from this session object's segmented session data unset($_SESSION[$this->segmentName][$name]); } } /** - * Clears the session segment ($_SESSION[$this->segmentName]) and restores + * Clears the session segment ($_SESSION[$this->segmentName]) and restores * this object to its default original state after creation. */ public function clear(): void { if ($this->isStarted() && isset($_SESSION[$this->segmentName])) { - - // Get rid of this session object's segmented session data, but we + // Get rid of this session object's segmented session data, but we // don't destroy $_SESSION since other data may be stored in it by // other instances of this class or other code in the application // this class is being used in. unset($_SESSION[$this->segmentName]); - + // Reset segment to empty array $_SESSION[$this->segmentName] = []; - + // Reset the flash data in session segment to an empty arrays $this->flashDataForCurrentRequest = []; $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; @@ -360,7 +346,7 @@ public function getId(): string /** * Sets the session ID. - * + * * This method will be of no effect if called outside the constructor * of this class since the session will already be started after the * constructor method finishes execution @@ -388,7 +374,7 @@ public function getName(): string /** * Sets the session name. - * + * * This method will be of no effect if called outside the constructor * of this class since the session will already be started after the * constructor method finishes execution @@ -399,15 +385,15 @@ public function setName(string $name): void } /** - * Clears the session segment ($_SESSION[$this->segmentName]) and restores + * Clears the session segment ($_SESSION[$this->segmentName]) and restores * this object to its original state after creation. - * - * The session ($_SESSION) is not destroyed. + * + * The session ($_SESSION) is not destroyed. */ public function destroy(): bool { $this->clear(); - + return true; } @@ -418,40 +404,39 @@ public function isStarted(): bool { return $this->storage->isStarted(); } - + /** - * Sets an item with the specified $key in the flash storage for an instance + * Sets an item with the specified $key in the flash storage for an instance * of this class (i.e. $this->flashDataForCurrentRequest). - * + * * The item will only be retrievable from the instance of this class it was set in. */ public function setInCurrentFlash(string $key, mixed $value): void { $this->flashDataForCurrentRequest[$key] = $value; } - + /** - * Sets an item with the specified $key in the flash storage located in + * Sets an item with the specified $key in the flash storage located in * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - * - * The item will only be retrievable by calling the getFromCurrentFlash + * + * The item will only be retrievable by calling the getFromCurrentFlash * on the next instance of this class created with the same segment name. */ public function setInNextFlash(string $key, mixed $value): void { - if( - $this->isStarted() + $canSet = $this->isStarted() && isset($_SESSION[$this->segmentName]) - && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) - ) { + && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]); + + if ($canSet) { // Set it in this session object's segmented session data $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key] = $value; - } } - + /** - * Check if item with specified $key exists in the flash storage for + * Check if item with specified $key exists in the flash storage for * an instance of this class (i.e. in $this->flashDataForCurrentRequest). */ public function hasInCurrentFlash(string $key): bool @@ -465,7 +450,7 @@ public function hasInCurrentFlash(string $key): bool //////////////////////////////////////////////////////////////////////// return \array_key_exists($key, $this->flashDataForCurrentRequest); } - + /** * Check if item with specified $key exists in * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]. @@ -479,7 +464,7 @@ public function hasInNextFlash(string $key): bool // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request //////////////////////////////////////////////////////////////////////// - return + return ( // Check in this session object's segmented session data $this->isStarted() && isset($_SESSION[$this->segmentName]) @@ -488,12 +473,12 @@ public function hasInNextFlash(string $key): bool && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]) ); } - + /** - * Get an item with the specified $key from the flash storage for an instance + * Get an item with the specified $key from the flash storage for an instance * of this class (i.e. $this->flashDataForCurrentRequest) if it exists or return $default. */ - public function getFromCurrentFlash(string $key, mixed $default=null): mixed + public function getFromCurrentFlash(string $key, mixed $default = null): mixed { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside @@ -504,82 +489,79 @@ public function getFromCurrentFlash(string $key, mixed $default=null): mixed //////////////////////////////////////////////////////////////////////// return ($this->isStarted() && $this->hasInCurrentFlash($key)) ? $this->flashDataForCurrentRequest[$key] : $default; } - + /** * Get an item with the specified $key from - * + * * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] * if it exists or return $default. */ - public function getFromNextFlash(string $key, mixed $default=null): mixed - { + public function getFromNextFlash(string $key, mixed $default = null): mixed + { return ($this->isStarted() && $this->hasInNextFlash($key)) ? $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key] : $default; } - + /** * Remove an item with the specified $key (if it exists) from: * - the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest), if $for_current_request === true * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], if $for_next_request === true */ public function removeFromFlash( - string $key, - bool $for_current_request=true, - bool $for_next_request=false - ): void - { + string $key, + bool $for_current_request = true, + bool $for_next_request = false + ): void { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside // $this->flashDataForCurrentRequest - // while + // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request //////////////////////////////////////////////////////////////////////// - if($for_current_request && $this->hasInCurrentFlash($key)) { - + if ($for_current_request && $this->hasInCurrentFlash($key)) { unset($this->flashDataForCurrentRequest[$key]); } - - if($for_next_request && $this->isStarted() && $this->hasInNextFlash($key)) { - + + if ($for_next_request && $this->isStarted() && $this->hasInNextFlash($key)) { // Remove it from this session object's segmented session data unset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]); } // if($for_next_request) } - + /** * Get all items in the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest) */ public function getAllFromCurrentFlash(): array - { + { return $this->flashDataForCurrentRequest; } - + /** * Get all items in $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] */ public function getAllFromNextFlash(): array { - if( - $this->isStarted() + $canGet = $this->isStarted() && isset($_SESSION[$this->segmentName]) && isset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) - && is_array($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]) - ) { + && is_array($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]); + + if ($canGet) { // Get it from this session object's segmented session data return $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]; } - + return []; } - + public function getSegmentName(): string { return $this->segmentName; } - - public function getStorage(): SessionInterface + + public function getStorage(): SessionInterface { return $this->storage; } From 28ca6a441a274972630f51f38393a692d427b7b0 Mon Sep 17 00:00:00 2001 From: rotimi Date: Tue, 13 Aug 2024 16:23:36 -0600 Subject: [PATCH 10/19] phpcs & phpmd fixes --- phpcs.xml | 4 +- src/FlashableSessionSegment.php | 51 +++++++------- src/Session.php | 16 ++--- tests/AllMethodSegmentedSessionTest.php | 28 ++++---- tests/ClearMethodSegmentedSessionTest.php | 27 +++---- .../ConstructorMethodSegmentedSessionTest.php | 70 ++++++++++--------- tests/DestroyMethodSegmentedSessionTest.php | 34 ++++----- tests/GetAllFromCurrentFlashMethodTest.php | 20 +++--- tests/GetAllFromNextFlashMethodTest.php | 22 +++--- tests/GetFromCurrentFlashMethodTest.php | 24 +++---- tests/GetFromNextFlashMethodTest.php | 24 +++---- tests/GetIdMethodSegmentedSessionTest.php | 6 +- tests/GetMethodSegmentedSessionTest.php | 12 ++-- tests/GetSegmentNameMethodTest.php | 2 +- tests/GetStorageMethodTest.php | 5 +- tests/HasInCurrentFlashMethodTest.php | 18 ++--- tests/HasInNextFlashMethodTest.php | 18 ++--- tests/HasMethodSegmentedSessionTest.php | 2 +- tests/IsStartedMethodSegmentedSessionTest.php | 4 +- tests/PullMethodSegmentedSessionTest.php | 8 +-- ...RegenerateIdMethodSegmentedSessionTest.php | 2 +- tests/RemoveFromFlashMethodTest.php | 25 +++---- tests/RemoveMethodSegmentedSessionTest.php | 16 ++--- tests/ReplaceMethodSegmentedSessionTest.php | 14 ++-- tests/SetIdMethodSegmentedSessionTest.php | 2 +- tests/SetInCurrentFlashMethodTest.php | 9 +-- tests/SetInNextFlashMethodTest.php | 9 +-- tests/SetNameMethodSegmentedSessionTest.php | 2 +- tests/StartMethodSegmentedSessionTest.php | 2 +- tests/StartMethodTest.php | 2 +- 30 files changed, 246 insertions(+), 232 deletions(-) diff --git a/phpcs.xml b/phpcs.xml index 97e64cc..b81d01d 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -38,8 +38,8 @@ - - + + diff --git a/src/FlashableSessionSegment.php b/src/FlashableSessionSegment.php index 10843a9..191f081 100644 --- a/src/FlashableSessionSegment.php +++ b/src/FlashableSessionSegment.php @@ -20,6 +20,7 @@ * @author https://github.com/rotexdegba * * Each valid instance of this class will always have a valid session started or resumed + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class FlashableSessionSegment implements SessionInterface { @@ -38,10 +39,10 @@ class FlashableSessionSegment implements SessionInterface * every time an instance of this class is created. * * If $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - * isn't set, this $this->flashDataForCurrentRequest should maintain + * isn't set, this $this->currentFlashData should maintain * the default value of empty array. */ - protected array $flashDataForCurrentRequest = []; + protected array $currentFlashData = []; /** * When different libraries and projects try to modify data with the same keys @@ -164,20 +165,20 @@ protected function moveNextFlashToCurrentFlash(): void // Flash update logic: We update the flash data by copying the existing // flash data stored in // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // to $this->flashDataForCurrentRequest & then reset + // to $this->currentFlashData & then reset // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // to an empty array. // // Flash data inside $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // will only be accessible in the next request // - // Flash data copied from $_SESSION into $this->flashDataForCurrentRequest from the previous + // Flash data copied from $_SESSION into $this->currentFlashData from the previous // request is flash data that will be accessible in the current request. /////////////////////////////////////////////////////////////////////////// - $this->flashDataForCurrentRequest = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; + $this->currentFlashData = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; // Reset the flash data in session to an empty array - // but we still have the existing flash data in $this->flashDataForCurrentRequest + // but we still have the existing flash data in $this->currentFlashData $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } @@ -331,7 +332,7 @@ public function clear(): void $_SESSION[$this->segmentName] = []; // Reset the flash data in session segment to an empty arrays - $this->flashDataForCurrentRequest = []; + $this->currentFlashData = []; $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } @@ -407,13 +408,13 @@ public function isStarted(): bool /** * Sets an item with the specified $key in the flash storage for an instance - * of this class (i.e. $this->flashDataForCurrentRequest). + * of this class (i.e. $this->currentFlashData). * * The item will only be retrievable from the instance of this class it was set in. */ public function setInCurrentFlash(string $key, mixed $value): void { - $this->flashDataForCurrentRequest[$key] = $value; + $this->currentFlashData[$key] = $value; } /** @@ -437,18 +438,18 @@ public function setInNextFlash(string $key, mixed $value): void /** * Check if item with specified $key exists in the flash storage for - * an instance of this class (i.e. in $this->flashDataForCurrentRequest). + * an instance of this class (i.e. in $this->currentFlashData). */ public function hasInCurrentFlash(string $key): bool { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside - // $this->flashDataForCurrentRequest + // $this->currentFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request //////////////////////////////////////////////////////////////////////// - return \array_key_exists($key, $this->flashDataForCurrentRequest); + return \array_key_exists($key, $this->currentFlashData); } /** @@ -459,7 +460,7 @@ public function hasInNextFlash(string $key): bool { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside - // $this->flashDataForCurrentRequest + // $this->currentFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request @@ -476,18 +477,18 @@ public function hasInNextFlash(string $key): bool /** * Get an item with the specified $key from the flash storage for an instance - * of this class (i.e. $this->flashDataForCurrentRequest) if it exists or return $default. + * of this class (i.e. $this->currentFlashData) if it exists or return $default. */ public function getFromCurrentFlash(string $key, mixed $default = null): mixed { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside - // $this->flashDataForCurrentRequest + // $this->currentFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request //////////////////////////////////////////////////////////////////////// - return ($this->isStarted() && $this->hasInCurrentFlash($key)) ? $this->flashDataForCurrentRequest[$key] : $default; + return ($this->isStarted() && $this->hasInCurrentFlash($key)) ? $this->currentFlashData[$key] : $default; } /** @@ -505,37 +506,37 @@ public function getFromNextFlash(string $key, mixed $default = null): mixed /** * Remove an item with the specified $key (if it exists) from: - * - the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest), if $for_current_request === true + * - the flash storage for an instance of this class (i.e. in $this->currentFlashData), if $for_current_request === true * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], if $for_next_request === true */ public function removeFromFlash( string $key, - bool $for_current_request = true, - bool $for_next_request = false + bool $forCurrentRequest = true, + bool $forNextRequest = false ): void { //////////////////////////////////////////////////////////////////////// // Accessible flash data for current request is always inside - // $this->flashDataForCurrentRequest + // $this->currentFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // contains flash data for the next request //////////////////////////////////////////////////////////////////////// - if ($for_current_request && $this->hasInCurrentFlash($key)) { - unset($this->flashDataForCurrentRequest[$key]); + if ($forCurrentRequest && $this->hasInCurrentFlash($key)) { + unset($this->currentFlashData[$key]); } - if ($for_next_request && $this->isStarted() && $this->hasInNextFlash($key)) { + if ($forNextRequest && $this->isStarted() && $this->hasInNextFlash($key)) { // Remove it from this session object's segmented session data unset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]); } // if($for_next_request) } /** - * Get all items in the flash storage for an instance of this class (i.e. in $this->flashDataForCurrentRequest) + * Get all items in the flash storage for an instance of this class (i.e. in $this->currentFlashData) */ public function getAllFromCurrentFlash(): array { - return $this->flashDataForCurrentRequest; + return $this->currentFlashData; } /** diff --git a/src/Session.php b/src/Session.php index 946d2f3..72ff932 100644 --- a/src/Session.php +++ b/src/Session.php @@ -24,7 +24,7 @@ class Session implements SessionInterface { use ExceptionThrowingMethodsTrait; - + /** * Starts the session. * @@ -68,12 +68,11 @@ public function start(array $options = []): bool $this->throwExceptionIfHeadersWereSent(); $this->throwExceptionIfSessionWasStarted(); $this->throwExceptionIfHasWrongOptions($options); - - if(isset($options['name'])) { - + + if (isset($options['name'])) { session_name($options['name']); } - + return session_start($options); } @@ -176,9 +175,10 @@ public function clear(): void */ public function getId(): string { - $id = session_id(); - - return ($id !== false) ? $id : ''; // session_id returns false on failure + $sessionId = session_id(); + + // session_id returns false on failure + return ($sessionId !== false) ? $sessionId : ''; } /** diff --git a/tests/AllMethodSegmentedSessionTest.php b/tests/AllMethodSegmentedSessionTest.php index 560d9d2..1634d15 100644 --- a/tests/AllMethodSegmentedSessionTest.php +++ b/tests/AllMethodSegmentedSessionTest.php @@ -29,26 +29,26 @@ public function setUp(): void public function test_should_get_all_attributes_in_segment(): void { $session = new SegSession('da-segment'); - + $this->assertIsArray($_SESSION); $session->set('foo', 'bar'); $this->assertEquals(['foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $session->all()); - + // foo should only be inside $_SESSION[$session->getSegmentName()] $this->assertArrayNotHasKey('foo', $_SESSION); - + // SegSession::FLASH_DATA_FOR_NEXT_REQUEST should only be inside $_SESSION[$session->getSegmentName()] $this->assertArrayNotHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION); - + $this->assertEquals( [ - $session->getSegmentName() => + $session->getSegmentName() => [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [] ] - ], + ], $_SESSION ); } @@ -59,33 +59,33 @@ public function test_should_get_all_attributes_in_segment(): void public function test_should_get_all_attributes_in_segment_when_session_started_outside_library(): void { session_start(); - + $this->assertIsArray($_SESSION); - + $session = new SegSession('da-segment'); - + $_SESSION['top-key'] = 'top-value'; $session->set('foo', 'bar'); $this->assertEquals(['foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $session->all()); - + // foo should only be inside $_SESSION[$session->getSegmentName()] $this->assertArrayNotHasKey('foo', $_SESSION); - + // SegSession::FLASH_DATA_FOR_NEXT_REQUEST should only be inside $_SESSION[$session->getSegmentName()] $this->assertArrayNotHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION); - + // Make sure both data set in $_SESSION from outside & within this // library are where they should be $this->assertEquals( [ 'top-key' => 'top-value', - $session->getSegmentName() => + $session->getSegmentName() => [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [] ] - ], + ], $_SESSION ); } diff --git a/tests/ClearMethodSegmentedSessionTest.php b/tests/ClearMethodSegmentedSessionTest.php index b428281..9b8f7db 100644 --- a/tests/ClearMethodSegmentedSessionTest.php +++ b/tests/ClearMethodSegmentedSessionTest.php @@ -16,6 +16,9 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; +/** + * @SuppressWarnings(PHPMD.LongVariable) + */ class ClearMethodSegmentedSessionTest extends TestCase { public function setUp(): void @@ -31,14 +34,14 @@ public function test_should_clear_only_session_segment(): void $session = new SegSession('da-segment'); $_SESSION['bar'] = 'foo'; - + $session->set('foo', 'bar'); - + $segmentBeforeClearing = [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], ]; - + // Verify segment data before clearing $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); @@ -46,10 +49,10 @@ public function test_should_clear_only_session_segment(): void // Cleared segment should only contain an empty array for flash data $this->assertEquals( - [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], $_SESSION[$session->getSegmentName()] ); - + // Items set directly in $_SESSION should still be present & not cleared $this->assertArrayHasKey('bar', $_SESSION); $this->assertEquals('foo', $_SESSION['bar']); @@ -61,20 +64,20 @@ public function test_should_clear_only_session_segment(): void public function test_should_clear_only_session_segment_when_session_started_outside_library(): void { session_start(); - + $_SESSION['bar'] = 'foo'; - + $session = new SegSession('da-segment'); $_SESSION['bar1'] = 'foo1'; - + $session->set('foo', 'bar'); - + $segmentBeforeClearing = [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], ]; - + // Verify segment data before clearing $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); @@ -82,10 +85,10 @@ public function test_should_clear_only_session_segment_when_session_started_outs // Cleared segment should only contain an empty array for flash data $this->assertEquals( - [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], $_SESSION[$session->getSegmentName()] ); - + // Items set directly in $_SESSION should still be present & not cleared $this->assertArrayHasKey('bar', $_SESSION); $this->assertArrayHasKey('bar1', $_SESSION); diff --git a/tests/ConstructorMethodSegmentedSessionTest.php b/tests/ConstructorMethodSegmentedSessionTest.php index 1da1293..13cbafa 100644 --- a/tests/ConstructorMethodSegmentedSessionTest.php +++ b/tests/ConstructorMethodSegmentedSessionTest.php @@ -28,7 +28,7 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ @@ -40,25 +40,25 @@ public function test_should_verify_segment_exists_in_session_and_session_options ]; $segmentName = 'da-segment'; $session = new SegSession($segmentName, null, $options); - + // Session was started outside the library. $this->assertTrue($session->isStarted()); - + // Check that the segment name was properly set in the session object $this->assertEquals($segmentName, $session->getSegmentName()); - + // Check that session options were not set in the constructor // since in this scenario the session was started outside the library. $this->assertEquals($options['name'], $session->getName()); $this->assertEquals($options['cookie_lifetime'], ini_get('session.cookie_lifetime')); - + // check that flash was initialized - $this->assertArrayHasKey($segmentName , $_SESSION); - $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []] , $_SESSION[$segmentName]); - $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST , $_SESSION[$segmentName]); - $this->assertEquals([] , $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); + $this->assertArrayHasKey($segmentName, $_SESSION); + $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $_SESSION[$segmentName]); + $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION[$segmentName]); + $this->assertEquals([], $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); } - + /** * @runInSeparateProcess */ @@ -71,26 +71,26 @@ public function test_should_verify_segment_exists_in_session_and_session_options ]; $segmentName = 'da-segment'; $session = new SegSession($segmentName, null, $options); - + // Session was started outside the library. $this->assertTrue($session->isStarted()); - + // Check that the segment name was properly set in the session object $this->assertEquals($segmentName, $session->getSegmentName()); - + // Check that session options were not set in the constructor // since in this scenario the session was started outside the library. $this->assertEquals('PHPSESSID', $session->getName()); $this->assertNotEquals($options['name'], $session->getName()); $this->assertNotEquals($options['cookie_lifetime'], ini_get('session.cookie_lifetime')); - + // check that flash was initialized - $this->assertArrayHasKey($segmentName , $_SESSION); - $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []] , $_SESSION[$segmentName]); - $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST , $_SESSION[$segmentName]); - $this->assertEquals([] , $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); + $this->assertArrayHasKey($segmentName, $_SESSION); + $this->assertEquals([SegSession::FLASH_DATA_FOR_NEXT_REQUEST => []], $_SESSION[$segmentName]); + $this->assertArrayHasKey(SegSession::FLASH_DATA_FOR_NEXT_REQUEST, $_SESSION[$segmentName]); + $this->assertEquals([], $_SESSION[$segmentName][SegSession::FLASH_DATA_FOR_NEXT_REQUEST]); } - + /** * @runInSeparateProcess */ @@ -99,11 +99,11 @@ public function test_should_verify_injected_session_object_was_properly_set(): v $segmentName = 'da-segment'; $storage = new Session(); $session = new SegSession($segmentName, $storage); - + // Injected $storage should be returned by $session->getStorage() $this->assertSame($storage, $session->getStorage()); } - + /** * @runInSeparateProcess */ @@ -113,13 +113,14 @@ public function test_should_verify_injected_session_object_was_properly_set_when $segmentName = 'da-segment'; $storage = new Session(); $session = new SegSession($segmentName, $storage); - + // Injected $storage should be returned by $session->getStorage() $this->assertSame($storage, $session->getStorage()); } - + /** * @runInSeparateProcess + * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function test_should_fail_with_empty_segment_name(): void { @@ -127,9 +128,10 @@ public function test_should_fail_with_empty_segment_name(): void $session = new SegSession(''); } - + /** * @runInSeparateProcess + * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ public function test_should_fail_with_wrong_options(): void { @@ -137,7 +139,10 @@ public function test_should_fail_with_wrong_options(): void $session = new SegSession('a', null, ['foo' => 'bar']); } - + + /** + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ public function test_should_fail_when_headers_sent(): void { // Because we are not running this in a separate process it will trigger the exception @@ -145,27 +150,28 @@ public function test_should_fail_when_headers_sent(): void $session = new SegSession('a'); } - + /** * @runInSeparateProcess + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function test_should_fail_when_session_not_startable(): void { $this->expectException(SessionNotStartedException::class); - $sessionStorageThatNeverStarts = new class('vlah') extends SegSession { - - public function start(array $options = []): bool + $unstartableSsStorage = new class ('vlah') extends SegSession { + public function start(array $options = []): bool { return false; } - + public function isStarted(): bool { return false; } }; - - $session = new SegSession('a', $sessionStorageThatNeverStarts); + + $session = new SegSession('a', $unstartableSsStorage); } } diff --git a/tests/DestroyMethodSegmentedSessionTest.php b/tests/DestroyMethodSegmentedSessionTest.php index be8d26e..f4b2ed2 100644 --- a/tests/DestroyMethodSegmentedSessionTest.php +++ b/tests/DestroyMethodSegmentedSessionTest.php @@ -31,26 +31,26 @@ public function test_should_clear_only_session_segment(): void $session = new SegSession('da-segment'); $_SESSION['bar'] = 'foo'; - + $session->set('foo', 'bar'); - - $segmentBeforeClearing = [ + + $segmBeforeClearing = [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], ]; - + // Verify segment data before clearing - $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); - + $this->assertEquals($segmBeforeClearing, $_SESSION[$session->getSegmentName()]); + // Verify that it always returns true $this->assertTrue($session->destroy()); // Cleared segment should only contain an empty array for flash data $this->assertEquals( - [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], $_SESSION[$session->getSegmentName()] ); - + // Items set directly in $_SESSION should still be present & not cleared $this->assertArrayHasKey('bar', $_SESSION); $this->assertEquals('foo', $_SESSION['bar']); @@ -62,32 +62,32 @@ public function test_should_clear_only_session_segment(): void public function test_should_clear_only_session_segment_when_session_started_outside_library(): void { session_start(); - + $_SESSION['bar'] = 'foo'; - + $session = new SegSession('da-segment'); $_SESSION['bar1'] = 'foo1'; - + $session->set('foo', 'bar'); - - $segmentBeforeClearing = [ + + $segBeforeClearing = [ 'foo' => 'bar', SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [], ]; - + // Verify segment data before clearing - $this->assertEquals($segmentBeforeClearing, $_SESSION[$session->getSegmentName()]); + $this->assertEquals($segBeforeClearing, $_SESSION[$session->getSegmentName()]); // Verify that it always returns true $this->assertTrue($session->destroy()); // Cleared segment should only contain an empty array for flash data $this->assertEquals( - [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], + [SegSession::FLASH_DATA_FOR_NEXT_REQUEST => [],], $_SESSION[$session->getSegmentName()] ); - + // Items set directly in $_SESSION should still be present & not cleared $this->assertArrayHasKey('bar', $_SESSION); $this->assertArrayHasKey('bar1', $_SESSION); diff --git a/tests/GetAllFromCurrentFlashMethodTest.php b/tests/GetAllFromCurrentFlashMethodTest.php index bbf0fc2..a4baaf3 100644 --- a/tests/GetAllFromCurrentFlashMethodTest.php +++ b/tests/GetAllFromCurrentFlashMethodTest.php @@ -22,41 +22,41 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_empty_array_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - + $this->assertEquals([], $session->getAllFromCurrentFlash()); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_before_and_after_setting_items_in_current_flash(): void { $session = new SegSession('da-segment'); - + $session->setInCurrentFlash('foo', 'bar'); $session->setInCurrentFlash('bar', 'foo'); - + $this->assertEquals( - ['foo'=>'bar', 'bar'=>'foo'], + ['foo' => 'bar', 'bar' => 'foo'], $session->getAllFromCurrentFlash() ); - + // these values should be available in the current flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should now be in the current flash for this instance $this->assertEquals( - ['foo2'=>'bar2', 'foo3'=>'bar3'], + ['foo2' => 'bar2', 'foo3' => 'bar3'], $session2->getAllFromCurrentFlash() ); } diff --git a/tests/GetAllFromNextFlashMethodTest.php b/tests/GetAllFromNextFlashMethodTest.php index 79cd079..9ef1af9 100644 --- a/tests/GetAllFromNextFlashMethodTest.php +++ b/tests/GetAllFromNextFlashMethodTest.php @@ -22,45 +22,45 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_empty_array_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - + $this->assertEquals([], $session->getAllFromNextFlash()); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_before_and_after_setting_items_in_next_flash(): void { $session = new SegSession('da-segment'); - + $session->setInNextFlash('foo', 'bar'); $session->setInNextFlash('bar', 'foo'); - + $this->assertEquals( - ['foo'=>'bar', 'bar'=>'foo'], + ['foo' => 'bar', 'bar' => 'foo'], $session->getAllFromNextFlash() ); - + // these values should not be available in the next flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should not be in the next flash for this instance $this->assertEquals([], $session2->getAllFromNextFlash()); - + // test the return [] scenario in getAllFromNextFlash $session2->getStorage()->clear(); // we clear the actual session, not just the segment $session2->getStorage()->destroy(); // we destroy the actual session, not just the segment - + $this->assertEquals([], $session2->getAllFromNextFlash()); } } diff --git a/tests/GetFromCurrentFlashMethodTest.php b/tests/GetFromCurrentFlashMethodTest.php index d3f5900..4aad141 100644 --- a/tests/GetFromCurrentFlashMethodTest.php +++ b/tests/GetFromCurrentFlashMethodTest.php @@ -22,48 +22,48 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_null_default_for_non_existent_attribute(): void { $session = new SegSession('da-segment'); - + $this->assertNull($session->getFromCurrentFlash('foo')); } - + /** * @runInSeparateProcess */ public function test_should_return_custom_default_for_non_existent_attribute(): void { $session = new SegSession('da-segment'); - + $this->assertEquals('bar', $session->getFromCurrentFlash('foo', 'bar')); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_after_setting_items_in_current_flash(): void { $session = new SegSession('da-segment'); - + $session->setInCurrentFlash('foo', 'bar'); $session->setInCurrentFlash('bar', 'foo'); - - $this->assertEquals('bar', $session->getFromCurrentFlash('foo')); + + $this->assertEquals('bar', $session->getFromCurrentFlash('foo')); $this->assertEquals('foo', $session->getFromCurrentFlash('bar')); - + // these values should be available in the current flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should now be in the current flash for this instance - $this->assertEquals('bar2', $session2->getFromCurrentFlash('foo2')); + $this->assertEquals('bar2', $session2->getFromCurrentFlash('foo2')); $this->assertEquals('bar3', $session2->getFromCurrentFlash('foo3')); } } diff --git a/tests/GetFromNextFlashMethodTest.php b/tests/GetFromNextFlashMethodTest.php index c4ca63a..6160010 100644 --- a/tests/GetFromNextFlashMethodTest.php +++ b/tests/GetFromNextFlashMethodTest.php @@ -22,48 +22,48 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_null_default_for_non_existent_attribute(): void { $session = new SegSession('da-segment'); - + $this->assertNull($session->getFromNextFlash('foo')); } - + /** * @runInSeparateProcess */ public function test_should_return_custom_default_for_non_existent_attribute(): void { $session = new SegSession('da-segment'); - + $this->assertEquals('bar', $session->getFromNextFlash('foo', 'bar')); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_after_setting_items_in_current_flash(): void { $session = new SegSession('da-segment'); - + $session->setInNextFlash('foo', 'bar'); $session->setInNextFlash('bar', 'foo'); - - $this->assertEquals('bar', $session->getFromNextFlash('foo')); + + $this->assertEquals('bar', $session->getFromNextFlash('foo')); $this->assertEquals('foo', $session->getFromNextFlash('bar')); - + // these values should NOT be available in the next flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should NOT be in the next flash for this instance - $this->assertNotEquals('bar2', $session2->getFromNextFlash('foo2')); + $this->assertNotEquals('bar2', $session2->getFromNextFlash('foo2')); $this->assertNotEquals('bar3', $session2->getFromNextFlash('foo3')); } } diff --git a/tests/GetIdMethodSegmentedSessionTest.php b/tests/GetIdMethodSegmentedSessionTest.php index 926822c..8b8d6ed 100644 --- a/tests/GetIdMethodSegmentedSessionTest.php +++ b/tests/GetIdMethodSegmentedSessionTest.php @@ -29,7 +29,7 @@ public function setUp(): void public function test_should_get_session_id(): void { $session = new SegSession('da-segment'); - + // Should have the same id as it's internal storage object $this->assertEquals($session->getId(), $session->getStorage()->getId()); } @@ -40,9 +40,9 @@ public function test_should_get_session_id(): void public function test_should_get_session_id_when_session_started_outside_library(): void { session_start(); - + $session = new SegSession('da-segment'); - + // Should have the same id as it's internal storage object $this->assertEquals($session->getId(), $session->getStorage()->getId()); } diff --git a/tests/GetMethodSegmentedSessionTest.php b/tests/GetMethodSegmentedSessionTest.php index e43cda5..f215fb3 100644 --- a/tests/GetMethodSegmentedSessionTest.php +++ b/tests/GetMethodSegmentedSessionTest.php @@ -33,7 +33,7 @@ public function test_should_get_attribute_if_exists(): void $session->set('foo', 'bar'); $this->assertEquals('bar', $session->get('foo')); - + // Verify that set item was inside the segment in $_SESSION and not directly in $_SESSION $this->assertArrayHasKey('foo', $_SESSION[$session->getSegmentName()]); $this->assertEquals('bar', $_SESSION[$session->getSegmentName()]['foo']); @@ -46,13 +46,13 @@ public function test_should_get_attribute_if_exists(): void public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void { session_start(); - + $session = new SegSession('da-segment'); $session->set('foo', 'bar'); $this->assertEquals('bar', $session->get('foo')); - + // Verify that set item was inside the segment in $_SESSION and not directly in $_SESSION $this->assertArrayHasKey('foo', $_SESSION[$session->getSegmentName()]); $this->assertEquals('bar', $_SESSION[$session->getSegmentName()]['foo']); @@ -75,7 +75,7 @@ public function test_should_get_default_value_if_not_exists(): void public function test_should_get_default_value_if_not_exists_when_session_started_outside_library(): void { session_start(); - + $session = new SegSession('da-segment'); $this->assertNull($session->get('foo')); @@ -97,7 +97,7 @@ public function test_should_get_custom_default_value_if_not_exists(): void public function test_should_get_custom_default_value_if_not_exists_when_session_started_outside_library(): void { session_start(); - + $session = new SegSession('da-segment'); $this->assertEquals('bar', $session->get('foo', 'bar')); @@ -111,7 +111,7 @@ public function test_should_not_get_attribute_defined_outside_library(): void session_start(); $_SESSION['foo'] = 'bar'; - + $session = new SegSession('da-segment'); $this->assertNull($session->get('foo')); diff --git a/tests/GetSegmentNameMethodTest.php b/tests/GetSegmentNameMethodTest.php index 13f062d..218550b 100644 --- a/tests/GetSegmentNameMethodTest.php +++ b/tests/GetSegmentNameMethodTest.php @@ -29,7 +29,7 @@ public function setUp(): void public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void { $session = new SegSession('da-segment'); - + $this->assertEquals('da-segment', $session->getSegmentName()); } } diff --git a/tests/GetStorageMethodTest.php b/tests/GetStorageMethodTest.php index 5edd832..9557b48 100644 --- a/tests/GetStorageMethodTest.php +++ b/tests/GetStorageMethodTest.php @@ -14,6 +14,7 @@ namespace Josantonius\Session\Tests; use PHPUnit\Framework\TestCase; +use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; class GetStorageMethodTest extends TestCase @@ -28,9 +29,9 @@ public function setUp(): void */ public function test_should_get_attribute_if_exists_when_session_started_outside_library(): void { - $storage = new \Josantonius\Session\Session(); + $storage = new Session(); $session = new SegSession('da-segment', $storage); - + $this->assertSame($storage, $session->getStorage()); } } diff --git a/tests/HasInCurrentFlashMethodTest.php b/tests/HasInCurrentFlashMethodTest.php index 8a6e37e..af190b5 100644 --- a/tests/HasInCurrentFlashMethodTest.php +++ b/tests/HasInCurrentFlashMethodTest.php @@ -22,36 +22,36 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_false_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - + $this->assertFalse($session->hasInCurrentFlash('foo')); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_before_and_after_setting_items_in_current_flash(): void { $session = new SegSession('da-segment'); - + $this->assertFalse($session->hasInCurrentFlash('foo')); - + $session->setInCurrentFlash('foo', 'bar'); - + $this->assertTrue($session->hasInCurrentFlash('foo')); - + // these values should be available in the current flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should now be in the current flash for this instance $this->assertTrue($session2->hasInCurrentFlash('foo2')); $this->assertTrue($session2->hasInCurrentFlash('foo3')); diff --git a/tests/HasInNextFlashMethodTest.php b/tests/HasInNextFlashMethodTest.php index 94a2730..92335f6 100644 --- a/tests/HasInNextFlashMethodTest.php +++ b/tests/HasInNextFlashMethodTest.php @@ -22,36 +22,36 @@ public function setUp(): void { parent::setUp(); } - + /** * @runInSeparateProcess */ public function test_should_return_false_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - + $this->assertFalse($session->hasInNextFlash('foo')); } - + /** * @runInSeparateProcess */ public function test_should_return_right_values_before_and_after_setting_items_in_next_flash(): void { $session = new SegSession('da-segment'); - + $this->assertFalse($session->hasInNextFlash('foo')); - + $session->setInNextFlash('foo', 'bar'); - + $this->assertTrue($session->hasInNextFlash('foo')); - + // these values should not be available in the next flash of the next instance below $session->setInNextFlash('foo2', 'bar2'); $session->setInNextFlash('foo3', 'bar3'); - + $session2 = new SegSession('da-segment'); - + // previous next flash items should not be in the next flash for this instance $this->assertFalse($session2->hasInNextFlash('foo2')); $this->assertFalse($session2->hasInNextFlash('foo3')); diff --git a/tests/HasMethodSegmentedSessionTest.php b/tests/HasMethodSegmentedSessionTest.php index f0d6a40..6bade0c 100644 --- a/tests/HasMethodSegmentedSessionTest.php +++ b/tests/HasMethodSegmentedSessionTest.php @@ -42,7 +42,7 @@ public function test_should_check_attribute_defined_outside_library(): void { session_start(); $_SESSION['foo'] = 'bar'; - + $session = new SegSession('da-segment'); $this->assertFalse($session->has('foo')); } diff --git a/tests/IsStartedMethodSegmentedSessionTest.php b/tests/IsStartedMethodSegmentedSessionTest.php index 1dfd125..0cde5ca 100644 --- a/tests/IsStartedMethodSegmentedSessionTest.php +++ b/tests/IsStartedMethodSegmentedSessionTest.php @@ -29,7 +29,7 @@ public function setUp(): void public function test_should_check_if_session_is_active(): void { $session = new SegSession('da-segment'); - + $this->assertTrue($session->isStarted()); // always auto-started $session->start(); @@ -44,7 +44,7 @@ public function test_should_check_if_session_is_active_when_session_started_outs { session_start(); $session = new SegSession('da-segment'); - + $this->assertTrue($session->isStarted()); // always auto-started $session->start(); diff --git a/tests/PullMethodSegmentedSessionTest.php b/tests/PullMethodSegmentedSessionTest.php index 13a5f10..1e0df02 100644 --- a/tests/PullMethodSegmentedSessionTest.php +++ b/tests/PullMethodSegmentedSessionTest.php @@ -38,16 +38,16 @@ public function test_should_pull_attribute_and_return_the_value_if_exists(): voi // pull above should not affect $_SESSION['foo'] $this->assertArrayHasKey('foo', $_SESSION); - + $session->set('foo', 'bar2'); // this will be stored in the segment - + // we are pulling the foo in the segment & not $_SESSION['foo'] $this->assertEquals('bar2', $session->pull('foo')); - + // foo set directly in $_SESSION remains unchanged $this->assertArrayHasKey('foo', $_SESSION); $this->assertEquals('bar', $_SESSION['foo']); - + // foo in segment has been removed $this->assertIsArray($_SESSION[$session->getSegmentName()]); $this->assertArrayNotHasKey('foo', $_SESSION[$session->getSegmentName()]); diff --git a/tests/RegenerateIdMethodSegmentedSessionTest.php b/tests/RegenerateIdMethodSegmentedSessionTest.php index 82d72ca..27d1f39 100644 --- a/tests/RegenerateIdMethodSegmentedSessionTest.php +++ b/tests/RegenerateIdMethodSegmentedSessionTest.php @@ -34,7 +34,7 @@ public function test_should_regenerate_session_id_without_deleting_old_session() $this->assertTrue($session->regenerateId()); $this->assertNotEquals($sessionId, session_id()); - + $sessionId2 = session_id(); $this->assertTrue($session->regenerateId()); diff --git a/tests/RemoveFromFlashMethodTest.php b/tests/RemoveFromFlashMethodTest.php index 3a6e1b2..6e8274c 100644 --- a/tests/RemoveFromFlashMethodTest.php +++ b/tests/RemoveFromFlashMethodTest.php @@ -14,6 +14,7 @@ namespace Josantonius\Session\Tests; use PHPUnit\Framework\TestCase; +use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; class RemoveFromFlashMethodTest extends TestCase @@ -28,43 +29,43 @@ public function setUp(): void */ public function test_should_remove_set_attributes(): void { - $storage = new \Josantonius\Session\Session(); + $storage = new Session(); $session = new SegSession('da-segment', $storage); - + $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); - + $session->setInNextFlash('foo-next-1', 'val-in-next-1'); $session->setInNextFlash('foo-next-2', 'val-in-next-2'); - + $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); $this->assertTrue($session->hasInNextFlash('foo-next-1')); $this->assertTrue($session->hasInNextFlash('foo-next-2')); - + $session->removeFromFlash('foo-current-1', true); - + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); $this->assertTrue($session->hasInNextFlash('foo-next-1')); $this->assertTrue($session->hasInNextFlash('foo-next-2')); - + $session->removeFromFlash('foo-current-2', true); - + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); $this->assertTrue($session->hasInNextFlash('foo-next-1')); $this->assertTrue($session->hasInNextFlash('foo-next-2')); - + $session->removeFromFlash('foo-next-1', true, true); - + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); $this->assertFalse($session->hasInNextFlash('foo-next-1')); $this->assertTrue($session->hasInNextFlash('foo-next-2')); - + $session->removeFromFlash('foo-next-2', true, true); - + $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); $this->assertFalse($session->hasInNextFlash('foo-next-1')); diff --git a/tests/RemoveMethodSegmentedSessionTest.php b/tests/RemoveMethodSegmentedSessionTest.php index 201cbf2..63ec7af 100644 --- a/tests/RemoveMethodSegmentedSessionTest.php +++ b/tests/RemoveMethodSegmentedSessionTest.php @@ -29,14 +29,14 @@ public function setUp(): void public function test_should_remove_attribute_even_if_not_exist(): void { $session = new SegSession('da-segment'); - - $originalSegmentContent = $session->all(); + + $originalSegContent = $session->all(); $session->remove('foo'); - $this->assertEquals($originalSegmentContent, $session->all()); + $this->assertEquals($originalSegContent, $session->all()); } - + /** * @runInSeparateProcess */ @@ -51,17 +51,17 @@ public function test_should_remove_attribute_if_exist(): void // Remove above should not affect $_SESSION['foo'] $this->assertArrayHasKey('foo', $_SESSION); $this->assertEquals('bar', $_SESSION['foo']); - + // Set foo in the segment $session->set('foo', 'bar2'); - + // foo should be in segment $this->assertTrue($session->has('foo')); $this->assertEquals('bar2', $session->get('foo')); - + $session->remove('foo'); // foo in the segment will be removed $this->assertFalse($session->has('foo')); - + // $_SESSION['foo'] should still remain unaffected $this->assertArrayHasKey('foo', $_SESSION); $this->assertEquals('bar', $_SESSION['foo']); diff --git a/tests/ReplaceMethodSegmentedSessionTest.php b/tests/ReplaceMethodSegmentedSessionTest.php index 4733df6..947a027 100644 --- a/tests/ReplaceMethodSegmentedSessionTest.php +++ b/tests/ReplaceMethodSegmentedSessionTest.php @@ -34,18 +34,18 @@ public function test_should_add_attributes_if_not_exist(): void // foo has not yet been set in the segment $this->assertFalse($session->has('foo')); - + // bar should not be in the segment $this->assertFalse($session->has('bar')); - + $session->replace(['foo' => 'bar']); - + // foo was just set via the call to replace above $this->assertTrue($session->has('foo')); // $_SESSION['bar'] should be untouched $this->assertEquals('foo', $_SESSION['bar']); - + // assert that replaced value is present $this->assertEquals('bar', $session->get('foo')); } @@ -56,15 +56,15 @@ public function test_should_add_attributes_if_not_exist(): void public function test_should_replace_attributes_if_exist(): void { $session = new SegSession('da-segment'); - + $session->set('foo', 'bar'); $session->set('bar', 'foo'); $session->replace(['foo' => 'val']); - + $this->assertEquals('val', $session->get('foo')); $this->assertEquals('foo', $session->get('bar')); - + $this->assertArrayNotHasKey('foo', $_SESSION); $this->assertArrayNotHasKey('bar', $_SESSION); } diff --git a/tests/SetIdMethodSegmentedSessionTest.php b/tests/SetIdMethodSegmentedSessionTest.php index c1aa18e..50ceac0 100644 --- a/tests/SetIdMethodSegmentedSessionTest.php +++ b/tests/SetIdMethodSegmentedSessionTest.php @@ -30,7 +30,7 @@ public function test_should_not_set_session_id_since_session_is_auto_started(): { $session = new SegSession('da-segment'); $originalId = $session->getId(); - + $session->setId('foo'); $this->assertEquals($originalId, session_id()); diff --git a/tests/SetInCurrentFlashMethodTest.php b/tests/SetInCurrentFlashMethodTest.php index e7852fa..0f20221 100644 --- a/tests/SetInCurrentFlashMethodTest.php +++ b/tests/SetInCurrentFlashMethodTest.php @@ -14,6 +14,7 @@ namespace Josantonius\Session\Tests; use PHPUnit\Framework\TestCase; +use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; class SetInCurrentFlashMethodTest extends TestCase @@ -28,15 +29,15 @@ public function setUp(): void */ public function test_should_correctly_set_attributes(): void { - $storage = new \Josantonius\Session\Session(); + $storage = new Session(); $session = new SegSession('da-segment', $storage); - + $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); - + $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); - + $this->assertEquals('val-in-current-1', $session->getFromCurrentFlash('foo-current-1')); $this->assertEquals('val-in-current-2', $session->getFromCurrentFlash('foo-current-2')); } diff --git a/tests/SetInNextFlashMethodTest.php b/tests/SetInNextFlashMethodTest.php index f7d6946..163dc69 100644 --- a/tests/SetInNextFlashMethodTest.php +++ b/tests/SetInNextFlashMethodTest.php @@ -14,6 +14,7 @@ namespace Josantonius\Session\Tests; use PHPUnit\Framework\TestCase; +use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; class SetInNextFlashMethodTest extends TestCase @@ -28,15 +29,15 @@ public function setUp(): void */ public function test_should_correctly_set_attributes(): void { - $storage = new \Josantonius\Session\Session(); + $storage = new Session(); $session = new SegSession('da-segment', $storage); - + $session->setInNextFlash('foo-next-1', 'val-in-next-1'); $session->setInNextFlash('foo-next-2', 'val-in-next-2'); - + $this->assertTrue($session->hasInNextFlash('foo-next-1')); $this->assertTrue($session->hasInNextFlash('foo-next-2')); - + $this->assertEquals('val-in-next-1', $session->getFromNextFlash('foo-next-1')); $this->assertEquals('val-in-next-2', $session->getFromNextFlash('foo-next-2')); } diff --git a/tests/SetNameMethodSegmentedSessionTest.php b/tests/SetNameMethodSegmentedSessionTest.php index d1001a8..01b6747 100644 --- a/tests/SetNameMethodSegmentedSessionTest.php +++ b/tests/SetNameMethodSegmentedSessionTest.php @@ -30,7 +30,7 @@ public function test_should_not_set_session_name_since_session_is_auto_started() { $session = new SegSession('da-segment'); // auto-starts session $originalSessionName = $session->getName(); - + $session->setName('foo'); $this->assertEquals($originalSessionName, session_name()); diff --git a/tests/StartMethodSegmentedSessionTest.php b/tests/StartMethodSegmentedSessionTest.php index 39ba890..1d1965a 100644 --- a/tests/StartMethodSegmentedSessionTest.php +++ b/tests/StartMethodSegmentedSessionTest.php @@ -29,7 +29,7 @@ public function setUp(): void public function test_session_should_always_be_started_since_it_gets_auto_started_in_constructor(): void { $session = new SegSession('da-segment'); - + $this->assertTrue($session->start()); $this->assertEquals(PHP_SESSION_ACTIVE, session_status()); diff --git a/tests/StartMethodTest.php b/tests/StartMethodTest.php index fe8cf74..b061a3c 100644 --- a/tests/StartMethodTest.php +++ b/tests/StartMethodTest.php @@ -48,7 +48,7 @@ public function test_should_start_session(): void */ public function test_should_accept_options(): void { - $this->session->start(['cookie_lifetime' => 8000, 'name'=>'boooo']); + $this->session->start(['cookie_lifetime' => 8000, 'name' => 'boooo']); $this->assertEquals(8000, ini_get('session.cookie_lifetime')); $this->assertEquals('boooo', $this->session->getName()); From 3a72e4ae2129864cfe859da7e408c8ee4ab72c73 Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 10:26:50 -0600 Subject: [PATCH 11/19] Tweaks --- .github/workflows/ci.yml | 6 +++--- src/FlashableSessionSegment.php | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1318904..96deb7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: name: 'Coding style' steps: - name: 'Checkout' - uses: 'actions/checkout@v3' + uses: 'actions/checkout@v4' - name: 'Setup PHP' uses: 'shivammathur/setup-php@v2' @@ -51,7 +51,7 @@ jobs: - '8.3' steps: - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: 'Setup PHP' uses: 'shivammathur/setup-php@v2' @@ -73,7 +73,7 @@ jobs: name: 'Code Coverage' steps: - name: 'Checkout' - uses: 'actions/checkout@v3' + uses: 'actions/checkout@v4' - name: 'Setup PHP' uses: 'shivammathur/setup-php@v2' diff --git a/src/FlashableSessionSegment.php b/src/FlashableSessionSegment.php index 191f081..ecfb2ed 100644 --- a/src/FlashableSessionSegment.php +++ b/src/FlashableSessionSegment.php @@ -112,7 +112,9 @@ class FlashableSessionSegment implements SessionInterface * * @param array $options session start configuration options that will be used to * automatically start a new session or resume existing session - * when an instance of this class is created + * when an instance of this class is created. It must contain + * the same valid options acceptable by + * https://www.php.net/manual/en/function.session-start.php * * @throws \Josantonius\Session\Exceptions\EmptySegmentNameException * @throws \Josantonius\Session\Exceptions\HeadersSentException @@ -532,7 +534,8 @@ public function removeFromFlash( } /** - * Get all items in the flash storage for an instance of this class (i.e. in $this->currentFlashData) + * Get all items in the flash storage for an instance of this class + * (i.e. in $this->currentFlashData) */ public function getAllFromCurrentFlash(): array { From 5954dfdcaa094a6b088a8bcd5c687050d51941bc Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 16:27:33 -0600 Subject: [PATCH 12/19] Refactorings --- src/FlashableSessionSegment.php | 114 +++++++++--------- ...p => GetAllFromObjectsFlashMethodTest.php} | 16 +-- ...p => GetAllFromSessionFlashMethodTest.php} | 20 +-- ....php => GetFromObjectsFlashMethodTest.php} | 22 ++-- ....php => GetFromSessionFlashMethodTest.php} | 22 ++-- ...st.php => HasInObjectsFlashMethodTest.php} | 18 +-- ...st.php => HasInSessionFlashMethodTest.php} | 18 +-- tests/RemoveFromFlashMethodTest.php | 48 ++++---- ...st.php => SetInObjectsFlashMethodTest.php} | 14 +-- ...st.php => SetInSessionFlashMethodTest.php} | 14 +-- 10 files changed, 154 insertions(+), 152 deletions(-) rename tests/{GetAllFromCurrentFlashMethodTest.php => GetAllFromObjectsFlashMethodTest.php} (76%) rename tests/{GetAllFromNextFlashMethodTest.php => GetAllFromSessionFlashMethodTest.php} (71%) rename tests/{GetFromCurrentFlashMethodTest.php => GetFromObjectsFlashMethodTest.php} (69%) rename tests/{GetFromNextFlashMethodTest.php => GetFromSessionFlashMethodTest.php} (65%) rename tests/{HasInCurrentFlashMethodTest.php => HasInObjectsFlashMethodTest.php} (69%) rename tests/{HasInNextFlashMethodTest.php => HasInSessionFlashMethodTest.php} (68%) rename tests/{SetInCurrentFlashMethodTest.php => SetInObjectsFlashMethodTest.php} (72%) rename tests/{SetInNextFlashMethodTest.php => SetInSessionFlashMethodTest.php} (61%) diff --git a/src/FlashableSessionSegment.php b/src/FlashableSessionSegment.php index ecfb2ed..f5e0da8 100644 --- a/src/FlashableSessionSegment.php +++ b/src/FlashableSessionSegment.php @@ -32,17 +32,17 @@ class FlashableSessionSegment implements SessionInterface protected SessionInterface $storage; /** - * Flash data for current request is stored here. + * Flash data previously stored in session is copied here. * * It must be copied from * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] * every time an instance of this class is created. * * If $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - * isn't set, this $this->currentFlashData should maintain + * isn't set, this $this->objectsFlashData should maintain * the default value of empty array. */ - protected array $currentFlashData = []; + protected array $objectsFlashData = []; /** * When different libraries and projects try to modify data with the same keys @@ -112,8 +112,8 @@ class FlashableSessionSegment implements SessionInterface * * @param array $options session start configuration options that will be used to * automatically start a new session or resume existing session - * when an instance of this class is created. It must contain - * the same valid options acceptable by + * when an instance of this class is created. It must contain + * the same valid options acceptable by * https://www.php.net/manual/en/function.session-start.php * * @throws \Josantonius\Session\Exceptions\EmptySegmentNameException @@ -141,7 +141,7 @@ public function __construct(string $segmentName, ?SessionInterface $storage = nu } $this->initializeOrReinitialize(); - $this->moveNextFlashToCurrentFlash(); + $this->moveSessionFlashToObjectsFlash(); } protected function initializeOrReinitialize(): void @@ -160,27 +160,21 @@ protected function initializeOrReinitialize(): void } } - protected function moveNextFlashToCurrentFlash(): void + protected function moveSessionFlashToObjectsFlash(): void { if ($this->isStarted()) { /////////////////////////////////////////////////////////////////////////// // Flash update logic: We update the flash data by copying the existing // flash data stored in // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // to $this->currentFlashData & then reset + // to $this->objectsFlashData & then reset // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] // to an empty array. - // - // Flash data inside $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // will only be accessible in the next request - // - // Flash data copied from $_SESSION into $this->currentFlashData from the previous - // request is flash data that will be accessible in the current request. /////////////////////////////////////////////////////////////////////////// - $this->currentFlashData = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; + $this->objectsFlashData = $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] ?? []; // Reset the flash data in session to an empty array - // but we still have the existing flash data in $this->currentFlashData + // but we still have the existing flash data in $this->objectsFlashData $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } @@ -334,7 +328,7 @@ public function clear(): void $_SESSION[$this->segmentName] = []; // Reset the flash data in session segment to an empty arrays - $this->currentFlashData = []; + $this->objectsFlashData = []; $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] = []; } } @@ -410,23 +404,23 @@ public function isStarted(): bool /** * Sets an item with the specified $key in the flash storage for an instance - * of this class (i.e. $this->currentFlashData). + * of this class (i.e. $this->objectsFlashData). * * The item will only be retrievable from the instance of this class it was set in. */ - public function setInCurrentFlash(string $key, mixed $value): void + public function setInObjectsFlash(string $key, mixed $value): void { - $this->currentFlashData[$key] = $value; + $this->objectsFlashData[$key] = $value; } /** * Sets an item with the specified $key in the flash storage located in * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] * - * The item will only be retrievable by calling the getFromCurrentFlash + * The item will only be retrievable by calling getFromObjectsFlash * on the next instance of this class created with the same segment name. */ - public function setInNextFlash(string $key, mixed $value): void + public function setInSessionFlash(string $key, mixed $value): void { $canSet = $this->isStarted() && isset($_SESSION[$this->segmentName]) @@ -440,32 +434,36 @@ public function setInNextFlash(string $key, mixed $value): void /** * Check if item with specified $key exists in the flash storage for - * an instance of this class (i.e. in $this->currentFlashData). + * an instance of this class (i.e. in $this->objectsFlashData). */ - public function hasInCurrentFlash(string $key): bool + public function hasInObjectsFlash(string $key): bool { //////////////////////////////////////////////////////////////////////// - // Accessible flash data for current request is always inside - // $this->currentFlashData + // Flash data previously stored in $_SESSION is always loaded into + // $this->objectsFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // contains flash data for the next request + // contains flash data that will be loaded into $this->objectsFlashData + // for the next instance of this class with the same segmentName as this + // instance //////////////////////////////////////////////////////////////////////// - return \array_key_exists($key, $this->currentFlashData); + return \array_key_exists($key, $this->objectsFlashData); } /** * Check if item with specified $key exists in * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]. */ - public function hasInNextFlash(string $key): bool + public function hasInSessionFlash(string $key): bool { //////////////////////////////////////////////////////////////////////// - // Accessible flash data for current request is always inside - // $this->currentFlashData + // Flash data previously stored in $_SESSION is always loaded into + // $this->objectsFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // contains flash data for the next request + // contains flash data that will be loaded into $this->objectsFlashData + // for the next instance of this class with the same segmentName as this + // instance //////////////////////////////////////////////////////////////////////// return ( // Check in this session object's segmented session data @@ -479,18 +477,20 @@ public function hasInNextFlash(string $key): bool /** * Get an item with the specified $key from the flash storage for an instance - * of this class (i.e. $this->currentFlashData) if it exists or return $default. + * of this class (i.e. $this->objectsFlashData) if it exists or return $default. */ - public function getFromCurrentFlash(string $key, mixed $default = null): mixed + public function getFromObjectsFlash(string $key, mixed $default = null): mixed { //////////////////////////////////////////////////////////////////////// - // Accessible flash data for current request is always inside - // $this->currentFlashData + // Flash data previously stored in $_SESSION is always loaded into + // $this->objectsFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // contains flash data for the next request + // contains flash data that will be loaded into $this->objectsFlashData + // for the next instance of this class with the same segmentName as this + // instance //////////////////////////////////////////////////////////////////////// - return ($this->isStarted() && $this->hasInCurrentFlash($key)) ? $this->currentFlashData[$key] : $default; + return ($this->isStarted() && $this->hasInObjectsFlash($key)) ? $this->objectsFlashData[$key] : $default; } /** @@ -499,53 +499,55 @@ public function getFromCurrentFlash(string $key, mixed $default = null): mixed * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] * if it exists or return $default. */ - public function getFromNextFlash(string $key, mixed $default = null): mixed + public function getFromSessionFlash(string $key, mixed $default = null): mixed { - return ($this->isStarted() && $this->hasInNextFlash($key)) + return ($this->isStarted() && $this->hasInSessionFlash($key)) ? $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key] : $default; } /** * Remove an item with the specified $key (if it exists) from: - * - the flash storage for an instance of this class (i.e. in $this->currentFlashData), if $for_current_request === true - * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], if $for_next_request === true + * - the flash storage for an instance of this class (i.e. in $this->objectsFlashData), if $fromObjectsFlash === true + * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], if $fromSessionFlash === true */ public function removeFromFlash( string $key, - bool $forCurrentRequest = true, - bool $forNextRequest = false + bool $fromObjectsFlash = true, + bool $fromSessionFlash = false ): void { //////////////////////////////////////////////////////////////////////// - // Accessible flash data for current request is always inside - // $this->currentFlashData + // Flash data previously stored in $_SESSION is always loaded into + // $this->objectsFlashData // while // $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] - // contains flash data for the next request + // contains flash data that will be loaded into $this->objectsFlashData + // for the next instance of this class with the same segmentName as this + // instance //////////////////////////////////////////////////////////////////////// - if ($forCurrentRequest && $this->hasInCurrentFlash($key)) { - unset($this->currentFlashData[$key]); + if ($fromObjectsFlash && $this->hasInObjectsFlash($key)) { + unset($this->objectsFlashData[$key]); } - if ($forNextRequest && $this->isStarted() && $this->hasInNextFlash($key)) { + if ($fromSessionFlash && $this->isStarted() && $this->hasInSessionFlash($key)) { // Remove it from this session object's segmented session data unset($_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST][$key]); - } // if($for_next_request) + } } /** - * Get all items in the flash storage for an instance of this class - * (i.e. in $this->currentFlashData) + * Get all items in the flash storage for an instance of this class + * (i.e. in $this->objectsFlashData) */ - public function getAllFromCurrentFlash(): array + public function getAllFromObjectsFlash(): array { - return $this->currentFlashData; + return $this->objectsFlashData; } /** * Get all items in $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] */ - public function getAllFromNextFlash(): array + public function getAllFromSessionFlash(): array { $canGet = $this->isStarted() && isset($_SESSION[$this->segmentName]) diff --git a/tests/GetAllFromCurrentFlashMethodTest.php b/tests/GetAllFromObjectsFlashMethodTest.php similarity index 76% rename from tests/GetAllFromCurrentFlashMethodTest.php rename to tests/GetAllFromObjectsFlashMethodTest.php index a4baaf3..955a25c 100644 --- a/tests/GetAllFromCurrentFlashMethodTest.php +++ b/tests/GetAllFromObjectsFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class GetAllFromCurrentFlashMethodTest extends TestCase +class GetAllFromObjectsFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_empty_array_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - $this->assertEquals([], $session->getAllFromCurrentFlash()); + $this->assertEquals([], $session->getAllFromObjectsFlash()); } /** @@ -40,24 +40,24 @@ public function test_should_return_right_values_before_and_after_setting_items_i { $session = new SegSession('da-segment'); - $session->setInCurrentFlash('foo', 'bar'); - $session->setInCurrentFlash('bar', 'foo'); + $session->setInObjectsFlash('foo', 'bar'); + $session->setInObjectsFlash('bar', 'foo'); $this->assertEquals( ['foo' => 'bar', 'bar' => 'foo'], - $session->getAllFromCurrentFlash() + $session->getAllFromObjectsFlash() ); // these values should be available in the current flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should now be in the current flash for this instance $this->assertEquals( ['foo2' => 'bar2', 'foo3' => 'bar3'], - $session2->getAllFromCurrentFlash() + $session2->getAllFromObjectsFlash() ); } } diff --git a/tests/GetAllFromNextFlashMethodTest.php b/tests/GetAllFromSessionFlashMethodTest.php similarity index 71% rename from tests/GetAllFromNextFlashMethodTest.php rename to tests/GetAllFromSessionFlashMethodTest.php index 9ef1af9..ca94e06 100644 --- a/tests/GetAllFromNextFlashMethodTest.php +++ b/tests/GetAllFromSessionFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class GetAllFromNextFlashMethodTest extends TestCase +class GetAllFromSessionFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_empty_array_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - $this->assertEquals([], $session->getAllFromNextFlash()); + $this->assertEquals([], $session->getAllFromSessionFlash()); } /** @@ -40,27 +40,27 @@ public function test_should_return_right_values_before_and_after_setting_items_i { $session = new SegSession('da-segment'); - $session->setInNextFlash('foo', 'bar'); - $session->setInNextFlash('bar', 'foo'); + $session->setInSessionFlash('foo', 'bar'); + $session->setInSessionFlash('bar', 'foo'); $this->assertEquals( ['foo' => 'bar', 'bar' => 'foo'], - $session->getAllFromNextFlash() + $session->getAllFromSessionFlash() ); // these values should not be available in the next flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should not be in the next flash for this instance - $this->assertEquals([], $session2->getAllFromNextFlash()); + $this->assertEquals([], $session2->getAllFromSessionFlash()); - // test the return [] scenario in getAllFromNextFlash + // test the return [] scenario in getAllFromSessionFlash $session2->getStorage()->clear(); // we clear the actual session, not just the segment $session2->getStorage()->destroy(); // we destroy the actual session, not just the segment - $this->assertEquals([], $session2->getAllFromNextFlash()); + $this->assertEquals([], $session2->getAllFromSessionFlash()); } } diff --git a/tests/GetFromCurrentFlashMethodTest.php b/tests/GetFromObjectsFlashMethodTest.php similarity index 69% rename from tests/GetFromCurrentFlashMethodTest.php rename to tests/GetFromObjectsFlashMethodTest.php index 4aad141..4c9cf09 100644 --- a/tests/GetFromCurrentFlashMethodTest.php +++ b/tests/GetFromObjectsFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class GetFromCurrentFlashMethodTest extends TestCase +class GetFromObjectsFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_null_default_for_non_existent_attribute(): vo { $session = new SegSession('da-segment'); - $this->assertNull($session->getFromCurrentFlash('foo')); + $this->assertNull($session->getFromObjectsFlash('foo')); } /** @@ -40,7 +40,7 @@ public function test_should_return_custom_default_for_non_existent_attribute(): { $session = new SegSession('da-segment'); - $this->assertEquals('bar', $session->getFromCurrentFlash('foo', 'bar')); + $this->assertEquals('bar', $session->getFromObjectsFlash('foo', 'bar')); } /** @@ -50,20 +50,20 @@ public function test_should_return_right_values_after_setting_items_in_current_f { $session = new SegSession('da-segment'); - $session->setInCurrentFlash('foo', 'bar'); - $session->setInCurrentFlash('bar', 'foo'); + $session->setInObjectsFlash('foo', 'bar'); + $session->setInObjectsFlash('bar', 'foo'); - $this->assertEquals('bar', $session->getFromCurrentFlash('foo')); - $this->assertEquals('foo', $session->getFromCurrentFlash('bar')); + $this->assertEquals('bar', $session->getFromObjectsFlash('foo')); + $this->assertEquals('foo', $session->getFromObjectsFlash('bar')); // these values should be available in the current flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should now be in the current flash for this instance - $this->assertEquals('bar2', $session2->getFromCurrentFlash('foo2')); - $this->assertEquals('bar3', $session2->getFromCurrentFlash('foo3')); + $this->assertEquals('bar2', $session2->getFromObjectsFlash('foo2')); + $this->assertEquals('bar3', $session2->getFromObjectsFlash('foo3')); } } diff --git a/tests/GetFromNextFlashMethodTest.php b/tests/GetFromSessionFlashMethodTest.php similarity index 65% rename from tests/GetFromNextFlashMethodTest.php rename to tests/GetFromSessionFlashMethodTest.php index 6160010..03ca176 100644 --- a/tests/GetFromNextFlashMethodTest.php +++ b/tests/GetFromSessionFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class GetFromNextFlashMethodTest extends TestCase +class GetFromSessionFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_null_default_for_non_existent_attribute(): vo { $session = new SegSession('da-segment'); - $this->assertNull($session->getFromNextFlash('foo')); + $this->assertNull($session->getFromSessionFlash('foo')); } /** @@ -40,7 +40,7 @@ public function test_should_return_custom_default_for_non_existent_attribute(): { $session = new SegSession('da-segment'); - $this->assertEquals('bar', $session->getFromNextFlash('foo', 'bar')); + $this->assertEquals('bar', $session->getFromSessionFlash('foo', 'bar')); } /** @@ -50,20 +50,20 @@ public function test_should_return_right_values_after_setting_items_in_current_f { $session = new SegSession('da-segment'); - $session->setInNextFlash('foo', 'bar'); - $session->setInNextFlash('bar', 'foo'); + $session->setInSessionFlash('foo', 'bar'); + $session->setInSessionFlash('bar', 'foo'); - $this->assertEquals('bar', $session->getFromNextFlash('foo')); - $this->assertEquals('foo', $session->getFromNextFlash('bar')); + $this->assertEquals('bar', $session->getFromSessionFlash('foo')); + $this->assertEquals('foo', $session->getFromSessionFlash('bar')); // these values should NOT be available in the next flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should NOT be in the next flash for this instance - $this->assertNotEquals('bar2', $session2->getFromNextFlash('foo2')); - $this->assertNotEquals('bar3', $session2->getFromNextFlash('foo3')); + $this->assertNotEquals('bar2', $session2->getFromSessionFlash('foo2')); + $this->assertNotEquals('bar3', $session2->getFromSessionFlash('foo3')); } } diff --git a/tests/HasInCurrentFlashMethodTest.php b/tests/HasInObjectsFlashMethodTest.php similarity index 69% rename from tests/HasInCurrentFlashMethodTest.php rename to tests/HasInObjectsFlashMethodTest.php index af190b5..4ec4aec 100644 --- a/tests/HasInCurrentFlashMethodTest.php +++ b/tests/HasInObjectsFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class HasInCurrentFlashMethodTest extends TestCase +class HasInObjectsFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_false_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - $this->assertFalse($session->hasInCurrentFlash('foo')); + $this->assertFalse($session->hasInObjectsFlash('foo')); } /** @@ -40,20 +40,20 @@ public function test_should_return_right_values_before_and_after_setting_items_i { $session = new SegSession('da-segment'); - $this->assertFalse($session->hasInCurrentFlash('foo')); + $this->assertFalse($session->hasInObjectsFlash('foo')); - $session->setInCurrentFlash('foo', 'bar'); + $session->setInObjectsFlash('foo', 'bar'); - $this->assertTrue($session->hasInCurrentFlash('foo')); + $this->assertTrue($session->hasInObjectsFlash('foo')); // these values should be available in the current flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should now be in the current flash for this instance - $this->assertTrue($session2->hasInCurrentFlash('foo2')); - $this->assertTrue($session2->hasInCurrentFlash('foo3')); + $this->assertTrue($session2->hasInObjectsFlash('foo2')); + $this->assertTrue($session2->hasInObjectsFlash('foo3')); } } diff --git a/tests/HasInNextFlashMethodTest.php b/tests/HasInSessionFlashMethodTest.php similarity index 68% rename from tests/HasInNextFlashMethodTest.php rename to tests/HasInSessionFlashMethodTest.php index 92335f6..d65cd5f 100644 --- a/tests/HasInNextFlashMethodTest.php +++ b/tests/HasInSessionFlashMethodTest.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestCase; use Josantonius\Session\FlashableSessionSegment as SegSession; -class HasInNextFlashMethodTest extends TestCase +class HasInSessionFlashMethodTest extends TestCase { public function setUp(): void { @@ -30,7 +30,7 @@ public function test_should_return_false_on_newly_created_segment(): void { $session = new SegSession('da-segment'); - $this->assertFalse($session->hasInNextFlash('foo')); + $this->assertFalse($session->hasInSessionFlash('foo')); } /** @@ -40,20 +40,20 @@ public function test_should_return_right_values_before_and_after_setting_items_i { $session = new SegSession('da-segment'); - $this->assertFalse($session->hasInNextFlash('foo')); + $this->assertFalse($session->hasInSessionFlash('foo')); - $session->setInNextFlash('foo', 'bar'); + $session->setInSessionFlash('foo', 'bar'); - $this->assertTrue($session->hasInNextFlash('foo')); + $this->assertTrue($session->hasInSessionFlash('foo')); // these values should not be available in the next flash of the next instance below - $session->setInNextFlash('foo2', 'bar2'); - $session->setInNextFlash('foo3', 'bar3'); + $session->setInSessionFlash('foo2', 'bar2'); + $session->setInSessionFlash('foo3', 'bar3'); $session2 = new SegSession('da-segment'); // previous next flash items should not be in the next flash for this instance - $this->assertFalse($session2->hasInNextFlash('foo2')); - $this->assertFalse($session2->hasInNextFlash('foo3')); + $this->assertFalse($session2->hasInSessionFlash('foo2')); + $this->assertFalse($session2->hasInSessionFlash('foo3')); } } diff --git a/tests/RemoveFromFlashMethodTest.php b/tests/RemoveFromFlashMethodTest.php index 6e8274c..51190a8 100644 --- a/tests/RemoveFromFlashMethodTest.php +++ b/tests/RemoveFromFlashMethodTest.php @@ -32,43 +32,43 @@ public function test_should_remove_set_attributes(): void $storage = new Session(); $session = new SegSession('da-segment', $storage); - $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); - $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); + $session->setInObjectsFlash('foo-current-1', 'val-in-current-1'); + $session->setInObjectsFlash('foo-current-2', 'val-in-current-2'); - $session->setInNextFlash('foo-next-1', 'val-in-next-1'); - $session->setInNextFlash('foo-next-2', 'val-in-next-2'); + $session->setInSessionFlash('foo-next-1', 'val-in-next-1'); + $session->setInSessionFlash('foo-next-2', 'val-in-next-2'); - $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); - $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); - $this->assertTrue($session->hasInNextFlash('foo-next-1')); - $this->assertTrue($session->hasInNextFlash('foo-next-2')); + $this->assertTrue($session->hasInObjectsFlash('foo-current-1')); + $this->assertTrue($session->hasInObjectsFlash('foo-current-2')); + $this->assertTrue($session->hasInSessionFlash('foo-next-1')); + $this->assertTrue($session->hasInSessionFlash('foo-next-2')); $session->removeFromFlash('foo-current-1', true); - $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); - $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); - $this->assertTrue($session->hasInNextFlash('foo-next-1')); - $this->assertTrue($session->hasInNextFlash('foo-next-2')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-1')); + $this->assertTrue($session->hasInObjectsFlash('foo-current-2')); + $this->assertTrue($session->hasInSessionFlash('foo-next-1')); + $this->assertTrue($session->hasInSessionFlash('foo-next-2')); $session->removeFromFlash('foo-current-2', true); - $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); - $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); - $this->assertTrue($session->hasInNextFlash('foo-next-1')); - $this->assertTrue($session->hasInNextFlash('foo-next-2')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-1')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-2')); + $this->assertTrue($session->hasInSessionFlash('foo-next-1')); + $this->assertTrue($session->hasInSessionFlash('foo-next-2')); $session->removeFromFlash('foo-next-1', true, true); - $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); - $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); - $this->assertFalse($session->hasInNextFlash('foo-next-1')); - $this->assertTrue($session->hasInNextFlash('foo-next-2')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-1')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-2')); + $this->assertFalse($session->hasInSessionFlash('foo-next-1')); + $this->assertTrue($session->hasInSessionFlash('foo-next-2')); $session->removeFromFlash('foo-next-2', true, true); - $this->assertFalse($session->hasInCurrentFlash('foo-current-1')); - $this->assertFalse($session->hasInCurrentFlash('foo-current-2')); - $this->assertFalse($session->hasInNextFlash('foo-next-1')); - $this->assertFalse($session->hasInNextFlash('foo-next-2')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-1')); + $this->assertFalse($session->hasInObjectsFlash('foo-current-2')); + $this->assertFalse($session->hasInSessionFlash('foo-next-1')); + $this->assertFalse($session->hasInSessionFlash('foo-next-2')); } } diff --git a/tests/SetInCurrentFlashMethodTest.php b/tests/SetInObjectsFlashMethodTest.php similarity index 72% rename from tests/SetInCurrentFlashMethodTest.php rename to tests/SetInObjectsFlashMethodTest.php index 0f20221..eabc886 100644 --- a/tests/SetInCurrentFlashMethodTest.php +++ b/tests/SetInObjectsFlashMethodTest.php @@ -17,7 +17,7 @@ use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; -class SetInCurrentFlashMethodTest extends TestCase +class SetInObjectsFlashMethodTest extends TestCase { public function setUp(): void { @@ -32,13 +32,13 @@ public function test_should_correctly_set_attributes(): void $storage = new Session(); $session = new SegSession('da-segment', $storage); - $session->setInCurrentFlash('foo-current-1', 'val-in-current-1'); - $session->setInCurrentFlash('foo-current-2', 'val-in-current-2'); + $session->setInObjectsFlash('foo-current-1', 'val-in-current-1'); + $session->setInObjectsFlash('foo-current-2', 'val-in-current-2'); - $this->assertTrue($session->hasInCurrentFlash('foo-current-1')); - $this->assertTrue($session->hasInCurrentFlash('foo-current-2')); + $this->assertTrue($session->hasInObjectsFlash('foo-current-1')); + $this->assertTrue($session->hasInObjectsFlash('foo-current-2')); - $this->assertEquals('val-in-current-1', $session->getFromCurrentFlash('foo-current-1')); - $this->assertEquals('val-in-current-2', $session->getFromCurrentFlash('foo-current-2')); + $this->assertEquals('val-in-current-1', $session->getFromObjectsFlash('foo-current-1')); + $this->assertEquals('val-in-current-2', $session->getFromObjectsFlash('foo-current-2')); } } diff --git a/tests/SetInNextFlashMethodTest.php b/tests/SetInSessionFlashMethodTest.php similarity index 61% rename from tests/SetInNextFlashMethodTest.php rename to tests/SetInSessionFlashMethodTest.php index 163dc69..108ad11 100644 --- a/tests/SetInNextFlashMethodTest.php +++ b/tests/SetInSessionFlashMethodTest.php @@ -17,7 +17,7 @@ use Josantonius\Session\Session; use Josantonius\Session\FlashableSessionSegment as SegSession; -class SetInNextFlashMethodTest extends TestCase +class SetInSessionFlashMethodTest extends TestCase { public function setUp(): void { @@ -32,13 +32,13 @@ public function test_should_correctly_set_attributes(): void $storage = new Session(); $session = new SegSession('da-segment', $storage); - $session->setInNextFlash('foo-next-1', 'val-in-next-1'); - $session->setInNextFlash('foo-next-2', 'val-in-next-2'); + $session->setInSessionFlash('foo-next-1', 'val-in-next-1'); + $session->setInSessionFlash('foo-next-2', 'val-in-next-2'); - $this->assertTrue($session->hasInNextFlash('foo-next-1')); - $this->assertTrue($session->hasInNextFlash('foo-next-2')); + $this->assertTrue($session->hasInSessionFlash('foo-next-1')); + $this->assertTrue($session->hasInSessionFlash('foo-next-2')); - $this->assertEquals('val-in-next-1', $session->getFromNextFlash('foo-next-1')); - $this->assertEquals('val-in-next-2', $session->getFromNextFlash('foo-next-2')); + $this->assertEquals('val-in-next-1', $session->getFromSessionFlash('foo-next-1')); + $this->assertEquals('val-in-next-2', $session->getFromSessionFlash('foo-next-2')); } } From 77dd406b7f846eaee08584c7aa70d33f62b035b1 Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 18:15:38 -0600 Subject: [PATCH 13/19] Documentation --- README.md | 733 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 728 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fbc47cd..bf70c8e 100644 --- a/README.md +++ b/README.md @@ -344,14 +344,289 @@ Destroys the session: public static function destroy(): bool; ``` -## Exceptions Used + +### Flashable Session Segment Class + +`Josantonius\Session\FlashableSessionSegment` + +This is a special type of Session class whose data is always stored in a sub-array in **$_SESSION**. This sub-array is automatically created & managed by each instance of this class and its key in **$_SESSION** is the string value passed as the first argument to this class' constructor. The session is always either auto-started or auto-resumed when an instance of this class is created, so you never need to explicitly call the **start** method after creating an instance of this class. This class also has flash functionality that allows you to store values in session via an instance of this class that are meant to be read once from session and removed after that one-time read (for example, you can set a login success notification message in session in your application using this flash mechanism and once the success message is read once from the session, it will no longer be available in session). You can also store non-flash values in session via each instance of this class that will stay in session until you explicitly remove them or the session expires or is destroyed. Both flash and non-flash values are stored in the earlier mentioned sub-array in **$_SESSION** and as a result, they are shielded from being overwritten by other parts of your application that write to **$_SESSION** directly as long as the key / segment name you specified for each instance of this class is unique & not being already used to store some other stuff in **$_SESSION**. + +The first non-optional argument to its constructor is a key (also referred to as a segment name) to the sub-array in **$_SESSION** where all the data for the instance of `Josantonius\Session\FlashableSessionSegment` you are creating will be stored. Make sure the key you specify is a unique key that isn't being used by other packages in your application that write to **$_SESSION** so you don't have your data stored via an instance of this class overwritten by some other packages in your application. + +An instance of **Josantonius\Session\SessionInterface** can optionally be passed as the second argument to the constructor. +This instance will be used to interact with the session (**$_SESSION**). If the second argument is **null** +then an instance of **Josantonius\Session\Session** will be created & used to interact with the session (**$_SESSION**). + +The optional third argument to its constructor is an array of options for configuring the session. It must contain the same valid options acceptable by [session_start](https://www.php.net/manual/en/function.session-start.php). + + +Creates an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +/** + * @throws EmptySegmentNameException if an empty string (i.e. '' or "") was passed as the first argument + * @throws HeadersSentException if headers already sent. + * @throws SessionNotStartedException if session could not be started. + * @throws WrongSessionOptionException if setting options failed. + * + * @param string $segmentName key to be used in $_SESSION to store all the data for an instance of this class + + * @param null|\Josantonius\Session\SessionInterface $storage used for performing some session operations for each instance of this class. If null, an instance of \Josantonius\Session\Session will be created & used. + * + * @param array $options session start configuration options that will be used to automatically start a new session or resume an existing session. It must contain the same valid options acceptable by https://www.php.net/manual/en/function.session-start.php. + * + * @see https://php.net/session.configuration for List of available $options. + */ +public function __construct(string $segmentName, ?SessionInterface $storage = null, array $options = []); +``` + +Get the segment name (this is the key to the sub-array inside **$_SESSION** where all the data for an instance of `Josantonius\Session\FlashableSessionSegment` will be stored. It is the first argument passed to the constructor above): + +```php +public function getSegmentName(): string; +``` + +Get the instance of `\Josantonius\Session\SessionInterface` being used to perform session operations on behalf of an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +public function getStorage(): SessionInterface; +``` + +Starts the session: + +```php +public function start(array $options = []): bool +``` + +Check if the session is started: + +```php +public function isStarted(): bool; +``` + +Gets all values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +public function all(): array +``` + +Checks if an attribute exists via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +public function has(string $name): bool +``` + +Get the corresponding value associated with an attribute that was stored via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +/** + * Optionally defines a default value when the attribute does not exist. + */ +public function get(string $name, mixed $default = null): mixed +``` + +Sets an attribute and its corresponding value via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +public function set(string $name, mixed $value): void +``` + +Sets several attribute & value pairs at once via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +/** + * If attributes exist they are replaced, if they do not exist they are created. + */ +public function replace(array $data): void +``` + +Deletes an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name and returns its value: + +```php +/** + * Optionally defines a default value when the attribute does not exist. + */ +public function pull(string $name, mixed $default = null): mixed +``` + +Deletes an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name: ```php -use Josantonius\Session\Exceptions\HeadersSentException; -use Josantonius\Session\Exceptions\SessionException; +public function remove(string $name): void +``` + +Clears / frees all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +public function clear(): void +``` + +Gets the session ID: + +```php +public function getId(): string +``` + +Sets the session ID: + +```php +/** + * This method will be of no effect if called outside the constructor + * of this class since the session will already be started after the + * constructor method finishes execution + */ +public function setId(string $sessionId): void +``` + +Update the current session ID with a newly generated one: + +```php +public function regenerateId(bool $deleteOldSession = false): bool +``` + +Gets the session name: + +```php +public function getName(): string; +``` + +Sets the session name: + +```php +/** + * This method will be of no effect if called outside the constructor + * of this class since the session will already be started after the + * constructor method finishes execution. + */ +public function setName(string $name): void; +``` + +Clears / frees all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`, but does not destroy the session **$_SESSION**. **$_SESSION** data written outside this class will remain intact: + +```php +/** + * Always returns true + */ +public function destroy(): bool; +``` + + +> **Flash Mechanism:** every time an instance of `Josantonius\Session\FlashableSessionSegment` is created, an array to store flash data (meant to be read only once by the next instance of `Josantonius\Session\FlashableSessionSegment` with the same key / segment name) is either created inside the sub-array inside **$_SESSION** where all the data for the created instance of `Josantonius\Session\FlashableSessionSegment` will be stored or if that sub-sub-array for the flash data already exists in **$_SESSION**, it is copied into the **objectsFlashData** property of the created instance of `Josantonius\Session\FlashableSessionSegment` and reset to an empty array in **$_SESSION**. + +> Flash data contained in the **objectsFlashData** property of an instance of `Josantonius\Session\FlashableSessionSegment` is referred to as the **current / object instance's flash data** (which is the copy of flash data read once from the session). Flash data set inside the sub-array in **$_SESSION** is referred to as the **next / session flash data** (i.e. flash data to be copied from **$_SESSION** into the **objectsFlashData** property of the next instance of `Josantonius\Session\FlashableSessionSegment` with the same key / segment name as the current instance used to store the flash data in **$_SESSION**). + +> Below are methods related to storing and retrieving flash data. More concrete examples of how to store and retrieve flash data will be shown in the usage section later below. + +Set an attribute & value in the object instance's flash for an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +/** + * Sets an item with the specified $key in the flash storage for an instance + * of this class (i.e. $this->objectsFlashData). + * + * The item will only be retrievable from the instance of this class it was set in. + */ +public function setInObjectsFlash(string $key, mixed $value): void +``` + +Set an attribute & value in the session flash for an instance of `Josantonius\Session\FlashableSessionSegment`: + +```php +/** + * Sets an item with the specified $key in the flash storage located in + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * + * The item will only be retrievable by calling the getFromObjectsFlash + * on the next instance of this class created with the same segment name. + */ +public function setInSessionFlash(string $key, mixed $value): void +``` + +Check if an attribute exists in the object instance's flash: + +```php +/** + * Check if item with specified $key exists in the flash storage for + * an instance of this class (i.e. in $this->objectsFlashData). + */ +public function hasInObjectsFlash(string $key): bool +``` + + +Check if an attribute exists in the session flash: + +```php +/** + * Check if item with specified $key exists in + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST]. + */ +public function hasInSessionFlash(string $key): bool +``` + +Get the value associated with a specified attribute from the object instance's flash: + +```php +/** + * Get an item with the specified $key from the flash storage for an instance + * of this class (i.e. $this->objectsFlashData) if it exists or return $default. + */ +public function getFromObjectsFlash(string $key, mixed $default = null): mixed +``` + + +Get the value associated with a specified attribute from the session flash: + +```php +/** + * Get an item with the specified $key from + * + * $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + * if it exists or return $default. + */ +public function getFromSessionFlash(string $key, mixed $default = null): mixed +``` + +Remove an attribute & its corresponding value from the object instance's and / or session flash: + +```php +/** + * Remove an item with the specified $key (if it exists) from: + * - the flash storage for an instance of this class (i.e. in $this->objectsFlashData), + * if $fromObjectsFlash === true + * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], + * if $fromSessionFlash === true + */ +public function removeFromFlash( + string $key, + bool $fromObjectsFlash = true, + bool $fromSessionFlash = false +): void +``` + +Get all attributes & their corresponding values from the object instance's flash: + +```php +/** + * Get all items in the flash storage for an instance of this class + * (i.e. in $this->objectsFlashData) + */ +public function getAllFromObjectsFlash(): array +``` + +Get all attributes & their corresponding values from the session flash: + +```php +/** + * Get all items in $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST] + */ +public function getAllFromSessionFlash(): array +``` + +## Exceptions Used in \Josantonius\Session\FlashableSessionSegment + +```php +use Josantonius\Session\Exceptions\EmptySegmentNameException; use Josantonius\Session\Exceptions\SessionNotStartedException; -use Josantonius\Session\Exceptions\SessionStartedException; -use Josantonius\Session\Exceptions\WrongSessionOptionException; ``` ## Usage @@ -374,6 +649,26 @@ use Josantonius\Session\Facades\Session; Session::start(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); +``` + + ### Starts the session setting options ```php @@ -419,6 +714,29 @@ Session::start([ ]); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment( + 'demo-segment', + null, + ['cookie_httponly' => true] +); +``` + ### Check if the session is started ```php @@ -435,6 +753,27 @@ use Josantonius\Session\Facades\Session; Session::isStarted(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->isStarted(); +``` + ### Sets an attribute by name ```php @@ -451,6 +790,27 @@ use Josantonius\Session\Facades\Session; Session::set('foo', 'bar'); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->set('foo', 'bar'); +``` + ### Gets an attribute by name without setting a default value ```php @@ -467,6 +827,27 @@ use Josantonius\Session\Facades\Session; Session::get('foo'); // null if attribute does not exist ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->get('foo'); // null if attribute does not exist +``` + ### Gets an attribute by name setting a default value ```php @@ -483,6 +864,27 @@ use Josantonius\Session\Facades\Session; Session::get('foo', false); // false if attribute does not exist ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->get('foo', false); // false if attribute does not exist +``` + ### Gets all attributes ```php @@ -499,6 +901,27 @@ use Josantonius\Session\Facades\Session; Session::all(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->all(); +``` + ### Check if an attribute exists in the session ```php @@ -515,6 +938,27 @@ use Josantonius\Session\Facades\Session; Session::has('foo'); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->has('foo'); +``` + ### Sets several attributes at once ```php @@ -531,6 +975,28 @@ use Josantonius\Session\Facades\Session; Session::replace(['foo' => 'bar', 'bar' => 'foo']); ``` + +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->replace(['foo' => 'bar', 'bar' => 'foo']); +``` + ### Deletes an attribute and returns its value or the default value if not exist ```php @@ -547,6 +1013,28 @@ use Josantonius\Session\Facades\Session; Session::pull('foo'); // null if attribute does not exist ``` + +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->pull('foo'); // null if attribute does not exist +``` + ### Deletes an attribute and returns its value or the custom value if not exist ```php @@ -563,6 +1051,27 @@ use Josantonius\Session\Facades\Session; Session::pull('foo', false); // false if attribute does not exist ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->pull('foo', false); // false if attribute does not exist +``` + ### Deletes an attribute by name ```php @@ -579,6 +1088,27 @@ use Josantonius\Session\Facades\Session; Session::remove('foo'); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->remove('foo'); +``` + ### Free all session variables ```php @@ -595,6 +1125,31 @@ use Josantonius\Session\Facades\Session; Session::clear(); ``` +### Free all session segment variables + +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +// Only removes flash and non-flash data from the segment's +// sub-array in $_SESSION +$sessionSegment->clear(); +``` + ### Gets the session ID ```php @@ -611,6 +1166,27 @@ use Josantonius\Session\Facades\Session; Session::getId(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->getId(); +``` + ### Sets the session ID ```php @@ -627,6 +1203,31 @@ use Josantonius\Session\Facades\Session; Session::setId('foo'); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +// Does nothing because sessions are auto-started for each +// instance of \Josantonius\Session\FlashableSessionSegment. +// Setting the ID after the session has already been started +// is of no effect. +$sessionSegment->setId('foo'); +``` + ### Update the current session ID with a newly generated one ```php @@ -643,6 +1244,27 @@ use Josantonius\Session\Facades\Session; Session::regenerateId(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->regenerateId(); +``` + ### Update the current session ID with a newly generated one deleting the old session ```php @@ -659,6 +1281,27 @@ use Josantonius\Session\Facades\Session; Session::regenerateId(true); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->regenerateId(true); +``` + ### Gets the session name ```php @@ -675,6 +1318,27 @@ use Josantonius\Session\Facades\Session; Session::getName(); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +$sessionSegment->getName(); +``` + ### Sets the session name ```php @@ -691,6 +1355,31 @@ use Josantonius\Session\Facades\Session; Session::setName('foo'); ``` +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +// Does nothing because sessions are auto-started for each +// instance of \Josantonius\Session\FlashableSessionSegment. +// Setting the session name after the session has already +// been started is of no effect. +$sessionSegment->setName('foo'); +``` + ### Destroys the session ```php @@ -707,6 +1396,40 @@ use Josantonius\Session\Facades\Session; Session::destroy(); ``` +### Destroy the session segment but not the session + +```php +use Josantonius\Session\FlashableSessionSegment; + +///////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session flash data +// to an empty array +// +// OR +// +// auto-resume existing session & read flash +// data in $_SESSION (if any) into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +///////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +// Only removes flash and non-flash data from the segment's +// sub-array in $_SESSION +$sessionSegment->destroy(); +``` + +## Usage of Flash Functionality + +The major use case of flashes is to store data that is only meant to be read from the session flash storage once and only once and immediately it is read once, it is automatically removed from the session flash storage. + + + +``` + + ## Tests To run [tests](tests) you just need [composer](http://getcomposer.org/download/) From af0597a7718d3ce6f9fa6304c5904f81512d9fcb Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 18:20:00 -0600 Subject: [PATCH 14/19] Documentation --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index bf70c8e..5d491bc 100644 --- a/README.md +++ b/README.md @@ -1425,6 +1425,21 @@ $sessionSegment->destroy(); The major use case of flashes is to store data that is only meant to be read from the session flash storage once and only once and immediately it is read once, it is automatically removed from the session flash storage. +For example you may want to store a message indicating the status of an operation (like whether or not you were able to successfully delete a record from the database) in the the flash storage, which you intend to be read only once when another script runs that tries to read that data. Let's show how you can accomplish that between two scripts: **script-a.php** and **script-b.php** + +### script-a.php + +```php +use Josantonius\Session\FlashableSessionSegment; + +// perform some operations +// ...... +// ..... + +$operationStatusMessage = "Operation Successful"; + +$sessionSegment = new FlashableSessionSegment('demo-segment'); + ``` From 8ffef43943e2270cd4c257afa8edae268ecdc5d6 Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 21:10:52 -0600 Subject: [PATCH 15/19] Documentation --- README.md | 243 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 192 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 5d491bc..78fe271 100644 --- a/README.md +++ b/README.md @@ -513,7 +513,7 @@ public function destroy(): bool; > **Flash Mechanism:** every time an instance of `Josantonius\Session\FlashableSessionSegment` is created, an array to store flash data (meant to be read only once by the next instance of `Josantonius\Session\FlashableSessionSegment` with the same key / segment name) is either created inside the sub-array inside **$_SESSION** where all the data for the created instance of `Josantonius\Session\FlashableSessionSegment` will be stored or if that sub-sub-array for the flash data already exists in **$_SESSION**, it is copied into the **objectsFlashData** property of the created instance of `Josantonius\Session\FlashableSessionSegment` and reset to an empty array in **$_SESSION**. -> Flash data contained in the **objectsFlashData** property of an instance of `Josantonius\Session\FlashableSessionSegment` is referred to as the **current / object instance's flash data** (which is the copy of flash data read once from the session). Flash data set inside the sub-array in **$_SESSION** is referred to as the **next / session flash data** (i.e. flash data to be copied from **$_SESSION** into the **objectsFlashData** property of the next instance of `Josantonius\Session\FlashableSessionSegment` with the same key / segment name as the current instance used to store the flash data in **$_SESSION**). +> Flash data contained in the **objectsFlashData** property of an instance of `Josantonius\Session\FlashableSessionSegment` is referred to as the **current / object instance's flash data** (which is the copy of flash data read once from the session). Flash data set inside the sub-array in **$_SESSION** is referred to as the **next / session segment's flash data** (i.e. flash data to be copied from **$_SESSION** into the **objectsFlashData** property of the next instance of `Josantonius\Session\FlashableSessionSegment` with the same key / segment name as the current instance used to store the flash data in **$_SESSION**). > Below are methods related to storing and retrieving flash data. More concrete examples of how to store and retrieve flash data will be shown in the usage section later below. @@ -529,7 +529,7 @@ Set an attribute & value in the object instance's flash for an instance of `Josa public function setInObjectsFlash(string $key, mixed $value): void ``` -Set an attribute & value in the session flash for an instance of `Josantonius\Session\FlashableSessionSegment`: +Set an attribute & value in the session segment's flash for an instance of `Josantonius\Session\FlashableSessionSegment`: ```php /** @@ -553,7 +553,7 @@ public function hasInObjectsFlash(string $key): bool ``` -Check if an attribute exists in the session flash: +Check if an attribute exists in the session segment's flash: ```php /** @@ -574,7 +574,7 @@ public function getFromObjectsFlash(string $key, mixed $default = null): mixed ``` -Get the value associated with a specified attribute from the session flash: +Get the value associated with a specified attribute from the session segment's flash: ```php /** @@ -586,7 +586,7 @@ Get the value associated with a specified attribute from the session flash: public function getFromSessionFlash(string $key, mixed $default = null): mixed ``` -Remove an attribute & its corresponding value from the object instance's and / or session flash: +Remove an attribute & its corresponding value from the object instance's and / or session segment's flash: ```php /** @@ -613,7 +613,7 @@ Get all attributes & their corresponding values from the object instance's flash public function getAllFromObjectsFlash(): array ``` -Get all attributes & their corresponding values from the session flash: +Get all attributes & their corresponding values from the session segment's flash: ```php /** @@ -655,8 +655,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -720,8 +720,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -759,8 +759,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -796,8 +796,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -833,8 +833,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -870,8 +870,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -907,8 +907,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -944,8 +944,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -982,8 +982,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1020,8 +1020,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1057,8 +1057,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1094,8 +1094,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1133,8 +1133,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1172,8 +1172,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1209,8 +1209,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1250,8 +1250,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1287,8 +1287,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1324,8 +1324,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1361,8 +1361,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1404,8 +1404,8 @@ use Josantonius\Session\FlashableSessionSegment; ///////////////////////////////////////////////// // Auto-start new session & initialize sub-array // inside $_SESSION to store this objects data -// in $_SESSION & initialize session flash data -// to an empty array +// in $_SESSION & initialize session segment's +// flash data to an empty array // // OR // @@ -1423,28 +1423,169 @@ $sessionSegment->destroy(); ## Usage of Flash Functionality -The major use case of flashes is to store data that is only meant to be read from the session flash storage once and only once and immediately it is read once, it is automatically removed from the session flash storage. +The major use case of flashes is to store data that is only meant to be read from the session segment's flash storage once and only once and immediately it is read once, it is automatically removed from the session segment's flash storage. For example you may want to store a message indicating the status of an operation (like whether or not you were able to successfully delete a record from the database) in the the flash storage, which you intend to be read only once when another script runs that tries to read that data. Let's show how you can accomplish that between two scripts: **script-a.php** and **script-b.php** +> Both scripts must create an instance of `\Josantonius\Session\FlashableSessionSegment` with the same segment name passed as the first argument to the constructor, in order to both be able to access flash data from the same session segment. + ### script-a.php ```php +include './vendor/autoload.php'; + use Josantonius\Session\FlashableSessionSegment; -// perform some operations -// ...... -// ..... +// Message to store in session segment's flash +$statusMsg = "Operation Successful"; + +////////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session segment's +// flash data to an empty array. +// +// This instance's objectsFlashData property has +// a value of an empty array, since at this point +// there is no data in the session segment's flash +// array to be removed and copied into this instance's +// objectsFlashData property at this point. +////////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +////////////////////////////////////////////////// +// Store your message in the session segment's flash. +// It will be loaded into the objectsFlashData property +// of the next instance of FlashableSessionSegment with +// the same segment name `demo-segment` and removed from +// the session segment's flash when the constructor of +// that next instance gets executed. +////////////////////////////////////////////////// +$sessionSegment->setInSessionFlash('operation-status', $statusMsg); +``` -$operationStatusMessage = "Operation Successful"; +### script-b.php +```php +include './vendor/autoload.php'; + +use Josantonius\Session\FlashableSessionSegment; + +////////////////////////////////////////////////// +// Auto-resume existing session & read flash data +// inside $_SESSION into this object's +// objectsFlashData property & reset the flash +// data in $_SESSION to an empty array +// +// This instance's objectsFlashData property now +// points to an array of all the flash data read +// and removed from the session segment's flash +// at this point. +////////////////////////////////////////////////// $sessionSegment = new FlashableSessionSegment('demo-segment'); +////////////////////////////////////////////////// +// Retrieve the message from script-a.php stored +// in the session segment's flash with a key named +// `operation-status` which is now contained +// in this object's flash +// (i.e. its objectsFlashData property) +////////////////////////////////////////////////// +$statusMsg = + $sessionSegment->getFromObjectsFlash('operation-status'); +// $statusMsg should contain the string "Operation Successful" +var_dump($statusMsg); + +$nonExistentItem = + $sessionSegment->getFromObjectsFlash('non-existent', false); +// $nonExistentItem will contain false because no item +// with the key value of `non-existent` was ever stored +// in the session segment's flash +var_dump($nonExistentItem); +``` + +To test the 2 scripts above you should use a web-server or start php's built-in web-server. +> Running the scripts on the command line will not work because php cli always creates a new session for each script you execute that tries to start a session. +To test both scripts, save both scripts in the same directory and start the built-in web-server by running the command below: + +`php -S 0.0.0.0:8888 -t .` + +Open your browser & browse to http://localhost:8888/script-a.php & then to http://localhost:8888/script-b.php + +You should see the output below: + +``` +string(20) "Operation Successful" bool(false) +``` + +### Other methods for interacting with flash data in both the session segment and instances of `\Josantonius\Session\FlashableSessionSegment` + +```php +use Josantonius\Session\FlashableSessionSegment; + +// Message to store in session segment's flash +$statusMsg = "Operation Successful"; + +////////////////////////////////////////////////// +// Auto-start new session & initialize sub-array +// inside $_SESSION to store this objects data +// in $_SESSION & initialize session segment's +// flash data to an empty array. +// +// This instance's objectsFlashData property has +// a value of an empty array, since at this point +// there is no data in the session segment's flash +// array to be removed and copied into this +// instance's objectsFlashData property at this point. +////////////////////////////////////////////////// +$sessionSegment = new FlashableSessionSegment('demo-segment'); + +////////////////////////////////////////////////// +// Store your message in the session segment's flash. +// It will be loaded into the objectsFlashData property +// of the next instance of FlashableSessionSegment with +// the same segment name `demo-segment` and removed from +// the session segment's flash when the constructor of +// that next instance gets executed. +////////////////////////////////////////////////// +$sessionSegment->setInSessionFlash('operation-status', $statusMsg); + +// To get a value stored in the current object's +// session segment's flash in the same script or +// page request where the value was stored +$sessionFlashVal = + $sessionSegment->getFromSessionFlash('operation-status'); +// $sessionFlashVal will contain "Operation Successful" + +// To get an array of all values stored in the current object's +// session segment's flash in the same script or +// page request where the value was stored +$allSessionFlashValues = + $sessionSegment->getAllFromSessionFlash(); + +// To store a value in the current object's flash storage +// (not the session segment's flash storage inside $_SESSION) +// This value will only always be available in the script +// where it was set and will disappear once the object is +// unset, garbage collected or the script finishes executing. +$sessionSegment->setInObjectsFlash('value-in-object-flash', 'foo'); + +// To get a value that was stored in the current object's +// flash storage (not the session segment's flash storage +// inside $_SESSION) +$val = $sessionSegment->getFromObjectsFlash('value-in-object-flash'); +// $val will have a value of 'foo' + +// To get an array of all values stored in the current object's +// flash storage (not the session segment's flash storage +// inside $_SESSION) +$allValues = $sessionSegment->getAllFromObjectsFlash(); ``` + ## Tests To run [tests](tests) you just need [composer](http://getcomposer.org/download/) From e72461bafd4983d3b0904335eaae8a51a5c8f578 Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 21:26:55 -0600 Subject: [PATCH 16/19] Documentation --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 78fe271..7e4d3f0 100644 --- a/README.md +++ b/README.md @@ -1565,6 +1565,11 @@ $sessionFlashVal = $allSessionFlashValues = $sessionSegment->getAllFromSessionFlash(); +// To remove a value from the current object's +// session segment's flash in the same script or +// page request where the value was stored +$sessionSegment->removeFromFlash('operation-status', false, true); + // To store a value in the current object's flash storage // (not the session segment's flash storage inside $_SESSION) // This value will only always be available in the script @@ -1582,6 +1587,19 @@ $val = $sessionSegment->getFromObjectsFlash('value-in-object-flash'); // flash storage (not the session segment's flash storage // inside $_SESSION) $allValues = $sessionSegment->getAllFromObjectsFlash(); + +// To remove a value from the current object's flash storage +// (not the session segment's flash storage inside $_SESSION) +$sessionSegment->removeFromFlash('value-in-object-flash', true, false); + +// To check if an attribute exists in the current object's +// flash storage (not the session segment's flash storage +// inside $_SESSION) +$sessionSegment->hasInObjectsFlash('value-in-object-flash'); // returns true or false + +// To check if an attribute exists in the current object's +// session segment's flash +$sessionSegment->hasInSessionFlash('operation-status'); // returns true or false ``` From 1b5536bbc0baeb64a6591a180b523ed4c80b8bec Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 21:42:30 -0600 Subject: [PATCH 17/19] Documentation --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7e4d3f0..d0cb884 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ then an instance of **Josantonius\Session\Session** will be created & used to in The optional third argument to its constructor is an array of options for configuring the session. It must contain the same valid options acceptable by [session_start](https://www.php.net/manual/en/function.session-start.php). -Creates an instance of `Josantonius\Session\FlashableSessionSegment`: +Create an instance of `Josantonius\Session\FlashableSessionSegment`: ```php /** @@ -392,7 +392,7 @@ Get the instance of `\Josantonius\Session\SessionInterface` being used to perfor public function getStorage(): SessionInterface; ``` -Starts the session: +Start the session: ```php public function start(array $options = []): bool @@ -404,13 +404,13 @@ Check if the session is started: public function isStarted(): bool; ``` -Gets all values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: +Get all values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: ```php public function all(): array ``` -Checks if an attribute exists via an instance of `Josantonius\Session\FlashableSessionSegment`: +Check if an attribute exists via an instance of `Josantonius\Session\FlashableSessionSegment`: ```php public function has(string $name): bool @@ -425,13 +425,13 @@ Get the corresponding value associated with an attribute that was stored via an public function get(string $name, mixed $default = null): mixed ``` -Sets an attribute and its corresponding value via an instance of `Josantonius\Session\FlashableSessionSegment`: +Set an attribute and its corresponding value via an instance of `Josantonius\Session\FlashableSessionSegment`: ```php public function set(string $name, mixed $value): void ``` -Sets several attribute & value pairs at once via an instance of `Josantonius\Session\FlashableSessionSegment`: +Set several attribute & value pairs at once via an instance of `Josantonius\Session\FlashableSessionSegment`: ```php /** @@ -440,7 +440,7 @@ Sets several attribute & value pairs at once via an instance of `Josantonius\Ses public function replace(array $data): void ``` -Deletes an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name and returns its value: +Delete an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name and returns its value: ```php /** @@ -449,25 +449,25 @@ Deletes an attribute associated with an instance of `Josantonius\Session\Flashab public function pull(string $name, mixed $default = null): mixed ``` -Deletes an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name: +Delete an attribute associated with an instance of `Josantonius\Session\FlashableSessionSegment` by name: ```php public function remove(string $name): void ``` -Clears / frees all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: +Clear / free all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`: ```php public function clear(): void ``` -Gets the session ID: +Get the session ID: ```php public function getId(): string ``` -Sets the session ID: +Set the session ID: ```php /** @@ -484,13 +484,13 @@ Update the current session ID with a newly generated one: public function regenerateId(bool $deleteOldSession = false): bool ``` -Gets the session name: +Get the session name: ```php public function getName(): string; ``` -Sets the session name: +Set the session name: ```php /** @@ -501,7 +501,7 @@ Sets the session name: public function setName(string $name): void; ``` -Clears / frees all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`, but does not destroy the session **$_SESSION**. **$_SESSION** data written outside this class will remain intact: +Clear / free all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`, but does not destroy the session **$_SESSION**. **$_SESSION** data written outside this class will remain intact: ```php /** From 0590e96728ff51ce8674c6ffbf6c236873d3ec5e Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 21:48:31 -0600 Subject: [PATCH 18/19] Documentation --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0cb884..966573e 100644 --- a/README.md +++ b/README.md @@ -501,7 +501,9 @@ Set the session name: public function setName(string $name): void; ``` -Clear / free all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`, but does not destroy the session **$_SESSION**. **$_SESSION** data written outside this class will remain intact: +Clear / free all attributes and corresponding values stored via an instance of `Josantonius\Session\FlashableSessionSegment`, but does not destroy the session **$_SESSION**. + +**$_SESSION** data written outside this class will remain intact: ```php /** From 687320d7ca121e0373881c77b8893d051e7e58ee Mon Sep 17 00:00:00 2001 From: rotimi Date: Fri, 25 Oct 2024 22:24:47 -0600 Subject: [PATCH 19/19] Documentation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 966573e..b906f94 100644 --- a/README.md +++ b/README.md @@ -593,8 +593,10 @@ Remove an attribute & its corresponding value from the object instance's and / o ```php /** * Remove an item with the specified $key (if it exists) from: + * * - the flash storage for an instance of this class (i.e. in $this->objectsFlashData), * if $fromObjectsFlash === true + * * - $_SESSION[$this->segmentName][static::FLASH_DATA_FOR_NEXT_REQUEST], * if $fromSessionFlash === true */