8000 [HttpFoundation] Added structured namespacing to session attributes. · Pull Request #2541 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[HttpFoundation] Added structured namespacing to session attributes. #2541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations 10000
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added structured namespacing to session attributes.
  • Loading branch information
Drak committed Nov 2, 2011
commit df69589d4cf8a618053b50f219cd799cc561eba6
102 changes: 89 additions & 13 deletions src/Symfony/Component/HttpFoundation/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,52 @@
*/
class Session implements \Serializable
{
/**
* Storage driver.
*
* @var SessionStorageInterface
*/
protected $storage;

/**
* Flag if session has started.
*
* @var boolean
*/
protected $started;

/**
* Array of attributes.
*
* @var array
*/
protected $attributes;

/**
* Array of flash messages.
*
* @var array
*/
protected $flashes;

/**
* Flashes to be removed.
*
* @var array
*/
protected $oldFlashes;

/**
* Flag if session has terminated.
*
* @var boolean
*/
protected $closed;

/**
* Constructor.
*
* @param SessionStorageInterface $storage A SessionStorageInterface instance
* @param SessionStorageInterface $storage A SessionStorageInterface instance.
*/
public function __construct(SessionStorageInterface $storage)
{
Expand Down Expand Up @@ -79,41 +114,80 @@ public function start()
*
* @api
*/
public function has($name)
public function has($name, $namespace = '/')
{
return array_key_exists($name, $this->attributes);
$attributes = & $this->resolveAttributePath($namespace);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why = & ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is functional and not an optimization. We are returning a reference to a key inside the $this->attributes property. This allows you to get structured data rather than a flat array . this allowing deep namespacing,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why you need a reference when doing an array_key_exists call on it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not addressing flat arrays, ie $array[$key], but potentially deep arrays, like $array['user']['permissions'].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not change anything to the fact that the method does not modify the array at all so assigning it by reference is useless

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it might look odd, but it's required, if you remove it the code stops working. It's functional, not optimizational (sic). Remember, we're working on $this->attributes ultimately, or somewhere inside the structured array that is $this->attributes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how a read-only check could stop working if you use it with a real array instead of a reference. I don't ask removing the use of references everywhere, only here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof - ah, I misunderstood - let me check the consequences and update the PR as necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be exact, the get method is also concerned as it is also read-only.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof - I've removed the reference from get() and has() methods in a01e624


return array_key_exists($name, $attributes);
}

/**
* Returns an attribute.
*
* @param string $name The attribute name
* @param mixed $default The default value
* @param string $name The attribute name
* @param mixed $default The default value
* @param string $namespace Namespace
*
* @return mixed
*
* @api
*/
public function get($name, $default = null)
public function get($name, $default = null, $namespace = '/')
{
return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
$attributes = & $this->resolveAttributePath($namespace);

return array_key_exists($name, $attributes) ? $attributes[$name] : $default;
}

/**
* Sets an attribute.
*
* @param string $name
* @param mixed $value
* @param string $namespace
*
* @api
*/
public function set($name, $value)
public function set($name, $value, $namespace = '/')
{
if (false === $this->started) {
$this->start();
}

$attributes = & $this->resolveAttributePath($namespace);
$attributes[$name] = $value;
}

/**
* Resolves a path in attributes property and returns it as a reference.
*
* This method allows structured namespacing of session attributes.
*
* @param string $namespace
*
* @return array
*/
private function &resolveAttributePath($namespace)
{
$array = & $this->attributes;
$namespace = (strpos($namespace, '/') === 0) ? substr($namespace, 1) : $namespace;

// Check if there is anything to do, else return
if (!$namespace) {
return $array;
}

$parts = explode('/', $namespace);

foreach ($parts as $part) {
if (!array_key_exists($part, $array)) {
$array[$part] = array();
}

$this->attributes[$name] = $value;
$array = & $array[$part];
}

return $array;
}

/**
Expand Down Expand Up @@ -148,17 +222,19 @@ public function replace(array $attributes)
* Removes an attribute.
*
* @param string $name
* @param string $namespace
*
* @api
*/
public function remove($name)
public function remove($name, $namespace = '/')
{
if (false === $this->started) {
$this->start();
}

if (array_key_exists($name, $this->attributes)) {
unset($this->attributes[$name]);

$attributes = & $this->resolveAttributePath($namespace);
if (array_key_exists($name, $attributes)) {
unset($attributes[$name]);
}
}

Expand Down
18 changes: 15 additions & 3 deletions tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,31 @@ public function testAll()
$this->assertFalse($this->session->has('foo'));
$this->assertNull($this->session->get('foo'));

$this->assertFalse($this->session->has('foo', '/example'));
$this->assertNull($this->session->get('foo', null, '/example'));

$this->session->set('foo', 'bar');

$this->assertTrue($this->session->has('foo'));
$this->assertSame('bar', $this->session->get('foo'));

// test namespacing
$this->session->set('foo', 'bar', '/example');
$this->assertTrue($this->session->has('foo', '/example'));
$this->assertSame('bar', $this->session->get('foo', '/example'));

$this->session = $this->getSession();

$this->session->remove('foo');
$this->session->set('foo', 'bar');

$this->session->remove('foo');

$this->assertFalse($this->session->has('foo'));
$this->assertTrue($this->session->has('foo', '/example'));

$this->session->remove('foo', '/example');
$this->session->set('foo', 'bar', '/example');
$this->session->remove('foo', '/example');
$this->assertFalse($this->session->has('foo'));
$this->assertFalse($this->session->has('foo', '/example'));

$attrs = array('foo' => 'bar', 'bar' => 'foo');

Expand Down
0