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

Prevents collision of internal cache ids when using DbSelectAdapter #46

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@ interface AdapterInterface extends Countable
* @return array
*/
public function getItems($offset, $itemCountPerPage);

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId();
}
10 changes: 10 additions & 0 deletions src/Adapter/ArrayAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,14 @@ public function count()
{
return $this->count;
}

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId()
{
return json_encode($this);
}
}
10 changes: 10 additions & 0 deletions src/Adapter/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,14 @@ public function count()
{
return call_user_func($this->countCallback);
}

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId()
{
return json_encode($this);
}
}
8 changes: 8 additions & 0 deletions src/Adapter/DbSelect.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,12 @@ protected function getSelectCount()

return $countSelect;
}

/**
* @return string
*/
public function getCacheInternalId()
{
return hash('sha512', $this->select->getSqlString());
}
}
10 changes: 10 additions & 0 deletions src/Adapter/Iterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,14 @@ public function count()
{
return $this->count;
}

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId()
{
return json_encode($this);
}
}
10 changes: 10 additions & 0 deletions src/Adapter/NullFill.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,14 @@ public function count()
{
return $this->count;
}

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId()
{
return json_encode($this);
}
}
2 changes: 1 addition & 1 deletion src/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ protected function _getCacheInternalId()
// @codingStandardsIgnoreEnd
return md5(
get_class($this->getAdapter())
. json_encode($this->getAdapter())
. $this->getAdapter()->getCacheInternalId()
. $this->getItemCountPerPage()
);
}
Expand Down
96 changes: 95 additions & 1 deletion test/PaginatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace ZendTest\Paginator;

use ArrayIterator;
use ArrayObject;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
Expand Down Expand Up @@ -945,6 +944,101 @@ public function testAcceptsComplexAdapters()
$this->assertInstanceOf('ArrayObject', $paginator->getCurrentItems());
}

/**
* This piece of code tests the failure in determine different cache_id for different queries when using the
* generic TestAdapter. All the results will hit the same cache_id when simulating DbSelectAdapter object.
*/
public function testDbSelectAdapterLikeFailure()
{
$paginator = new Paginator\Paginator(
new TestAsset\TestAdapter(function () {
// Simulate some "real" params
return [
'driver' => [
'name' => 'mysql',
'uptime' => new \DateTime('Y-m-d H:i:s'),
],
'sql' => 'Select * FROM table1 where ID = 1'
];
})
);

$reflectionGetCacheInternalId = new ReflectionMethod($paginator, '_getCacheInternalId');
$reflectionGetCacheInternalId->setAccessible(true);
$firstOutputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($paginator);

sleep(1);

$paginator = new Paginator\Paginator(
new TestAsset\TestAdapter(function () {
return [
// Simulate some "real" params
'driver' => [
'name' => 'mysql',
'uptime' => new \DateTime('Y-m-d H:i:s'),
],
'sql' => 'Select * FROM table2 where ID = 2'
];
})
);
$reflectionGetCacheInternalId = new ReflectionMethod($paginator, '_getCacheInternalId');
$reflectionGetCacheInternalId->setAccessible(true);
$secondOutputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($paginator);

$this->assertEquals($firstOutputGetCacheInternalId, $secondOutputGetCacheInternalId);

$this->assertInstanceOf('ArrayObject', $paginator->getCurrentItems());
}

/**
* This piece of code tests the success in determine different cache_id
* for different queries when using DbSelectAdapter object.
*/
public function testDbSelectAdapterLikeSuccess()
{
$select = new Sql\Select('table1');
$select->where('id = 1');
$select->where('nick = \'test\'');
$paginator = new Paginator\Paginator(
new TestAsset\TestDbSelectAdapter(
$select,
new DbAdapter\Adapter(
new DbAdapter\Driver\Pdo\Pdo(
new DbAdapter\Driver\Pdo\Connection([])
)
)
)
);

$reflectionGetCacheInternalId = new ReflectionMethod($paginator, '_getCacheInternalId');
$reflectionGetCacheInternalId->setAccessible(true);
$firstOutputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($paginator);
$this->assertCount(10, $paginator->getCurrentItems());
$this->assertInstanceOf('ArrayObject', $paginator->getCurrentItems());

$select = new Sql\Select('table2');
$select->where('id = 2');
$select->where('nick = \'test\'');
$paginator = new Paginator\Paginator(
new TestAsset\TestDbSelectAdapter(
$select,
new DbAdapter\Adapter(
new DbAdapter\Driver\Pdo\Pdo(
new DbAdapter\Driver\Pdo\Connection([])
)
)
)
);
$reflectionGetCacheInternalId = new ReflectionMethod($paginator, '_getCacheInternalId');
$reflectionGetCacheInternalId->setAccessible(true);
$secondOutputGetCacheInternalId = $reflectionGetCacheInternalId->invoke($paginator);

$this->assertInstanceOf('ArrayObject', $paginator->getCurrentItems());
$this->assertCount(10, $paginator->getCurrentItems());

$this->assertNotEquals($firstOutputGetCacheInternalId, $secondOutputGetCacheInternalId);
}

/**
* @group 6808
* @group 6809
Expand Down
10 changes: 10 additions & 0 deletions test/TestAsset/TestAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@ public function getItems($pageNumber, $itemCountPerPage)
{
return new \ArrayObject(range(1, 10));
}

/**
* Returns the internal cache id
*
* @return string
*/
public function getCacheInternalId()
{
return json_encode($this);
}
}
23 changes: 23 additions & 0 deletions test/TestAsset/TestDbSelectAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/

namespace ZendTest\Paginator\TestAsset;

class TestDbSelectAdapter extends \Zend\Paginator\Adapter\DbSelect
{
public function count()
{
return 10;
}

public function getItems($pageNumber, $itemCountPerPage)
{
return new \ArrayObject(range(1, 10));
}
}