diff --git a/core/lib/Drupal/Core/Flood/DatabaseBackend.php b/core/lib/Drupal/Core/Flood/DatabaseBackend.php index 95b19ff..2f59e0d 100644 --- a/core/lib/Drupal/Core/Flood/DatabaseBackend.php +++ b/core/lib/Drupal/Core/Flood/DatabaseBackend.php @@ -7,7 +7,6 @@ namespace Drupal\Core\Flood; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Drupal\Core\Database\Connection; @@ -24,9 +23,9 @@ class DatabaseBackend implements FloodInterface { protected $connection; /** - * A request object. + * The request stack. * - * @var \Symfony\Component\HttpFoundation\Request + * @var \Symfony\Component\HttpFoundation\RequestStack */ protected $requestStack; @@ -49,7 +48,7 @@ public function __construct(Connection $connection, RequestStack $request_stack) */ public function register($name, $window = 3600, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->getDefaultIdentifier(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } $this->connection->insert('flood') ->fields(array( @@ -66,7 +65,7 @@ public function register($name, $window = 3600, $identifier = NULL) { */ public function clear($name, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->getDefaultIdentifier(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } $this->connection->delete('flood') ->condition('event', $name) @@ -79,7 +78,7 @@ public function clear($name, $identifier = NULL) { */ public function isAllowed($name, $threshold, $window = 3600, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->getDefaultIdentifier(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } $number = $this->connection->select('flood', 'f') ->condition('event', $name) @@ -100,17 +99,4 @@ public function garbageCollection() { ->execute(); } - /** - * Return the default identifier. - */ - protected function getDefaultIdentifier() { - $request = $this->requestStack->getCurrentRequest(); - - if (!$request) { - $request = Request::createFromGlobals(); - } - - return $request->getClientIp(); - } - } diff --git a/core/lib/Drupal/Core/Flood/MemoryBackend.php b/core/lib/Drupal/Core/Flood/MemoryBackend.php index 13ab55a..e05e64f 100644 --- a/core/lib/Drupal/Core/Flood/MemoryBackend.php +++ b/core/lib/Drupal/Core/Flood/MemoryBackend.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Flood; -use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; /** * Defines the memory flood backend. This is used for testing. @@ -15,11 +15,11 @@ class MemoryBackend implements FloodInterface { /** - * A request object. + * The request stack. * - * @var \Symfony\Component\HttpFoundation\Request + * @var \Symfony\Component\HttpFoundation\RequestStack */ - protected $request; + protected $requestStack; /** * An array holding flood events, keyed by event name and identifier. @@ -29,11 +29,11 @@ class MemoryBackend implements FloodInterface { /** * Construct the MemoryBackend. * - * @param \Symfony\Component\HttpFoundation\Request $request - * The HttpRequest object representing the current request. + * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack + * The request stack used to retrieve the current request. */ - public function __construct(Request $request) { - $this->request = $request; + public function __construct(RequestStack $request_stack) { + $this->requestStack = $request_stack; } /** @@ -41,11 +41,11 @@ public function __construct(Request $request) { */ public function register($name, $window = 3600, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->request->getClientIP(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } // We can't use REQUEST_TIME here, because that would not guarantee // uniqueness. - $time = microtime(true); + $time = microtime(TRUE); $this->events[$name][$identifier][$time + $window] = $time; } @@ -54,7 +54,7 @@ public function register($name, $window = 3600, $identifier = NULL) { */ public function clear($name, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->request->getClientIP(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } unset($this->events[$name][$identifier]); } @@ -64,9 +64,9 @@ public function clear($name, $identifier = NULL) { */ public function isAllowed($name, $threshold, $window = 3600, $identifier = NULL) { if (!isset($identifier)) { - $identifier = $this->request->getClientIP(); + $identifier = $this->requestStack->getCurrentRequest()->getClientIp(); } - $limit = microtime(true) - $window; + $limit = microtime(TRUE) - $window; $number = count(array_filter($this->events[$name][$identifier], function ($timestamp) use ($limit) { return $timestamp > $limit; })); @@ -83,7 +83,7 @@ public function garbageCollection() { $this->events[$name][$identifier] = array_filter($timestamps, function () use (&$timestamps) { $expiration = key($timestamps); next($timestamps); - return $expiration > microtime(true); + return $expiration > microtime(TRUE); }); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/System/FloodTest.php b/core/modules/system/lib/Drupal/system/Tests/System/FloodTest.php index e7cbdb2..088a641 100644 --- a/core/modules/system/lib/Drupal/system/Tests/System/FloodTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/System/FloodTest.php @@ -16,12 +16,8 @@ class FloodTest extends WebTestBase { /** - * The Request object that flood classes should use. - * - * @var \Symfony\Component\HttpFoundation\Request + * {@inheritdoc} */ - protected $request; - public static function getInfo() { return array( 'name' => 'Flood control mechanism', @@ -30,19 +26,22 @@ public static function getInfo() { ); } + /** + * {@inheritdoc} + */ public function setUp() { parent::setUp(); // Flood backends need a request object. Create a dummy one and insert it // to the container. - $this->request = Request::createFromGlobals(); - $this->container->set('request', $this->request); + $request = Request::createFromGlobals(); + $this->container->get('request_stack')->push($request); } /** * Test flood control mechanism clean-up. */ - function testCleanUp() { + public function testCleanUp() { $threshold = 1; $window_expired = -1; $name = 'flood_test_cleanup'; @@ -68,12 +67,13 @@ function testCleanUp() { /** * Test flood control memory backend. */ - function testMemoryBackend() { + public function testMemoryBackend() { $threshold = 1; $window_expired = -1; $name = 'flood_test_cleanup'; - $flood = new \Drupal\Core\Flood\MemoryBackend($this->request); + $request_stack = \Drupal::service('request_stack'); + $flood = new \Drupal\Core\Flood\MemoryBackend($request_stack); // Register expired event. $flood->register($name, $window_expired); // Verify event is not allowed. @@ -90,4 +90,33 @@ function testMemoryBackend() { $flood->garbageCollection(); $this->assertFalse($flood->isAllowed($name, $threshold)); } + + /** + * Test flood control database backend. + */ + public function testDatabaseBackend() { + $threshold = 1; + $window_expired = -1; + $name = 'flood_test_cleanup'; + + $connection = \Drupal::service('database'); + $request_stack = \Drupal::service('request_stack'); + $flood = new \Drupal\Core\Flood\DatabaseBackend($connection, $request_stack); + // Register expired event. + $flood->register($name, $window_expired); + // Verify event is not allowed. + $this->assertFalse($flood->isAllowed($name, $threshold)); + // Run cron and verify event is now allowed. + $flood->garbageCollection(); + $this->assertTrue($flood->isAllowed($name, $threshold)); + + // Register unexpired event. + $flood->register($name); + // Verify event is not allowed. + $this->assertFalse($flood->isAllowed($name, $threshold)); + // Run cron and verify event is still not allowed. + $flood->garbageCollection(); + $this->assertFalse($flood->isAllowed($name, $threshold)); + } + }