MemoryBackend.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <?php
  2. namespace Drupal\Core\Flood;
  3. use Symfony\Component\HttpFoundation\RequestStack;
  4. /**
  5. * Defines the memory flood backend. This is used for testing.
  6. */
  7. class MemoryBackend implements FloodInterface {
  8. /**
  9. * The request stack.
  10. *
  11. * @var \Symfony\Component\HttpFoundation\RequestStack
  12. */
  13. protected $requestStack;
  14. /**
  15. * An array holding flood events, keyed by event name and identifier.
  16. */
  17. protected $events = [];
  18. /**
  19. * Construct the MemoryBackend.
  20. *
  21. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
  22. * The request stack used to retrieve the current request.
  23. */
  24. public function __construct(RequestStack $request_stack) {
  25. $this->requestStack = $request_stack;
  26. }
  27. /**
  28. * {@inheritdoc}
  29. */
  30. public function register($name, $window = 3600, $identifier = NULL) {
  31. if (!isset($identifier)) {
  32. $identifier = $this->requestStack->getCurrentRequest()->getClientIp();
  33. }
  34. // We can't use REQUEST_TIME here, because that would not guarantee
  35. // uniqueness.
  36. $time = microtime(TRUE);
  37. $this->events[$name][$identifier][$time + $window] = $time;
  38. }
  39. /**
  40. * {@inheritdoc}
  41. */
  42. public function clear($name, $identifier = NULL) {
  43. if (!isset($identifier)) {
  44. $identifier = $this->requestStack->getCurrentRequest()->getClientIp();
  45. }
  46. unset($this->events[$name][$identifier]);
  47. }
  48. /**
  49. * {@inheritdoc}
  50. */
  51. public function isAllowed($name, $threshold, $window = 3600, $identifier = NULL) {
  52. if (!isset($identifier)) {
  53. $identifier = $this->requestStack->getCurrentRequest()->getClientIp();
  54. }
  55. if (!isset($this->events[$name][$identifier])) {
  56. return $threshold > 0;
  57. }
  58. $limit = microtime(TRUE) - $window;
  59. $number = count(array_filter($this->events[$name][$identifier], function ($timestamp) use ($limit) {
  60. return $timestamp > $limit;
  61. }));
  62. return ($number < $threshold);
  63. }
  64. /**
  65. * {@inheritdoc}
  66. */
  67. public function garbageCollection() {
  68. foreach ($this->events as $name => $identifiers) {
  69. foreach ($this->events[$name] as $identifier => $timestamps) {
  70. // Filter by key (expiration) but preserve key => value associations.
  71. $this->events[$name][$identifier] = array_filter($timestamps, function () use (&$timestamps) {
  72. $expiration = key($timestamps);
  73. next($timestamps);
  74. return $expiration > microtime(TRUE);
  75. });
  76. }
  77. }
  78. }
  79. }