data = (array)$data; $this->segments = []; $this->flashMessages = $this->createFlashMessageCollection(); $this->csrfTokens = $this->createCsrfTokenManager(); } /** * Clears all Session data and flash messages * * @return void */ public function clearAll() { $this->data = []; $this->segments = []; $this->flashMessages = new FlashMessageCollection(); } /** * Gets a value with a specific key from the current Segment * * @param string $segment * @param string $key * @param null $default * @param bool $clear true=remove entry from the session * * @return mixed|null */ public function getValue($segment, $key, $default = null, $clear = false) { return $this->getSegment($segment)->getValue($key, $default, $clear); } /** * Makes an entry to the current Segment * * @param string $segment * @param string $key * @param string|int|float|array $value * * @throws InvalidArgumentException * * @return void */ public function setValue($segment, $key, $value) { $this->getSegment($segment)->setValue($key, $value); } /** * Removes a single Entry from the current segment * * @param string $segment * @param string $key * * @throws InvalidArgumentException * * @return void */ public function removeValue($segment, $key) { $this->getSegment($segment)->removeValue($key); } /** * Gets a segment object by it's name * * @param string $name * * @throws InvalidArgumentException * * @return Segment */ public function getSegment($name = '') { if ($name === self::FLASH_SEGMENTKEY || $name === self::CSRF_SEGMENTKEY) { throw new SessionSegmentException( sprintf('"%s" is a reserved segment name.', self::FLASH_SEGMENTKEY) ); } $segmentId = $this->getSegmentKey($name); if (array_key_exists($segmentId, $this->segments)) { return $this->segments[$segmentId]; } $data = []; if (array_key_exists($segmentId, $this->data)) { $data = $this->data[$segmentId]; } $segment = new Segment($this, $name, $data); $this->segments[$segmentId] = $segment; return $segment; } /** * Dumps the whole session into specific target variable. * * @param mixed $targetVariable */ public function dumpSession(&$targetVariable) { $this->mergeSession(); $targetVariable = $this->data; } /** * @return array */ public function __debugInfo() { $this->dumpSession($dump); $this->csrfTokens->dumpTokens($tokendump); $tokendump = array_keys($tokendump); return [ 'data' => $dump, 'tokens' => $tokendump ]; } /** * Adds new flash message to specific segment. * * @param string $segment if empty: default segment will be used * @param string $message * @param string $type * @param int $priority * * @return void */ public function addFlashMessage($segment, $message, $type = FlashMessageData::FLASHTYPE_DEFAULT, $priority = 0) { $flash = new FlashMessageData($message, $type, $segment, $priority); $flashData = $flash->toSessionArray(); $key = (string)$this->getSegmentKey(self::FLASH_SEGMENTKEY); $this->data[$key][] = $flashData; } /** * Gets flash message(s) by specific filter conditions. * * The flash message will be cleared from the session after retrieving * * @param string|null $segment filter for segment name * @param string|null $type filter for message type * * @return FlashMessageData[] flash messages sorted by priority */ public function getFlashMessages($segment = null, $type = null) { return $this->flashMessages->getMessages($segment, $type); } /** * Creates a CSRF Token and stores it in the Session * * @param string $tokenKey * * @throws InvalidArgumentException * * @return string */ public function createCsrfToken($tokenKey) { return $this->csrfTokens->createToken($tokenKey); } /** * Returns true if specified Token is valid * * @param string $tokenKey * @param string $tokenValue * @param bool $remove true=remove token from session to mitigate second use * * @throws InvalidArgumentException * * @return bool */ public function isCsrfTokenValid($tokenKey, $tokenValue, $remove = false) { return $this->csrfTokens->isTokenValid($tokenKey, $tokenValue, $remove); } /** * @param $segmentName * * @throws InvalidArgumentException * * @return string */ private function getSegmentKey($segmentName) { $this->ensureSegmentNameFormat($segmentName); return sprintf('segment_%s', $segmentName); } /** * Merge all Segments and Flashmessages and CsrfTokens into the session array. * * @return void */ private function mergeSession() { foreach ($this->segments as $key => $segment) { $segmentData = $segment->getAll(); if (count($segmentData) > 0) { $this->data[$key] = $segmentData; } } $flashKey = $this->getSegmentKey(self::FLASH_SEGMENTKEY); $newFlashes = []; if (array_key_exists($flashKey, $this->data)) { $newFlashes = $this->data[$flashKey]; } $oldFlashes = $this->flashMessages->toSessionArray(); $this->flashMessages = new FlashMessageCollection(); $allFlashes = array_merge($oldFlashes, $newFlashes); if (count($allFlashes) > 0) { $this->data[$flashKey] = $allFlashes; } else { unset($this->data[$flashKey]); } $this->csrfTokens->dumpTokens($tokens); $tokenSegmentKey = $this->getSegmentKey(self::CSRF_SEGMENTKEY); if (is_array($tokens) && count($tokens) > 0) { $this->data[$tokenSegmentKey] = $tokens; } else { unset($this->data[$tokenSegmentKey]); } } /** * @return FlashMessageCollection */ private function createFlashMessageCollection() { $key = $this->getSegmentKey(self::FLASH_SEGMENTKEY); if (!array_key_exists($key, $this->data)) { return new FlashMessageCollection(); } $messages = $this->data[$key]; $result = new FlashMessageCollection($messages); unset($this->data[$key]); $this->data[$key] = []; return $result; } /** * @return CsrfTokenManager */ private function createCsrfTokenManager() { $key = $this->getSegmentKey(self::CSRF_SEGMENTKEY); if (!array_key_exists($key, $this->data)) { return new CsrfTokenManager(); } $tokens = $this->data[$key]; $result = new CsrfTokenManager($tokens); unset($this->data[$key]); $this->data[$key] = []; return $result; } /** * @param $name * * @throws InvalidArgumentException * * @return void */ private function ensureSegmentNameFormat($name) { if (!preg_match('/^[a-z][a-z0-9_]*$/', $name)) { throw new InvalidArgumentException('Invalid segment name format.'); } } }