diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74349bf..c04c3f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,12 +12,12 @@ jobs: - uses: php-actions/composer@v6 with: version: 2 - php_version: "7.4" + php_version: "8.1" - name: PHPUnit Tests uses: php-actions/phpunit@v3 with: version: 9 - php_version: "7.4" + php_version: "8.1" configuration: phpunit.xml.dist bootstrap: vendor/autoload.php diff --git a/composer.json b/composer.json index 4efd88a..1652c33 100755 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">=7.3", + "php": "^8.1", "naucon/utility": "~1.0", "naucon/registry": "~1.0", "doctrine/common": "^3.0.3" diff --git a/src/Provider/SessionBag.php b/src/Provider/SessionBag.php index df0a937..2e66ace 100644 --- a/src/Provider/SessionBag.php +++ b/src/Provider/SessionBag.php @@ -9,7 +9,8 @@ */ namespace Naucon\Storage\Provider; -use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag; + +use Naucon\Storage\Session\AttributeBag\LegacyNamespacedAttributeBag; /** * Class SessionBag @@ -17,7 +18,7 @@ * @package Naucon\Storage\Provider * @author Sven Sanzenbacher */ -class SessionBag extends NamespacedAttributeBag +class SessionBag extends LegacyNamespacedAttributeBag { /** * @var string default session storage key diff --git a/src/Session/AttributeBag/LegacyNamespacedAttributeBag.php b/src/Session/AttributeBag/LegacyNamespacedAttributeBag.php new file mode 100644 index 0000000..99fb719 --- /dev/null +++ b/src/Session/AttributeBag/LegacyNamespacedAttributeBag.php @@ -0,0 +1,144 @@ +namespaceCharacter = $namespaceCharacter; + parent::__construct($storageKey); + } + + /** + * {@inheritdoc} + */ + public function has($name): bool + { + $attributes = $this->resolveAttributePath($name); + $name = $this->resolveKey($name); + + if (null === $attributes) { + return false; + } + + return array_key_exists($name, $attributes); + } + + /** + * {@inheritdoc} + */ + public function get($name, $default = null): mixed + { + $attributes = $this->resolveAttributePath($name); + $name = $this->resolveKey($name); + + if (null === $attributes) { + return $default; + } + + return array_key_exists($name, $attributes) ? $attributes[$name] : $default; + } + + /** + * {@inheritdoc} + */ + public function set($name, $value): void + { + $attributes = &$this->resolveAttributePath($name, true); + $name = $this->resolveKey($name); + $attributes[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function remove($name): mixed + { + $retval = null; + $attributes = &$this->resolveAttributePath($name); + $name = $this->resolveKey($name); + if (null !== $attributes && array_key_exists($name, $attributes)) { + $retval = $attributes[$name]; + unset($attributes[$name]); + } + + return $retval; + } + + /** + * Resolves a path in attributes property and returns it as a reference. + * + * This method allows structured namespacing of session attributes. + * + * @param string $name Key name + * @param bool $writeContext Write context, default false + * + * @return array|null + */ + protected function &resolveAttributePath(string $name, bool $writeContext = false): ?array + { + $array = &$this->attributes; + $name = (str_starts_with($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; + + // Check if there is anything to do, else return + if (!$name) { + return $array; + } + + $parts = explode($this->namespaceCharacter, $name); + if (count($parts) < 2) { + if (!$writeContext) { + return $array; + } + + $array[$parts[0]] = []; + + return $array; + } + + unset($parts[count($parts) - 1]); + + foreach ($parts as $part) { + if (null !== $array && !array_key_exists($part, $array)) { + if (!$writeContext) { + $null = null; + + return $null; + } + + $array[$part] = []; + } + + $array = &$array[$part]; + } + + return $array; + } + + /** + * Resolves the key from the name. + * + * This is the last part in a dot separated string. + * + * @return string + */ + protected function resolveKey(string $name): string + { + if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { + $name = substr($name, $pos + 1); + } + + return $name; + } +}