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