1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Elgg\Database; |
4
|
|
|
|
5
|
|
|
use Elgg\Database; |
6
|
|
|
use Elgg\Email\DelayedQueue\DatabaseRecord; |
7
|
|
|
use Elgg\Traits\TimeUsing; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Interfaces with the database to perform operations on the delayed_email_queue table |
11
|
|
|
* |
12
|
|
|
* @internal |
13
|
|
|
* @since 4.0 |
14
|
|
|
*/ |
15
|
|
|
class DelayedEmailQueueTable { |
16
|
|
|
|
17
|
|
|
use TimeUsing; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var string name of the database table |
21
|
|
|
*/ |
22
|
|
|
const TABLE_NAME = 'delayed_email_queue'; |
23
|
|
|
|
24
|
|
|
protected Database $db; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Create new service |
28
|
|
|
* |
29
|
|
|
* @param Database $db the database service |
30
|
|
|
*/ |
31
|
505 |
|
public function __construct(Database $db) { |
32
|
505 |
|
$this->db = $db; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Insert a delayed email into the queue |
37
|
|
|
* |
38
|
|
|
* @param int $recipient_guid the recipient of the email |
39
|
|
|
* @param string $delivery_interval the desired interval of the recipient |
40
|
|
|
* @param mixed $item the email to queue |
41
|
|
|
* |
42
|
|
|
* @return bool |
43
|
|
|
*/ |
44
|
14 |
|
public function queueEmail(int $recipient_guid, string $delivery_interval, $item): bool { |
45
|
14 |
|
$insert = Insert::intoTable(self::TABLE_NAME); |
46
|
14 |
|
$insert->values([ |
47
|
14 |
|
'recipient_guid' => $insert->param($recipient_guid, ELGG_VALUE_GUID), |
48
|
14 |
|
'delivery_interval' => $insert->param($delivery_interval, ELGG_VALUE_STRING), |
49
|
14 |
|
'data' => $insert->param(serialize($item), ELGG_VALUE_STRING), |
50
|
14 |
|
'timestamp' => $insert->param($this->getCurrentTime()->getTimestamp(), ELGG_VALUE_TIMESTAMP), |
51
|
14 |
|
]); |
52
|
|
|
|
53
|
14 |
|
return $this->db->insertData($insert) !== 0; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Get a row from the queue |
58
|
|
|
* |
59
|
|
|
* @param int $id the ID to fetch |
60
|
|
|
* |
61
|
|
|
* @return DatabaseRecord|null database row |
62
|
|
|
*/ |
63
|
2 |
|
public function getRow(int $id): ?DatabaseRecord { |
64
|
2 |
|
$select = Select::fromTable(self::TABLE_NAME); |
65
|
2 |
|
$select->select('*') |
66
|
2 |
|
->where($select->compare('id', '=', $id, ELGG_VALUE_ID)); |
67
|
|
|
|
68
|
2 |
|
return $this->db->getDataRow($select, [$this, 'rowToRecord']); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* Get all the rows in the queue for a given recipient |
73
|
|
|
* |
74
|
|
|
* @param int $recipient_guid the recipient |
75
|
|
|
* @param string $delivery_interval the interval for the recipient |
76
|
|
|
* @param null|int $timestamp (optional) all queue items before time (default: now) |
77
|
|
|
* @param int $max_results (optional) maximum number of rows to return |
78
|
|
|
* |
79
|
|
|
* @return DatabaseRecord[] database rows |
80
|
|
|
*/ |
81
|
8 |
|
public function getRecipientRows(int $recipient_guid, string $delivery_interval, int $timestamp = null, int $max_results = 0): array { |
82
|
8 |
|
$select = Select::fromTable(self::TABLE_NAME); |
83
|
8 |
|
$select->select('*') |
84
|
8 |
|
->where($select->compare('recipient_guid', '=', $recipient_guid, ELGG_VALUE_GUID)) |
85
|
8 |
|
->andWhere($select->compare('delivery_interval', '=', $delivery_interval, ELGG_VALUE_STRING)) |
86
|
8 |
|
->andWhere($select->compare('timestamp', '<', $timestamp ?? $this->getCurrentTime()->getTimestamp(), ELGG_VALUE_TIMESTAMP)) |
87
|
8 |
|
->orderBy('timestamp', 'ASC') |
88
|
8 |
|
->addOrderBy('id', 'ASC'); |
89
|
|
|
|
90
|
8 |
|
if ($max_results > 0) { |
91
|
3 |
|
$select->setMaxResults($max_results); |
92
|
|
|
} |
93
|
|
|
|
94
|
8 |
|
return $this->db->getData($select, [$this, 'rowToRecord']); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Fetch the GUID of the next recipient to process |
99
|
|
|
* |
100
|
|
|
* @param string $delivery_interval the delivery interval to get |
101
|
|
|
* @param null|int $timestamp (optional) based on queue items before time (default: now) |
102
|
|
|
* |
103
|
|
|
* @return null|int |
104
|
|
|
*/ |
105
|
2 |
|
public function getNextRecipientGUID(string $delivery_interval, int $timestamp = null): ?int { |
106
|
2 |
|
$select = Select::fromTable(self::TABLE_NAME); |
107
|
2 |
|
$select->select('recipient_guid') |
108
|
2 |
|
->where($select->compare('delivery_interval', '=', $delivery_interval, ELGG_VALUE_STRING)) |
109
|
2 |
|
->andWhere($select->compare('timestamp', '<', $timestamp ?? $this->getCurrentTime()->getTimestamp())) |
110
|
2 |
|
->orderBy('timestamp', 'ASC') |
111
|
2 |
|
->addOrderBy('id', 'ASC') |
112
|
2 |
|
->setMaxResults(1); |
113
|
|
|
|
114
|
2 |
|
$row = $this->db->getDataRow($select); |
115
|
2 |
|
if (empty($row)) { |
116
|
1 |
|
return null; |
117
|
|
|
} |
118
|
|
|
|
119
|
2 |
|
return (int) $row->recipient_guid; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Remove a queue items from the database |
124
|
|
|
* |
125
|
|
|
* @param int $id the row to delete |
126
|
|
|
* |
127
|
|
|
* @return int number of deleted rows |
128
|
|
|
*/ |
129
|
2 |
|
public function deleteRow(int $id): int { |
130
|
2 |
|
$delete = Delete::fromTable(self::TABLE_NAME); |
131
|
2 |
|
$delete->where($delete->compare('id', '=', $id, ELGG_VALUE_ID)); |
132
|
|
|
|
133
|
2 |
|
return $this->db->deleteData($delete); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Delete all the queue items from the database for the given recipient and interval |
138
|
|
|
* |
139
|
|
|
* @param int $recipient_guid the recipient |
140
|
|
|
* @param string $delivery_interval the interval for the recipient |
141
|
|
|
* @param null|int $timestamp (optional) all queue items before time (default: now) |
142
|
|
|
* @param int $max_id (optional) the max row ID to remove (this includes the given row ID) |
143
|
|
|
* |
144
|
|
|
* @return int number of deleted rows |
145
|
|
|
*/ |
146
|
3 |
|
public function deleteRecipientRows(int $recipient_guid, string $delivery_interval, int $timestamp = null, int $max_id = 0): int { |
147
|
3 |
|
$delete = Delete::fromTable(self::TABLE_NAME); |
148
|
3 |
|
$delete->where($delete->compare('recipient_guid', '=', $recipient_guid, ELGG_VALUE_GUID)) |
149
|
3 |
|
->andWhere($delete->compare('delivery_interval', '=', $delivery_interval, ELGG_VALUE_STRING)) |
150
|
3 |
|
->andWhere($delete->compare('timestamp', '<', $timestamp ?? $this->getCurrentTime()->getTimestamp(), ELGG_VALUE_INTEGER)) |
151
|
3 |
|
->orderBy('timestamp', 'ASC') |
152
|
3 |
|
->addOrderBy('id', 'ASC'); |
153
|
|
|
|
154
|
3 |
|
if ($max_id > 0) { |
155
|
2 |
|
$delete->andWhere($delete->compare('id', '<=', $max_id, ELGG_VALUE_ID)); |
156
|
|
|
} |
157
|
|
|
|
158
|
3 |
|
return $this->db->deleteData($delete); |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
/** |
162
|
|
|
* Deletes all the queue items from the database for the given recipient |
163
|
|
|
* |
164
|
|
|
* @param int $recipient_guid the recipient |
165
|
|
|
* |
166
|
|
|
* @return int number of deleted rows |
167
|
|
|
*/ |
168
|
1290 |
|
public function deleteAllRecipientRows(int $recipient_guid): int { |
169
|
1290 |
|
$delete = Delete::fromTable(self::TABLE_NAME); |
170
|
1290 |
|
$delete->where($delete->compare('recipient_guid', '=', $recipient_guid, ELGG_VALUE_GUID)); |
171
|
|
|
|
172
|
1290 |
|
return $this->db->deleteData($delete); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Update the queued notifications for the recipient to a new delivery interval |
177
|
|
|
* |
178
|
|
|
* @param int $recipient_guid the recipient |
179
|
|
|
* @param string $delivery_interval the new delivery interval |
180
|
|
|
* |
181
|
|
|
* @return bool |
182
|
|
|
*/ |
183
|
1 |
|
public function updateRecipientInterval(int $recipient_guid, string $delivery_interval): bool { |
184
|
1 |
|
$update = Update::table(self::TABLE_NAME); |
185
|
1 |
|
$update->set('delivery_interval', $update->param($delivery_interval, ELGG_VALUE_STRING)) |
186
|
1 |
|
->where($update->compare('recipient_guid', '=', $recipient_guid, ELGG_VALUE_GUID)); |
187
|
|
|
|
188
|
1 |
|
return $this->db->updateData($update); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Convert a database row to a manageable object |
193
|
|
|
* |
194
|
|
|
* @param \stdClass $row the database record |
195
|
|
|
* |
196
|
|
|
* @return DatabaseRecord |
197
|
|
|
*/ |
198
|
7 |
|
public function rowToRecord(\stdClass $row): DatabaseRecord { |
199
|
7 |
|
return new DatabaseRecord($row); |
200
|
|
|
} |
201
|
|
|
} |
202
|
|
|
|