mirror of
https://github.com/silverstripe/silverstripe-versionfeed
synced 2024-10-22 11:05:31 +02:00
Update from SS_Cache to Symfony/Cache
This commit is contained in:
parent
9a7651b017
commit
17699f2b8a
@ -28,12 +28,13 @@ class CachedContentFilter extends ContentFilter {
|
|||||||
$cacheEnabled = Config::inst()->get(get_class(), 'cache_enabled');
|
$cacheEnabled = Config::inst()->get(get_class(), 'cache_enabled');
|
||||||
$result = (isset($_GET['flush']) || !$cacheEnabled)
|
$result = (isset($_GET['flush']) || !$cacheEnabled)
|
||||||
? null
|
? null
|
||||||
: $cache->load($key);
|
: $cache->get($key);
|
||||||
if($result) return $result;
|
if($result) return $result;
|
||||||
|
|
||||||
// Fallback to generate result
|
// Fallback to generate result
|
||||||
$result = parent::getContent($key, $callback);
|
$result = parent::getContent($key, $callback);
|
||||||
$cache->save($result, $key);
|
$lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
|
||||||
|
$cache->set($result, $key, $lifetime);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@ use SS_Cache;
|
|||||||
|
|
||||||
use SilverStripe\VersionFeed\VersionFeedController;
|
use SilverStripe\VersionFeed\VersionFeedController;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
|
use Psr\SimpleCache\CacheInterface;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -41,13 +42,9 @@ abstract class ContentFilter {
|
|||||||
* @return Zend_Cache_Frontend
|
* @return Zend_Cache_Frontend
|
||||||
*/
|
*/
|
||||||
protected function getCache() {
|
protected function getCache() {
|
||||||
$cache = \SS_Cache::factory(VersionFeedController::class);
|
return Injector::inst()->get(
|
||||||
$cache->setOption('automatic_serialization', true);
|
CacheInterface::class . '.' . VersionFeedController::class
|
||||||
|
);
|
||||||
// Map 0 to null for unlimited lifetime
|
|
||||||
$lifetime = Config::inst()->get(get_class($this), 'cache_lifetime') ?: null;
|
|
||||||
$cache->setLifetime($lifetime);
|
|
||||||
return $cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,7 +94,7 @@ class RateLimitFilter extends ContentFilter {
|
|||||||
// Generate result with rate limiting enabled
|
// Generate result with rate limiting enabled
|
||||||
$limitKey = $this->getCacheKey($key);
|
$limitKey = $this->getCacheKey($key);
|
||||||
$cache = $this->getCache();
|
$cache = $this->getCache();
|
||||||
if($lockedUntil = $cache->load($limitKey)) {
|
if($lockedUntil = $cache->get($limitKey)) {
|
||||||
if(time() < $lockedUntil) {
|
if(time() < $lockedUntil) {
|
||||||
// Politely inform visitor of limit
|
// Politely inform visitor of limit
|
||||||
$response = new HTTPResponse_Exception('Too Many Requests.', 429);
|
$response = new HTTPResponse_Exception('Too Many Requests.', 429);
|
||||||
@ -102,9 +102,11 @@ class RateLimitFilter extends ContentFilter {
|
|||||||
throw $response;
|
throw $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
|
||||||
|
|
||||||
// Apply rate limit
|
// Apply rate limit
|
||||||
$cache->save(time() + $timeout, $limitKey);
|
$cache->set(time() + $timeout, $limitKey, $lifetime);
|
||||||
|
|
||||||
// Generate results
|
// Generate results
|
||||||
$result = parent::getContent($key, $callback);
|
$result = parent::getContent($key, $callback);
|
||||||
@ -112,7 +114,7 @@ class RateLimitFilter extends ContentFilter {
|
|||||||
// Reset rate limit with optional cooldown
|
// Reset rate limit with optional cooldown
|
||||||
if($cooldown = Config::inst()->get(get_class(), 'lock_cooldown')) {
|
if($cooldown = Config::inst()->get(get_class(), 'lock_cooldown')) {
|
||||||
// Set cooldown on successful query execution
|
// Set cooldown on successful query execution
|
||||||
$cache->save(time() + $cooldown, $limitKey);
|
$cache->set(time() + $cooldown, $limitKey, $lifetime);
|
||||||
} else {
|
} else {
|
||||||
// Without cooldown simply disable lock
|
// Without cooldown simply disable lock
|
||||||
$cache->remove($limitKey);
|
$cache->remove($limitKey);
|
||||||
|
@ -121,7 +121,7 @@ class VersionFeed extends SiteTreeExtension {
|
|||||||
$changed = true;
|
$changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the link so it can be cached by SS_Cache.
|
// Copy the link so it can be cached.
|
||||||
$version->GeneratedLink = $version->AbsoluteLink();
|
$version->GeneratedLink = $version->AbsoluteLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ class VersionFeed extends SiteTreeExtension {
|
|||||||
$first = clone($previous);
|
$first = clone($previous);
|
||||||
$first->DiffContent = new HTMLText();
|
$first->DiffContent = new HTMLText();
|
||||||
$first->DiffContent->setValue('<div>' . $first->Content . '</div>');
|
$first->DiffContent->setValue('<div>' . $first->Content . '</div>');
|
||||||
// Copy the link so it can be cached by SS_Cache.
|
// Copy the link so it can be cached.
|
||||||
$first->GeneratedLink = $first->AbsoluteLink();
|
$first->GeneratedLink = $first->AbsoluteLink();
|
||||||
$changeList->push($first);
|
$changeList->push($first);
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\VersionFeed;
|
namespace SilverStripe\VersionFeed;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
use SilverStripe\VersionFeed\VersionFeed;
|
use SilverStripe\VersionFeed\VersionFeed;
|
||||||
use SilverStripe\Control\RSS\RSSFeed;
|
use SilverStripe\Control\RSS\RSSFeed;
|
||||||
@ -25,8 +14,7 @@ use SilverStripe\Versioned\Versioned_Version;
|
|||||||
use SilverStripe\Core\Convert;
|
use SilverStripe\Core\Convert;
|
||||||
use SilverStripe\View\Requirements;
|
use SilverStripe\View\Requirements;
|
||||||
use SilverStripe\Core\Extension;
|
use SilverStripe\Core\Extension;
|
||||||
|
use SilverStripe\VersionFeed\Filters\ContentFilter;
|
||||||
|
|
||||||
|
|
||||||
class VersionFeed_Controller extends Extension {
|
class VersionFeed_Controller extends Extension {
|
||||||
|
|
||||||
@ -38,16 +26,16 @@ class VersionFeed_Controller extends Extension {
|
|||||||
/**
|
/**
|
||||||
* Content handler
|
* Content handler
|
||||||
*
|
*
|
||||||
* @var \VersionFeed\Filters\ContentFilter
|
* @var ContentFilter
|
||||||
*/
|
*/
|
||||||
protected $contentFilter;
|
protected $contentFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the content filter
|
* Sets the content filter
|
||||||
*
|
*
|
||||||
* @param \VersionFeed\Filters\ContentFilter $contentFilter
|
* @param ContentFilter $contentFilter
|
||||||
*/
|
*/
|
||||||
public function setContentFilter(\VersionFeed\Filters\ContentFilter $contentFilter) {
|
public function setContentFilter(ContentFilter $contentFilter) {
|
||||||
$this->contentFilter = $contentFilter;
|
$this->contentFilter = $contentFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,16 +2,14 @@
|
|||||||
|
|
||||||
namespace SilverStripe\VersionFeed\Tests;
|
namespace SilverStripe\VersionFeed\Tests;
|
||||||
|
|
||||||
|
|
||||||
use SS_Cache;
|
|
||||||
use Zend_Cache;
|
|
||||||
|
|
||||||
|
|
||||||
use Page;
|
use Page;
|
||||||
|
|
||||||
use SilverStripe\VersionFeed\VersionFeed;
|
use SilverStripe\VersionFeed\VersionFeed;
|
||||||
|
use SilverStripe\VersionFeed\Filters\CachedContentFilter;
|
||||||
|
use SilverStripe\VersionFeed\Filters\RateLimitFilter;
|
||||||
use SilverStripe\VersionFeed\VersionFeedController;
|
use SilverStripe\VersionFeed\VersionFeedController;
|
||||||
use SilverStripe\Core\Config\Config;
|
use SilverStripe\Core\Config\Config;
|
||||||
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\CMS\Model\SiteTree;
|
use SilverStripe\CMS\Model\SiteTree;
|
||||||
use SilverStripe\Versioned\Versioned;
|
use SilverStripe\Versioned\Versioned;
|
||||||
use SilverStripe\SiteConfig\SiteConfig;
|
use SilverStripe\SiteConfig\SiteConfig;
|
||||||
@ -21,7 +19,7 @@ use SilverStripe\Dev\FunctionalTest;
|
|||||||
class VersionFeedFunctionalTest extends FunctionalTest {
|
class VersionFeedFunctionalTest extends FunctionalTest {
|
||||||
protected $usesDatabase = true;
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
protected $required_extensions = array(
|
||||||
'Page' => array(VersionFeed::class),
|
'Page' => array(VersionFeed::class),
|
||||||
'Page_Controller' => array(VersionFeedController::class),
|
'Page_Controller' => array(VersionFeedController::class),
|
||||||
);
|
);
|
||||||
@ -31,8 +29,10 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
|||||||
public function setUp() {
|
public function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$cache = SS_Cache::factory(VersionFeedController::class);
|
$cache = Injector::inst()->get(
|
||||||
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
|
CacheInterface::class . '.' . VersionFeedController::class
|
||||||
|
);
|
||||||
|
$cache->clear();
|
||||||
|
|
||||||
$this->userIP = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : null;
|
$this->userIP = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : null;
|
||||||
|
|
||||||
@ -42,11 +42,11 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
|||||||
Config::inst()->update(VersionFeed::class, 'allchanges_enabled', true);
|
Config::inst()->update(VersionFeed::class, 'allchanges_enabled', true);
|
||||||
|
|
||||||
// Disable caching and locking by default
|
// Disable caching and locking by default
|
||||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false);
|
Config::inst()->update(CachedContentFilter::class, 'cache_enabled', false);
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0);
|
Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 0);
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_bypage', false);
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_cooldown', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_cooldown', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown() {
|
public function tearDown() {
|
||||||
@ -83,17 +83,18 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
|||||||
|
|
||||||
public function testRateLimiting() {
|
public function testRateLimiting() {
|
||||||
// Re-enable locking just for this test
|
// Re-enable locking just for this test
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 20);
|
Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 20);
|
||||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', true);
|
Config::inst()->update(CachedContentFilter::class, 'cache_enabled', true);
|
||||||
|
|
||||||
$page1 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page1'));
|
$page1 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page1'));
|
||||||
$page2 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page2'));
|
$page2 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page2'));
|
||||||
|
|
||||||
// Artifically set cache lock
|
// Artifically set cache lock
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
|
||||||
$cache = SS_Cache::factory(VersionFeedController::class);
|
$cache = Injector::inst()->get(
|
||||||
$cache->setOption('automatic_serialization', true);
|
CacheInterface::class . '.' . VersionFeedController::class
|
||||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX);
|
);
|
||||||
|
$cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX);
|
||||||
|
|
||||||
// Test normal hit
|
// Test normal hit
|
||||||
$response = $this->get($page1->RelativeLink('changes'));
|
$response = $this->get($page1->RelativeLink('changes'));
|
||||||
@ -104,39 +105,39 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
|||||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||||
|
|
||||||
// Test page specific lock
|
// Test page specific lock
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', true);
|
Config::inst()->update(RateLimitFilter::class, 'lock_bypage', true);
|
||||||
$key = implode('_', array(
|
$key = implode('_', array(
|
||||||
'changes',
|
'changes',
|
||||||
$page1->ID,
|
$page1->ID,
|
||||||
Versioned::get_versionnumber_by_stage(SiteTree::class, 'Live', $page1->ID, false)
|
Versioned::get_versionnumber_by_stage(SiteTree::class, 'Live', $page1->ID, false)
|
||||||
));
|
));
|
||||||
$key = \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5($key);
|
$key = \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5($key);
|
||||||
$cache->save(time() + 10, $key);
|
$cache->set(time() + 10, $key);
|
||||||
$response = $this->get($page1->RelativeLink('changes'));
|
$response = $this->get($page1->RelativeLink('changes'));
|
||||||
$this->assertEquals(429, $response->getStatusCode());
|
$this->assertEquals(429, $response->getStatusCode());
|
||||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||||
$response = $this->get($page2->RelativeLink('changes'));
|
$response = $this->get($page2->RelativeLink('changes'));
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_bypage', false);
|
||||||
|
|
||||||
// Test rate limit hit by IP
|
// Test rate limit hit by IP
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', true);
|
Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', true);
|
||||||
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
|
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
|
||||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
$cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
||||||
$response = $this->get($page1->RelativeLink('changes'));
|
$response = $this->get($page1->RelativeLink('changes'));
|
||||||
$this->assertEquals(429, $response->getStatusCode());
|
$this->assertEquals(429, $response->getStatusCode());
|
||||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||||
|
|
||||||
// Test rate limit doesn't hit other IP
|
// Test rate limit doesn't hit other IP
|
||||||
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.20';
|
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.20';
|
||||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
$cache->set(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
||||||
$response = $this->get($page1->RelativeLink('changes'));
|
$response = $this->get($page1->RelativeLink('changes'));
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
// Restore setting
|
// Restore setting
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
Config::inst()->update(RateLimitFilter::class, 'lock_byuserip', false);
|
||||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0);
|
Config::inst()->update(RateLimitFilter::class, 'lock_timeout', 0);
|
||||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false);
|
Config::inst()->update(CachedContentFilter::class, 'cache_enabled', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testContainsChangesForPageOnly() {
|
public function testContainsChangesForPageOnly() {
|
||||||
|
@ -13,7 +13,7 @@ class VersionFeedTest extends SapphireTest {
|
|||||||
|
|
||||||
protected $usesDatabase = true;
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
protected $requiredExtensions = array(
|
protected $required_extensions = array(
|
||||||
'SiteTree' => array(VersionFeed::class),
|
'SiteTree' => array(VersionFeed::class),
|
||||||
'ContentController' => array(VersionFeedController::class),
|
'ContentController' => array(VersionFeedController::class),
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user