mirror of
https://github.com/silverstripe/silverstripe-versionfeed
synced 2024-10-22 11:05:31 +02:00
Merge pull request #42 from creative-commoners/pulls/2.0/new-version-feed-v2
Pulls/2.0/new version feed v2
This commit is contained in:
commit
17cf3d7487
@ -1,9 +1,15 @@
|
||||
inherit: true
|
||||
|
||||
build:
|
||||
nodes:
|
||||
analysis:
|
||||
tests:
|
||||
override: [php-scrutinizer-run]
|
||||
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
duplication: true
|
||||
|
||||
filter:
|
||||
paths: [code/*, tests/*]
|
||||
paths: [src/*, tests/*]
|
45
.travis.yml
45
.travis.yml
@ -1,34 +1,35 @@
|
||||
# See https://github.com/silverstripe/silverstripe-travis-support for setup details
|
||||
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
env:
|
||||
- DB=MYSQL CORE_RELEASE=3.5
|
||||
global:
|
||||
- COMPOSER_ROOT_VERSION=2.0.x-dev
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=3
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=3.1
|
||||
- php: 5.6
|
||||
env: DB=PGSQL CORE_RELEASE=3.2
|
||||
env: DB=MYSQL PHPCS_TEST=1 PHPUNIT_TEST=1
|
||||
- php: 7.0
|
||||
env: DB=MYSQL PHPUNIT_TEST=1
|
||||
- php: 7.1
|
||||
env: DB=MYSQL CORE_RELEASE=3.6
|
||||
env: DB=PGSQL PHPUNIT_COVERAGE_TEST=1
|
||||
- php: 7.2
|
||||
env: DB=MYSQL PHPUNIT_TEST=1
|
||||
|
||||
before_script:
|
||||
- composer self-update || true
|
||||
- git clone git://github.com/silverstripe/silverstripe-travis-support.git ~/travis-support
|
||||
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss
|
||||
- cd ~/builds/ss
|
||||
- composer install
|
||||
# Init PHP
|
||||
- phpenv rehash
|
||||
- phpenv config-rm xdebug.ini
|
||||
|
||||
# Install composer dependencies
|
||||
- composer validate
|
||||
- composer require --no-update silverstripe/recipe-core:1.0.x-dev
|
||||
- if [[ $DB == PGSQL ]]; then composer require --no-update silverstripe/postgresql 2.0.x-dev; fi
|
||||
- composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile
|
||||
|
||||
script:
|
||||
- vendor/bin/phpunit versionfeed/tests
|
||||
- if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit; fi
|
||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi
|
||||
- if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs src/ tests/; fi
|
||||
|
||||
after_success:
|
||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml; fi
|
12
.upgrade.yml
Normal file
12
.upgrade.yml
Normal file
@ -0,0 +1,12 @@
|
||||
mappings:
|
||||
VersionFeed: SilverStripe\VersionFeed\VersionFeed
|
||||
VersionFeed_Controller: SilverStripe\VersionFeed\VersionFeedController
|
||||
VersionFeedSiteConfig: SilverStripe\VersionFeed\VersionFeedSiteConfig
|
||||
CachedContentFilter: SilverStripe\VersionFeed\Filters\CachedContentFilter
|
||||
ContentFilter: SilverStripe\VersionFeed\Filters\ContentFilter
|
||||
RateLimitFilter: SilverStripe\VersionFeed\Filters\RateLimitFilter
|
||||
\VersionFeed\Filters\CachedContentFilter: SilverStripe\VersionFeed\Filters\CachedContentFilter
|
||||
\VersionFeed\Filters\ContentFilter: SilverStripe\VersionFeed\Filters\ContentFilter
|
||||
\VersionFeed\Filters\RateLimitFilter: SilverStripe\VersionFeed\Filters\RateLimitFilter
|
||||
VersionFeedFunctionalTest: SilverStripe\VersionFeed\Tests\VersionFeedFunctionalTest
|
||||
VersionFeedTest: SilverStripe\VersionFeed\Tests\VersionFeedTest
|
@ -1,21 +1,25 @@
|
||||
---
|
||||
Name: versionedfeedconfig
|
||||
---
|
||||
Injector:
|
||||
RateLimitFilter: \VersionFeed\Filters\RateLimitFilter
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
RateLimitFilter: SilverStripe\VersionFeed\Filters\RateLimitFilter
|
||||
ContentFilter:
|
||||
class: \VersionFeed\Filters\CachedContentFilter
|
||||
class: SilverStripe\VersionFeed\Filters\CachedContentFilter
|
||||
constructor:
|
||||
- %$RateLimitFilter
|
||||
SiteTree:
|
||||
Psr\SimpleCache\CacheInterface.VersionFeedController:
|
||||
factory: SilverStripe\Core\Cache\CacheFactory
|
||||
constructor:
|
||||
namespace: 'VersionFeedController'
|
||||
SilverStripe\CMS\Model\SiteTree:
|
||||
extensions:
|
||||
- VersionFeed
|
||||
SiteConfig:
|
||||
- SilverStripe\VersionFeed\VersionFeed
|
||||
SilverStripe\SiteConfig\SiteConfig:
|
||||
extensions:
|
||||
- VersionFeedSiteConfig
|
||||
ContentController:
|
||||
- SilverStripe\VersionFeed\VersionFeedSiteConfig
|
||||
SilverStripe\CMS\Controllers\ContentController:
|
||||
extensions:
|
||||
- VersionFeed_Controller
|
||||
VersionFeed_Controller:
|
||||
- SilverStripe\VersionFeed\VersionFeedController
|
||||
SilverStripe\VersionFeed\VersionFeedController:
|
||||
dependencies:
|
||||
ContentFilter: %$ContentFilter
|
||||
|
29
changelog.md
29
changelog.md
@ -1,29 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [1.2.2]
|
||||
|
||||
* Consistent sorting for getDiffList()
|
||||
|
||||
## [1.2.1]
|
||||
|
||||
* Updated userguide documentation
|
||||
* Added standard Scrutinizer config
|
||||
* Added standard code of conduct
|
||||
* Added standard gitattributes
|
||||
* Added standard editor config
|
||||
* Added standard license
|
||||
* Added standard Travis config
|
||||
* Updated license year
|
||||
* Updated translations
|
||||
|
||||
## [1.2.0]
|
||||
|
||||
* Changelog added.
|
||||
* Added Scrutinizer support
|
||||
* Add `ContentFilter.cache_lifetime` config to set the cache lifetime.
|
||||
* Update alternate xml link tag to be W3 compliant
|
||||
* Added CWP keyword
|
1
codecov.yml
Normal file
1
codecov.yml
Normal file
@ -0,0 +1 @@
|
||||
comment: false
|
@ -42,7 +42,7 @@ Two filters are applied on top of one another:
|
||||
server. This filter will only be applied if the `CachedContentFilter` does not have any cached record
|
||||
for a request.
|
||||
|
||||
Either one of these can be replaced, added to, or removed, by adjusting the `VersionFeed_Controller.dependencies`
|
||||
Either one of these can be replaced, added to, or removed, by adjusting the `SilverStripe\VersionFeed\VersionFeedController.dependencies`
|
||||
config to point to a replacement (or no) filter.
|
||||
|
||||
For smaller servers where it's reasonable to apply a strict approach to rate limiting the default
|
||||
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2016, SilverStripe Limited
|
||||
Copyright (c) 2017, SilverStripe Limited
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
9
phpcs.xml.dist
Normal file
9
phpcs.xml.dist
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ruleset name="SilverStripe">
|
||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||
|
||||
<rule ref="PSR2" >
|
||||
<!-- Current exclusions -->
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||
</rule>
|
||||
</ruleset>
|
13
phpunit.xml.dist
Normal file
13
phpunit.xml.dist
Normal file
@ -0,0 +1,13 @@
|
||||
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
|
||||
<testsuite name="Default">
|
||||
<directory>tests/</directory>
|
||||
</testsuite>
|
||||
<filter>
|
||||
<whitelist addUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">src/</directory>
|
||||
<exclude>
|
||||
<directory suffix=".php">tests/</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
@ -1,6 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace VersionFeed\Filters;
|
||||
namespace SilverStripe\VersionFeed\Filters;
|
||||
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Caches results of a callback
|
||||
@ -19,15 +25,16 @@ class CachedContentFilter extends ContentFilter {
|
||||
$cache = $this->getCache();
|
||||
|
||||
// Return cached value if available
|
||||
$cacheEnabled = \Config::inst()->get(get_class(), 'cache_enabled');
|
||||
$cacheEnabled = Config::inst()->get(get_class(), 'cache_enabled');
|
||||
$result = (isset($_GET['flush']) || !$cacheEnabled)
|
||||
? null
|
||||
: $cache->load($key);
|
||||
: $cache->get($key);
|
||||
if($result) return $result;
|
||||
|
||||
// Fallback to generate result
|
||||
$result = parent::getContent($key, $callback);
|
||||
$cache->save($result, $key);
|
||||
$lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
|
||||
$cache->set($key, $result, $lifetime);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace VersionFeed\Filters;
|
||||
namespace SilverStripe\VersionFeed\Filters;
|
||||
|
||||
use SilverStripe\VersionFeed\VersionFeedController;
|
||||
use SilverStripe\Core\Config\Configurable;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Conditionally executes a given callback, attempting to return the desired results
|
||||
@ -8,6 +15,8 @@ namespace VersionFeed\Filters;
|
||||
*/
|
||||
abstract class ContentFilter {
|
||||
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* Nested content filter
|
||||
*
|
||||
@ -33,13 +42,9 @@ abstract class ContentFilter {
|
||||
* @return Zend_Cache_Frontend
|
||||
*/
|
||||
protected function getCache() {
|
||||
$cache = \SS_Cache::factory('VersionFeed_Controller');
|
||||
$cache->setOption('automatic_serialization', true);
|
||||
|
||||
// Map 0 to null for unlimited lifetime
|
||||
$lifetime = \Config::inst()->get(get_class($this), 'cache_lifetime') ?: null;
|
||||
$cache->setLifetime($lifetime);
|
||||
return $cache;
|
||||
return Injector::inst()->get(
|
||||
CacheInterface::class . '.VersionFeedController'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace VersionFeed\Filters;
|
||||
namespace SilverStripe\VersionFeed\Filters;
|
||||
|
||||
|
||||
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\HTTPResponse_Exception;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Provides rate limiting of execution of a callback
|
||||
@ -60,13 +70,13 @@ class RateLimitFilter extends ContentFilter {
|
||||
$key = self::CACHE_PREFIX;
|
||||
|
||||
// Add global identifier
|
||||
if(\Config::inst()->get(get_class(), 'lock_bypage')) {
|
||||
if($this->config()->get('lock_bypage')) {
|
||||
$key .= '_' . md5($itemkey);
|
||||
}
|
||||
|
||||
// Add user-specific identifier
|
||||
if(\Config::inst()->get(get_class(), 'lock_byuserip') && \Controller::has_curr()) {
|
||||
$ip = \Controller::curr()->getRequest()->getIP();
|
||||
if($this->config()->get('lock_byuserip') && Controller::has_curr()) {
|
||||
$ip = Controller::curr()->getRequest()->getIP();
|
||||
$key .= '_' . md5($ip);
|
||||
}
|
||||
|
||||
@ -76,7 +86,7 @@ class RateLimitFilter extends ContentFilter {
|
||||
|
||||
public function getContent($key, $callback) {
|
||||
// Bypass rate limiting if flushing, or timeout isn't set
|
||||
$timeout = \Config::inst()->get(get_class(), 'lock_timeout');
|
||||
$timeout = $this->config()->get('lock_timeout');
|
||||
if(isset($_GET['flush']) || !$timeout) {
|
||||
return parent::getContent($key, $callback);
|
||||
}
|
||||
@ -84,28 +94,30 @@ class RateLimitFilter extends ContentFilter {
|
||||
// Generate result with rate limiting enabled
|
||||
$limitKey = $this->getCacheKey($key);
|
||||
$cache = $this->getCache();
|
||||
if($lockedUntil = $cache->load($limitKey)) {
|
||||
if($lockedUntil = $cache->get($limitKey)) {
|
||||
if(time() < $lockedUntil) {
|
||||
// Politely inform visitor of limit
|
||||
$response = new \SS_HTTPResponse_Exception('Too Many Requests.', 429);
|
||||
$response = new HTTPResponse_Exception('Too Many Requests.', 429);
|
||||
$response->getResponse()->addHeader('Retry-After', 1 + $lockedUntil - time());
|
||||
throw $response;
|
||||
}
|
||||
}
|
||||
|
||||
$lifetime = Config::inst()->get(ContentFilter::class, 'cache_lifetime') ?: null;
|
||||
|
||||
// Apply rate limit
|
||||
$cache->save(time() + $timeout, $limitKey);
|
||||
$cache->set($limitKey, time() + $timeout, $lifetime);
|
||||
|
||||
// Generate results
|
||||
$result = parent::getContent($key, $callback);
|
||||
|
||||
// Reset rate limit with optional cooldown
|
||||
if($cooldown = \Config::inst()->get(get_class(), 'lock_cooldown')) {
|
||||
if($cooldown = $this->config()->get('lock_cooldown')) {
|
||||
// Set cooldown on successful query execution
|
||||
$cache->save(time() + $cooldown, $limitKey);
|
||||
$cache->set($limitKey, time() + $cooldown, $lifetime);
|
||||
} else {
|
||||
// Without cooldown simply disable lock
|
||||
$cache->remove($limitKey);
|
||||
$cache->delete($limitKey);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -1,5 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\VersionFeed;
|
||||
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\View\Parsers\Diff;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
use SilverStripe\Forms\LiteralField;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\CMS\Model\SiteTreeExtension;
|
||||
|
||||
class VersionFeed extends SiteTreeExtension {
|
||||
|
||||
private static $db = array(
|
||||
@ -80,7 +93,7 @@ class VersionFeed extends SiteTreeExtension {
|
||||
if ($version->Title != $previous->Title) {
|
||||
$diffTitle = Diff::compareHTML($version->Title, $previous->Title);
|
||||
|
||||
$version->DiffTitle = new HTMLText();
|
||||
$version->DiffTitle = DBField::create_field('HTMLText', null);
|
||||
$version->DiffTitle->setValue(
|
||||
sprintf(
|
||||
'<div><em>%s</em> ' . $diffTitle . '</div>',
|
||||
@ -93,12 +106,12 @@ class VersionFeed extends SiteTreeExtension {
|
||||
if ($version->Content != $previous->Content) {
|
||||
$diffContent = Diff::compareHTML($version->Content, $previous->Content);
|
||||
|
||||
$version->DiffContent = new HTMLText();
|
||||
$version->DiffContent = DBField::create_field('HTMLText', null);
|
||||
$version->DiffContent->setValue('<div>'.$diffContent.'</div>');
|
||||
$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();
|
||||
}
|
||||
|
||||
@ -117,9 +130,9 @@ class VersionFeed extends SiteTreeExtension {
|
||||
// a diff on the initial version we will just get that version, verbatim.
|
||||
if ($previous && $versions->count()<$qLimit) {
|
||||
$first = clone($previous);
|
||||
$first->DiffContent = new HTMLText();
|
||||
$first->DiffContent = DBField::create_field('HTMLText', null);
|
||||
$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();
|
||||
$changeList->push($first);
|
||||
}
|
||||
|
@ -1,6 +1,22 @@
|
||||
<?php
|
||||
|
||||
class VersionFeed_Controller extends Extension {
|
||||
namespace SilverStripe\VersionFeed;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\VersionFeed\VersionFeed;
|
||||
use SilverStripe\Control\RSS\RSSFeed;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Versioned\Versioned_Version;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\View\Requirements;
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\VersionFeed\Filters\ContentFilter;
|
||||
|
||||
class VersionFeedController extends Extension {
|
||||
|
||||
private static $allowed_actions = array(
|
||||
'changes',
|
||||
@ -10,16 +26,16 @@ class VersionFeed_Controller extends Extension {
|
||||
/**
|
||||
* Content handler
|
||||
*
|
||||
* @var \VersionFeed\Filters\ContentFilter
|
||||
* @var ContentFilter
|
||||
*/
|
||||
protected $contentFilter;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@ -48,7 +64,7 @@ class VersionFeed_Controller extends Extension {
|
||||
*/
|
||||
public function changes() {
|
||||
// Check viewability of changes
|
||||
if(!Config::inst()->get('VersionFeed', 'changes_enabled')
|
||||
if(!Config::inst()->get(VersionFeed::class, 'changes_enabled')
|
||||
|| !$this->owner->PublicHistory
|
||||
|| $this->owner->Version == ''
|
||||
) {
|
||||
@ -59,7 +75,7 @@ class VersionFeed_Controller extends Extension {
|
||||
$target = $this->owner;
|
||||
$key = implode('_', array('changes', $this->owner->ID, $this->owner->Version));
|
||||
$entries = $this->filterContent($key, function() use ($target) {
|
||||
return $target->getDiffList(null, Config::inst()->get('VersionFeed', 'changes_limit'));
|
||||
return $target->getDiffList(null, Config::inst()->get(VersionFeed::class, 'changes_limit'));
|
||||
});
|
||||
|
||||
// Generate the output.
|
||||
@ -74,13 +90,13 @@ class VersionFeed_Controller extends Extension {
|
||||
*/
|
||||
public function allchanges() {
|
||||
// Check viewability of allchanges
|
||||
if(!Config::inst()->get('VersionFeed', 'allchanges_enabled')
|
||||
if(!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
|
||||
|| !SiteConfig::current_site_config()->AllChangesEnabled
|
||||
) {
|
||||
return $this->owner->httpError(404, 'Global history not viewable');
|
||||
}
|
||||
|
||||
$limit = (int)Config::inst()->get('VersionFeed', 'allchanges_limit');
|
||||
$limit = (int)Config::inst()->get(VersionFeed::class, 'allchanges_limit');
|
||||
$latestChanges = DB::query('
|
||||
SELECT * FROM "SiteTree_versions"
|
||||
WHERE "WasPublished" = \'1\'
|
||||
@ -135,7 +151,7 @@ class VersionFeed_Controller extends Extension {
|
||||
* Generates and embeds the RSS header link for the page-specific version rss feed
|
||||
*/
|
||||
public function linkToPageRSSFeed() {
|
||||
if (!Config::inst()->get('VersionFeed', 'changes_enabled') || !$this->owner->PublicHistory) {
|
||||
if (!Config::inst()->get(VersionFeed::class, 'changes_enabled') || !$this->owner->PublicHistory) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,7 +168,7 @@ class VersionFeed_Controller extends Extension {
|
||||
* Generates and embeds the RSS header link for the global version rss feed
|
||||
*/
|
||||
public function linkToAllSiteRSSFeed() {
|
||||
if(!Config::inst()->get('VersionFeed', 'allchanges_enabled')
|
||||
if(!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')
|
||||
|| !SiteConfig::current_site_config()->AllChangesEnabled
|
||||
) {
|
||||
return;
|
||||
|
@ -1,5 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\VersionFeed;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\VersionFeed\VersionFeed;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows global configuration of all changes
|
||||
*/
|
||||
@ -17,8 +33,8 @@ class VersionFeedSiteConfig extends DataExtension {
|
||||
$labels['AllChangesEnabled'] = _t('VersionFeedSiteConfig.ALLCHANGESLABEL', 'Make global changes feed public');
|
||||
}
|
||||
|
||||
public function updateCMSFields(\FieldList $fields) {
|
||||
if(!Config::inst()->get('VersionFeed', 'allchanges_enabled')) return;
|
||||
public function updateCMSFields(FieldList $fields) {
|
||||
if(!Config::inst()->get(VersionFeed::class, 'allchanges_enabled')) return;
|
||||
|
||||
$fields->addFieldToTab('Root.Access',
|
||||
FieldGroup::create(new CheckboxField('AllChangesEnabled', $this->owner->fieldLabel('AllChangesEnabled')))
|
||||
|
@ -1,39 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\VersionFeed\Tests;
|
||||
|
||||
use Page;
|
||||
|
||||
use SilverStripe\VersionFeed\VersionFeed;
|
||||
use SilverStripe\VersionFeed\Filters\CachedContentFilter;
|
||||
use SilverStripe\VersionFeed\Filters\RateLimitFilter;
|
||||
use SilverStripe\VersionFeed\VersionFeedController;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\Control\Director;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
|
||||
class VersionFeedFunctionalTest extends FunctionalTest {
|
||||
protected $usesDatabase = true;
|
||||
|
||||
protected $requiredExtensions = array(
|
||||
'Page' => array('VersionFeed'),
|
||||
'Page_Controller' => array('VersionFeed_Controller'),
|
||||
protected $baseURI = 'http://www.fakesite.test';
|
||||
|
||||
protected static $required_extensions = array(
|
||||
'Page' => array(VersionFeed::class),
|
||||
'PageController' => array(VersionFeedController::class),
|
||||
);
|
||||
|
||||
protected $userIP;
|
||||
|
||||
public function setUp() {
|
||||
protected function setUp() {
|
||||
Director::config()->set('alternate_base_url', $this->baseURI);
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$cache = SS_Cache::factory('VersionFeed_Controller');
|
||||
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
|
||||
$cache = Injector::inst()->get(
|
||||
CacheInterface::class . '.VersionFeedController'
|
||||
);
|
||||
$cache->clear();
|
||||
|
||||
$this->userIP = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : null;
|
||||
$this->userIP = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
|
||||
|
||||
Config::nest();
|
||||
// Enable history by default
|
||||
Config::inst()->update('VersionFeed', 'changes_enabled', true);
|
||||
Config::inst()->update('VersionFeed', 'allchanges_enabled', true);
|
||||
Config::modify()->set(VersionFeed::class, 'changes_enabled', true);
|
||||
Config::modify()->set(VersionFeed::class, 'allchanges_enabled', true);
|
||||
|
||||
// Disable caching and locking by default
|
||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false);
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0);
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false);
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_cooldown', false);
|
||||
Config::modify()->set(CachedContentFilter::class, 'cache_enabled', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_timeout', 0);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_bypage', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_byuserip', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_cooldown', false);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
Config::unnest();
|
||||
Director::config()->set('alternate_base_url', null);
|
||||
|
||||
$_SERVER['HTTP_CLIENT_IP'] = $this->userIP;
|
||||
$_SERVER['REMOTE_ADDR'] = $this->userIP;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
@ -64,17 +88,18 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
||||
|
||||
public function testRateLimiting() {
|
||||
// Re-enable locking just for this test
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 20);
|
||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', true);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_timeout', 20);
|
||||
Config::modify()->set(CachedContentFilter::class, 'cache_enabled', true);
|
||||
|
||||
$page1 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page1'));
|
||||
$page2 = $this->createPageWithChanges(array('PublicHistory' => true, 'Title' => 'Page2'));
|
||||
|
||||
// Artifically set cache lock
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
||||
$cache = SS_Cache::factory('VersionFeed_Controller');
|
||||
$cache->setOption('automatic_serialization', true);
|
||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_byuserip', false);
|
||||
$cache = Injector::inst()->get(
|
||||
CacheInterface::class . '.VersionFeedController'
|
||||
);
|
||||
$cache->set(RateLimitFilter::CACHE_PREFIX, time() + 10);
|
||||
|
||||
// Test normal hit
|
||||
$response = $this->get($page1->RelativeLink('changes'));
|
||||
@ -85,39 +110,39 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||
|
||||
// Test page specific lock
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', true);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_bypage', true);
|
||||
$key = implode('_', array(
|
||||
'changes',
|
||||
$page1->ID,
|
||||
Versioned::get_versionnumber_by_stage('SiteTree', 'Live', $page1->ID, false)
|
||||
Versioned::get_versionnumber_by_stage(SiteTree::class, 'Live', $page1->ID, false)
|
||||
));
|
||||
$key = \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5($key);
|
||||
$cache->save(time() + 10, $key);
|
||||
$key = RateLimitFilter::CACHE_PREFIX . '_' . md5($key);
|
||||
$cache->set($key, time() + 10);
|
||||
$response = $this->get($page1->RelativeLink('changes'));
|
||||
$this->assertEquals(429, $response->getStatusCode());
|
||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||
$response = $this->get($page2->RelativeLink('changes'));
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_bypage', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_bypage', false);
|
||||
|
||||
// Test rate limit hit by IP
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', true);
|
||||
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
|
||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_byuserip', true);
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$cache->set(RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'), time() + 10);
|
||||
$response = $this->get($page1->RelativeLink('changes'));
|
||||
$this->assertEquals(429, $response->getStatusCode());
|
||||
$this->assertGreaterThan(0, $response->getHeader('Retry-After'));
|
||||
|
||||
// Test rate limit doesn't hit other IP
|
||||
$_SERVER['HTTP_CLIENT_IP'] = '127.0.0.20';
|
||||
$cache->save(time() + 10, \VersionFeed\Filters\RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'));
|
||||
$_SERVER['REMOTE_ADDR'] = '127.0.0.20';
|
||||
$cache->set(RateLimitFilter::CACHE_PREFIX . '_' . md5('127.0.0.1'), time() + 10);
|
||||
$response = $this->get($page1->RelativeLink('changes'));
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
// Restore setting
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_byuserip', false);
|
||||
Config::inst()->update('VersionFeed\Filters\RateLimitFilter', 'lock_timeout', 0);
|
||||
Config::inst()->update('VersionFeed\Filters\CachedContentFilter', 'cache_enabled', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_byuserip', false);
|
||||
Config::modify()->set(RateLimitFilter::class, 'lock_timeout', 0);
|
||||
Config::modify()->set(CachedContentFilter::class, 'cache_enabled', false);
|
||||
}
|
||||
|
||||
public function testContainsChangesForPageOnly() {
|
||||
@ -195,7 +220,7 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
||||
|
||||
// Test requests to 'changes' action
|
||||
foreach(array(true, false) as $publicHistory_Config) {
|
||||
Config::inst()->update('VersionFeed', 'changes_enabled', $publicHistory_Config);
|
||||
Config::modify()->set(VersionFeed::class, 'changes_enabled', $publicHistory_Config);
|
||||
$expectedResponse = $publicHistory_Page && $publicHistory_Config ? 200 : 404;
|
||||
$response = $this->get($page->RelativeLink('changes'));
|
||||
$this->assertEquals($expectedResponse, $response->getStatusCode());
|
||||
@ -204,7 +229,7 @@ class VersionFeedFunctionalTest extends FunctionalTest {
|
||||
// Test requests to 'allchanges' action on each page
|
||||
foreach(array(true, false) as $allChanges_Config) {
|
||||
foreach(array(true, false) as $allChanges_SiteConfig) {
|
||||
Config::inst()->update('VersionFeed', 'allchanges_enabled', $allChanges_Config);
|
||||
Config::modify()->set(VersionFeed::class, 'allchanges_enabled', $allChanges_Config);
|
||||
$siteConfig = SiteConfig::current_site_config();
|
||||
$siteConfig->AllChangesEnabled = $allChanges_SiteConfig;
|
||||
$siteConfig->write();
|
||||
|
@ -1,16 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\VersionFeed\Tests;
|
||||
|
||||
|
||||
use Page;
|
||||
use SilverStripe\VersionFeed\VersionFeed;
|
||||
use SilverStripe\VersionFeed\VersionFeedController;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\CMS\Controllers\ContentController;
|
||||
|
||||
|
||||
class VersionFeedTest extends SapphireTest {
|
||||
|
||||
protected $usesDatabase = true;
|
||||
|
||||
protected $requiredExtensions = array(
|
||||
'SiteTree' => array('VersionFeed'),
|
||||
'ContentController' => array('VersionFeed_Controller'),
|
||||
);
|
||||
protected static $required_extensions = [
|
||||
SiteTree::class => [VersionFeed::class],
|
||||
ContentController::class => [VersionFeedController::class],
|
||||
];
|
||||
|
||||
protected $illegalExtensions = array(
|
||||
'SiteTree' => array('Translatable')
|
||||
);
|
||||
protected $illegalExtensions = [
|
||||
'SiteTree' => ['Translatable']
|
||||
];
|
||||
|
||||
public function testDiffedChangesExcludesRestrictedItems() {
|
||||
$this->markTestIncomplete();
|
||||
@ -21,7 +33,7 @@ class VersionFeedTest extends SapphireTest {
|
||||
}
|
||||
|
||||
public function testDiffedChangesTitle() {
|
||||
$page = new Page(array('Title' => 'My Title'));
|
||||
$page = new Page(['Title' => 'My Title']);
|
||||
$page->write();
|
||||
$page->publish('Stage', 'Live');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user