8000 [HttpFoundation] Added a migrating session handler · symfony/symfony@3acd548 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3acd548

Browse files
rossmotleyfabpot
authored andcommitted
[HttpFoundation] Added a migrating session handler
1 parent f77c1d0 commit 3acd548

File tree

3 files changed

+239
-0
lines changed

3 files changed

+239
-0
lines changed

src/Symfony/Component/HttpFoundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
* added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`,
1616
`IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to
1717
handle failed `UploadedFile`.
8000 18+
* added `MigratingSessionHandler` for migrating between two session handlers without losing sessions
1819

1920
4.0.0
2021
-----
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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+
/**
15+
* Migrating session handler for migrating from one handler to another. It reads
16+
* from the current handler and writes both the current and new ones.
17+
*
18+
* It ignores errors from the new handler.
19+
*
20+
* @author Ross Motley <ross.motley@amara.com>
21+
* @author Oliver Radwell <oliver.radwell@amara.com>
22+
*/
23+
class MigratingSessionHandler implements \SessionHandlerInterface
24+
{
25+
private $currentHandler;
26+
private $writeOnlyHandler;
27+
28+
public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler)
29+
{
30+
$this->currentHandler = $currentHandler;
31+
$this->writeOnlyHandler = $writeOnlyHandler;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function close()
38+
{
39+
$result = $this->currentHandler->close();
40+
$this->writeOnlyHandler->close();
41+
42+
return $result;
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
*/
48+
public function destroy($sessionId)
49+
{
50+
$result = $this->currentHandler->destroy($sessionId);
51+
$this->writeOnlyHandler->destroy($sessionId);
52+
53+
return $result;
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
public function gc($maxlifetime)
60+
{
61+
$result = $this->currentHandler->gc($maxlifetime);
62+
$this->writeOnlyHandler->gc($maxlifetime);
63+
64+
return $result;
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function open($savePath, $sessionId)
71+
{
72+
$result = $this->currentHandler->open($savePath, $sessionId);
73+
$this->writeOnlyHandler->open($savePath, $sessionId);
74+
75+
return $result;
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
public function read($sessionId)
82+
{
83+
// No reading from new handler until switch-over
84+
return $this->currentHandler->read($sessionId);
85+
}
86+
87+
/**
88+
* {@inheritdoc}
89+
*/
90+
public function write($sessionId, $sessionData)
91+
{
92+
$result = $this->currentHandler->write($sessionId, $sessionData);
93+
$this->writeOnlyHandler->write($sessionId, $sessionData);
94+
95+
return $result;
96+
}
97+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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\MigratingSessionHandler;
16+
17+
class MigratingSessionHandlerTest extends TestCase
18+
{
19+
private $dualHandler;
20+
private $currentHandler;
21+
private $writeOnlyHandler;
22+
23+
protected function setUp()
24+
{
25+
$this->currentHandler = $this->createMock(\SessionHandlerInterface::class);
26+
$this->writeOnlyHandler = $this->createMock(\SessionHandlerInterface::class);
27+
28+
$this->dualHandler = new MigratingSessionHandler($this->currentHandler, $this->writeOnlyHandler);
29+
}
30+
31+
public function testCloses()
32+
{
33+
$this->currentHandler->expects($this->once())
34+
->method('close')
35+
->will($this->returnValue(true));
36+
37+
$this->writeOnlyHandler->expects($this->once())
38+
->method('close')
39+
->will($this->returnValue(false));
40+
41+
$result = $this->dualHandler->close();
42+
43+
$this->assertTrue($result);
44+
}
45+
46+
public function testDestroys()
47+
{
48+
$sessionId = 'xyz';
49+
50+
$this->currentHandler->expects($this->once())
51+
->method('destroy')
52+
->with($sessionId)
53+
->will($this->returnValue(true));
54+
55+
$this->writeOnlyHandler->expects($this->once())
56+
->method('destroy')
57+
->with($sessionId)
58+
->will($this->returnValue(false));
59+
60+
$result = $this->dualHandler->destroy($sessionId);
61+
62+
$this->assertTrue($result);
63+
}
64+
65+
public function testGc()
66+
{
67+
$maxlifetime = 357;
68+
69+
$this->currentHandler->expects($this->once())
70+
->method('gc')
71+
->with($maxlifetime)
72+
->will($this->returnValue(true));
73+
74+
$this->writeOnlyHandler->expects($this->once())
75+
->method('gc')
76+
->with($maxlifetime)
77+
->will($this->returnValue(false));
78+
79+
$result = $this->dualHandler->gc($maxlifetime);
80+
$this->assertTrue($result);
81+
}
82+
83+
public function testOpens()
84+
{
85+
$savePath = '/path/to/save/location';
86+
$sessionId = 'xyz';
87+
88+
$this->currentHandler->expects($this->once())
89+
->method('open')
90+
->with($savePath, $sessionId)
91+
->will($this->returnValue(true));
92+
93+
$this->writeOnlyHandler->expects($this->once())
94+
->method('open')
95+
->with($savePath, $sessionId)
96+
->will($this->returnValue(false));
97+
98+
$result = $this->dualHandler->open($savePath, $sessionId);
99+
100+
$this->assertTrue($result);
101+
}
102+
103+
public function testReads()
104+
{
105+
$sessionId = 'xyz';
106+
$readValue = 'something';
107+
108+
$this->currentHandler->expects($this->once())
109+
->method('read')
110+
->with($sessionId)
111+
->will($this->returnValue($readValue));
112+
113+
$this->writeOnlyHandler->expects($this->never())
114+
->method('read')
115+
->with($this->any());
116+
117+
$result = $this->dualHandler->read($sessionId);
118+
119+
$this->assertEquals($readValue, $result);
120+
}
121+
122+
public function testWrites()
123+
{
124+
$sessionId = 'xyz';
125+
$data = 'my-serialized-data';
126+
127+
$this->currentHandler->expects($this->once())
128+
->method('write')
129+
->with($sessionId, $data)
130+
->will($this->returnValue(true));
131+
132+
$this->writeOnlyHandler->expects($this->once())
133+
->method('write')
134+
->with($sessionId, $data)
135+
->will($this->returnValue(false));
136+
137+
$result = $this->dualHandler->write($sessionId, $data);
138+
139+
$this->assertTrue($result);
140+
}
141+
}

0 commit comments

Comments
 (0)
0