NamespacedAttributeBag.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpFoundation\Session\Attribute;
  11. /**
  12. * This class provides structured storage of session attributes using
  13. * a name spacing character in the key.
  14. *
  15. * @author Drak <drak@zikula.org>
  16. */
  17. class NamespacedAttributeBag extends AttributeBag
  18. {
  19. private $namespaceCharacter;
  20. /**
  21. * @param string $storageKey Session storage key
  22. * @param string $namespaceCharacter Namespace character to use in keys
  23. */
  24. public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/')
  25. {
  26. $this->namespaceCharacter = $namespaceCharacter;
  27. parent::__construct($storageKey);
  28. }
  29. /**
  30. * {@inheritdoc}
  31. */
  32. public function has($name)
  33. {
  34. // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is
  35. $attributes = $this->resolveAttributePath($name);
  36. $name = $this->resolveKey($name);
  37. if (null === $attributes) {
  38. return false;
  39. }
  40. return \array_key_exists($name, $attributes);
  41. }
  42. /**
  43. * {@inheritdoc}
  44. */
  45. public function get($name, $default = null)
  46. {
  47. // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is
  48. $attributes = $this->resolveAttributePath($name);
  49. $name = $this->resolveKey($name);
  50. if (null === $attributes) {
  51. return $default;
  52. }
  53. return \array_key_exists($name, $attributes) ? $attributes[$name] : $default;
  54. }
  55. /**
  56. * {@inheritdoc}
  57. */
  58. public function set($name, $value)
  59. {
  60. $attributes = &$this->resolveAttributePath($name, true);
  61. $name = $this->resolveKey($name);
  62. $attributes[$name] = $value;
  63. }
  64. /**
  65. * {@inheritdoc}
  66. */
  67. public function remove($name)
  68. {
  69. $retval = null;
  70. $attributes = &$this->resolveAttributePath($name);
  71. $name = $this->resolveKey($name);
  72. if (null !== $attributes && \array_key_exists($name, $attributes)) {
  73. $retval = $attributes[$name];
  74. unset($attributes[$name]);
  75. }
  76. return $retval;
  77. }
  78. /**
  79. * Resolves a path in attributes property and returns it as a reference.
  80. *
  81. * This method allows structured namespacing of session attributes.
  82. *
  83. * @param string $name Key name
  84. * @param bool $writeContext Write context, default false
  85. *
  86. * @return array|null
  87. */
  88. protected function &resolveAttributePath($name, $writeContext = false)
  89. {
  90. $array = &$this->attributes;
  91. $name = (str_starts_with($name, $this->namespaceCharacter)) ? substr($name, 1) : $name;
  92. // Check if there is anything to do, else return
  93. if (!$name) {
  94. return $array;
  95. }
  96. $parts = explode($this->namespaceCharacter, $name);
  97. if (\count($parts) < 2) {
  98. if (!$writeContext) {
  99. return $array;
  100. }
  101. $array[$parts[0]] = [];
  102. return $array;
  103. }
  104. unset($parts[\count($parts) - 1]);
  105. foreach ($parts as $part) {
  106. if (null !== $array && !\array_key_exists($part, $array)) {
  107. if (!$writeContext) {
  108. $null = null;
  109. return $null;
  110. }
  111. $array[$part] = [];
  112. }
  113. $array = &$array[$part];
  114. }
  115. return $array;
  116. }
  117. /**
  118. * Resolves the key from the name.
  119. *
  120. * This is the last part in a dot separated string.
  121. *
  122. * @param string $name
  123. *
  124. * @return string
  125. */
  126. protected function resolveKey($name)
  127. {
  128. if (false !== $pos = strrpos($name, $this->namespaceCharacter)) {
  129. $name = substr($name, $pos + 1);
  130. }
  131. return $name;
  132. }
  133. }