Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php
namespace Drupal\private_message_flood\Service;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
/**
* Provides services for the Private Message Flood Protection module.
*/
class PrivateMessageFloodService implements PrivateMessageFloodServiceInterface {
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* Constructs a PrivateMessageFloodService object.
*
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user.
* @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
* The configuration factory.
* @param \Drupal\Component\Datetime\TimeInterface $time
* The time service.
*/
public function __construct(
AccountProxyInterface $currentUser,
ConfigFactoryInterface $configFactory,
TimeInterface $time
) {
$this->currentUser = $currentUser;
$this->configFactory = $configFactory;
$this->time = $time;
}
/**
* {@inheritdoc}
*/
public function checkUserFlood() {
$flood_info = $this->getFloodProtectionInfo();
// Check if we even need to check anything.
if ($limit = $flood_info['limit']) {
// Get the amount of time in which they are limited to make said number of
// posts.
$duration = new \DateInterval($flood_info['duration']);
// Get the current time.
$now = new \DateTime();
$now->setTimestamp($this->time->getRequestTime());
// Get the UNIX timestamp for time that is $duration ago from now. For
// example, if $duration is one year, then $since will be the exact date
// and time one year ago from now.
$since = $now->sub($duration)->format('U');
// Query the number of posts that the user has made since the given
// timestamp.
$post_count = db_select('private_messages', 'pm')
->fields('pm', ['id'])
->condition('owner', $this->currentUser->id())
->condition('created', $since, '>=')
->countQuery()
->execute()
->fetchField();
// Return TRUE if they've posted their limit already, FALSE if they have
// not.
return $post_count >= $limit;
}
// If there is no limit for the user, then they have no flood protection
// applied to them, and therefore are unable to flood.
return FALSE;
}
/**
* Gets flood protection info for the current user, based on their roles.
*
* Each role in the system can be assigned flood protection settings. Roles
* are also assigned a priority. This function fetches the flood protection
* data for the highest prioirty role that the current user has.
*
* @return array
* An array of flood protection data for the current user based on their
* roles.
*/
private function getFloodProtectionInfo() {
$user_roles = $this->currentUser->getRoles();
$role = array_intersect_key($this->getRoleInfo(), array_flip($user_roles));
$role_id = key($role);
$config = $this->configFactory->get('private_message_flood.role.' . $role_id);
if ($config) {
return $config->get();
}
return [
'limit' => 0,
];
}
/**
* Fetches an array of roles, ordered by priority.
*
* Each role in the system may have flood protection settings that determine
* how many posts a user can make in a given duration. Roles have priority,
* and the highest priority role is the one that a user is checked against
* when determining whether or not they have crossed the threshold for their
* flood settings.
*
* @return array
* An array of roles that have flood protection assigned to them, keyed by
* the role ID, with the value being the weight. Roles in the array are
* ordered highest to lowest priority.
*/
private function getRoleInfo() {
$roles = array_map(['\Drupal\Component\Utility\Html', 'escape'], user_role_names(TRUE));
$items = [];
foreach (array_keys($roles) as $role_id) {
$role_info = $this->configFactory->get('private_message_flood.role.' . $role_id)->get();
$items[$role_id] = $role_info['weight'];
}
uasort($items, [$this, 'sortByWeight']);
return $items;
}
/**
* Sorting callback to sort arrays by their 'weight' attribute.
*/
private function sortByWeight($a, $b) {
if ($a === $b) {
return 0;
}
return $a > $b ? 1 : -1;
}
}