8000 [HttpFoundation][Cache] Added MarshallingSessionHandler · symfony/symfony@2c2dce6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2c2dce6

Browse files
committed
[HttpFoundation][Cache] Added MarshallingSessionHandler
1 parent cde44fc commit 2c2dce6

File tree

6 files changed

+331
-0
lines changed

6 files changed

+331
-0
lines changed

src/Symfony/Component/HttpFoundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CHANGELOG
1313
* added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference
1414
according to [RFC 8674](https://tools.ietf.org/html/rfc8674)
1515
* made the Mime component an optional dependency
16+
* added `MarshallingSessionHandler`, `IdentityMarshaller`
1617

1718
5.0.0
1819
-----
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
13+
14+
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
15+
16+
/**
17+
* @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
18+
*/
19+
class IdentityMarshaller implements MarshallerInterface
20+
{
21+
/**
22+
* {@inheritdoc}
23+
*/
24+
public function marshall(array $values, ?array &$failed): array
25+
{
26+
foreach ($values as $key => $value) {
27+
if (!\is_string($value)) {
28+
throw new \LogicException(sprintf('%s accepts only string as data.', __METHOD__));
29+
}
30+
}
31+
32+
return $values;
33+
}
34+
35+
/**
36+
* {@inheritdoc}
37+
*/
38+
public function unmarshall(string $value): string
39+
{
40+
return $value;
41+
}
42+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
13+
14+
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
15+
16+
/**
17+
* @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
18+
*/
19+
class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
20+
{
21+
private $handler;
22+
private $marshaller;
23+
24+
public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller)
25+
{
26+
$this->handler = $handler;
27+
$this->marshaller = $marshaller;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function open($savePath, $name)
34+
{
35+
return $this->handler->open($savePath, $name);
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function close()
42+
{
43+
return $this->handler->close();
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function destroy($sessionId)
50+
{
51+
return $this->handler->destroy($sessionId);
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function gc($maxlifetime)
58+
{
59+
return $this->handler->gc($maxlifetime);
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function read($sessionId)
66+
{
67+
return $this->marshaller->unmarshall($this->handler->read($sessionId));
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
public function write($sessionId, $data)
74+
{
75+
$failed = [];
76+
$marshalledData = $this->marshaller->marshall(['data' => $data], $failed);
77+
78+
if (!isset($failed['data'])) {
79+
$data = $marshalledData['data'];
80+
}
81+
82+
return $this->handler->write($sessionId, $data);
83+
}
84+
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
public function validateId($sessionId)
89+
{
90+
return $this->handler->validateId($sessionId);
91+
}
92+
93+
/**
94+
* {@inheritdoc}
95+
*/
96+
public function updateTimestamp($sessionId, $data)
97+
{
98+
return $this->handler->updateTimestamp($sessionId, $data);
99+
}
100+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Session\Storage\Handler\IdentityMarshaller;
16+
17+
/**
18+
* @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
19+
*/
20+
class IdentityMarshallerTest extends Testcase
21+
{
22+
public function testMarshall()
23+
{
24+
$marshaller = new IdentityMarshaller();
25+
$values = ['data' => 'string_data'];
26+
$failed = [];
27+
28+
$this->assertSame($values, $marshaller->marshall($values, $failed));
29+
}
30+
31+
/**
32+
* @dataProvider invalidMarshallDataProvider
33+
*/
34+
public function testMarshallInvalidData($values)
35+
{
36+
$marshaller = new IdentityMarshaller();
37+
$failed = [];
38+
39+
$this->expectException(\LogicException::class);
40+
$this->expectExceptionMessage('Symfony\Component\HttpFoundation\Session\Storage\Handler\IdentityMarshaller::marshall accepts only string as data');
41+
42+
$marshaller->marshall($values, $failed);
43+
}
44+
45+
public function testUnmarshall()
46+
{
47+
$marshaller = new IdentityMarshaller();
48+
49+
$this->assertEquals('data', $marshaller->unmarshall('data'));
50+
}
51+
52+
public function invalidMarshallDataProvider(): iterable
53+
{
54+
return [
55+
[['object' => new \stdClass()]],
56+
[['foo' => ['bar']]],
57+
];
58+
}
59+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler;
13+
14+
use PHPUnit\Framework\MockObject\MockObject;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
17+
use Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler;
18+
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MarshallingSessionHandler;
19+
20+
/**
21+
* @author Ahmed TAILOULOUTE <ahmed.tailouloute@gmail.com>
22+
*/
23+
class MarshallingSessionHandlerTest extends TestCase
24+
{
25+
/**
26+
* @var MockObject|\SessionHandlerInterface
27+
*/
28+
protected $handler;
29+
30+
/**
31+
* @var MockObject|MarshallerInterface
32+
*/
33+
protected $marshaller;
34+
35+
protected function setUp(): void
36+
{
37+
$this->marshaller = $this->getMockBuilder(MarshallerInterface::class)->getMock();
38+
$this->handler = $this->getMockBuilder(AbstractSessionHandler::class)->getMock();
39+
}
40+
41+
public function testOpen()
42+
{
43+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
44+
45+
$this->handler->expects($this->once())->method('open')
46+
->with('path', 'name')->willReturn(true);
47+
48+
$marshallingSessionHandler->open('path', 'name');
49+
}
50+
51+
public function testClose()
52+
{
53+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
54+
55+
$this->handler->expects($this->once())->method('close')->willReturn(true);
56+
57+
$this->assertTrue($marshallingSessionHandler->close());
58+
}
59+
60+
public function testDestroy()
61+
{
62+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
63+
64+
$this->handler->expects($this->once())->method('destroy')
65+
->with('session_id')->willReturn(true);
66+
67+
$marshallingSessionHandler->destroy('session_id');
68+
}
69+
70+
public function testGc()
71+
{
72+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
73+
74+
$this->handler->expects($this->once())->method('gc')
75+
->with('maxlifetime')->willReturn(true);
76+
77+
$marshallingSessionHandler->gc('maxlifetime');
78+
}
79+
80+
public function testRead()
81+
{
82+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
83+
84+
$this->handler->expects($this->once())->method('read')->with('session_id')
85+
->willReturn('data');
86+
$this->marshaller->expects($this->once())->method('unmarshall')->with('data')
87+
->willReturn('unmarshalled_data')
88+
;
89+
90+
$result = $marshallingSessionHandler->read('session_id');
91+
$this->assertEquals('unmarshalled_data', $result);
92+
}
93+
94+
public function testWrite()
95+
{
96+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
97+
98+
$this->marshaller->expects($this->once())->method('marshall')
99+
->with(['data' => 'data'], [])
100+
->willReturn(['data' => 'marshalled_data']);
101+
102+
$this->handler->expects($this->once())->method('write')
103+
->with('session_id', 'marshalled_data')
104+
;
105+
106+
$marshallingSessionHandler->write('session_id', 'data');
107+
}
108+
109+
public function testValidateId()
110+
{
111+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
112+
113+
$this->handler->expects($this->once())->method('validateId')
114+
->with('session_id')->willReturn(true);
115+
116+
$marshallingSessionHandler->validateId('session_id');
117+
}
118+
119+
public function testUpdateTimestamp()
120+
{
121+
$marshallingSessionHandler = new MarshallingSessionHandler($this->handler, $this->marshaller);
122+
123+
$this->handler->expects($this->once())->method('updateTimestamp')
124+
->with('session_id', 'data')->willReturn(true);
125+
126+
$marshallingSessionHandler->updateTimestamp('session_id', 'data');
127+
}
128+
}

src/Symfony/Component/HttpFoundation/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"require-dev": {
2424
"predis/predis": "~1.0",
25+
"symfony/cache": "^4.4|^5.0",
2526
"symfony/mime": "^4.4|^5.0",
2627
"symfony/expression-language": "^4.4|^5.0"
2728
},

0 commit comments

Comments
 (0)
0