Skip to content
This repository was archived by the owner on Jan 31, 2020. It is now read-only.

Commit 156e398

Browse files
committed
Merge pull request #51 from joegreen88-liquid/master
Prevent recursion in DbTableGateway save handler.
2 parents c0e5922 + 1eecfdc commit 156e398

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

src/SaveHandler/DbTableGateway.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,10 @@ public function close()
9090
* Read session data
9191
*
9292
* @param string $id
93+
* @param bool $destroyExpired Optional; true by default
9394
* @return string
9495
*/
95-
public function read($id)
96+
public function read($id, $destroyExpired = true)
9697
{
9798
$rows = $this->tableGateway->select([
9899
$this->options->getIdColumn() => $id,
@@ -104,7 +105,9 @@ public function read($id)
104105
$row->{$this->options->getLifetimeColumn()} > time()) {
105106
return (string) $row->{$this->options->getDataColumn()};
106107
}
107-
$this->destroy($id);
108+
if ($destroyExpired) {
109+
$this->destroy($id);
110+
}
108111
}
109112
return '';
110113
}
@@ -149,7 +152,7 @@ public function write($id, $data)
149152
*/
150153
public function destroy($id)
151154
{
152-
if (! (bool) $this->read($id)) {
155+
if (! (bool) $this->read($id, false)) {
153156
return true;
154157
}
155158

test/SaveHandler/DbTableGatewayTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Zend\Session\SaveHandler\DbTableGatewayOptions;
1414
use Zend\Db\Adapter\Adapter;
1515
use Zend\Db\TableGateway\TableGateway;
16+
use ZendTest\Session\TestAsset\TestDbTableGatewaySaveHandler;
1617

1718
/**
1819
* Unit testing for DbTableGateway include all tests for
@@ -167,6 +168,38 @@ public function testDestroyReturnsTrueWhenSessionIsDeleted()
167168

168169
$this->assertTrue($result);
169170
}
171+
172+
public function testExpiredSessionDoesNotCauseARecursion()
173+
{
174+
// puts an expired session in the db
175+
$query = "
176+
INSERT INTO `sessions` (
177+
`{$this->options->getIdColumn()}`,
178+
`{$this->options->getNameColumn()}`,
179+
`{$this->options->getModifiedColumn()}`,
180+
`{$this->options->getLifetimeColumn()}`,
181+
`{$this->options->getDataColumn()}`
182+
) VALUES (
183+
'123', 'zend-session-test', ".(time() - 31).", 30, 'foobar'
184+
);
185+
";
186+
$this->adapter->query($query, Adapter::QUERY_MODE_EXECUTE);
187+
188+
$this->usedSaveHandlers[] = $saveHandler = new TestDbTableGatewaySaveHandler($this->tableGateway, $this->options);
189+
$saveHandler->open('savepath', 'zend-session-test');
190+
191+
$this->assertSame(0, $saveHandler->getNumReadCalls());
192+
$this->assertSame(0, $saveHandler->getNumDestroyCalls());
193+
194+
$success = (boolean) $saveHandler->read('123');
195+
$this->assertFalse($success);
196+
197+
$this->assertSame(2, $saveHandler->getNumReadCalls());
198+
$this->assertSame(1, $saveHandler->getNumDestroyCalls());
199+
200+
// cleans the test record from the db
201+
$this->adapter->query("DELETE FROM `sessions` WHERE `{$this->options->getIdColumn()}` = '123';");
202+
}
170203

171204
/**
172205
* Sets up the database connection and creates the table for session data
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace ZendTest\Session\TestAsset;
11+
12+
use Zend\Session\SaveHandler\DbTableGateway;
13+
14+
class TestDbTableGatewaySaveHandler extends DbTableGateway
15+
{
16+
protected $numReadCalls = 0;
17+
18+
protected $numDestroyCalls = 0;
19+
20+
public function getNumReadCalls()
21+
{
22+
return $this->numReadCalls;
23+
}
24+
25+
public function getNumDestroyCalls()
26+
{
27+
return $this->numDestroyCalls;
28+
}
29+
30+
public function read($id, $destroyExpired = true)
31+
{
32+
$this->numReadCalls++;
33+
return parent::read($id, $destroyExpired);
34+
}
35+
36+
public function destroy($id)
37+
{
38+
$this->numDestroyCalls++;
39+
return parent::destroy($id);
40+
}
41+
}

0 commit comments

Comments
 (0)